Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Stephen Boyd:
"This has been a semi-quiet cycle. The core framework remains unchanged
this time around.
In terms of shiny new code though, we have support for the SpacemiT K1
SoC, Sophgo SG2044, and T-HEAD TH1520 VO clk drivers joining the usual
silicon players like Qualcomm, Samsung, Allwinner, and Renesas.
Surprisingly, the Qualcomm pile was smaller than usual but that is
likely because they put one SoC support inside a driver for a
different SoC that is very similar.
Other than all those new clk drivers there are the usual clk data
updates to fix parents, frequency tables, and add missing clks along
with some Kconfig changes to make compile testing simpler and even
more DT binding conversions to boot.
The exciting part is still the new SoC support like SpacemiT and
Sophgo support though, which really dominate the diffstat because they
introduce a whole new silicon vendor clk driver.
New Drivers:
- Camera clock controller driver for Qualcomm QCS8300
- DE (display engine) 3.3 clocks on Allwinner H616
- Samsung ExynosAutov920 CPU cluster CL0, CL1 and CL2 clock controllers
- Video Output (VO) subsystem clk controller in the T-HEAD TH1520 SoC
- Clock driver for Sophgo SG2044
- Clock driver for SpacemiT K1 SoC
- Renesas RZ/V2N (R9A09G056) SoC clk driver
Updates:
- Correct data in various SoC clk drivers
- Allow clkaN to be optional in the Qualcomm RPMh clock controller
driver if command db doesn't define it
- Change Kconfig options to not enable by default during compile
testing
- Add missing clks in various SoC clk drivers
- Remove some duplicate clk DT bindings and convert some more to
YAML"
* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (93 commits)
clk: qcom: gcc-x1e80100: Set FORCE MEM CORE for UFS clocks
clk: qcom: gcc: Set FORCE_MEM_CORE_ON for gcc_ufs_axi_clk for 8650/8750
clk: qcom: rpmh: make clkaN optional
clk: qcom: Add support for Camera Clock Controller on QCS8300
clk: rockchip: rk3528: add slab.h header include
clk: rockchip: rk3576: add missing slab.h include
clk: meson: Do not enable by default during compile testing
clk: meson-g12a: add missing fclk_div2 to spicc
clk: qcom: gcc-msm8939: Fix mclk0 & mclk1 for 24 MHz
clk: rockchip: rename gate-grf clk file
clk: rockchip: rename branch_muxgrf to branch_grf_mux
clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support
dt-bindings: allwinner: add H616 DE33 clock binding
clk: samsung: correct clock summary for hsi1 block
dt-bindings: clock: add SM6350 QCOM video clock bindings
clk: rockchip: Pass NULL as reg pointer when registering GRF MMC clocks
clk: sunxi-ng: h616: Add LVDS reset for LCD TCON
dt-bindings: clock: sun50i-h616-ccu: Add LVDS reset
clk: rockchip: rk3036: mark ddrphy as critical
clk: rockchip: rk3036: fix implementation of usb480m clock mux
...
This commit is contained in:
@@ -25,6 +25,7 @@ properties:
|
||||
- const: allwinner,sun50i-a64-de2-clk
|
||||
- const: allwinner,sun50i-h5-de2-clk
|
||||
- const: allwinner,sun50i-h6-de3-clk
|
||||
- const: allwinner,sun50i-h616-de33-clk
|
||||
- items:
|
||||
- const: allwinner,sun8i-r40-de2-clk
|
||||
- const: allwinner,sun8i-h3-de2-clk
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
Broadcom BCM2835 auxiliary peripheral support
|
||||
|
||||
This binding uses the common clock binding:
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
The auxiliary peripherals (UART, SPI1, and SPI2) have a small register
|
||||
area controlling clock gating to the peripherals, and providing an IRQ
|
||||
status register.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "brcm,bcm2835-aux"
|
||||
- #clock-cells: Should be <1>. The permitted clock-specifier values can be
|
||||
found in include/dt-bindings/clock/bcm2835-aux.h
|
||||
- reg: Specifies base physical address and size of the registers
|
||||
- clocks: The parent clock phandle
|
||||
|
||||
Example:
|
||||
|
||||
clocks: cprman@7e101000 {
|
||||
compatible = "brcm,bcm2835-cprman";
|
||||
#clock-cells = <1>;
|
||||
reg = <0x7e101000 0x2000>;
|
||||
clocks = <&clk_osc>;
|
||||
};
|
||||
|
||||
aux: aux@7e215004 {
|
||||
compatible = "brcm,bcm2835-aux";
|
||||
#clock-cells = <1>;
|
||||
reg = <0x7e215000 0x8>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/brcm,bcm2835-aux-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom BCM2835 auxiliary peripheral clock
|
||||
|
||||
maintainers:
|
||||
- Stefan Wahren <wahrenst@gmx.net>
|
||||
- Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
|
||||
|
||||
description:
|
||||
The auxiliary peripherals (UART, SPI1, and SPI2) have a small register
|
||||
area controlling clock gating to the peripherals, and providing an IRQ
|
||||
status register.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-aux
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
clock@7e215000 {
|
||||
compatible = "brcm,bcm2835-aux";
|
||||
reg = <0x7e215000 0x8>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>;
|
||||
};
|
||||
58
Documentation/devicetree/bindings/clock/fsl,vf610-ccm.yaml
Normal file
58
Documentation/devicetree/bindings/clock/fsl,vf610-ccm.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/fsl,vf610-ccm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Clock for Freescale Vybrid VF610 SOC
|
||||
|
||||
description:
|
||||
The clock consumer should specify the desired clock by having the clock
|
||||
ID in its "clocks" phandle cell. See include/dt-bindings/clock/vf610-clock.h
|
||||
for the full list of VF610 clock IDs
|
||||
|
||||
maintainers:
|
||||
- Frank Li <Frank.Li@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,vf610-ccm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: external crystal oscillator 32KHz, recommended
|
||||
- description: external crystal oscillator 24MHz, recommended
|
||||
- description: audio
|
||||
- description: enet
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: sxosc
|
||||
- const: fxosc
|
||||
- const: enet_ext
|
||||
- const: audio_ext
|
||||
minItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@4006b000 {
|
||||
compatible = "fsl,vf610-ccm";
|
||||
reg = <0x4006b000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&sxosc>, <&fxosc>;
|
||||
clock-names = "sxosc", "fxosc";
|
||||
};
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
Binding for Maxim MAX77686/MAX77802/MAX77620 32k clock generator block
|
||||
|
||||
This is a part of device tree bindings of MAX77686/MAX77802/MAX77620
|
||||
multi-function device. More information can be found in MFD DT binding
|
||||
doc as follows:
|
||||
bindings/mfd/max77686.txt for MAX77686 and
|
||||
bindings/mfd/max77802.txt for MAX77802 and
|
||||
bindings/mfd/max77620.txt for MAX77620.
|
||||
|
||||
The MAX77686 contains three 32.768khz clock outputs that can be controlled
|
||||
(gated/ungated) over I2C. Clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/maxim,max77686.h.
|
||||
|
||||
|
||||
The MAX77802 contains two 32.768khz clock outputs that can be controlled
|
||||
(gated/ungated) over I2C. Clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/maxim,max77802.h.
|
||||
|
||||
The MAX77686 contains one 32.768khz clock outputs that can be controlled
|
||||
(gated/ungated) over I2C. Clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/maxim,max77620.h.
|
||||
|
||||
Following properties should be presend in main device node of the MFD chip.
|
||||
|
||||
Required properties:
|
||||
|
||||
- #clock-cells: from common clock binding; shall be set to 1.
|
||||
|
||||
Optional properties:
|
||||
- clock-output-names: From common clock binding.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. Following indices are allowed:
|
||||
- 0: 32khz_ap clock (max77686, max77802), 32khz_out0 (max77620)
|
||||
- 1: 32khz_cp clock (max77686, max77802),
|
||||
- 2: 32khz_pmic clock (max77686).
|
||||
|
||||
Clocks are defined as preprocessor macros in above dt-binding header for
|
||||
respective chips.
|
||||
|
||||
Example:
|
||||
|
||||
1. With MAX77686:
|
||||
|
||||
#include <dt-bindings/clock/maxim,max77686.h>
|
||||
/* ... */
|
||||
|
||||
Node of the MFD chip
|
||||
max77686: max77686@9 {
|
||||
compatible = "maxim,max77686";
|
||||
interrupt-parent = <&wakeup_eint>;
|
||||
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
|
||||
reg = <0x09>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
Clock consumer node
|
||||
|
||||
foo@0 {
|
||||
compatible = "bar,foo";
|
||||
/* ... */
|
||||
clock-names = "my-clock";
|
||||
clocks = <&max77686 MAX77686_CLK_PMIC>;
|
||||
};
|
||||
|
||||
2. With MAX77802:
|
||||
|
||||
#include <dt-bindings/clock/maxim,max77802.h>
|
||||
/* ... */
|
||||
|
||||
Node of the MFD chip
|
||||
max77802: max77802@9 {
|
||||
compatible = "maxim,max77802";
|
||||
interrupt-parent = <&wakeup_eint>;
|
||||
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
|
||||
reg = <0x09>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
Clock consumer node
|
||||
|
||||
foo@0 {
|
||||
compatible = "bar,foo";
|
||||
/* ... */
|
||||
clock-names = "my-clock";
|
||||
clocks = <&max77802 MAX77802_CLK_32K_AP>;
|
||||
};
|
||||
|
||||
|
||||
3. With MAX77620:
|
||||
|
||||
#include <dt-bindings/clock/maxim,max77620.h>
|
||||
/* ... */
|
||||
|
||||
Node of the MFD chip
|
||||
max77620: max77620@3c {
|
||||
compatible = "maxim,max77620";
|
||||
reg = <0x3c>;
|
||||
#clock-cells = <1>;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
Clock consumer node
|
||||
|
||||
foo@0 {
|
||||
compatible = "bar,foo";
|
||||
/* ... */
|
||||
clock-names = "my-clock";
|
||||
clocks = <&max77620 MAX77620_CLK_32K_OUT0>;
|
||||
};
|
||||
@@ -14,6 +14,7 @@ description: |
|
||||
domains on Qualcomm SoCs.
|
||||
|
||||
See also::
|
||||
include/dt-bindings/clock/qcom,sm6350-videocc.h
|
||||
include/dt-bindings/clock/qcom,videocc-sc7180.h
|
||||
include/dt-bindings/clock/qcom,videocc-sc7280.h
|
||||
include/dt-bindings/clock/qcom,videocc-sdm845.h
|
||||
@@ -26,6 +27,7 @@ properties:
|
||||
- qcom,sc7180-videocc
|
||||
- qcom,sc7280-videocc
|
||||
- qcom,sdm845-videocc
|
||||
- qcom,sm6350-videocc
|
||||
- qcom,sm8150-videocc
|
||||
- qcom,sm8250-videocc
|
||||
|
||||
@@ -87,6 +89,24 @@ allOf:
|
||||
- const: bi_tcxo
|
||||
- const: bi_tcxo_ao
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sm6350-videocc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Video AHB clock from GCC
|
||||
- description: Board XO source
|
||||
- description: Sleep Clock source
|
||||
clock-names:
|
||||
items:
|
||||
- const: iface
|
||||
- const: bi_tcxo
|
||||
- const: sleep_clk
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
$id: http://devicetree.org/schemas/clock/renesas,rzv2h-cpg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/{G3E,V2H(P)} Clock Pulse Generator (CPG)
|
||||
title: Renesas RZ/{G3E,V2H(P),V2N} Clock Pulse Generator (CPG)
|
||||
|
||||
maintainers:
|
||||
- Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
|
||||
|
||||
description:
|
||||
On Renesas RZ/{G3E,V2H(P)} SoCs, the CPG (Clock Pulse Generator) handles
|
||||
On Renesas RZ/{G3E,V2H(P),V2N} SoCs, the CPG (Clock Pulse Generator) handles
|
||||
generation and control of clock signals for the IP modules, generation and
|
||||
control of resets, and control over booting, low power consumption and power
|
||||
supply domains.
|
||||
@@ -19,6 +19,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r9a09g047-cpg # RZ/G3E
|
||||
- renesas,r9a09g056-cpg # RZ/V2N
|
||||
- renesas,r9a09g057-cpg # RZ/V2H
|
||||
|
||||
reg:
|
||||
|
||||
@@ -8,6 +8,7 @@ title: Samsung ExynosAuto v920 SoC clock controller
|
||||
|
||||
maintainers:
|
||||
- Sunyeal Hong <sunyeal.hong@samsung.com>
|
||||
- Shin Son <shin.son@samsung.com>
|
||||
- Chanwoo Choi <cw00.choi@samsung.com>
|
||||
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||
- Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
@@ -32,6 +33,9 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- samsung,exynosautov920-cmu-top
|
||||
- samsung,exynosautov920-cmu-cpucl0
|
||||
- samsung,exynosautov920-cmu-cpucl1
|
||||
- samsung,exynosautov920-cmu-cpucl2
|
||||
- samsung,exynosautov920-cmu-peric0
|
||||
- samsung,exynosautov920-cmu-peric1
|
||||
- samsung,exynosautov920-cmu-misc
|
||||
@@ -69,6 +73,71 @@ allOf:
|
||||
items:
|
||||
- const: oscclk
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,exynosautov920-cmu-cpucl0
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (38.4 MHz)
|
||||
- description: CMU_CPUCL0 SWITCH clock (from CMU_TOP)
|
||||
- description: CMU_CPUCL0 CLUSTER clock (from CMU_TOP)
|
||||
- description: CMU_CPUCL0 DBG clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: switch
|
||||
- const: cluster
|
||||
- const: dbg
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,exynosautov920-cmu-cpucl1
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (38.4 MHz)
|
||||
- description: CMU_CPUCL1 SWITCH clock (from CMU_TOP)
|
||||
- description: CMU_CPUCL1 CLUSTER clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: switch
|
||||
- const: cluster
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,exynosautov920-cmu-cpucl2
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (38.4 MHz)
|
||||
- description: CMU_CPUCL2 SWITCH clock (from CMU_TOP)
|
||||
- description: CMU_CPUCL2 CLUSTER clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: switch
|
||||
- const: cluster
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -11,10 +11,18 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sophgo,cv1800-clk
|
||||
- sophgo,cv1810-clk
|
||||
- sophgo,sg2000-clk
|
||||
oneOf:
|
||||
- enum:
|
||||
- sophgo,cv1800b-clk
|
||||
- sophgo,cv1812h-clk
|
||||
- sophgo,sg2000-clk
|
||||
- items:
|
||||
- const: sophgo,sg2002-clk
|
||||
- const: sophgo,sg2000-clk
|
||||
- const: sophgo,cv1800-clk
|
||||
deprecated: true
|
||||
- const: sophgo,cv1810-clk
|
||||
deprecated: true
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/sophgo,sg2044-clk.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sophgo SG2044 Clock Controller
|
||||
|
||||
maintainers:
|
||||
- Inochi Amaoto <inochiama@gmail.com>
|
||||
|
||||
description: |
|
||||
The Sophgo SG2044 clock controller requires an external oscillator
|
||||
as input clock.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
include/dt-bindings/clock/sophgo,sg2044-clk.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sophgo,sg2044-clk
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: fpll0
|
||||
- description: fpll1
|
||||
- description: fpll2
|
||||
- description: dpll0
|
||||
- description: dpll1
|
||||
- description: dpll2
|
||||
- description: dpll3
|
||||
- description: dpll4
|
||||
- description: dpll5
|
||||
- description: dpll6
|
||||
- description: dpll7
|
||||
- description: mpll0
|
||||
- description: mpll1
|
||||
- description: mpll2
|
||||
- description: mpll3
|
||||
- description: mpll4
|
||||
- description: mpll5
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fpll0
|
||||
- const: fpll1
|
||||
- const: fpll2
|
||||
- const: dpll0
|
||||
- const: dpll1
|
||||
- const: dpll2
|
||||
- const: dpll3
|
||||
- const: dpll4
|
||||
- const: dpll5
|
||||
- const: dpll6
|
||||
- const: dpll7
|
||||
- const: mpll0
|
||||
- const: mpll1
|
||||
- const: mpll2
|
||||
- const: mpll3
|
||||
- const: mpll4
|
||||
- const: mpll5
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/sophgo,sg2044-pll.h>
|
||||
|
||||
clock-controller@50002000 {
|
||||
compatible = "sophgo,sg2044-clk";
|
||||
reg = <0x50002000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&syscon CLK_FPLL0>, <&syscon CLK_FPLL1>,
|
||||
<&syscon CLK_FPLL2>, <&syscon CLK_DPLL0>,
|
||||
<&syscon CLK_DPLL1>, <&syscon CLK_DPLL2>,
|
||||
<&syscon CLK_DPLL3>, <&syscon CLK_DPLL4>,
|
||||
<&syscon CLK_DPLL5>, <&syscon CLK_DPLL6>,
|
||||
<&syscon CLK_DPLL7>, <&syscon CLK_MPLL0>,
|
||||
<&syscon CLK_MPLL1>, <&syscon CLK_MPLL2>,
|
||||
<&syscon CLK_MPLL3>, <&syscon CLK_MPLL4>,
|
||||
<&syscon CLK_MPLL5>;
|
||||
clock-names = "fpll0", "fpll1", "fpll2", "dpll0",
|
||||
"dpll1", "dpll2", "dpll3", "dpll4",
|
||||
"dpll5", "dpll6", "dpll7", "mpll0",
|
||||
"mpll1", "mpll2", "mpll3", "mpll4",
|
||||
"mpll5";
|
||||
};
|
||||
50
Documentation/devicetree/bindings/clock/spacemit,k1-pll.yaml
Normal file
50
Documentation/devicetree/bindings/clock/spacemit,k1-pll.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/spacemit,k1-pll.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SpacemiT K1 PLL
|
||||
|
||||
maintainers:
|
||||
- Haylen Chu <heylenay@4d2.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: spacemit,k1-pll
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: External 24MHz oscillator
|
||||
|
||||
spacemit,mpmu:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the "Main PMU (MPMU)" syscon. It is used to check PLL
|
||||
lock status.
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/spacemit,k1-syscon.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- spacemit,mpmu
|
||||
- "#clock-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@d4090000 {
|
||||
compatible = "spacemit,k1-pll";
|
||||
reg = <0xd4090000 0x1000>;
|
||||
clocks = <&vctcxo_24m>;
|
||||
spacemit,mpmu = <&sysctl_mpmu>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
STMicroelectronics STM32H7 Reset and Clock Controller
|
||||
=====================================================
|
||||
|
||||
The RCC IP is both a reset and a clock controller.
|
||||
|
||||
Please refer to clock-bindings.txt for common clock controller binding usage.
|
||||
Please also refer to reset.txt for common reset controller binding usage.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be:
|
||||
"st,stm32h743-rcc"
|
||||
|
||||
- reg: should be register base and length as documented in the
|
||||
datasheet
|
||||
|
||||
- #reset-cells: 1, see below
|
||||
|
||||
- #clock-cells : from common clock binding; shall be set to 1
|
||||
|
||||
- clocks: External oscillator clock phandle
|
||||
- high speed external clock signal (HSE)
|
||||
- low speed external clock signal (LSE)
|
||||
- external I2S clock (I2S_CKIN)
|
||||
|
||||
Optional properties:
|
||||
- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
|
||||
write protection (RTC clock).
|
||||
|
||||
Example:
|
||||
|
||||
rcc: reset-clock-controller@58024400 {
|
||||
compatible = "st,stm32h743-rcc", "st,stm32-rcc";
|
||||
reg = <0x58024400 0x400>;
|
||||
#reset-cells = <1>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>;
|
||||
|
||||
st,syscfg = <&pwrcfg>;
|
||||
};
|
||||
|
||||
The peripheral clock consumer should specify the desired clock by
|
||||
having the clock ID in its "clocks" phandle cell.
|
||||
|
||||
Example:
|
||||
|
||||
timer5: timer@40000c00 {
|
||||
compatible = "st,stm32-timer";
|
||||
reg = <0x40000c00 0x400>;
|
||||
interrupts = <50>;
|
||||
clocks = <&rcc TIM5_CK>;
|
||||
};
|
||||
|
||||
Specifying softreset control of devices
|
||||
=======================================
|
||||
|
||||
Device nodes should specify the reset channel required in their "resets"
|
||||
property, containing a phandle to the reset device node and an index specifying
|
||||
which channel to use.
|
||||
The index is the bit number within the RCC registers bank, starting from RCC
|
||||
base address.
|
||||
It is calculated as: index = register_offset / 4 * 32 + bit_offset.
|
||||
Where bit_offset is the bit offset within the register.
|
||||
|
||||
For example, for CRC reset:
|
||||
crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107
|
||||
|
||||
Example:
|
||||
|
||||
timer2 {
|
||||
resets = <&rcc STM32H7_APB1L_RESET(TIM2)>;
|
||||
};
|
||||
@@ -8,7 +8,8 @@ title: T-HEAD TH1520 AP sub-system clock controller
|
||||
|
||||
description: |
|
||||
The T-HEAD TH1520 AP sub-system clock controller configures the
|
||||
CPU, DPU, GMAC and TEE PLLs.
|
||||
CPU, DPU, GMAC and TEE PLLs. Additionally the VO subsystem configures
|
||||
the clock gates for the HDMI, MIPI and the GPU.
|
||||
|
||||
SoC reference manual
|
||||
https://openbeagle.org/beaglev-ahead/beaglev-ahead/-/blob/main/docs/TH1520%20System%20User%20Manual.pdf
|
||||
@@ -20,14 +21,24 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: thead,th1520-clk-ap
|
||||
enum:
|
||||
- thead,th1520-clk-ap
|
||||
- thead,th1520-clk-vo
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: main oscillator (24MHz)
|
||||
- description: |
|
||||
One input clock:
|
||||
- For "thead,th1520-clk-ap": the clock input must be the 24 MHz
|
||||
main oscillator.
|
||||
- For "thead,th1520-clk-vo": the clock input must be the VIDEO_PLL,
|
||||
which is configured by the AP clock controller. According to the
|
||||
TH1520 manual, VIDEO_PLL is a Silicon Creations Sigma-Delta PLL
|
||||
(integer PLL) typically running at 792 MHz (FOUTPOSTDIV), with
|
||||
a maximum FOUTVCO of 2376 MHz.
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
* Clock bindings for Freescale Vybrid VF610 SOC
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "fsl,vf610-ccm"
|
||||
- reg: Address and length of the register set
|
||||
- #clock-cells: Should be <1>
|
||||
|
||||
Optional properties:
|
||||
- clocks: list of clock identifiers which are external input clocks to the
|
||||
given clock controller. Please refer the next section to find
|
||||
the input clocks for a given controller.
|
||||
- clock-names: list of names of clocks which are external input clocks to the
|
||||
given clock controller.
|
||||
|
||||
Input clocks for top clock controller:
|
||||
- sxosc (external crystal oscillator 32KHz, recommended)
|
||||
- fxosc (external crystal oscillator 24MHz, recommended)
|
||||
- audio_ext
|
||||
- enet_ext
|
||||
|
||||
The clock consumer should specify the desired clock by having the clock
|
||||
ID in its "clocks" phandle cell. See include/dt-bindings/clock/vf610-clock.h
|
||||
for the full list of VF610 clock IDs.
|
||||
|
||||
Examples:
|
||||
|
||||
clks: ccm@4006b000 {
|
||||
compatible = "fsl,vf610-ccm";
|
||||
reg = <0x4006b000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&sxosc>, <&fxosc>;
|
||||
clock-names = "sxosc", "fxosc";
|
||||
};
|
||||
|
||||
uart1: serial@40028000 {
|
||||
compatible = "fsl,vf610-uart";
|
||||
reg = <0x40028000 0x1000>;
|
||||
interrupts = <0 62 0x04>;
|
||||
clocks = <&clks VF610_CLK_UART1>;
|
||||
clock-names = "ipg";
|
||||
};
|
||||
@@ -27,6 +27,7 @@ properties:
|
||||
- renesas,r9a07g044-pinctrl # RZ/G2{L,LC}
|
||||
- renesas,r9a08g045-pinctrl # RZ/G3S
|
||||
- renesas,r9a09g047-pinctrl # RZ/G3E
|
||||
- renesas,r9a09g056-pinctrl # RZ/V2N
|
||||
- renesas,r9a09g057-pinctrl # RZ/V2H(P)
|
||||
|
||||
- items:
|
||||
@@ -145,6 +146,7 @@ allOf:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,r9a09g047-pinctrl
|
||||
- renesas,r9a09g056-pinctrl
|
||||
- renesas,r9a09g057-pinctrl
|
||||
then:
|
||||
properties:
|
||||
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a09g047-sys # RZ/G3E
|
||||
- renesas,r9a09g056-sys # RZ/V2N
|
||||
- renesas,r9a09g057-sys # RZ/V2H
|
||||
|
||||
reg:
|
||||
|
||||
@@ -551,6 +551,21 @@ properties:
|
||||
- renesas,r9a09g047e58 # Quad Cortex-A55 + Cortex-M33 + Ethos-U55 (21mm BGA)
|
||||
- const: renesas,r9a09g047
|
||||
|
||||
- description: RZ/V2N (R9A09G056)
|
||||
items:
|
||||
- enum:
|
||||
- renesas,rzv2n-evk # RZ/V2N EVK (RTK0EF0186C03000BJ)
|
||||
- enum:
|
||||
- renesas,r9a09g056n41 # RZ/V2N
|
||||
- renesas,r9a09g056n42 # RZ/V2N with Mali-G31 support
|
||||
- renesas,r9a09g056n43 # RZ/V2N with Mali-C55 support
|
||||
- renesas,r9a09g056n44 # RZ/V2N with Mali-G31 + Mali-C55 support
|
||||
- renesas,r9a09g056n45 # RZ/V2N with cryptographic extension support
|
||||
- renesas,r9a09g056n46 # RZ/V2N with Mali-G31 + cryptographic extension support
|
||||
- renesas,r9a09g056n47 # RZ/V2N with Mali-C55 + cryptographic extension support
|
||||
- renesas,r9a09g056n48 # RZ/V2N with Mali-G31 + Mali-C55 + cryptographic extension support
|
||||
- const: renesas,r9a09g056
|
||||
|
||||
- description: RZ/V2H(P) (R9A09G057)
|
||||
items:
|
||||
- enum:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/sophgo/sophgo,sg2044-top-syscon.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sophgo SG2044 SoC TOP system controller
|
||||
|
||||
maintainers:
|
||||
- Inochi Amaoto <inochiama@gmail.com>
|
||||
|
||||
description:
|
||||
The Sophgo SG2044 TOP system controller is a hardware block grouping
|
||||
multiple small functions, such as clocks and some other internal
|
||||
function.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: sophgo,sg2044-top-syscon
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/sophgo,sg2044-pll.h> for valid clock.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
syscon@50000000 {
|
||||
compatible = "sophgo,sg2044-top-syscon", "syscon";
|
||||
reg = <0x50000000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc>;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/spacemit/spacemit,k1-syscon.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SpacemiT K1 SoC System Controller
|
||||
|
||||
maintainers:
|
||||
- Haylen Chu <heylenay@4d2.org>
|
||||
|
||||
description:
|
||||
System controllers found on SpacemiT K1 SoC, which are capable of
|
||||
clock, reset and power-management functions.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- spacemit,k1-syscon-apbc
|
||||
- spacemit,k1-syscon-apmu
|
||||
- spacemit,k1-syscon-mpmu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: osc
|
||||
- const: vctcxo_1m
|
||||
- const: vctcxo_3m
|
||||
- const: vctcxo_24m
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/spacemit,k1-syscon.h> for valid indices.
|
||||
|
||||
"#power-domain-cells":
|
||||
const: 1
|
||||
|
||||
"#reset-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- "#clock-cells"
|
||||
- "#reset-cells"
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: spacemit,k1-syscon-apbc
|
||||
then:
|
||||
properties:
|
||||
"#power-domain-cells": false
|
||||
else:
|
||||
required:
|
||||
- "#power-domain-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
system-controller@d4050000 {
|
||||
compatible = "spacemit,k1-syscon-mpmu";
|
||||
reg = <0xd4050000 0x209c>;
|
||||
clocks = <&osc>, <&vctcxo_1m>, <&vctcxo_3m>, <&vctcxo_24m>;
|
||||
clock-names = "osc", "vctcxo_1m", "vctcxo_3m", "vctcxo_24m";
|
||||
#clock-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -14765,7 +14765,6 @@ F: Documentation/devicetree/bindings/*/maxim,max77686.yaml
|
||||
F: Documentation/devicetree/bindings/*/maxim,max77693.yaml
|
||||
F: Documentation/devicetree/bindings/*/maxim,max77705*.yaml
|
||||
F: Documentation/devicetree/bindings/*/maxim,max77843.yaml
|
||||
F: Documentation/devicetree/bindings/clock/maxim,max77686.txt
|
||||
F: drivers/leds/leds-max77705.c
|
||||
F: drivers/*/*max77843.c
|
||||
F: drivers/*/max14577*.c
|
||||
|
||||
@@ -517,6 +517,7 @@ source "drivers/clk/samsung/Kconfig"
|
||||
source "drivers/clk/sifive/Kconfig"
|
||||
source "drivers/clk/socfpga/Kconfig"
|
||||
source "drivers/clk/sophgo/Kconfig"
|
||||
source "drivers/clk/spacemit/Kconfig"
|
||||
source "drivers/clk/sprd/Kconfig"
|
||||
source "drivers/clk/starfive/Kconfig"
|
||||
source "drivers/clk/sunxi/Kconfig"
|
||||
|
||||
@@ -145,6 +145,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
|
||||
obj-$(CONFIG_CLK_SIFIVE) += sifive/
|
||||
obj-y += socfpga/
|
||||
obj-y += sophgo/
|
||||
obj-y += spacemit/
|
||||
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
||||
obj-y += sprd/
|
||||
obj-$(CONFIG_ARCH_STI) += st/
|
||||
|
||||
@@ -53,24 +53,6 @@ static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
|
||||
return (u64)reg_div + ((u64)1 << div->u.s.frac_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a scaled divider value as close as possible to the
|
||||
* given whole part (div_value) and fractional part (expressed
|
||||
* in billionths).
|
||||
*/
|
||||
u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
|
||||
{
|
||||
u64 combined;
|
||||
|
||||
BUG_ON(!div_value);
|
||||
BUG_ON(billionths >= BILLION);
|
||||
|
||||
combined = (u64)div_value * BILLION + billionths;
|
||||
combined <<= div->u.s.frac_width;
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(combined, BILLION);
|
||||
}
|
||||
|
||||
/* The scaled minimum divisor representable by a divider */
|
||||
static inline u64
|
||||
scaled_div_min(struct bcm_clk_div *div)
|
||||
|
||||
@@ -492,8 +492,6 @@ extern struct clk_ops kona_peri_clk_ops;
|
||||
/* Externally visible functions */
|
||||
|
||||
extern u64 scaled_div_max(struct bcm_clk_div *div);
|
||||
extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value,
|
||||
u32 billionths);
|
||||
|
||||
extern void __init kona_dt_ccu_setup(struct ccu_data *ccu,
|
||||
struct device_node *node);
|
||||
|
||||
@@ -286,6 +286,8 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
|
||||
init.name = devm_kasprintf(rpi->dev, GFP_KERNEL,
|
||||
"fw-clk-%s",
|
||||
rpi_firmware_clk_names[id]);
|
||||
if (!init.name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
init.ops = &raspberrypi_firmware_clk_ops;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
|
||||
@@ -480,4 +482,3 @@ module_platform_driver(raspberrypi_clk_driver);
|
||||
MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
|
||||
MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:raspberrypi-clk");
|
||||
|
||||
@@ -763,13 +763,14 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
child = of_get_child_by_name(node, "pllout");
|
||||
if (of_device_is_available(child))
|
||||
child = of_get_available_child_by_name(node, "pllout");
|
||||
if (child) {
|
||||
of_clk_add_provider(child, of_clk_src_simple_get, clk);
|
||||
of_node_put(child);
|
||||
of_node_put(child);
|
||||
}
|
||||
|
||||
child = of_get_child_by_name(node, "sysclk");
|
||||
if (of_device_is_available(child)) {
|
||||
child = of_get_available_child_by_name(node, "sysclk");
|
||||
if (child) {
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct clk **clks;
|
||||
int n_clks = max_sysclk_id + 1;
|
||||
@@ -803,11 +804,11 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
|
||||
clks[(*div_info)->id] = clk;
|
||||
}
|
||||
of_clk_add_provider(child, of_clk_src_onecell_get, clk_data);
|
||||
of_node_put(child);
|
||||
}
|
||||
of_node_put(child);
|
||||
|
||||
child = of_get_child_by_name(node, "auxclk");
|
||||
if (of_device_is_available(child)) {
|
||||
child = of_get_available_child_by_name(node, "auxclk");
|
||||
if (child) {
|
||||
char child_name[MAX_NAME_SIZE];
|
||||
|
||||
snprintf(child_name, MAX_NAME_SIZE, "%s_auxclk", info->name);
|
||||
@@ -818,11 +819,12 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
|
||||
child_name, PTR_ERR(clk));
|
||||
else
|
||||
of_clk_add_provider(child, of_clk_src_simple_get, clk);
|
||||
}
|
||||
of_node_put(child);
|
||||
|
||||
child = of_get_child_by_name(node, "obsclk");
|
||||
if (of_device_is_available(child)) {
|
||||
of_node_put(child);
|
||||
}
|
||||
|
||||
child = of_get_available_child_by_name(node, "obsclk");
|
||||
if (child) {
|
||||
if (obsclk_info)
|
||||
clk = davinci_pll_obsclk_register(dev, obsclk_info, base);
|
||||
else
|
||||
@@ -833,8 +835,8 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
|
||||
PTR_ERR(clk));
|
||||
else
|
||||
of_clk_add_provider(child, of_clk_src_simple_get, clk);
|
||||
of_node_put(child);
|
||||
}
|
||||
of_node_put(child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ config COMMON_CLK_MESON_CPU_DYNDIV
|
||||
config COMMON_CLK_MESON8B
|
||||
bool "Meson8 SoC Clock controller support"
|
||||
depends on ARM
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_CLKC_UTILS
|
||||
select COMMON_CLK_MESON_MPLL
|
||||
@@ -70,7 +70,7 @@ config COMMON_CLK_MESON8B
|
||||
config COMMON_CLK_GXBB
|
||||
tristate "GXBB and GXL SoC clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_DUALDIV
|
||||
select COMMON_CLK_MESON_VID_PLL_DIV
|
||||
@@ -86,7 +86,7 @@ config COMMON_CLK_GXBB
|
||||
config COMMON_CLK_AXG
|
||||
tristate "AXG SoC clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_DUALDIV
|
||||
select COMMON_CLK_MESON_MPLL
|
||||
@@ -136,7 +136,7 @@ config COMMON_CLK_A1_PERIPHERALS
|
||||
config COMMON_CLK_C3_PLL
|
||||
tristate "Amlogic C3 PLL clock controller"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_PLL
|
||||
select COMMON_CLK_MESON_CLKC_UTILS
|
||||
@@ -149,7 +149,7 @@ config COMMON_CLK_C3_PLL
|
||||
config COMMON_CLK_C3_PERIPHERALS
|
||||
tristate "Amlogic C3 peripherals clock controller"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_DUALDIV
|
||||
select COMMON_CLK_MESON_CLKC_UTILS
|
||||
@@ -163,7 +163,7 @@ config COMMON_CLK_C3_PERIPHERALS
|
||||
config COMMON_CLK_G12A
|
||||
tristate "G12 and SM1 SoC clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_DUALDIV
|
||||
select COMMON_CLK_MESON_MPLL
|
||||
@@ -181,7 +181,7 @@ config COMMON_CLK_G12A
|
||||
config COMMON_CLK_S4_PLL
|
||||
tristate "S4 SoC PLL clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_CLKC_UTILS
|
||||
select COMMON_CLK_MESON_MPLL
|
||||
select COMMON_CLK_MESON_PLL
|
||||
@@ -194,7 +194,7 @@ config COMMON_CLK_S4_PLL
|
||||
config COMMON_CLK_S4_PERIPHERALS
|
||||
tristate "S4 SoC peripherals clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
default ARCH_MESON
|
||||
select COMMON_CLK_MESON_CLKC_UTILS
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_DUALDIV
|
||||
|
||||
@@ -4093,6 +4093,7 @@ static const struct clk_parent_data spicc_sclk_parent_data[] = {
|
||||
{ .hw = &g12a_clk81.hw },
|
||||
{ .hw = &g12a_fclk_div4.hw },
|
||||
{ .hw = &g12a_fclk_div3.hw },
|
||||
{ .hw = &g12a_fclk_div2.hw },
|
||||
{ .hw = &g12a_fclk_div5.hw },
|
||||
{ .hw = &g12a_fclk_div7.hw },
|
||||
};
|
||||
|
||||
@@ -111,7 +111,11 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev)
|
||||
* driver, there seems to be no better place to do this. So do it here!
|
||||
*/
|
||||
cpu_dev = get_cpu_device(0);
|
||||
dev_pm_domain_attach(cpu_dev, true);
|
||||
ret = dev_pm_domain_attach(cpu_dev, true);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "can't get PM domain: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <dt-bindings/clock/qcom,sa8775p-camcc.h>
|
||||
#include <dt-bindings/clock/qcom,qcs8300-camcc.h>
|
||||
|
||||
#include "clk-alpha-pll.h"
|
||||
#include "clk-branch.h"
|
||||
@@ -1681,6 +1681,24 @@ static struct clk_branch cam_cc_sm_obs_clk = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch cam_cc_titan_top_accu_shift_clk = {
|
||||
.halt_reg = 0x131f0,
|
||||
.halt_check = BRANCH_HALT_VOTED,
|
||||
.clkr = {
|
||||
.enable_reg = 0x131f0,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(const struct clk_init_data) {
|
||||
.name = "cam_cc_titan_top_accu_shift_clk",
|
||||
.parent_hws = (const struct clk_hw*[]) {
|
||||
&cam_cc_xo_clk_src.clkr.hw,
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct gdsc cam_cc_titan_top_gdsc = {
|
||||
.gdscr = 0x131bc,
|
||||
.en_rest_wait_val = 0x2,
|
||||
@@ -1775,6 +1793,7 @@ static struct clk_regmap *cam_cc_sa8775p_clocks[] = {
|
||||
[CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr,
|
||||
[CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr,
|
||||
[CAM_CC_SM_OBS_CLK] = &cam_cc_sm_obs_clk.clkr,
|
||||
[CAM_CC_TITAN_TOP_ACCU_SHIFT_CLK] = NULL,
|
||||
[CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr,
|
||||
[CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr,
|
||||
};
|
||||
@@ -1811,6 +1830,7 @@ static const struct qcom_cc_desc cam_cc_sa8775p_desc = {
|
||||
};
|
||||
|
||||
static const struct of_device_id cam_cc_sa8775p_match_table[] = {
|
||||
{ .compatible = "qcom,qcs8300-camcc" },
|
||||
{ .compatible = "qcom,sa8775p-camcc" },
|
||||
{ }
|
||||
};
|
||||
@@ -1841,10 +1861,83 @@ static int cam_cc_sa8775p_probe(struct platform_device *pdev)
|
||||
clk_lucid_evo_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
|
||||
clk_lucid_evo_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config);
|
||||
|
||||
/* Keep some clocks always enabled */
|
||||
qcom_branch_set_clk_en(regmap, 0x13194); /* CAM_CC_CAMNOC_XO_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_GDSC_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x13208); /* CAM_CC_SLEEP_CLK */
|
||||
if (device_is_compatible(&pdev->dev, "qcom,qcs8300-camcc")) {
|
||||
cam_cc_camnoc_axi_clk_src.cmd_rcgr = 0x13154;
|
||||
cam_cc_camnoc_axi_clk.halt_reg = 0x1316c;
|
||||
cam_cc_camnoc_axi_clk.clkr.enable_reg = 0x1316c;
|
||||
cam_cc_camnoc_dcd_xo_clk.halt_reg = 0x13174;
|
||||
cam_cc_camnoc_dcd_xo_clk.clkr.enable_reg = 0x13174;
|
||||
|
||||
cam_cc_csi0phytimer_clk_src.cmd_rcgr = 0x15054;
|
||||
cam_cc_csi1phytimer_clk_src.cmd_rcgr = 0x15078;
|
||||
cam_cc_csi2phytimer_clk_src.cmd_rcgr = 0x15098;
|
||||
cam_cc_csid_clk_src.cmd_rcgr = 0x13134;
|
||||
|
||||
cam_cc_mclk0_clk_src.cmd_rcgr = 0x15000;
|
||||
cam_cc_mclk1_clk_src.cmd_rcgr = 0x1501c;
|
||||
cam_cc_mclk2_clk_src.cmd_rcgr = 0x15038;
|
||||
|
||||
cam_cc_fast_ahb_clk_src.cmd_rcgr = 0x13104;
|
||||
cam_cc_slow_ahb_clk_src.cmd_rcgr = 0x1311c;
|
||||
cam_cc_xo_clk_src.cmd_rcgr = 0x131b8;
|
||||
cam_cc_sleep_clk_src.cmd_rcgr = 0x131d4;
|
||||
|
||||
cam_cc_core_ahb_clk.halt_reg = 0x131b4;
|
||||
cam_cc_core_ahb_clk.clkr.enable_reg = 0x131b4;
|
||||
|
||||
cam_cc_cpas_ahb_clk.halt_reg = 0x130f4;
|
||||
cam_cc_cpas_ahb_clk.clkr.enable_reg = 0x130f4;
|
||||
cam_cc_cpas_fast_ahb_clk.halt_reg = 0x130fc;
|
||||
cam_cc_cpas_fast_ahb_clk.clkr.enable_reg = 0x130fc;
|
||||
|
||||
cam_cc_csi0phytimer_clk.halt_reg = 0x1506c;
|
||||
cam_cc_csi0phytimer_clk.clkr.enable_reg = 0x1506c;
|
||||
cam_cc_csi1phytimer_clk.halt_reg = 0x15090;
|
||||
cam_cc_csi1phytimer_clk.clkr.enable_reg = 0x15090;
|
||||
cam_cc_csi2phytimer_clk.halt_reg = 0x150b0;
|
||||
cam_cc_csi2phytimer_clk.clkr.enable_reg = 0x150b0;
|
||||
cam_cc_csid_clk.halt_reg = 0x1314c;
|
||||
cam_cc_csid_clk.clkr.enable_reg = 0x1314c;
|
||||
cam_cc_csid_csiphy_rx_clk.halt_reg = 0x15074;
|
||||
cam_cc_csid_csiphy_rx_clk.clkr.enable_reg = 0x15074;
|
||||
cam_cc_csiphy0_clk.halt_reg = 0x15070;
|
||||
cam_cc_csiphy0_clk.clkr.enable_reg = 0x15070;
|
||||
cam_cc_csiphy1_clk.halt_reg = 0x15094;
|
||||
cam_cc_csiphy1_clk.clkr.enable_reg = 0x15094;
|
||||
cam_cc_csiphy2_clk.halt_reg = 0x150b4;
|
||||
cam_cc_csiphy2_clk.clkr.enable_reg = 0x150b4;
|
||||
|
||||
cam_cc_mclk0_clk.halt_reg = 0x15018;
|
||||
cam_cc_mclk0_clk.clkr.enable_reg = 0x15018;
|
||||
cam_cc_mclk1_clk.halt_reg = 0x15034;
|
||||
cam_cc_mclk1_clk.clkr.enable_reg = 0x15034;
|
||||
cam_cc_mclk2_clk.halt_reg = 0x15050;
|
||||
cam_cc_mclk2_clk.clkr.enable_reg = 0x15050;
|
||||
cam_cc_qdss_debug_xo_clk.halt_reg = 0x1319c;
|
||||
cam_cc_qdss_debug_xo_clk.clkr.enable_reg = 0x1319c;
|
||||
|
||||
cam_cc_titan_top_gdsc.gdscr = 0x131a0;
|
||||
|
||||
cam_cc_sa8775p_clocks[CAM_CC_CCI_3_CLK] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_CCI_3_CLK_SRC] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_CSI3PHYTIMER_CLK] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_CSI3PHYTIMER_CLK_SRC] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_CSIPHY3_CLK] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_MCLK3_CLK] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_MCLK3_CLK_SRC] = NULL;
|
||||
cam_cc_sa8775p_clocks[CAM_CC_TITAN_TOP_ACCU_SHIFT_CLK] =
|
||||
&cam_cc_titan_top_accu_shift_clk.clkr;
|
||||
|
||||
/* Keep some clocks always enabled */
|
||||
qcom_branch_set_clk_en(regmap, 0x13178); /* CAM_CC_CAMNOC_XO_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x131d0); /* CAM_CC_GDSC_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_SLEEP_CLK */
|
||||
} else {
|
||||
/* Keep some clocks always enabled */
|
||||
qcom_branch_set_clk_en(regmap, 0x13194); /* CAM_CC_CAMNOC_XO_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_GDSC_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x13208); /* CAM_CC_SLEEP_CLK */
|
||||
}
|
||||
|
||||
ret = qcom_cc_really_probe(&pdev->dev, &cam_cc_sa8775p_desc, regmap);
|
||||
|
||||
|
||||
@@ -1695,6 +1695,9 @@ static struct clk_branch camcc_sys_tmr_clk = {
|
||||
|
||||
static struct gdsc bps_gdsc = {
|
||||
.gdscr = 0x6004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "bps_gdsc",
|
||||
},
|
||||
@@ -1704,6 +1707,9 @@ static struct gdsc bps_gdsc = {
|
||||
|
||||
static struct gdsc ipe_0_gdsc = {
|
||||
.gdscr = 0x7004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "ipe_0_gdsc",
|
||||
},
|
||||
@@ -1713,6 +1719,9 @@ static struct gdsc ipe_0_gdsc = {
|
||||
|
||||
static struct gdsc ife_0_gdsc = {
|
||||
.gdscr = 0x9004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "ife_0_gdsc",
|
||||
},
|
||||
@@ -1721,6 +1730,9 @@ static struct gdsc ife_0_gdsc = {
|
||||
|
||||
static struct gdsc ife_1_gdsc = {
|
||||
.gdscr = 0xa004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "ife_1_gdsc",
|
||||
},
|
||||
@@ -1729,6 +1741,9 @@ static struct gdsc ife_1_gdsc = {
|
||||
|
||||
static struct gdsc ife_2_gdsc = {
|
||||
.gdscr = 0xb004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "ife_2_gdsc",
|
||||
},
|
||||
@@ -1737,6 +1752,9 @@ static struct gdsc ife_2_gdsc = {
|
||||
|
||||
static struct gdsc titan_top_gdsc = {
|
||||
.gdscr = 0x14004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "titan_top_gdsc",
|
||||
},
|
||||
|
||||
@@ -66,6 +66,8 @@ struct clk_rpmh {
|
||||
struct clk_rpmh_desc {
|
||||
struct clk_hw **clks;
|
||||
size_t num_clks;
|
||||
/* RPMh clock clkaN are optional for this platform */
|
||||
bool clka_optional;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(rpmh_clk_lock);
|
||||
@@ -648,6 +650,7 @@ static struct clk_hw *sm8550_rpmh_clocks[] = {
|
||||
static const struct clk_rpmh_desc clk_rpmh_sm8550 = {
|
||||
.clks = sm8550_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sm8550_rpmh_clocks),
|
||||
.clka_optional = true,
|
||||
};
|
||||
|
||||
static struct clk_hw *sm8650_rpmh_clocks[] = {
|
||||
@@ -679,6 +682,7 @@ static struct clk_hw *sm8650_rpmh_clocks[] = {
|
||||
static const struct clk_rpmh_desc clk_rpmh_sm8650 = {
|
||||
.clks = sm8650_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sm8650_rpmh_clocks),
|
||||
.clka_optional = true,
|
||||
};
|
||||
|
||||
static struct clk_hw *sc7280_rpmh_clocks[] = {
|
||||
@@ -847,6 +851,7 @@ static struct clk_hw *sm8750_rpmh_clocks[] = {
|
||||
static const struct clk_rpmh_desc clk_rpmh_sm8750 = {
|
||||
.clks = sm8750_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sm8750_rpmh_clocks),
|
||||
.clka_optional = true,
|
||||
};
|
||||
|
||||
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
|
||||
@@ -890,6 +895,12 @@ static int clk_rpmh_probe(struct platform_device *pdev)
|
||||
rpmh_clk = to_clk_rpmh(hw_clks[i]);
|
||||
res_addr = cmd_db_read_addr(rpmh_clk->res_name);
|
||||
if (!res_addr) {
|
||||
hw_clks[i] = NULL;
|
||||
|
||||
if (desc->clka_optional &&
|
||||
!strncmp(rpmh_clk->res_name, "clka", sizeof("clka") - 1))
|
||||
continue;
|
||||
|
||||
dev_err(&pdev->dev, "missing RPMh resource address for %s\n",
|
||||
rpmh_clk->res_name);
|
||||
return -ENODEV;
|
||||
|
||||
@@ -681,6 +681,9 @@ static struct clk_branch disp_cc_xo_clk = {
|
||||
|
||||
static struct gdsc mdss_gdsc = {
|
||||
.gdscr = 0x1004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "mdss_gdsc",
|
||||
},
|
||||
|
||||
@@ -432,7 +432,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_gpll6_sleep_map[] = {
|
||||
{ P_XO, 0 },
|
||||
{ P_GPLL0, 1 },
|
||||
{ P_GPLL1_AUX, 2 },
|
||||
{ P_GPLL6, 2 },
|
||||
{ P_GPLL6, 3 },
|
||||
{ P_SLEEP_CLK, 6 },
|
||||
};
|
||||
|
||||
@@ -1113,7 +1113,7 @@ static struct clk_rcg2 jpeg0_clk_src = {
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_camss_mclk0_1_clk[] = {
|
||||
F(24000000, P_GPLL0, 1, 1, 45),
|
||||
F(24000000, P_GPLL6, 1, 1, 45),
|
||||
F(66670000, P_GPLL0, 12, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -2320,6 +2320,9 @@ static struct clk_branch gcc_video_xo_clk = {
|
||||
|
||||
static struct gdsc usb30_prim_gdsc = {
|
||||
.gdscr = 0x1a004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "usb30_prim_gdsc",
|
||||
},
|
||||
@@ -2328,6 +2331,9 @@ static struct gdsc usb30_prim_gdsc = {
|
||||
|
||||
static struct gdsc ufs_phy_gdsc = {
|
||||
.gdscr = 0x3a004,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0xf,
|
||||
.pd = {
|
||||
.name = "ufs_phy_gdsc",
|
||||
},
|
||||
|
||||
@@ -3817,7 +3817,9 @@ static int gcc_sm8650_probe(struct platform_device *pdev)
|
||||
qcom_branch_set_clk_en(regmap, 0x32004); /* GCC_VIDEO_AHB_CLK */
|
||||
qcom_branch_set_clk_en(regmap, 0x32030); /* GCC_VIDEO_XO_CLK */
|
||||
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true);
|
||||
|
||||
/* Clear GDSC_SLEEP_ENA_VOTE to stop votes being auto-removed in sleep. */
|
||||
regmap_write(regmap, 0x52150, 0x0);
|
||||
|
||||
@@ -3244,8 +3244,9 @@ static int gcc_sm8750_probe(struct platform_device *pdev)
|
||||
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20));
|
||||
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21));
|
||||
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true);
|
||||
|
||||
return qcom_cc_really_probe(&pdev->dev, &gcc_sm8750_desc, regmap);
|
||||
}
|
||||
|
||||
@@ -6753,6 +6753,10 @@ static int gcc_x1e80100_probe(struct platform_device *pdev)
|
||||
/* Clear GDSC_SLEEP_ENA_VOTE to stop votes being auto-removed in sleep. */
|
||||
regmap_write(regmap, 0x52224, 0x0);
|
||||
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true);
|
||||
|
||||
return qcom_cc_really_probe(&pdev->dev, &gcc_x1e80100_desc, regmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -413,6 +413,9 @@ static struct clk_branch gpu_cc_gx_vsense_clk = {
|
||||
static struct gdsc gpu_cx_gdsc = {
|
||||
.gdscr = 0x106c,
|
||||
.gds_hw_ctrl = 0x1540,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0x8,
|
||||
.pd = {
|
||||
.name = "gpu_cx_gdsc",
|
||||
},
|
||||
@@ -423,6 +426,9 @@ static struct gdsc gpu_cx_gdsc = {
|
||||
static struct gdsc gpu_gx_gdsc = {
|
||||
.gdscr = 0x100c,
|
||||
.clamp_io_ctrl = 0x1508,
|
||||
.en_rest_wait_val = 0x2,
|
||||
.en_few_wait_val = 0x2,
|
||||
.clk_dis_wait_val = 0x2,
|
||||
.pd = {
|
||||
.name = "gpu_gx_gdsc",
|
||||
.power_on = gdsc_gx_do_nothing_enable,
|
||||
|
||||
@@ -41,6 +41,7 @@ config CLK_RENESAS
|
||||
select CLK_R9A08G045 if ARCH_R9A08G045
|
||||
select CLK_R9A09G011 if ARCH_R9A09G011
|
||||
select CLK_R9A09G047 if ARCH_R9A09G047
|
||||
select CLK_R9A09G056 if ARCH_R9A09G056
|
||||
select CLK_R9A09G057 if ARCH_R9A09G057
|
||||
select CLK_SH73A0 if ARCH_SH73A0
|
||||
|
||||
@@ -199,6 +200,10 @@ config CLK_R9A09G047
|
||||
bool "RZ/G3E clock support" if COMPILE_TEST
|
||||
select CLK_RZV2H
|
||||
|
||||
config CLK_R9A09G056
|
||||
bool "RZ/V2N clock support" if COMPILE_TEST
|
||||
select CLK_RZV2H
|
||||
|
||||
config CLK_R9A09G057
|
||||
bool "RZ/V2H(P) clock support" if COMPILE_TEST
|
||||
select CLK_RZV2H
|
||||
|
||||
@@ -38,6 +38,7 @@ obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o
|
||||
obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o
|
||||
obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o
|
||||
obj-$(CONFIG_CLK_R9A09G047) += r9a09g047-cpg.o
|
||||
obj-$(CONFIG_CLK_R9A09G056) += r9a09g056-cpg.o
|
||||
obj-$(CONFIG_CLK_R9A09G057) += r9a09g057-cpg.o
|
||||
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R9A09G047_IOTOP_0_SHCLK,
|
||||
LAST_DT_CORE_CLK = R9A09G047_GBETH_1_CLK_PTP_REF_I,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_AUDIO_EXTAL,
|
||||
@@ -31,7 +31,14 @@ enum clk_ids {
|
||||
CLK_PLLVDO,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_PLLCM33_DIV3,
|
||||
CLK_PLLCM33_DIV4,
|
||||
CLK_PLLCM33_DIV5,
|
||||
CLK_PLLCM33_DIV16,
|
||||
CLK_PLLCM33_GEAR,
|
||||
CLK_SMUX2_XSPI_CLK0,
|
||||
CLK_SMUX2_XSPI_CLK1,
|
||||
CLK_PLLCM33_XSPI,
|
||||
CLK_PLLCLN_DIV2,
|
||||
CLK_PLLCLN_DIV8,
|
||||
CLK_PLLCLN_DIV16,
|
||||
@@ -41,6 +48,7 @@ enum clk_ids {
|
||||
CLK_PLLDTY_ACPU_DIV4,
|
||||
CLK_PLLDTY_DIV16,
|
||||
CLK_PLLVDO_CRU0,
|
||||
CLK_PLLVDO_GPU,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE,
|
||||
@@ -60,6 +68,14 @@ static const struct clk_div_table dtable_2_4[] = {
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const struct clk_div_table dtable_2_16[] = {
|
||||
{0, 2},
|
||||
{1, 4},
|
||||
{2, 8},
|
||||
{3, 16},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const struct clk_div_table dtable_2_64[] = {
|
||||
{0, 2},
|
||||
{1, 4},
|
||||
@@ -69,6 +85,10 @@ static const struct clk_div_table dtable_2_64[] = {
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
/* Mux clock tables */
|
||||
static const char * const smux2_xspi_clk0[] = { ".pllcm33_div3", ".pllcm33_div4" };
|
||||
static const char * const smux2_xspi_clk1[] = { ".smux2_xspi_clk0", ".pllcm33_div5" };
|
||||
|
||||
static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
|
||||
@@ -79,12 +99,21 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
|
||||
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
|
||||
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLL_CONF(0x64)),
|
||||
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
|
||||
DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_FIXED(".pllcm33_div3", CLK_PLLCM33_DIV3, CLK_PLLCM33, 1, 3),
|
||||
DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
|
||||
DEF_FIXED(".pllcm33_div5", CLK_PLLCM33_DIV5, CLK_PLLCM33, 1, 5),
|
||||
DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
|
||||
|
||||
DEF_DDIV(".pllcm33_gear", CLK_PLLCM33_GEAR, CLK_PLLCM33_DIV4, CDDIV0_DIVCTL1, dtable_2_64),
|
||||
|
||||
DEF_SMUX(".smux2_xspi_clk0", CLK_SMUX2_XSPI_CLK0, SSEL1_SELCTL2, smux2_xspi_clk0),
|
||||
DEF_SMUX(".smux2_xspi_clk1", CLK_SMUX2_XSPI_CLK1, SSEL1_SELCTL3, smux2_xspi_clk1),
|
||||
DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI, CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3,
|
||||
dtable_2_16),
|
||||
DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
|
||||
DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
|
||||
DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
|
||||
@@ -96,6 +125,7 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
|
||||
DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
|
||||
|
||||
DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4),
|
||||
DEF_DDIV(".pllvdo_gpu", CLK_PLLVDO_GPU, CLK_PLLVDO, CDDIV3_DIVCTL1, dtable_2_64),
|
||||
|
||||
/* Core Clocks */
|
||||
DEF_FIXED("sys_0_pclk", R9A09G047_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
|
||||
@@ -108,6 +138,7 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
|
||||
DEF_DDIV("ca55_0_coreclk3", R9A09G047_CA55_0_CORECLK3, CLK_PLLCA55,
|
||||
CDDIV1_DIVCTL3, dtable_1_8),
|
||||
DEF_FIXED("iotop_0_shclk", R9A09G047_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
|
||||
DEF_FIXED("spi_clk_spi", R9A09G047_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2),
|
||||
};
|
||||
|
||||
static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
|
||||
@@ -153,6 +184,12 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
|
||||
BUS_MSTOP(10, BIT(14))),
|
||||
DEF_MOD("canfd_0_clkc", CLK_PLLCLN_DIV20, 9, 14, 4, 30,
|
||||
BUS_MSTOP(10, BIT(14))),
|
||||
DEF_MOD("spi_hclk", CLK_PLLCM33_GEAR, 9, 15, 4, 31,
|
||||
BUS_MSTOP(4, BIT(5))),
|
||||
DEF_MOD("spi_aclk", CLK_PLLCM33_GEAR, 10, 0, 5, 0,
|
||||
BUS_MSTOP(4, BIT(5))),
|
||||
DEF_MOD_NO_PM("spi_clk_spix2", CLK_PLLCM33_XSPI, 10, 1, 5, 2,
|
||||
BUS_MSTOP(4, BIT(5))),
|
||||
DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
|
||||
BUS_MSTOP(8, BIT(2))),
|
||||
DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
|
||||
@@ -183,6 +220,12 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
|
||||
BUS_MSTOP(9, BIT(4))),
|
||||
DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20,
|
||||
BUS_MSTOP(9, BIT(4))),
|
||||
DEF_MOD("ge3d_clk", CLK_PLLVDO_GPU, 15, 0, 7, 16,
|
||||
BUS_MSTOP(3, BIT(4))),
|
||||
DEF_MOD("ge3d_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
|
||||
BUS_MSTOP(3, BIT(4))),
|
||||
DEF_MOD("ge3d_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
|
||||
BUS_MSTOP(3, BIT(4))),
|
||||
DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10,
|
||||
BUS_MSTOP(2, BIT(15))),
|
||||
};
|
||||
@@ -207,12 +250,17 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = {
|
||||
DEF_RST(10, 0, 4, 17), /* RIIC_8_MRST */
|
||||
DEF_RST(10, 1, 4, 18), /* CANFD_0_RSTP_N */
|
||||
DEF_RST(10, 2, 4, 19), /* CANFD_0_RSTC_N */
|
||||
DEF_RST(10, 3, 4, 20), /* SPI_HRESETN */
|
||||
DEF_RST(10, 4, 4, 21), /* SPI_ARESETN */
|
||||
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
|
||||
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
|
||||
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
|
||||
DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
|
||||
DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
|
||||
DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
|
||||
DEF_RST(13, 13, 6, 14), /* GE3D_RESETN */
|
||||
DEF_RST(13, 14, 6, 15), /* GE3D_AXI_RESETN */
|
||||
DEF_RST(13, 15, 6, 16), /* GE3D_ACE_RESETN */
|
||||
DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */
|
||||
};
|
||||
|
||||
|
||||
152
drivers/clk/renesas/r9a09g056-cpg.c
Normal file
152
drivers/clk/renesas/r9a09g056-cpg.c
Normal file
@@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Renesas RZ/V2N CPG driver
|
||||
*
|
||||
* Copyright (C) 2025 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/clock/renesas,r9a09g056-cpg.h>
|
||||
|
||||
#include "rzv2h-cpg.h"
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R9A09G056_GBETH_1_CLK_PTP_REF_I,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_AUDIO_EXTAL,
|
||||
CLK_RTXIN,
|
||||
CLK_QEXTAL,
|
||||
|
||||
/* PLL Clocks */
|
||||
CLK_PLLCM33,
|
||||
CLK_PLLCLN,
|
||||
CLK_PLLDTY,
|
||||
CLK_PLLCA55,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_PLLCM33_DIV16,
|
||||
CLK_PLLCLN_DIV2,
|
||||
CLK_PLLCLN_DIV8,
|
||||
CLK_PLLDTY_ACPU,
|
||||
CLK_PLLDTY_ACPU_DIV4,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE,
|
||||
};
|
||||
|
||||
static const struct clk_div_table dtable_1_8[] = {
|
||||
{0, 1},
|
||||
{1, 2},
|
||||
{2, 4},
|
||||
{3, 8},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const struct clk_div_table dtable_2_64[] = {
|
||||
{0, 2},
|
||||
{1, 4},
|
||||
{2, 8},
|
||||
{3, 16},
|
||||
{4, 64},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
|
||||
DEF_INPUT("rtxin", CLK_RTXIN),
|
||||
DEF_INPUT("qextal", CLK_QEXTAL),
|
||||
|
||||
/* PLL Clocks */
|
||||
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
|
||||
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
|
||||
|
||||
DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
|
||||
DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
|
||||
|
||||
DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
|
||||
DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
|
||||
|
||||
/* Core Clocks */
|
||||
DEF_FIXED("sys_0_pclk", R9A09G056_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
|
||||
DEF_DDIV("ca55_0_coreclk0", R9A09G056_CA55_0_CORE_CLK0, CLK_PLLCA55,
|
||||
CDDIV1_DIVCTL0, dtable_1_8),
|
||||
DEF_DDIV("ca55_0_coreclk1", R9A09G056_CA55_0_CORE_CLK1, CLK_PLLCA55,
|
||||
CDDIV1_DIVCTL1, dtable_1_8),
|
||||
DEF_DDIV("ca55_0_coreclk2", R9A09G056_CA55_0_CORE_CLK2, CLK_PLLCA55,
|
||||
CDDIV1_DIVCTL2, dtable_1_8),
|
||||
DEF_DDIV("ca55_0_coreclk3", R9A09G056_CA55_0_CORE_CLK3, CLK_PLLCA55,
|
||||
CDDIV1_DIVCTL3, dtable_1_8),
|
||||
DEF_FIXED("iotop_0_shclk", R9A09G056_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
|
||||
};
|
||||
|
||||
static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = {
|
||||
DEF_MOD_CRITICAL("gic_0_gicclk", CLK_PLLDTY_ACPU_DIV4, 1, 3, 0, 19,
|
||||
BUS_MSTOP(3, BIT(5))),
|
||||
DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15,
|
||||
BUS_MSTOP(3, BIT(14))),
|
||||
DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
|
||||
BUS_MSTOP(8, BIT(2))),
|
||||
DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
|
||||
BUS_MSTOP(8, BIT(2))),
|
||||
DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5,
|
||||
BUS_MSTOP(8, BIT(2))),
|
||||
DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6,
|
||||
BUS_MSTOP(8, BIT(2))),
|
||||
DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7,
|
||||
BUS_MSTOP(8, BIT(3))),
|
||||
DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8,
|
||||
BUS_MSTOP(8, BIT(3))),
|
||||
DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9,
|
||||
BUS_MSTOP(8, BIT(3))),
|
||||
DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10,
|
||||
BUS_MSTOP(8, BIT(3))),
|
||||
DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11,
|
||||
BUS_MSTOP(8, BIT(4))),
|
||||
DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12,
|
||||
BUS_MSTOP(8, BIT(4))),
|
||||
DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13,
|
||||
BUS_MSTOP(8, BIT(4))),
|
||||
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
|
||||
BUS_MSTOP(8, BIT(4))),
|
||||
};
|
||||
|
||||
static const struct rzv2h_reset r9a09g056_resets[] __initconst = {
|
||||
DEF_RST(3, 0, 1, 1), /* SYS_0_PRESETN */
|
||||
DEF_RST(3, 8, 1, 9), /* GIC_0_GICRESET_N */
|
||||
DEF_RST(3, 9, 1, 10), /* GIC_0_DBG_GICRESET_N */
|
||||
DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
|
||||
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
|
||||
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
|
||||
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
|
||||
};
|
||||
|
||||
const struct rzv2h_cpg_info r9a09g056_cpg_info __initconst = {
|
||||
/* Core Clocks */
|
||||
.core_clks = r9a09g056_core_clks,
|
||||
.num_core_clks = ARRAY_SIZE(r9a09g056_core_clks),
|
||||
.last_dt_core_clk = LAST_DT_CORE_CLK,
|
||||
.num_total_core_clks = MOD_CLK_BASE,
|
||||
|
||||
/* Module Clocks */
|
||||
.mod_clks = r9a09g056_mod_clks,
|
||||
.num_mod_clks = ARRAY_SIZE(r9a09g056_mod_clks),
|
||||
.num_hw_mod_clks = 25 * 16,
|
||||
|
||||
/* Resets */
|
||||
.resets = r9a09g056_resets,
|
||||
.num_resets = ARRAY_SIZE(r9a09g056_resets),
|
||||
|
||||
.num_mstop_bits = 192,
|
||||
};
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R9A09G057_IOTOP_0_SHCLK,
|
||||
LAST_DT_CORE_CLK = R9A09G057_GBETH_1_CLK_PTP_REF_I,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_AUDIO_EXTAL,
|
||||
@@ -29,6 +29,7 @@ enum clk_ids {
|
||||
CLK_PLLDTY,
|
||||
CLK_PLLCA55,
|
||||
CLK_PLLVDO,
|
||||
CLK_PLLGPU,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_PLLCM33_DIV4,
|
||||
@@ -40,6 +41,7 @@ enum clk_ids {
|
||||
CLK_PLLDTY_ACPU,
|
||||
CLK_PLLDTY_ACPU_DIV2,
|
||||
CLK_PLLDTY_ACPU_DIV4,
|
||||
CLK_PLLDTY_DIV8,
|
||||
CLK_PLLDTY_DIV16,
|
||||
CLK_PLLDTY_RCPU,
|
||||
CLK_PLLDTY_RCPU_DIV4,
|
||||
@@ -47,6 +49,7 @@ enum clk_ids {
|
||||
CLK_PLLVDO_CRU1,
|
||||
CLK_PLLVDO_CRU2,
|
||||
CLK_PLLVDO_CRU3,
|
||||
CLK_PLLGPU_GEAR,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE,
|
||||
@@ -85,8 +88,9 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
|
||||
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
|
||||
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLL_CONF(0x64)),
|
||||
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
|
||||
DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
|
||||
DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
|
||||
@@ -101,6 +105,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
|
||||
DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
|
||||
DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
|
||||
DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
|
||||
DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8),
|
||||
DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
|
||||
DEF_DDIV(".plldty_rcpu", CLK_PLLDTY_RCPU, CLK_PLLDTY, CDDIV3_DIVCTL2, dtable_2_64),
|
||||
DEF_FIXED(".plldty_rcpu_div4", CLK_PLLDTY_RCPU_DIV4, CLK_PLLDTY_RCPU, 1, 4),
|
||||
@@ -110,6 +115,8 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
|
||||
DEF_DDIV(".pllvdo_cru2", CLK_PLLVDO_CRU2, CLK_PLLVDO, CDDIV4_DIVCTL1, dtable_2_4),
|
||||
DEF_DDIV(".pllvdo_cru3", CLK_PLLVDO_CRU3, CLK_PLLVDO, CDDIV4_DIVCTL2, dtable_2_4),
|
||||
|
||||
DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
|
||||
|
||||
/* Core Clocks */
|
||||
DEF_FIXED("sys_0_pclk", R9A09G057_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
|
||||
DEF_DDIV("ca55_0_coreclk0", R9A09G057_CA55_0_CORE_CLK0, CLK_PLLCA55,
|
||||
@@ -121,6 +128,8 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
|
||||
DEF_DDIV("ca55_0_coreclk3", R9A09G057_CA55_0_CORE_CLK3, CLK_PLLCA55,
|
||||
CDDIV1_DIVCTL3, dtable_1_8),
|
||||
DEF_FIXED("iotop_0_shclk", R9A09G057_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
|
||||
DEF_FIXED("usb2_0_clk_core0", R9A09G057_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1),
|
||||
DEF_FIXED("usb2_0_clk_core1", R9A09G057_USB2_0_CLK_CORE1, CLK_QEXTAL, 1, 1),
|
||||
};
|
||||
|
||||
static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
|
||||
@@ -214,6 +223,16 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
|
||||
BUS_MSTOP(8, BIT(4))),
|
||||
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
|
||||
BUS_MSTOP(8, BIT(4))),
|
||||
DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
|
||||
BUS_MSTOP(7, BIT(7))),
|
||||
DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20,
|
||||
BUS_MSTOP(7, BIT(8))),
|
||||
DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
|
||||
BUS_MSTOP(7, BIT(9))),
|
||||
DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22,
|
||||
BUS_MSTOP(7, BIT(10))),
|
||||
DEF_MOD("usb2_0_pclk_usbtst1", CLK_PLLDTY_ACPU_DIV4, 11, 7, 5, 23,
|
||||
BUS_MSTOP(7, BIT(11))),
|
||||
DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18,
|
||||
BUS_MSTOP(9, BIT(4))),
|
||||
DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19,
|
||||
@@ -238,6 +257,12 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
|
||||
BUS_MSTOP(9, BIT(7))),
|
||||
DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29,
|
||||
BUS_MSTOP(9, BIT(7))),
|
||||
DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16,
|
||||
BUS_MSTOP(3, BIT(4))),
|
||||
DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
|
||||
BUS_MSTOP(3, BIT(4))),
|
||||
DEF_MOD("gpu_0_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
|
||||
BUS_MSTOP(3, BIT(4))),
|
||||
};
|
||||
|
||||
static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
|
||||
@@ -275,6 +300,10 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
|
||||
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
|
||||
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
|
||||
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
|
||||
DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
|
||||
DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */
|
||||
DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
|
||||
DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
|
||||
DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
|
||||
DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
|
||||
DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
|
||||
@@ -287,6 +316,9 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
|
||||
DEF_RST(12, 14, 5, 31), /* CRU_3_PRESETN */
|
||||
DEF_RST(12, 15, 6, 0), /* CRU_3_ARESETN */
|
||||
DEF_RST(13, 0, 6, 1), /* CRU_3_S_RESETN */
|
||||
DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */
|
||||
DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */
|
||||
DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */
|
||||
};
|
||||
|
||||
const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/psci.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
|
||||
@@ -204,7 +205,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
|
||||
int error;
|
||||
|
||||
dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
|
||||
enable ? "ON" : "OFF");
|
||||
str_on_off(enable));
|
||||
spin_lock_irqsave(&priv->rmw_lock, flags);
|
||||
|
||||
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_choices.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
@@ -1217,7 +1218,7 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
|
||||
}
|
||||
|
||||
dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", CLK_ON_R(reg), hw->clk,
|
||||
enable ? "ON" : "OFF");
|
||||
str_on_off(enable));
|
||||
|
||||
value = bitmask << 16;
|
||||
if (enable)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
|
||||
@@ -44,10 +45,18 @@
|
||||
#define CPG_BUS_1_MSTOP (0xd00)
|
||||
#define CPG_BUS_MSTOP(m) (CPG_BUS_1_MSTOP + ((m) - 1) * 4)
|
||||
|
||||
#define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), (val)))
|
||||
#define MDIV(val) FIELD_GET(GENMASK(15, 6), (val))
|
||||
#define PDIV(val) FIELD_GET(GENMASK(5, 0), (val))
|
||||
#define SDIV(val) FIELD_GET(GENMASK(2, 0), (val))
|
||||
#define CPG_PLL_STBY(x) ((x))
|
||||
#define CPG_PLL_STBY_RESETB BIT(0)
|
||||
#define CPG_PLL_STBY_RESETB_WEN BIT(16)
|
||||
#define CPG_PLL_CLK1(x) ((x) + 0x004)
|
||||
#define CPG_PLL_CLK1_KDIV(x) ((s16)FIELD_GET(GENMASK(31, 16), (x)))
|
||||
#define CPG_PLL_CLK1_MDIV(x) FIELD_GET(GENMASK(15, 6), (x))
|
||||
#define CPG_PLL_CLK1_PDIV(x) FIELD_GET(GENMASK(5, 0), (x))
|
||||
#define CPG_PLL_CLK2(x) ((x) + 0x008)
|
||||
#define CPG_PLL_CLK2_SDIV(x) FIELD_GET(GENMASK(2, 0), (x))
|
||||
#define CPG_PLL_MON(x) ((x) + 0x010)
|
||||
#define CPG_PLL_MON_RESETB BIT(0)
|
||||
#define CPG_PLL_MON_LOCK BIT(4)
|
||||
|
||||
#define DDIV_DIVCTL_WEN(shift) BIT((shift) + 16)
|
||||
|
||||
@@ -94,8 +103,7 @@ struct pll_clk {
|
||||
struct rzv2h_cpg_priv *priv;
|
||||
void __iomem *base;
|
||||
struct clk_hw hw;
|
||||
unsigned int conf;
|
||||
unsigned int type;
|
||||
struct pll pll;
|
||||
};
|
||||
|
||||
#define to_pll(_hw) container_of(_hw, struct pll_clk, hw)
|
||||
@@ -110,7 +118,7 @@ struct pll_clk {
|
||||
* @on_index: register offset
|
||||
* @on_bit: ON/MON bit
|
||||
* @mon_index: monitor register offset
|
||||
* @mon_bit: montor bit
|
||||
* @mon_bit: monitor bit
|
||||
*/
|
||||
struct mod_clock {
|
||||
struct rzv2h_cpg_priv *priv;
|
||||
@@ -140,27 +148,78 @@ struct ddiv_clk {
|
||||
|
||||
#define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
|
||||
|
||||
static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct pll_clk *pll_clk = to_pll(hw);
|
||||
struct rzv2h_cpg_priv *priv = pll_clk->priv;
|
||||
u32 val = readl(priv->base + CPG_PLL_MON(pll_clk->pll.offset));
|
||||
|
||||
/* Ensure both RESETB and LOCK bits are set */
|
||||
return (val & (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK)) ==
|
||||
(CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK);
|
||||
}
|
||||
|
||||
static int rzv2h_cpg_pll_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct pll_clk *pll_clk = to_pll(hw);
|
||||
struct rzv2h_cpg_priv *priv = pll_clk->priv;
|
||||
struct pll pll = pll_clk->pll;
|
||||
u32 stby_offset;
|
||||
u32 mon_offset;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (rzv2h_cpg_pll_clk_is_enabled(hw))
|
||||
return 0;
|
||||
|
||||
stby_offset = CPG_PLL_STBY(pll.offset);
|
||||
mon_offset = CPG_PLL_MON(pll.offset);
|
||||
|
||||
writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
|
||||
priv->base + stby_offset);
|
||||
|
||||
/*
|
||||
* Ensure PLL enters into normal mode
|
||||
*
|
||||
* Note: There is no HW information about the worst case latency.
|
||||
*
|
||||
* Since this latency might depend on external crystal or PLL rate,
|
||||
* use a "super" safe timeout value.
|
||||
*/
|
||||
ret = readl_poll_timeout_atomic(priv->base + mon_offset, val,
|
||||
(val & (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK)) ==
|
||||
(CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK), 200, 2000);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to enable PLL 0x%x/%pC\n",
|
||||
stby_offset, hw->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct pll_clk *pll_clk = to_pll(hw);
|
||||
struct rzv2h_cpg_priv *priv = pll_clk->priv;
|
||||
struct pll pll = pll_clk->pll;
|
||||
unsigned int clk1, clk2;
|
||||
u64 rate;
|
||||
|
||||
if (!PLL_CLK_ACCESS(pll_clk->conf))
|
||||
if (!pll.has_clkn)
|
||||
return 0;
|
||||
|
||||
clk1 = readl(priv->base + PLL_CLK1_OFFSET(pll_clk->conf));
|
||||
clk2 = readl(priv->base + PLL_CLK2_OFFSET(pll_clk->conf));
|
||||
clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset));
|
||||
clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset));
|
||||
|
||||
rate = mul_u64_u32_shr(parent_rate, (MDIV(clk1) << 16) + KDIV(clk1),
|
||||
16 + SDIV(clk2));
|
||||
rate = mul_u64_u32_shr(parent_rate, (CPG_PLL_CLK1_MDIV(clk1) << 16) +
|
||||
CPG_PLL_CLK1_KDIV(clk1), 16 + CPG_PLL_CLK2_SDIV(clk2));
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(rate, PDIV(clk1));
|
||||
return DIV_ROUND_CLOSEST_ULL(rate, CPG_PLL_CLK1_PDIV(clk1));
|
||||
}
|
||||
|
||||
static const struct clk_ops rzv2h_cpg_pll_ops = {
|
||||
.is_enabled = rzv2h_cpg_pll_clk_is_enabled,
|
||||
.enable = rzv2h_cpg_pll_clk_enable,
|
||||
.recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
|
||||
};
|
||||
|
||||
@@ -193,10 +252,9 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
|
||||
init.num_parents = 1;
|
||||
|
||||
pll_clk->hw.init = &init;
|
||||
pll_clk->conf = core->cfg.conf;
|
||||
pll_clk->pll = core->cfg.pll;
|
||||
pll_clk->base = base;
|
||||
pll_clk->priv = priv;
|
||||
pll_clk->type = core->type;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &pll_clk->hw);
|
||||
if (ret)
|
||||
@@ -241,6 +299,9 @@ static inline int rzv2h_cpg_wait_ddiv_clk_update_done(void __iomem *base, u8 mon
|
||||
u32 bitmask = BIT(mon);
|
||||
u32 val;
|
||||
|
||||
if (mon == CSDIV_NO_MON)
|
||||
return 0;
|
||||
|
||||
return readl_poll_timeout_atomic(base + CPG_CLKSTATUS0, val, !(val & bitmask), 10, 200);
|
||||
}
|
||||
|
||||
@@ -272,12 +333,6 @@ static int rzv2h_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
writel(val, divider->reg);
|
||||
|
||||
ret = rzv2h_cpg_wait_ddiv_clk_update_done(priv->base, ddiv->mon);
|
||||
if (ret)
|
||||
goto ddiv_timeout;
|
||||
|
||||
spin_unlock_irqrestore(divider->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
ddiv_timeout:
|
||||
spin_unlock_irqrestore(divider->lock, flags);
|
||||
@@ -320,7 +375,10 @@ rzv2h_cpg_ddiv_clk_register(const struct cpg_core_clk *core,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = core->name;
|
||||
init.ops = &rzv2h_ddiv_clk_divider_ops;
|
||||
if (cfg_ddiv.no_rmw)
|
||||
init.ops = &clk_divider_ops;
|
||||
else
|
||||
init.ops = &rzv2h_ddiv_clk_divider_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
@@ -342,6 +400,24 @@ rzv2h_cpg_ddiv_clk_register(const struct cpg_core_clk *core,
|
||||
return div->hw.clk;
|
||||
}
|
||||
|
||||
static struct clk * __init
|
||||
rzv2h_cpg_mux_clk_register(const struct cpg_core_clk *core,
|
||||
struct rzv2h_cpg_priv *priv)
|
||||
{
|
||||
struct smuxed mux = core->cfg.smux;
|
||||
const struct clk_hw *clk_hw;
|
||||
|
||||
clk_hw = devm_clk_hw_register_mux(priv->dev, core->name,
|
||||
core->parent_names, core->num_parents,
|
||||
core->flag, priv->base + mux.offset,
|
||||
mux.shift, mux.width,
|
||||
core->mux_flags, &priv->rmw_lock);
|
||||
if (IS_ERR(clk_hw))
|
||||
return ERR_CAST(clk_hw);
|
||||
|
||||
return clk_hw->clk;
|
||||
}
|
||||
|
||||
static struct clk
|
||||
*rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
@@ -426,6 +502,9 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
|
||||
case CLK_TYPE_DDIV:
|
||||
clk = rzv2h_cpg_ddiv_clk_register(core, priv);
|
||||
break;
|
||||
case CLK_TYPE_SMUX:
|
||||
clk = rzv2h_cpg_mux_clk_register(core, priv);
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
@@ -494,11 +573,14 @@ static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw)
|
||||
if (clock->mon_index >= 0) {
|
||||
offset = GET_CLK_MON_OFFSET(clock->mon_index);
|
||||
bitmask = BIT(clock->mon_bit);
|
||||
} else {
|
||||
offset = GET_CLK_ON_OFFSET(clock->on_index);
|
||||
bitmask = BIT(clock->on_bit);
|
||||
|
||||
if (!(readl(priv->base + offset) & bitmask))
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = GET_CLK_ON_OFFSET(clock->on_index);
|
||||
bitmask = BIT(clock->on_bit);
|
||||
|
||||
return readl(priv->base + offset) & bitmask;
|
||||
}
|
||||
|
||||
@@ -514,7 +596,7 @@ static int rzv2h_mod_clock_endisable(struct clk_hw *hw, bool enable)
|
||||
int error;
|
||||
|
||||
dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", reg, hw->clk,
|
||||
enable ? "ON" : "OFF");
|
||||
str_on_off(enable));
|
||||
|
||||
if (enabled == enable)
|
||||
return 0;
|
||||
@@ -658,8 +740,8 @@ fail:
|
||||
mod->name, PTR_ERR(clk));
|
||||
}
|
||||
|
||||
static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
static int __rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
|
||||
unsigned int reg = GET_RST_OFFSET(priv->resets[id].reset_index);
|
||||
@@ -667,35 +749,31 @@ static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
|
||||
u8 monbit = priv->resets[id].mon_bit;
|
||||
u32 value = mask << 16;
|
||||
|
||||
dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, reg);
|
||||
dev_dbg(rcdev->dev, "%s id:%ld offset:0x%x\n",
|
||||
assert ? "assert" : "deassert", id, reg);
|
||||
|
||||
if (!assert)
|
||||
value |= mask;
|
||||
writel(value, priv->base + reg);
|
||||
|
||||
reg = GET_RST_MON_OFFSET(priv->resets[id].mon_index);
|
||||
mask = BIT(monbit);
|
||||
|
||||
return readl_poll_timeout_atomic(priv->base + reg, value,
|
||||
value & mask, 10, 200);
|
||||
assert ? (value & mask) : !(value & mask),
|
||||
10, 200);
|
||||
}
|
||||
|
||||
static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return __rzv2h_cpg_assert(rcdev, id, true);
|
||||
}
|
||||
|
||||
static int rzv2h_cpg_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
|
||||
unsigned int reg = GET_RST_OFFSET(priv->resets[id].reset_index);
|
||||
u32 mask = BIT(priv->resets[id].reset_bit);
|
||||
u8 monbit = priv->resets[id].mon_bit;
|
||||
u32 value = (mask << 16) | mask;
|
||||
|
||||
dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id, reg);
|
||||
|
||||
writel(value, priv->base + reg);
|
||||
|
||||
reg = GET_RST_MON_OFFSET(priv->resets[id].mon_index);
|
||||
mask = BIT(monbit);
|
||||
|
||||
return readl_poll_timeout_atomic(priv->base + reg, value,
|
||||
!(value & mask), 10, 200);
|
||||
return __rzv2h_cpg_assert(rcdev, id, false);
|
||||
}
|
||||
|
||||
static int rzv2h_cpg_reset(struct reset_controller_dev *rcdev,
|
||||
@@ -967,17 +1045,23 @@ static int __init rzv2h_cpg_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id rzv2h_cpg_match[] = {
|
||||
#ifdef CONFIG_CLK_R9A09G057
|
||||
{
|
||||
.compatible = "renesas,r9a09g057-cpg",
|
||||
.data = &r9a09g057_cpg_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CLK_R9A09G047
|
||||
{
|
||||
.compatible = "renesas,r9a09g047-cpg",
|
||||
.data = &r9a09g047_cpg_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CLK_R9A09G056
|
||||
{
|
||||
.compatible = "renesas,r9a09g056-cpg",
|
||||
.data = &r9a09g056_cpg_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CLK_R9A09G057
|
||||
{
|
||||
.compatible = "renesas,r9a09g057-cpg",
|
||||
.data = &r9a09g057_cpg_info,
|
||||
},
|
||||
#endif
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@@ -10,6 +10,26 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
/**
|
||||
* struct pll - Structure for PLL configuration
|
||||
*
|
||||
* @offset: STBY register offset
|
||||
* @has_clkn: Flag to indicate if CLK1/2 are accessible or not
|
||||
*/
|
||||
struct pll {
|
||||
unsigned int offset:9;
|
||||
unsigned int has_clkn:1;
|
||||
};
|
||||
|
||||
#define PLL_PACK(_offset, _has_clkn) \
|
||||
((struct pll){ \
|
||||
.offset = _offset, \
|
||||
.has_clkn = _has_clkn \
|
||||
})
|
||||
|
||||
#define PLLCA55 PLL_PACK(0x60, 1)
|
||||
#define PLLGPU PLL_PACK(0x120, 1)
|
||||
|
||||
/**
|
||||
* struct ddiv - Structure for dynamic switching divider
|
||||
*
|
||||
@@ -17,14 +37,25 @@
|
||||
* @shift: position of the divider bit
|
||||
* @width: width of the divider
|
||||
* @monbit: monitor bit in CPG_CLKSTATUS0 register
|
||||
* @no_rmw: flag to indicate if the register is read-modify-write
|
||||
* (1: no RMW, 0: RMW)
|
||||
*/
|
||||
struct ddiv {
|
||||
unsigned int offset:11;
|
||||
unsigned int shift:4;
|
||||
unsigned int width:4;
|
||||
unsigned int monbit:5;
|
||||
unsigned int no_rmw:1;
|
||||
};
|
||||
|
||||
/*
|
||||
* On RZ/V2H(P), the dynamic divider clock supports up to 19 monitor bits,
|
||||
* while on RZ/G3E, it supports up to 16 monitor bits. Use the maximum value
|
||||
* `0x1f` to indicate that monitor bits are not supported for static divider
|
||||
* clocks.
|
||||
*/
|
||||
#define CSDIV_NO_MON (0x1f)
|
||||
|
||||
#define DDIV_PACK(_offset, _shift, _width, _monbit) \
|
||||
((struct ddiv){ \
|
||||
.offset = _offset, \
|
||||
@@ -33,10 +64,41 @@ struct ddiv {
|
||||
.monbit = _monbit \
|
||||
})
|
||||
|
||||
#define DDIV_PACK_NO_RMW(_offset, _shift, _width, _monbit) \
|
||||
((struct ddiv){ \
|
||||
.offset = (_offset), \
|
||||
.shift = (_shift), \
|
||||
.width = (_width), \
|
||||
.monbit = (_monbit), \
|
||||
.no_rmw = 1 \
|
||||
})
|
||||
|
||||
/**
|
||||
* struct smuxed - Structure for static muxed clocks
|
||||
*
|
||||
* @offset: register offset
|
||||
* @shift: position of the divider field
|
||||
* @width: width of the divider field
|
||||
*/
|
||||
struct smuxed {
|
||||
unsigned int offset:11;
|
||||
unsigned int shift:4;
|
||||
unsigned int width:4;
|
||||
};
|
||||
|
||||
#define SMUX_PACK(_offset, _shift, _width) \
|
||||
((struct smuxed){ \
|
||||
.offset = (_offset), \
|
||||
.shift = (_shift), \
|
||||
.width = (_width), \
|
||||
})
|
||||
|
||||
#define CPG_SSEL1 (0x304)
|
||||
#define CPG_CDDIV0 (0x400)
|
||||
#define CPG_CDDIV1 (0x404)
|
||||
#define CPG_CDDIV3 (0x40C)
|
||||
#define CPG_CDDIV4 (0x410)
|
||||
#define CPG_CSDIV0 (0x500)
|
||||
|
||||
#define CDDIV0_DIVCTL1 DDIV_PACK(CPG_CDDIV0, 4, 3, 1)
|
||||
#define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
|
||||
@@ -44,12 +106,18 @@ struct ddiv {
|
||||
#define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5)
|
||||
#define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6)
|
||||
#define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7)
|
||||
#define CDDIV3_DIVCTL1 DDIV_PACK(CPG_CDDIV3, 4, 3, 13)
|
||||
#define CDDIV3_DIVCTL2 DDIV_PACK(CPG_CDDIV3, 8, 3, 14)
|
||||
#define CDDIV3_DIVCTL3 DDIV_PACK(CPG_CDDIV3, 12, 1, 15)
|
||||
#define CDDIV4_DIVCTL0 DDIV_PACK(CPG_CDDIV4, 0, 1, 16)
|
||||
#define CDDIV4_DIVCTL1 DDIV_PACK(CPG_CDDIV4, 4, 1, 17)
|
||||
#define CDDIV4_DIVCTL2 DDIV_PACK(CPG_CDDIV4, 8, 1, 18)
|
||||
|
||||
#define CSDIV0_DIVCTL3 DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON)
|
||||
|
||||
#define SSEL1_SELCTL2 SMUX_PACK(CPG_SSEL1, 8, 1)
|
||||
#define SSEL1_SELCTL3 SMUX_PACK(CPG_SSEL1, 12, 1)
|
||||
|
||||
#define BUS_MSTOP_IDX_MASK GENMASK(31, 16)
|
||||
#define BUS_MSTOP_BITS_MASK GENMASK(15, 0)
|
||||
#define BUS_MSTOP(idx, mask) (FIELD_PREP_CONST(BUS_MSTOP_IDX_MASK, (idx)) | \
|
||||
@@ -74,8 +142,13 @@ struct cpg_core_clk {
|
||||
union {
|
||||
unsigned int conf;
|
||||
struct ddiv ddiv;
|
||||
struct pll pll;
|
||||
struct smuxed smux;
|
||||
} cfg;
|
||||
const struct clk_div_table *dtable;
|
||||
const char * const *parent_names;
|
||||
unsigned int num_parents;
|
||||
u8 mux_flags;
|
||||
u32 flag;
|
||||
};
|
||||
|
||||
@@ -85,20 +158,15 @@ enum clk_types {
|
||||
CLK_TYPE_FF, /* Fixed Factor Clock */
|
||||
CLK_TYPE_PLL,
|
||||
CLK_TYPE_DDIV, /* Dynamic Switching Divider */
|
||||
CLK_TYPE_SMUX, /* Static Mux */
|
||||
};
|
||||
|
||||
/* BIT(31) indicates if CLK1/2 are accessible or not */
|
||||
#define PLL_CONF(n) (BIT(31) | ((n) & ~GENMASK(31, 16)))
|
||||
#define PLL_CLK_ACCESS(n) ((n) & BIT(31) ? 1 : 0)
|
||||
#define PLL_CLK1_OFFSET(n) ((n) & ~GENMASK(31, 16))
|
||||
#define PLL_CLK2_OFFSET(n) (((n) & ~GENMASK(31, 16)) + (0x4))
|
||||
|
||||
#define DEF_TYPE(_name, _id, _type...) \
|
||||
{ .name = _name, .id = _id, .type = _type }
|
||||
#define DEF_BASE(_name, _id, _type, _parent...) \
|
||||
DEF_TYPE(_name, _id, _type, .parent = _parent)
|
||||
#define DEF_PLL(_name, _id, _parent, _conf) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.conf = _conf)
|
||||
#define DEF_PLL(_name, _id, _parent, _pll_packed) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.pll = _pll_packed)
|
||||
#define DEF_INPUT(_name, _id) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_IN)
|
||||
#define DEF_FIXED(_name, _id, _parent, _mult, _div) \
|
||||
@@ -109,6 +177,15 @@ enum clk_types {
|
||||
.parent = _parent, \
|
||||
.dtable = _dtable, \
|
||||
.flag = CLK_DIVIDER_HIWORD_MASK)
|
||||
#define DEF_CSDIV(_name, _id, _parent, _ddiv_packed, _dtable) \
|
||||
DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable)
|
||||
#define DEF_SMUX(_name, _id, _smux_packed, _parent_names) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_SMUX, \
|
||||
.cfg.smux = _smux_packed, \
|
||||
.parent_names = _parent_names, \
|
||||
.num_parents = ARRAY_SIZE(_parent_names), \
|
||||
.flag = CLK_SET_RATE_PARENT, \
|
||||
.mux_flags = CLK_MUX_HIWORD_MASK)
|
||||
|
||||
/**
|
||||
* struct rzv2h_mod_clk - Module Clocks definitions
|
||||
@@ -221,6 +298,7 @@ struct rzv2h_cpg_info {
|
||||
};
|
||||
|
||||
extern const struct rzv2h_cpg_info r9a09g047_cpg_info;
|
||||
extern const struct rzv2h_cpg_info r9a09g056_cpg_info;
|
||||
extern const struct rzv2h_cpg_info r9a09g057_cpg_info;
|
||||
|
||||
#endif /* __RENESAS_RZV2H_CPG_H__ */
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_COMMON_CLK_ROCKCHIP) += clk-rockchip.o
|
||||
clk-rockchip-y += clk.o
|
||||
clk-rockchip-y += clk-pll.o
|
||||
clk-rockchip-y += clk-cpu.o
|
||||
clk-rockchip-y += clk-gate-grf.o
|
||||
clk-rockchip-y += clk-half-divider.o
|
||||
clk-rockchip-y += clk-inverter.o
|
||||
clk-rockchip-y += clk-mmc-phase.o
|
||||
|
||||
105
drivers/clk/rockchip/clk-gate-grf.c
Normal file
105
drivers/clk/rockchip/clk-gate-grf.c
Normal file
@@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2025 Collabora Ltd.
|
||||
* Author: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
|
||||
*
|
||||
* Certain clocks on Rockchip are "gated" behind an additional register bit
|
||||
* write in a GRF register, such as the SAI MCLKs on RK3576. This code
|
||||
* implements a clock driver for these types of gates, based on regmaps.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include "clk.h"
|
||||
|
||||
struct rockchip_gate_grf {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
unsigned int reg;
|
||||
unsigned int shift;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
#define to_gate_grf(_hw) container_of(_hw, struct rockchip_gate_grf, hw)
|
||||
|
||||
static int rockchip_gate_grf_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_gate_grf *gate = to_gate_grf(hw);
|
||||
u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? BIT(gate->shift) : 0;
|
||||
u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(gate->regmap, gate->reg,
|
||||
hiword | BIT(gate->shift), hiword | val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_gate_grf_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_gate_grf *gate = to_gate_grf(hw);
|
||||
u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : BIT(gate->shift);
|
||||
u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16);
|
||||
|
||||
regmap_update_bits(gate->regmap, gate->reg,
|
||||
hiword | BIT(gate->shift), hiword | val);
|
||||
}
|
||||
|
||||
static int rockchip_gate_grf_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_gate_grf *gate = to_gate_grf(hw);
|
||||
bool invert = !!(gate->flags & CLK_GATE_SET_TO_DISABLE);
|
||||
int ret;
|
||||
|
||||
ret = regmap_test_bits(gate->regmap, gate->reg, BIT(gate->shift));
|
||||
if (ret < 0)
|
||||
ret = 0;
|
||||
|
||||
return invert ? 1 - ret : ret;
|
||||
|
||||
}
|
||||
|
||||
static const struct clk_ops rockchip_gate_grf_ops = {
|
||||
.enable = rockchip_gate_grf_enable,
|
||||
.disable = rockchip_gate_grf_disable,
|
||||
.is_enabled = rockchip_gate_grf_is_enabled,
|
||||
};
|
||||
|
||||
struct clk *rockchip_clk_register_gate_grf(const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
struct regmap *regmap, unsigned int reg, unsigned int shift,
|
||||
u8 gate_flags)
|
||||
{
|
||||
struct rockchip_gate_grf *gate;
|
||||
struct clk_init_data init;
|
||||
struct clk *clk;
|
||||
|
||||
if (IS_ERR(regmap)) {
|
||||
pr_err("%s: regmap not available\n", __func__);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.flags = flags;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.ops = &rockchip_gate_grf_ops;
|
||||
|
||||
gate->hw.init = &init;
|
||||
gate->regmap = regmap;
|
||||
gate->reg = reg;
|
||||
gate->shift = shift;
|
||||
gate->flags = gate_flags;
|
||||
|
||||
clk = clk_register(NULL, &gate->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(gate);
|
||||
|
||||
return clk;
|
||||
}
|
||||
@@ -9,11 +9,14 @@
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/regmap.h>
|
||||
#include "clk.h"
|
||||
|
||||
struct rockchip_mmc_clock {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
struct regmap *grf;
|
||||
int grf_reg;
|
||||
int shift;
|
||||
int cached_phase;
|
||||
struct notifier_block clk_rate_change_nb;
|
||||
@@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
|
||||
if (!rate)
|
||||
return 0;
|
||||
|
||||
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
|
||||
if (mmc_clock->grf)
|
||||
regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
|
||||
else
|
||||
raw_value = readl(mmc_clock->reg);
|
||||
|
||||
raw_value >>= mmc_clock->shift;
|
||||
|
||||
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
|
||||
|
||||
@@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
|
||||
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
|
||||
raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
|
||||
raw_value |= nineties;
|
||||
writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
|
||||
mmc_clock->reg);
|
||||
raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift);
|
||||
|
||||
if (mmc_clock->grf)
|
||||
regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value);
|
||||
else
|
||||
writel(raw_value, mmc_clock->reg);
|
||||
|
||||
pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
|
||||
clk_hw_get_name(hw), degrees, delay_num,
|
||||
@@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
|
||||
|
||||
struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *reg, int shift)
|
||||
void __iomem *reg,
|
||||
struct regmap *grf, int grf_reg,
|
||||
int shift)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct rockchip_mmc_clock *mmc_clock;
|
||||
@@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
|
||||
mmc_clock->hw.init = &init;
|
||||
mmc_clock->reg = reg;
|
||||
mmc_clock->grf = grf;
|
||||
mmc_clock->grf_reg = grf_reg;
|
||||
mmc_clock->shift = shift;
|
||||
|
||||
clk = clk_register(NULL, &mmc_clock->hw);
|
||||
|
||||
@@ -1027,16 +1027,6 @@ static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)
|
||||
return !(pllcon & RK3588_PLLCON1_PWRDOWN);
|
||||
}
|
||||
|
||||
static int rockchip_rk3588_pll_init(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
|
||||
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
|
||||
.recalc_rate = rockchip_rk3588_pll_recalc_rate,
|
||||
.enable = rockchip_rk3588_pll_enable,
|
||||
@@ -1051,7 +1041,6 @@ static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
|
||||
.enable = rockchip_rk3588_pll_enable,
|
||||
.disable = rockchip_rk3588_pll_disable,
|
||||
.is_enabled = rockchip_rk3588_pll_is_enabled,
|
||||
.init = rockchip_rk3588_pll_init,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -123,6 +123,7 @@ PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" };
|
||||
PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" };
|
||||
PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" };
|
||||
|
||||
PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" };
|
||||
PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" };
|
||||
PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
|
||||
PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" };
|
||||
@@ -423,6 +424,9 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
|
||||
GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
|
||||
GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
|
||||
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
|
||||
|
||||
MUX(SCLK_USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_MISC_CON, 15, 1, MFLAGS),
|
||||
};
|
||||
|
||||
static const char *const rk3036_critical_clocks[] __initconst = {
|
||||
@@ -431,6 +435,7 @@ static const char *const rk3036_critical_clocks[] __initconst = {
|
||||
"hclk_peri",
|
||||
"pclk_peri",
|
||||
"pclk_ddrupctl",
|
||||
"ddrphy",
|
||||
};
|
||||
|
||||
static void __init rk3036_clk_init(struct device_node *np)
|
||||
@@ -438,7 +443,6 @@ static void __init rk3036_clk_init(struct device_node *np)
|
||||
struct rockchip_clk_provider *ctx;
|
||||
unsigned long clk_nr_clks;
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
@@ -462,11 +466,6 @@ static void __init rk3036_clk_init(struct device_node *np)
|
||||
return;
|
||||
}
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock usb480m: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
rockchip_clk_register_plls(ctx, rk3036_pll_clks,
|
||||
ARRAY_SIZE(rk3036_pll_clks),
|
||||
RK3036_GRF_SOC_STATUS0);
|
||||
|
||||
@@ -418,7 +418,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3288_CLKGATE_CON(3), 11, GFLAGS),
|
||||
MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS),
|
||||
RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS, grf_type_sys),
|
||||
GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
|
||||
RK3288_CLKGATE_CON(9), 0, GFLAGS),
|
||||
|
||||
|
||||
@@ -677,9 +677,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3328_CLKGATE_CON(3), 5, GFLAGS),
|
||||
MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT,
|
||||
RK3328_GRF_MAC_CON1, 10, 1, MFLAGS),
|
||||
RK3328_GRF_MAC_CON1, 10, 1, MFLAGS, grf_type_sys),
|
||||
MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT,
|
||||
RK3328_GRF_SOC_CON4, 14, 1, MFLAGS),
|
||||
RK3328_GRF_SOC_CON4, 14, 1, MFLAGS, grf_type_sys),
|
||||
|
||||
COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0,
|
||||
RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS,
|
||||
@@ -692,7 +692,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
RK3328_CLKSEL_CON(26), 8, 2, DFLAGS,
|
||||
RK3328_CLKGATE_CON(9), 2, GFLAGS),
|
||||
MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT,
|
||||
RK3328_GRF_MAC_CON2, 10, 1, MFLAGS),
|
||||
RK3328_GRF_MAC_CON2, 10, 1, MFLAGS, grf_type_sys),
|
||||
|
||||
FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/rockchip,rk3528-cru.h>
|
||||
|
||||
@@ -1061,23 +1064,65 @@ static struct rockchip_clk_branch rk3528_clk_branches[] __initdata = {
|
||||
0, 1, 1),
|
||||
};
|
||||
|
||||
static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = {
|
||||
MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0",
|
||||
RK3528_SDMMC_CON(0), 1, grf_type_vo),
|
||||
MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0",
|
||||
RK3528_SDMMC_CON(1), 1, grf_type_vo),
|
||||
};
|
||||
|
||||
static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = {
|
||||
MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0",
|
||||
RK3528_SDIO0_CON(0), 1, grf_type_vpu),
|
||||
MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0",
|
||||
RK3528_SDIO0_CON(1), 1, grf_type_vpu),
|
||||
MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1",
|
||||
RK3528_SDIO1_CON(0), 1, grf_type_vpu),
|
||||
MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1",
|
||||
RK3528_SDIO1_CON(1), 1, grf_type_vpu),
|
||||
};
|
||||
|
||||
static int __init clk_rk3528_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
|
||||
unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
|
||||
unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
|
||||
unsigned long nr_clks, nr_vo_clks, nr_vpu_clks;
|
||||
struct rockchip_aux_grf *vo_grf_e, *vpu_grf_e;
|
||||
struct regmap *vo_grf, *vpu_grf;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
|
||||
unsigned long nr_clks;
|
||||
struct rockchip_clk_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
|
||||
nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
|
||||
nr_branches) + 1;
|
||||
|
||||
reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(reg_base))
|
||||
return dev_err_probe(dev, PTR_ERR(reg_base),
|
||||
"could not map cru region");
|
||||
|
||||
nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
|
||||
nr_branches) + 1;
|
||||
|
||||
vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
|
||||
if (!IS_ERR(vo_grf)) {
|
||||
nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
|
||||
nr_vo_branches) + 1;
|
||||
nr_clks = max(nr_clks, nr_vo_clks);
|
||||
} else if (PTR_ERR(vo_grf) != -ENODEV) {
|
||||
return dev_err_probe(dev, PTR_ERR(vo_grf),
|
||||
"failed to look up VO GRF\n");
|
||||
}
|
||||
|
||||
vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
|
||||
if (!IS_ERR(vpu_grf)) {
|
||||
nr_vpu_clks = rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
|
||||
nr_vpu_branches) + 1;
|
||||
nr_clks = max(nr_clks, nr_vpu_clks);
|
||||
} else if (PTR_ERR(vpu_grf) != -ENODEV) {
|
||||
return dev_err_probe(dev, PTR_ERR(vpu_grf),
|
||||
"failed to look up VPU GRF\n");
|
||||
}
|
||||
|
||||
ctx = rockchip_clk_init(np, reg_base, nr_clks);
|
||||
if (IS_ERR(ctx))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx),
|
||||
@@ -1092,6 +1137,32 @@ static int __init clk_rk3528_probe(struct platform_device *pdev)
|
||||
ARRAY_SIZE(rk3528_cpuclk_rates));
|
||||
rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches);
|
||||
|
||||
if (!IS_ERR(vo_grf)) {
|
||||
vo_grf_e = devm_kzalloc(dev, sizeof(*vo_grf_e), GFP_KERNEL);
|
||||
if (!vo_grf_e)
|
||||
return -ENOMEM;
|
||||
|
||||
vo_grf_e->grf = vo_grf;
|
||||
vo_grf_e->type = grf_type_vo;
|
||||
hash_add(ctx->aux_grf_table, &vo_grf_e->node, grf_type_vo);
|
||||
|
||||
rockchip_clk_register_branches(ctx, rk3528_vo_clk_branches,
|
||||
nr_vo_branches);
|
||||
}
|
||||
|
||||
if (!IS_ERR(vpu_grf)) {
|
||||
vpu_grf_e = devm_kzalloc(dev, sizeof(*vpu_grf_e), GFP_KERNEL);
|
||||
if (!vpu_grf_e)
|
||||
return -ENOMEM;
|
||||
|
||||
vpu_grf_e->grf = vpu_grf;
|
||||
vpu_grf_e->type = grf_type_vpu;
|
||||
hash_add(ctx->aux_grf_table, &vpu_grf_e->node, grf_type_vpu);
|
||||
|
||||
rockchip_clk_register_branches(ctx, rk3528_vpu_clk_branches,
|
||||
nr_vpu_branches);
|
||||
}
|
||||
|
||||
rk3528_rst_init(np, reg_base);
|
||||
|
||||
rockchip_register_restart_notifier(ctx, RK3528_GLB_SRST_FST, NULL);
|
||||
|
||||
@@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
|
||||
RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0),
|
||||
RK3036_PLL_RATE(78750000, 4, 315, 6, 4, 1, 0),
|
||||
RK3036_PLL_RATE(74250000, 2, 99, 4, 4, 1, 0),
|
||||
RK3036_PLL_RATE(33300000, 4, 111, 5, 4, 1, 0),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
@@ -590,7 +591,7 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
|
||||
RK3568_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3568_CLKGATE_CON(4), 0, GFLAGS),
|
||||
MUXGRF(CLK_DDR1X, "clk_ddr1x", clk_ddr1x_p, CLK_SET_RATE_PARENT,
|
||||
RK3568_CLKSEL_CON(9), 15, 1, MFLAGS),
|
||||
RK3568_CLKSEL_CON(9), 15, 1, MFLAGS, grf_type_sys),
|
||||
|
||||
COMPOSITE_NOMUX(CLK_MSCH, "clk_msch", "clk_ddr1x", CLK_IGNORE_UNUSED,
|
||||
RK3568_CLKSEL_CON(10), 0, 2, DFLAGS,
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/clock/rockchip,rk3576-cru.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define RK3576_GRF_SOC_STATUS0 0x600
|
||||
#define RK3576_PMU0_GRF_OSC_CON6 0x18
|
||||
#define RK3576_VCCIO_IOC_MISC_CON0 0x6400
|
||||
|
||||
enum rk3576_plls {
|
||||
bpll, lpll, vpll, aupll, cpll, gpll, ppll,
|
||||
@@ -1481,6 +1483,14 @@ static struct rockchip_clk_branch rk3576_clk_branches[] __initdata = {
|
||||
RK3576_CLKGATE_CON(10), 0, GFLAGS),
|
||||
GATE(CLK_SAI0_MCLKOUT, "clk_sai0_mclkout", "mclk_sai0_8ch", 0,
|
||||
RK3576_CLKGATE_CON(10), 1, GFLAGS),
|
||||
GATE_GRF(CLK_SAI0_MCLKOUT_TO_IO, "mclk_sai0_to_io", "clk_sai0_mclkout",
|
||||
0, RK3576_VCCIO_IOC_MISC_CON0, 0, GFLAGS, grf_type_ioc),
|
||||
GATE_GRF(CLK_SAI1_MCLKOUT_TO_IO, "mclk_sai1_to_io", "clk_sai1_mclkout",
|
||||
0, RK3576_VCCIO_IOC_MISC_CON0, 1, GFLAGS, grf_type_ioc),
|
||||
GATE_GRF(CLK_SAI2_MCLKOUT_TO_IO, "mclk_sai2_to_io", "clk_sai2_mclkout",
|
||||
0, RK3576_VCCIO_IOC_MISC_CON0, 2, GFLAGS, grf_type_ioc),
|
||||
GATE_GRF(CLK_SAI3_MCLKOUT_TO_IO, "mclk_sai3_to_io", "clk_sai3_mclkout",
|
||||
0, RK3576_VCCIO_IOC_MISC_CON0, 3, GFLAGS, grf_type_ioc),
|
||||
|
||||
/* sdgmac */
|
||||
COMPOSITE_NODIV(HCLK_SDGMAC_ROOT, "hclk_sdgmac_root", mux_200m_100m_50m_24m_p, 0,
|
||||
@@ -1678,13 +1688,13 @@ static struct rockchip_clk_branch rk3576_clk_branches[] __initdata = {
|
||||
|
||||
/* phy ref */
|
||||
MUXGRF(CLK_PHY_REF_SRC, "clk_phy_ref_src", clk_phy_ref_src_p, 0,
|
||||
RK3576_PMU0_GRF_OSC_CON6, 4, 1, MFLAGS),
|
||||
RK3576_PMU0_GRF_OSC_CON6, 4, 1, MFLAGS, grf_type_pmu0),
|
||||
MUXGRF(CLK_USBPHY_REF_SRC, "clk_usbphy_ref_src", clk_usbphy_ref_src_p, 0,
|
||||
RK3576_PMU0_GRF_OSC_CON6, 2, 1, MFLAGS),
|
||||
RK3576_PMU0_GRF_OSC_CON6, 2, 1, MFLAGS, grf_type_pmu0),
|
||||
MUXGRF(CLK_CPLL_REF_SRC, "clk_cpll_ref_src", clk_cpll_ref_src_p, 0,
|
||||
RK3576_PMU0_GRF_OSC_CON6, 1, 1, MFLAGS),
|
||||
RK3576_PMU0_GRF_OSC_CON6, 1, 1, MFLAGS, grf_type_pmu0),
|
||||
MUXGRF(CLK_AUPLL_REF_SRC, "clk_aupll_ref_src", clk_aupll_ref_src_p, 0,
|
||||
RK3576_PMU0_GRF_OSC_CON6, 0, 1, MFLAGS),
|
||||
RK3576_PMU0_GRF_OSC_CON6, 0, 1, MFLAGS, grf_type_pmu0),
|
||||
|
||||
/* secure ns */
|
||||
COMPOSITE_NODIV(ACLK_SECURE_NS, "aclk_secure_ns", mux_350m_175m_116m_24m_p, CLK_IS_CRITICAL,
|
||||
@@ -1727,17 +1737,26 @@ static void __init rk3576_clk_init(struct device_node *np)
|
||||
struct rockchip_clk_provider *ctx;
|
||||
unsigned long clk_nr_clks;
|
||||
void __iomem *reg_base;
|
||||
struct regmap *grf;
|
||||
struct rockchip_aux_grf *ioc_grf_e;
|
||||
struct rockchip_aux_grf *pmu0_grf_e;
|
||||
struct regmap *ioc_grf;
|
||||
struct regmap *pmu0_grf;
|
||||
|
||||
clk_nr_clks = rockchip_clk_find_max_clk_id(rk3576_clk_branches,
|
||||
ARRAY_SIZE(rk3576_clk_branches)) + 1;
|
||||
|
||||
grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-pmu0-grf");
|
||||
if (IS_ERR(grf)) {
|
||||
pmu0_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-pmu0-grf");
|
||||
if (IS_ERR(pmu0_grf)) {
|
||||
pr_err("%s: could not get PMU0 GRF syscon\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ioc_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-ioc-grf");
|
||||
if (IS_ERR(ioc_grf)) {
|
||||
pr_err("%s: could not get IOC GRF syscon\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: could not map cru region\n", __func__);
|
||||
@@ -1747,11 +1766,24 @@ static void __init rk3576_clk_init(struct device_node *np)
|
||||
ctx = rockchip_clk_init(np, reg_base, clk_nr_clks);
|
||||
if (IS_ERR(ctx)) {
|
||||
pr_err("%s: rockchip clk init failed\n", __func__);
|
||||
iounmap(reg_base);
|
||||
return;
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
ctx->grf = grf;
|
||||
pmu0_grf_e = kzalloc(sizeof(*pmu0_grf_e), GFP_KERNEL);
|
||||
if (!pmu0_grf_e)
|
||||
goto err_unmap;
|
||||
|
||||
pmu0_grf_e->grf = pmu0_grf;
|
||||
pmu0_grf_e->type = grf_type_pmu0;
|
||||
hash_add(ctx->aux_grf_table, &pmu0_grf_e->node, grf_type_pmu0);
|
||||
|
||||
ioc_grf_e = kzalloc(sizeof(*ioc_grf_e), GFP_KERNEL);
|
||||
if (!ioc_grf_e)
|
||||
goto err_free_pmu0;
|
||||
|
||||
ioc_grf_e->grf = ioc_grf;
|
||||
ioc_grf_e->type = grf_type_ioc;
|
||||
hash_add(ctx->aux_grf_table, &ioc_grf_e->node, grf_type_ioc);
|
||||
|
||||
rockchip_clk_register_plls(ctx, rk3576_pll_clks,
|
||||
ARRAY_SIZE(rk3576_pll_clks),
|
||||
@@ -1774,6 +1806,14 @@ static void __init rk3576_clk_init(struct device_node *np)
|
||||
rockchip_register_restart_notifier(ctx, RK3576_GLB_SRST_FST, NULL);
|
||||
|
||||
rockchip_clk_of_add_provider(np, ctx);
|
||||
|
||||
return;
|
||||
|
||||
err_free_pmu0:
|
||||
kfree(pmu0_grf_e);
|
||||
err_unmap:
|
||||
iounmap(reg_base);
|
||||
return;
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(rk3576_cru, "rockchip,rk3576-cru", rk3576_clk_init);
|
||||
|
||||
@@ -64,6 +64,7 @@ static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
|
||||
RK3588_PLL_RATE(1560000000, 2, 260, 1, 0),
|
||||
RK3588_PLL_RATE(1536000000, 2, 256, 1, 0),
|
||||
RK3588_PLL_RATE(1512000000, 2, 252, 1, 0),
|
||||
RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
|
||||
RK3588_PLL_RATE(1488000000, 2, 248, 1, 0),
|
||||
RK3588_PLL_RATE(1464000000, 2, 244, 1, 0),
|
||||
RK3588_PLL_RATE(1440000000, 2, 240, 1, 0),
|
||||
|
||||
@@ -857,7 +857,7 @@ static struct rockchip_clk_branch rv1126_clk_branches[] __initdata = {
|
||||
RV1126_GMAC_CON, 5, 1, MFLAGS),
|
||||
MUXGRF(CLK_GMAC_SRC, "clk_gmac_src", mux_clk_gmac_src_p, CLK_SET_RATE_PARENT |
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
RV1126_GRF_IOFUNC_CON1, 12, 1, MFLAGS),
|
||||
RV1126_GRF_IOFUNC_CON1, 12, 1, MFLAGS, grf_type_sys),
|
||||
|
||||
GATE(CLK_GMAC_REF, "clk_gmac_ref", "clk_gmac_src", 0,
|
||||
RV1126_CLKGATE_CON(20), 7, GFLAGS),
|
||||
|
||||
@@ -382,6 +382,8 @@ static struct rockchip_clk_provider *rockchip_clk_init_base(
|
||||
ctx->cru_node = np;
|
||||
spin_lock_init(&ctx->lock);
|
||||
|
||||
hash_init(ctx->aux_grf_table);
|
||||
|
||||
ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
|
||||
"rockchip,grf");
|
||||
|
||||
@@ -496,6 +498,8 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
struct rockchip_clk_branch *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct regmap *grf = ctx->grf;
|
||||
struct rockchip_aux_grf *agrf;
|
||||
struct clk *clk;
|
||||
unsigned int idx;
|
||||
unsigned long flags;
|
||||
@@ -504,6 +508,19 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
flags = list->flags;
|
||||
clk = NULL;
|
||||
|
||||
/* for GRF-dependent branches, choose the right grf first */
|
||||
if ((list->branch_type == branch_grf_mux ||
|
||||
list->branch_type == branch_grf_gate ||
|
||||
list->branch_type == branch_grf_mmc) &&
|
||||
list->grf_type != grf_type_sys) {
|
||||
hash_for_each_possible(ctx->aux_grf_table, agrf, node, list->grf_type) {
|
||||
if (agrf->type == list->grf_type) {
|
||||
grf = agrf->grf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* catch simple muxes */
|
||||
switch (list->branch_type) {
|
||||
case branch_mux:
|
||||
@@ -523,10 +540,10 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
list->mux_shift, list->mux_width,
|
||||
list->mux_flags, &ctx->lock);
|
||||
break;
|
||||
case branch_muxgrf:
|
||||
case branch_grf_mux:
|
||||
clk = rockchip_clk_register_muxgrf(list->name,
|
||||
list->parent_names, list->num_parents,
|
||||
flags, ctx->grf, list->muxdiv_offset,
|
||||
flags, grf, list->muxdiv_offset,
|
||||
list->mux_shift, list->mux_width,
|
||||
list->mux_flags);
|
||||
break;
|
||||
@@ -573,6 +590,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
ctx->reg_base + list->gate_offset,
|
||||
list->gate_shift, list->gate_flags, &ctx->lock);
|
||||
break;
|
||||
case branch_grf_gate:
|
||||
flags |= CLK_SET_RATE_PARENT;
|
||||
clk = rockchip_clk_register_gate_grf(list->name,
|
||||
list->parent_names[0], flags, grf,
|
||||
list->gate_offset, list->gate_shift,
|
||||
list->gate_flags);
|
||||
break;
|
||||
case branch_composite:
|
||||
clk = rockchip_clk_register_branch(list->name,
|
||||
list->parent_names, list->num_parents,
|
||||
@@ -590,6 +614,16 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
list->name,
|
||||
list->parent_names, list->num_parents,
|
||||
ctx->reg_base + list->muxdiv_offset,
|
||||
NULL, 0,
|
||||
list->div_shift
|
||||
);
|
||||
break;
|
||||
case branch_grf_mmc:
|
||||
clk = rockchip_clk_register_mmc(
|
||||
list->name,
|
||||
list->parent_names, list->num_parents,
|
||||
NULL,
|
||||
grf, list->muxdiv_offset,
|
||||
list->div_shift
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/hashtable.h>
|
||||
|
||||
struct clk;
|
||||
|
||||
@@ -217,6 +218,9 @@ struct clk;
|
||||
#define RK3528_CLKSEL_CON(x) ((x) * 0x4 + 0x300)
|
||||
#define RK3528_CLKGATE_CON(x) ((x) * 0x4 + 0x800)
|
||||
#define RK3528_SOFTRST_CON(x) ((x) * 0x4 + 0xa00)
|
||||
#define RK3528_SDMMC_CON(x) ((x) * 0x4 + 0x24)
|
||||
#define RK3528_SDIO0_CON(x) ((x) * 0x4 + 0x4)
|
||||
#define RK3528_SDIO1_CON(x) ((x) * 0x4 + 0xc)
|
||||
#define RK3528_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PMU_CRU_BASE)
|
||||
#define RK3528_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RK3528_PMU_CRU_BASE)
|
||||
#define RK3528_PCIE_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE)
|
||||
@@ -440,12 +444,37 @@ enum rockchip_pll_type {
|
||||
.k = _k, \
|
||||
}
|
||||
|
||||
enum rockchip_grf_type {
|
||||
grf_type_sys = 0,
|
||||
grf_type_pmu0,
|
||||
grf_type_pmu1,
|
||||
grf_type_ioc,
|
||||
grf_type_vo,
|
||||
grf_type_vpu,
|
||||
};
|
||||
|
||||
/* ceil(sqrt(enums in rockchip_grf_type - 1)) */
|
||||
#define GRF_HASH_ORDER 2
|
||||
|
||||
/**
|
||||
* struct rockchip_aux_grf - entry for the aux_grf_table hashtable
|
||||
* @grf: pointer to the grf this entry references
|
||||
* @type: what type of GRF this is
|
||||
* @node: hlist node
|
||||
*/
|
||||
struct rockchip_aux_grf {
|
||||
struct regmap *grf;
|
||||
enum rockchip_grf_type type;
|
||||
struct hlist_node node;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rockchip_clk_provider - information about clock provider
|
||||
* @reg_base: virtual address for the register base.
|
||||
* @clk_data: holds clock related data like clk* and number of clocks.
|
||||
* @cru_node: device-node of the clock-provider
|
||||
* @grf: regmap of the general-register-files syscon
|
||||
* @aux_grf_table: hashtable of auxiliary GRF regmaps, indexed by grf_type
|
||||
* @lock: maintains exclusion between callbacks for a given clock-provider.
|
||||
*/
|
||||
struct rockchip_clk_provider {
|
||||
@@ -453,6 +482,7 @@ struct rockchip_clk_provider {
|
||||
struct clk_onecell_data clk_data;
|
||||
struct device_node *cru_node;
|
||||
struct regmap *grf;
|
||||
DECLARE_HASHTABLE(aux_grf_table, GRF_HASH_ORDER);
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
@@ -594,7 +624,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
|
||||
|
||||
struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *reg, int shift);
|
||||
void __iomem *reg,
|
||||
struct regmap *grf, int grf_reg,
|
||||
int shift);
|
||||
|
||||
/*
|
||||
* DDRCLK flags, including method of setting the rate
|
||||
@@ -622,17 +654,24 @@ struct clk *rockchip_clk_register_muxgrf(const char *name,
|
||||
int flags, struct regmap *grf, int reg,
|
||||
int shift, int width, int mux_flags);
|
||||
|
||||
struct clk *rockchip_clk_register_gate_grf(const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
struct regmap *regmap, unsigned int reg,
|
||||
unsigned int shift, u8 gate_flags);
|
||||
|
||||
#define PNAME(x) static const char *const x[] __initconst
|
||||
|
||||
enum rockchip_clk_branch_type {
|
||||
branch_composite,
|
||||
branch_mux,
|
||||
branch_muxgrf,
|
||||
branch_grf_mux,
|
||||
branch_divider,
|
||||
branch_fraction_divider,
|
||||
branch_gate,
|
||||
branch_grf_gate,
|
||||
branch_linked_gate,
|
||||
branch_mmc,
|
||||
branch_grf_mmc,
|
||||
branch_inverter,
|
||||
branch_factor,
|
||||
branch_ddrclk,
|
||||
@@ -660,6 +699,7 @@ struct rockchip_clk_branch {
|
||||
u8 gate_shift;
|
||||
u8 gate_flags;
|
||||
unsigned int linked_clk_id;
|
||||
enum rockchip_grf_type grf_type;
|
||||
struct rockchip_clk_branch *child;
|
||||
};
|
||||
|
||||
@@ -900,10 +940,10 @@ struct rockchip_clk_branch {
|
||||
.mux_table = mt, \
|
||||
}
|
||||
|
||||
#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \
|
||||
#define MUXGRF(_id, cname, pnames, f, o, s, w, mf, gt) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.branch_type = branch_muxgrf, \
|
||||
.branch_type = branch_grf_mux, \
|
||||
.name = cname, \
|
||||
.parent_names = pnames, \
|
||||
.num_parents = ARRAY_SIZE(pnames), \
|
||||
@@ -913,6 +953,7 @@ struct rockchip_clk_branch {
|
||||
.mux_width = w, \
|
||||
.mux_flags = mf, \
|
||||
.gate_offset = -1, \
|
||||
.grf_type = gt, \
|
||||
}
|
||||
|
||||
#define DIV(_id, cname, pname, f, o, s, w, df) \
|
||||
@@ -958,6 +999,20 @@ struct rockchip_clk_branch {
|
||||
.gate_flags = gf, \
|
||||
}
|
||||
|
||||
#define GATE_GRF(_id, cname, pname, f, o, b, gf, gt) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.branch_type = branch_grf_gate, \
|
||||
.name = cname, \
|
||||
.parent_names = (const char *[]){ pname }, \
|
||||
.num_parents = 1, \
|
||||
.flags = f, \
|
||||
.gate_offset = o, \
|
||||
.gate_shift = b, \
|
||||
.gate_flags = gf, \
|
||||
.grf_type = gt, \
|
||||
}
|
||||
|
||||
#define GATE_LINK(_id, cname, pname, linkedclk, f, o, b, gf) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
@@ -983,6 +1038,18 @@ struct rockchip_clk_branch {
|
||||
.div_shift = shift, \
|
||||
}
|
||||
|
||||
#define MMC_GRF(_id, cname, pname, offset, shift, grftype) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.branch_type = branch_grf_mmc, \
|
||||
.name = cname, \
|
||||
.parent_names = (const char *[]){ pname }, \
|
||||
.num_parents = 1, \
|
||||
.muxdiv_offset = offset, \
|
||||
.div_shift = shift, \
|
||||
.grf_type = grftype, \
|
||||
}
|
||||
|
||||
#define INVERTER(_id, cname, pname, io, is, if) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
|
||||
@@ -1269,6 +1269,45 @@ static const struct samsung_cpu_clock exynos4412_cpu_clks[] __initconst = {
|
||||
CPUCLK_LAYOUT_E4210, e4412_armclk_d),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cmu_info_exynos4 __initconst = {
|
||||
.mux_clks = exynos4_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(exynos4_mux_clks),
|
||||
.div_clks = exynos4_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(exynos4_div_clks),
|
||||
.gate_clks = exynos4_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(exynos4_gate_clks),
|
||||
.fixed_factor_clks = exynos4_fixed_factor_clks,
|
||||
.nr_fixed_factor_clks = ARRAY_SIZE(exynos4_fixed_factor_clks),
|
||||
.fixed_clks = exynos4_fixed_rate_clks,
|
||||
.nr_fixed_clks = ARRAY_SIZE(exynos4_fixed_rate_clks),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cmu_info_exynos4210 __initconst = {
|
||||
.mux_clks = exynos4210_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(exynos4210_mux_clks),
|
||||
.div_clks = exynos4210_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(exynos4210_div_clks),
|
||||
.gate_clks = exynos4210_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(exynos4210_gate_clks),
|
||||
.fixed_factor_clks = exynos4210_fixed_factor_clks,
|
||||
.nr_fixed_factor_clks = ARRAY_SIZE(exynos4210_fixed_factor_clks),
|
||||
.fixed_clks = exynos4210_fixed_rate_clks,
|
||||
.nr_fixed_clks = ARRAY_SIZE(exynos4210_fixed_rate_clks),
|
||||
.cpu_clks = exynos4210_cpu_clks,
|
||||
.nr_cpu_clks = ARRAY_SIZE(exynos4210_cpu_clks),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cmu_info_exynos4x12 __initconst = {
|
||||
.mux_clks = exynos4x12_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(exynos4x12_mux_clks),
|
||||
.div_clks = exynos4x12_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(exynos4x12_div_clks),
|
||||
.gate_clks = exynos4x12_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(exynos4x12_gate_clks),
|
||||
.fixed_factor_clks = exynos4x12_fixed_factor_clks,
|
||||
.nr_fixed_factor_clks = ARRAY_SIZE(exynos4x12_fixed_factor_clks),
|
||||
};
|
||||
|
||||
/* register exynos4 clocks */
|
||||
static void __init exynos4_clk_init(struct device_node *np,
|
||||
enum exynos4_soc soc)
|
||||
@@ -1322,41 +1361,12 @@ static void __init exynos4_clk_init(struct device_node *np,
|
||||
ARRAY_SIZE(exynos4x12_plls));
|
||||
}
|
||||
|
||||
samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
|
||||
ARRAY_SIZE(exynos4_fixed_rate_clks));
|
||||
samsung_clk_register_mux(ctx, exynos4_mux_clks,
|
||||
ARRAY_SIZE(exynos4_mux_clks));
|
||||
samsung_clk_register_div(ctx, exynos4_div_clks,
|
||||
ARRAY_SIZE(exynos4_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4_gate_clks,
|
||||
ARRAY_SIZE(exynos4_gate_clks));
|
||||
samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4_fixed_factor_clks));
|
||||
samsung_cmu_register_clocks(ctx, &cmu_info_exynos4);
|
||||
|
||||
if (exynos4_soc == EXYNOS4210) {
|
||||
samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
|
||||
ARRAY_SIZE(exynos4210_fixed_rate_clks));
|
||||
samsung_clk_register_mux(ctx, exynos4210_mux_clks,
|
||||
ARRAY_SIZE(exynos4210_mux_clks));
|
||||
samsung_clk_register_div(ctx, exynos4210_div_clks,
|
||||
ARRAY_SIZE(exynos4210_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4210_gate_clks,
|
||||
ARRAY_SIZE(exynos4210_gate_clks));
|
||||
samsung_clk_register_fixed_factor(ctx,
|
||||
exynos4210_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4210_fixed_factor_clks));
|
||||
samsung_clk_register_cpu(ctx, exynos4210_cpu_clks,
|
||||
ARRAY_SIZE(exynos4210_cpu_clks));
|
||||
samsung_cmu_register_clocks(ctx, &cmu_info_exynos4210);
|
||||
} else {
|
||||
samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
|
||||
ARRAY_SIZE(exynos4x12_mux_clks));
|
||||
samsung_clk_register_div(ctx, exynos4x12_div_clks,
|
||||
ARRAY_SIZE(exynos4x12_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
|
||||
ARRAY_SIZE(exynos4x12_gate_clks));
|
||||
samsung_clk_register_fixed_factor(ctx,
|
||||
exynos4x12_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4x12_fixed_factor_clks));
|
||||
samsung_cmu_register_clocks(ctx, &cmu_info_exynos4x12);
|
||||
if (soc == EXYNOS4412)
|
||||
samsung_clk_register_cpu(ctx, exynos4412_cpu_clks,
|
||||
ARRAY_SIZE(exynos4412_cpu_clks));
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
/* NOTE: Must be equal to the last clock ID increased by one */
|
||||
#define CLKS_NR_TOP (DOUT_CLKCMU_TAA_NOC + 1)
|
||||
#define CLKS_NR_CPUCL0 (CLK_DOUT_CPUCL0_NOCP + 1)
|
||||
#define CLKS_NR_CPUCL1 (CLK_DOUT_CPUCL1_NOCP + 1)
|
||||
#define CLKS_NR_CPUCL2 (CLK_DOUT_CPUCL2_NOCP + 1)
|
||||
#define CLKS_NR_PERIC0 (CLK_DOUT_PERIC0_I3C + 1)
|
||||
#define CLKS_NR_PERIC1 (CLK_DOUT_PERIC1_I3C + 1)
|
||||
#define CLKS_NR_MISC (CLK_DOUT_MISC_OSC_DIV2 + 1)
|
||||
@@ -1005,6 +1008,339 @@ static void __init exynosautov920_cmu_top_init(struct device_node *np)
|
||||
CLK_OF_DECLARE(exynosautov920_cmu_top, "samsung,exynosautov920-cmu-top",
|
||||
exynosautov920_cmu_top_init);
|
||||
|
||||
/* ---- CMU_CPUCL0 --------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_CPUCL0 (0x1EC00000) */
|
||||
#define PLL_LOCKTIME_PLL_CPUCL0 0x0000
|
||||
#define PLL_CON0_PLL_CPUCL0 0x0100
|
||||
#define PLL_CON1_PLL_CPUCL0 0x0104
|
||||
#define PLL_CON3_PLL_CPUCL0 0x010c
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL0_CLUSTER_USER 0x0600
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER 0x0610
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER 0x0620
|
||||
|
||||
#define CLK_CON_MUX_MUX_CLK_CPUCL0_CLUSTER 0x1000
|
||||
#define CLK_CON_MUX_MUX_CLK_CPUCL0_CORE 0x1004
|
||||
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK 0x1800
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK 0x1804
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_MPCLK 0x1808
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLK 0x180c
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK 0x1810
|
||||
#define CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_NOC 0x181c
|
||||
#define CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_PCLKDBG 0x1820
|
||||
#define CLK_CON_DIV_DIV_CLK_CPUCL0_NOCP 0x1824
|
||||
|
||||
static const unsigned long cpucl0_clk_regs[] __initconst = {
|
||||
PLL_LOCKTIME_PLL_CPUCL0,
|
||||
PLL_CON0_PLL_CPUCL0,
|
||||
PLL_CON1_PLL_CPUCL0,
|
||||
PLL_CON3_PLL_CPUCL0,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL0_CLUSTER_USER,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL0_CLUSTER,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL0_CORE,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER0_MPCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_NOC,
|
||||
CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_PCLKDBG,
|
||||
CLK_CON_DIV_DIV_CLK_CPUCL0_NOCP,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_CPUCL0 */
|
||||
PNAME(mout_pll_cpucl0_p) = { "oscclk", "fout_cpucl0_pll" };
|
||||
PNAME(mout_cpucl0_cluster_user_p) = { "oscclk", "dout_clkcmu_cpucl0_cluster" };
|
||||
PNAME(mout_cpucl0_dbg_user_p) = { "oscclk", "dout_clkcmu_cpucl0_dbg" };
|
||||
PNAME(mout_cpucl0_switch_user_p) = { "oscclk", "dout_clkcmu_cpucl0_switch" };
|
||||
PNAME(mout_cpucl0_cluster_p) = { "oscclk", "mout_cpucl0_cluster_user",
|
||||
"mout_cpucl0_switch_user"};
|
||||
PNAME(mout_cpucl0_core_p) = { "oscclk", "mout_pll_cpucl0",
|
||||
"mout_cpucl0_switch_user"};
|
||||
|
||||
static const struct samsung_pll_rate_table cpu_pll_rates[] __initconst = {
|
||||
PLL_35XX_RATE(38400000U, 2400000000U, 250, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 2304000000U, 240, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 2208000000U, 230, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 2112000000U, 220, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 2016000000U, 210, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 1824000000U, 190, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 1680000000U, 175, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 1344000000U, 140, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 1152000000U, 120, 4, 0),
|
||||
PLL_35XX_RATE(38400000U, 576000000U, 120, 4, 1),
|
||||
PLL_35XX_RATE(38400000U, 288000000U, 120, 4, 2),
|
||||
};
|
||||
|
||||
static const struct samsung_pll_clock cpucl0_pll_clks[] __initconst = {
|
||||
/* CMU_CPUCL0_PURECLKCOMP */
|
||||
PLL(pll_531x, CLK_FOUT_CPUCL0_PLL, "fout_cpucl0_pll", "oscclk",
|
||||
PLL_LOCKTIME_PLL_CPUCL0, PLL_CON3_PLL_CPUCL0, cpu_pll_rates),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock cpucl0_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_PLL_CPUCL0, "mout_pll_cpucl0", mout_pll_cpucl0_p,
|
||||
PLL_CON0_PLL_CPUCL0, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL0_CLUSTER_USER, "mout_cpucl0_cluster_user", mout_cpucl0_cluster_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL0_CLUSTER_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL0_DBG_USER, "mout_cpucl0_dbg_user", mout_cpucl0_dbg_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL0_SWITCH_USER, "mout_cpucl0_switch_user", mout_cpucl0_switch_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL0_CLUSTER, "mout_cpucl0_cluster", mout_cpucl0_cluster_p,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL0_CLUSTER, 0, 2),
|
||||
MUX(CLK_MOUT_CPUCL0_CORE, "mout_cpucl0_core", mout_cpucl0_core_p,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL0_CORE, 0, 2),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock cpucl0_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_CLUSTER0_ACLK, "dout_cluster0_aclk",
|
||||
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER0_ATCLK, "dout_cluster0_atclk",
|
||||
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER0_MPCLK, "dout_cluster0_mpclk",
|
||||
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_MPCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER0_PCLK, "dout_cluster0_pclk",
|
||||
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER0_PERIPHCLK, "dout_cluster0_periphclk",
|
||||
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CPUCL0_DBG_NOC, "dout_cpucl0_dbg_noc",
|
||||
"mout_cpucl0_dbg_user", CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_NOC, 0, 3),
|
||||
DIV(CLK_DOUT_CPUCL0_DBG_PCLKDBG, "dout_cpucl0_dbg_pclkdbg",
|
||||
"mout_cpucl0_dbg_user", CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_PCLKDBG, 0, 3),
|
||||
DIV(CLK_DOUT_CPUCL0_NOCP, "dout_cpucl0_nocp",
|
||||
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CPUCL0_NOCP, 0, 4),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cpucl0_cmu_info __initconst = {
|
||||
.pll_clks = cpucl0_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(cpucl0_pll_clks),
|
||||
.mux_clks = cpucl0_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(cpucl0_mux_clks),
|
||||
.div_clks = cpucl0_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(cpucl0_div_clks),
|
||||
.nr_clk_ids = CLKS_NR_CPUCL0,
|
||||
.clk_regs = cpucl0_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(cpucl0_clk_regs),
|
||||
.clk_name = "cpucl0",
|
||||
};
|
||||
|
||||
static void __init exynosautov920_cmu_cpucl0_init(struct device_node *np)
|
||||
{
|
||||
exynos_arm64_register_cmu(NULL, np, &cpucl0_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_CPUCL0 early, as CPU clocks should be available ASAP */
|
||||
CLK_OF_DECLARE(exynosautov920_cmu_cpucl0, "samsung,exynosautov920-cmu-cpucl0",
|
||||
exynosautov920_cmu_cpucl0_init);
|
||||
|
||||
/* ---- CMU_CPUCL1 --------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_CPUCL1 (0x1ED00000) */
|
||||
#define PLL_LOCKTIME_PLL_CPUCL1 0x0000
|
||||
#define PLL_CON0_PLL_CPUCL1 0x0100
|
||||
#define PLL_CON1_PLL_CPUCL1 0x0104
|
||||
#define PLL_CON3_PLL_CPUCL1 0x010c
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL1_CLUSTER_USER 0x0600
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER 0x0610
|
||||
|
||||
#define CLK_CON_MUX_MUX_CLK_CPUCL1_CLUSTER 0x1000
|
||||
#define CLK_CON_MUX_MUX_CLK_CPUCL1_CORE 0x1004
|
||||
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK 0x1800
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK 0x1804
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_MPCLK 0x1808
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLK 0x180c
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK 0x1810
|
||||
#define CLK_CON_DIV_DIV_CLK_CPUCL1_NOCP 0x181c
|
||||
|
||||
static const unsigned long cpucl1_clk_regs[] __initconst = {
|
||||
PLL_LOCKTIME_PLL_CPUCL1,
|
||||
PLL_CON0_PLL_CPUCL1,
|
||||
PLL_CON1_PLL_CPUCL1,
|
||||
PLL_CON3_PLL_CPUCL1,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL1_CLUSTER_USER,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL1_CLUSTER,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL1_CORE,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER1_MPCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CPUCL1_NOCP,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_CPUCL1 */
|
||||
PNAME(mout_pll_cpucl1_p) = { "oscclk", "fout_cpucl1_pll" };
|
||||
PNAME(mout_cpucl1_cluster_user_p) = { "oscclk", "dout_clkcmu_cpucl1_cluster" };
|
||||
PNAME(mout_cpucl1_switch_user_p) = { "oscclk", "dout_clkcmu_cpucl1_switch" };
|
||||
PNAME(mout_cpucl1_cluster_p) = { "oscclk", "mout_cpucl1_cluster_user",
|
||||
"mout_cpucl1_switch_user"};
|
||||
PNAME(mout_cpucl1_core_p) = { "oscclk", "mout_pll_cpucl1",
|
||||
"mout_cpucl1_switch_user"};
|
||||
|
||||
static const struct samsung_pll_clock cpucl1_pll_clks[] __initconst = {
|
||||
/* CMU_CPUCL1_PURECLKCOMP */
|
||||
PLL(pll_531x, CLK_FOUT_CPUCL1_PLL, "fout_cpucl1_pll", "oscclk",
|
||||
PLL_LOCKTIME_PLL_CPUCL1, PLL_CON3_PLL_CPUCL1, cpu_pll_rates),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock cpucl1_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_PLL_CPUCL1, "mout_pll_cpucl1", mout_pll_cpucl1_p,
|
||||
PLL_CON0_PLL_CPUCL1, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL1_CLUSTER_USER, "mout_cpucl1_cluster_user", mout_cpucl1_cluster_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL1_CLUSTER_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL1_SWITCH_USER, "mout_cpucl1_switch_user", mout_cpucl1_switch_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL1_CLUSTER, "mout_cpucl1_cluster", mout_cpucl1_cluster_p,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL1_CLUSTER, 0, 2),
|
||||
MUX(CLK_MOUT_CPUCL1_CORE, "mout_cpucl1_core", mout_cpucl1_core_p,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL1_CORE, 0, 2),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock cpucl1_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_CLUSTER1_ACLK, "dout_cluster1_aclk",
|
||||
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER1_ATCLK, "dout_cluster1_atclk",
|
||||
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER1_MPCLK, "dout_cluster1_mpclk",
|
||||
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_MPCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER1_PCLK, "dout_cluster1_pclk",
|
||||
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER1_PERIPHCLK, "dout_cluster1_periphclk",
|
||||
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CPUCL1_NOCP, "dout_cpucl1_nocp",
|
||||
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CPUCL1_NOCP, 0, 4),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cpucl1_cmu_info __initconst = {
|
||||
.pll_clks = cpucl1_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(cpucl1_pll_clks),
|
||||
.mux_clks = cpucl1_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(cpucl1_mux_clks),
|
||||
.div_clks = cpucl1_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(cpucl1_div_clks),
|
||||
.nr_clk_ids = CLKS_NR_CPUCL1,
|
||||
.clk_regs = cpucl1_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(cpucl1_clk_regs),
|
||||
.clk_name = "cpucl1",
|
||||
};
|
||||
|
||||
static void __init exynosautov920_cmu_cpucl1_init(struct device_node *np)
|
||||
{
|
||||
exynos_arm64_register_cmu(NULL, np, &cpucl1_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_CPUCL1 early, as CPU clocks should be available ASAP */
|
||||
CLK_OF_DECLARE(exynosautov920_cmu_cpucl1, "samsung,exynosautov920-cmu-cpucl1",
|
||||
exynosautov920_cmu_cpucl1_init);
|
||||
|
||||
/* ---- CMU_CPUCL2 --------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_CPUCL2 (0x1EE00000) */
|
||||
#define PLL_LOCKTIME_PLL_CPUCL2 0x0000
|
||||
#define PLL_CON0_PLL_CPUCL2 0x0100
|
||||
#define PLL_CON1_PLL_CPUCL2 0x0104
|
||||
#define PLL_CON3_PLL_CPUCL2 0x010c
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL2_CLUSTER_USER 0x0600
|
||||
#define PLL_CON0_MUX_CLKCMU_CPUCL2_SWITCH_USER 0x0610
|
||||
|
||||
#define CLK_CON_MUX_MUX_CLK_CPUCL2_CLUSTER 0x1000
|
||||
#define CLK_CON_MUX_MUX_CLK_CPUCL2_CORE 0x1004
|
||||
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_ACLK 0x1800
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_ATCLK 0x1804
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_MPCLK 0x1808
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_PCLK 0x180c
|
||||
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_PERIPHCLK 0x1810
|
||||
#define CLK_CON_DIV_DIV_CLK_CPUCL2_NOCP 0x181c
|
||||
|
||||
static const unsigned long cpucl2_clk_regs[] __initconst = {
|
||||
PLL_LOCKTIME_PLL_CPUCL2,
|
||||
PLL_CON0_PLL_CPUCL2,
|
||||
PLL_CON1_PLL_CPUCL2,
|
||||
PLL_CON3_PLL_CPUCL2,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL2_CLUSTER_USER,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL2_SWITCH_USER,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL2_CLUSTER,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL2_CORE,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER2_ACLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER2_ATCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER2_MPCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER2_PCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CLUSTER2_PERIPHCLK,
|
||||
CLK_CON_DIV_DIV_CLK_CPUCL2_NOCP,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_CPUCL2 */
|
||||
PNAME(mout_pll_cpucl2_p) = { "oscclk", "fout_cpucl2_pll" };
|
||||
PNAME(mout_cpucl2_cluster_user_p) = { "oscclk", "dout_clkcmu_cpucl2_cluster" };
|
||||
PNAME(mout_cpucl2_switch_user_p) = { "oscclk", "dout_clkcmu_cpucl2_switch" };
|
||||
PNAME(mout_cpucl2_cluster_p) = { "oscclk", "mout_cpucl2_cluster_user",
|
||||
"mout_cpucl2_switch_user"};
|
||||
PNAME(mout_cpucl2_core_p) = { "oscclk", "mout_pll_cpucl2",
|
||||
"mout_cpucl2_switch_user"};
|
||||
|
||||
static const struct samsung_pll_clock cpucl2_pll_clks[] __initconst = {
|
||||
/* CMU_CPUCL2_PURECLKCOMP */
|
||||
PLL(pll_531x, CLK_FOUT_CPUCL2_PLL, "fout_cpucl2_pll", "oscclk",
|
||||
PLL_LOCKTIME_PLL_CPUCL2, PLL_CON3_PLL_CPUCL2, cpu_pll_rates),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock cpucl2_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_PLL_CPUCL2, "mout_pll_cpucl2", mout_pll_cpucl2_p,
|
||||
PLL_CON0_PLL_CPUCL2, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL2_CLUSTER_USER, "mout_cpucl2_cluster_user", mout_cpucl2_cluster_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL2_CLUSTER_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL2_SWITCH_USER, "mout_cpucl2_switch_user", mout_cpucl2_switch_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CPUCL2_SWITCH_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CPUCL2_CLUSTER, "mout_cpucl2_cluster", mout_cpucl2_cluster_p,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL2_CLUSTER, 0, 2),
|
||||
MUX(CLK_MOUT_CPUCL2_CORE, "mout_cpucl2_core", mout_cpucl2_core_p,
|
||||
CLK_CON_MUX_MUX_CLK_CPUCL2_CORE, 0, 2),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock cpucl2_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_CLUSTER2_ACLK, "dout_cluster2_aclk",
|
||||
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_ACLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER2_ATCLK, "dout_cluster2_atclk",
|
||||
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_ATCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER2_MPCLK, "dout_cluster2_mpclk",
|
||||
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_MPCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER2_PCLK, "dout_cluster2_pclk",
|
||||
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_PCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CLUSTER2_PERIPHCLK, "dout_cluster2_periphclk",
|
||||
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_PERIPHCLK, 0, 4),
|
||||
DIV(CLK_DOUT_CPUCL2_NOCP, "dout_cpucl2_nocp",
|
||||
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CPUCL2_NOCP, 0, 4),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cpucl2_cmu_info __initconst = {
|
||||
.pll_clks = cpucl2_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(cpucl2_pll_clks),
|
||||
.mux_clks = cpucl2_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(cpucl2_mux_clks),
|
||||
.div_clks = cpucl2_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(cpucl2_div_clks),
|
||||
.nr_clk_ids = CLKS_NR_CPUCL2,
|
||||
.clk_regs = cpucl2_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(cpucl2_clk_regs),
|
||||
.clk_name = "cpucl2",
|
||||
};
|
||||
|
||||
static void __init exynosautov920_cmu_cpucl2_init(struct device_node *np)
|
||||
{
|
||||
exynos_arm64_register_cmu(NULL, np, &cpucl2_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_CPUCL2 early, as CPU clocks should be available ASAP */
|
||||
CLK_OF_DECLARE(exynosautov920_cmu_cpucl2, "samsung,exynosautov920-cmu-cpucl2",
|
||||
exynosautov920_cmu_cpucl2_init);
|
||||
|
||||
/* ---- CMU_PERIC0 --------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_PERIC0 (0x10800000) */
|
||||
@@ -1393,7 +1729,7 @@ static const unsigned long hsi1_clk_regs[] __initconst = {
|
||||
/* List of parent clocks for Muxes in CMU_HSI1 */
|
||||
PNAME(mout_hsi1_mmc_card_user_p) = {"oscclk", "dout_clkcmu_hsi1_mmc_card"};
|
||||
PNAME(mout_hsi1_noc_user_p) = { "oscclk", "dout_clkcmu_hsi1_noc" };
|
||||
PNAME(mout_hsi1_usbdrd_user_p) = { "oscclk", "mout_clkcmu_hsi1_usbdrd" };
|
||||
PNAME(mout_hsi1_usbdrd_user_p) = { "oscclk", "dout_clkcmu_hsi1_usbdrd" };
|
||||
PNAME(mout_hsi1_usbdrd_p) = { "dout_tcxo_div2", "mout_hsi1_usbdrd_user" };
|
||||
|
||||
static const struct samsung_mux_clock hsi1_mux_clks[] __initconst = {
|
||||
|
||||
@@ -83,9 +83,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
|
||||
unsigned long mdiv;
|
||||
unsigned long refdiv;
|
||||
unsigned long reg;
|
||||
u32 mdiv;
|
||||
u32 refdiv;
|
||||
u32 reg;
|
||||
unsigned long long vco_freq;
|
||||
|
||||
/* read VCO1 reg for numerator and denominator */
|
||||
|
||||
@@ -39,9 +39,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
|
||||
unsigned long divf, divq, reg;
|
||||
u32 divf, divq, reg;
|
||||
unsigned long long vco_freq;
|
||||
unsigned long bypass;
|
||||
u32 bypass;
|
||||
|
||||
reg = readl(socfpgaclk->hw.reg);
|
||||
bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS);
|
||||
|
||||
@@ -37,3 +37,22 @@ config CLK_SOPHGO_SG2042_RPGATE
|
||||
This clock IP depends on SG2042 Clock Generator because it uses
|
||||
clock from Clock Generator IP as input.
|
||||
This driver provides Gate function for RP.
|
||||
|
||||
config CLK_SOPHGO_SG2044
|
||||
tristate "Sophgo SG2044 clock controller support"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
help
|
||||
This driver supports the clock controller on the Sophgo SG2044
|
||||
SoC. This controller requires mulitple PLL clock as input.
|
||||
This clock control provides PLL clocks and common clock function
|
||||
for various IPs on the SoC.
|
||||
|
||||
config CLK_SOPHGO_SG2044_PLL
|
||||
tristate "Sophgo SG2044 PLL clock controller support"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This driver supports the PLL clock controller on the Sophgo
|
||||
SG2044 SoC. This controller requires 25M oscillator as input.
|
||||
This clock control provides PLL clocks on the SoC.
|
||||
|
||||
@@ -9,3 +9,5 @@ clk-sophgo-cv1800-y += clk-cv18xx-pll.o
|
||||
obj-$(CONFIG_CLK_SOPHGO_SG2042_CLKGEN) += clk-sg2042-clkgen.o
|
||||
obj-$(CONFIG_CLK_SOPHGO_SG2042_PLL) += clk-sg2042-pll.o
|
||||
obj-$(CONFIG_CLK_SOPHGO_SG2042_RPGATE) += clk-sg2042-rpgate.o
|
||||
obj-$(CONFIG_CLK_SOPHGO_SG2044) += clk-sg2044.o
|
||||
obj-$(CONFIG_CLK_SOPHGO_SG2044_PLL) += clk-sg2044-pll.o
|
||||
|
||||
@@ -1519,7 +1519,9 @@ static int cv1800_clk_probe(struct platform_device *pdev)
|
||||
|
||||
static const struct of_device_id cv1800_clk_ids[] = {
|
||||
{ .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc },
|
||||
{ .compatible = "sophgo,cv1800b-clk", .data = &cv1800_desc },
|
||||
{ .compatible = "sophgo,cv1810-clk", .data = &cv1810_desc },
|
||||
{ .compatible = "sophgo,cv1812h-clk", .data = &cv1810_desc },
|
||||
{ .compatible = "sophgo,sg2000-clk", .data = &sg2000_desc },
|
||||
{ }
|
||||
};
|
||||
|
||||
628
drivers/clk/sophgo/clk-sg2044-pll.c
Normal file
628
drivers/clk/sophgo/clk-sg2044-pll.c
Normal file
@@ -0,0 +1,628 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Sophgo SG2044 PLL clock controller driver
|
||||
*
|
||||
* Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <dt-bindings/clock/sophgo,sg2044-pll.h>
|
||||
|
||||
/* Low Control part */
|
||||
#define PLL_VCOSEL_MASK GENMASK(17, 16)
|
||||
|
||||
/* High Control part */
|
||||
#define PLL_FBDIV_MASK GENMASK(11, 0)
|
||||
#define PLL_REFDIV_MASK GENMASK(17, 12)
|
||||
#define PLL_POSTDIV1_MASK GENMASK(20, 18)
|
||||
#define PLL_POSTDIV2_MASK GENMASK(23, 21)
|
||||
|
||||
#define PLL_CALIBRATE_EN BIT(24)
|
||||
#define PLL_CALIBRATE_MASK GENMASK(29, 27)
|
||||
#define PLL_CALIBRATE_DEFAULT FIELD_PREP(PLL_CALIBRATE_MASK, 2)
|
||||
#define PLL_UPDATE_EN BIT(30)
|
||||
|
||||
#define PLL_HIGH_CTRL_MASK \
|
||||
(PLL_FBDIV_MASK | PLL_REFDIV_MASK | \
|
||||
PLL_POSTDIV1_MASK | PLL_POSTDIV2_MASK | \
|
||||
PLL_CALIBRATE_EN | PLL_CALIBRATE_MASK | \
|
||||
PLL_UPDATE_EN)
|
||||
|
||||
#define PLL_HIGH_CTRL_OFFSET 4
|
||||
|
||||
#define PLL_VCOSEL_1G6 0x2
|
||||
#define PLL_VCOSEL_2G4 0x3
|
||||
|
||||
#define PLL_LIMIT_FOUTVCO 0
|
||||
#define PLL_LIMIT_FOUT 1
|
||||
#define PLL_LIMIT_REFDIV 2
|
||||
#define PLL_LIMIT_FBDIV 3
|
||||
#define PLL_LIMIT_POSTDIV1 4
|
||||
#define PLL_LIMIT_POSTDIV2 5
|
||||
|
||||
#define for_each_pll_limit_range(_var, _limit) \
|
||||
for (_var = (_limit)->min; _var <= (_limit)->max; _var++)
|
||||
|
||||
struct sg2044_pll_limit {
|
||||
u64 min;
|
||||
u64 max;
|
||||
};
|
||||
|
||||
struct sg2044_pll_internal {
|
||||
u32 ctrl_offset;
|
||||
u32 status_offset;
|
||||
u32 enable_offset;
|
||||
|
||||
u8 status_lock_bit;
|
||||
u8 status_updating_bit;
|
||||
u8 enable_bit;
|
||||
|
||||
const struct sg2044_pll_limit *limits;
|
||||
};
|
||||
|
||||
struct sg2044_clk_common {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
spinlock_t *lock;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
struct sg2044_pll {
|
||||
struct sg2044_clk_common common;
|
||||
struct sg2044_pll_internal pll;
|
||||
unsigned int syscon_offset;
|
||||
};
|
||||
|
||||
struct sg2044_pll_desc_data {
|
||||
struct sg2044_clk_common * const *pll;
|
||||
u16 num_pll;
|
||||
};
|
||||
|
||||
#define SG2044_SYSCON_PLL_OFFSET 0x98
|
||||
|
||||
struct sg2044_pll_ctrl {
|
||||
spinlock_t lock;
|
||||
struct clk_hw_onecell_data data;
|
||||
};
|
||||
|
||||
#define hw_to_sg2044_clk_common(_hw) \
|
||||
container_of((_hw), struct sg2044_clk_common, hw)
|
||||
|
||||
static inline bool sg2044_clk_fit_limit(u64 value,
|
||||
const struct sg2044_pll_limit *limit)
|
||||
{
|
||||
return value >= limit->min && value <= limit->max;
|
||||
}
|
||||
|
||||
static inline struct sg2044_pll *hw_to_sg2044_pll(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw_to_sg2044_clk_common(hw),
|
||||
struct sg2044_pll, common);
|
||||
}
|
||||
|
||||
static unsigned long sg2044_pll_calc_vco_rate(unsigned long parent_rate,
|
||||
unsigned long refdiv,
|
||||
unsigned long fbdiv)
|
||||
{
|
||||
u64 numerator = parent_rate * fbdiv;
|
||||
|
||||
return div64_ul(numerator, refdiv);
|
||||
}
|
||||
|
||||
static unsigned long sg2044_pll_calc_rate(unsigned long parent_rate,
|
||||
unsigned long refdiv,
|
||||
unsigned long fbdiv,
|
||||
unsigned long postdiv1,
|
||||
unsigned long postdiv2)
|
||||
{
|
||||
u64 numerator, denominator;
|
||||
|
||||
numerator = parent_rate * fbdiv;
|
||||
denominator = refdiv * (postdiv1 + 1) * (postdiv2 + 1);
|
||||
|
||||
return div64_u64(numerator, denominator);
|
||||
}
|
||||
|
||||
static unsigned long sg2044_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.ctrl_offset + PLL_HIGH_CTRL_OFFSET,
|
||||
&value);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
return sg2044_pll_calc_rate(parent_rate,
|
||||
FIELD_GET(PLL_REFDIV_MASK, value),
|
||||
FIELD_GET(PLL_FBDIV_MASK, value),
|
||||
FIELD_GET(PLL_POSTDIV1_MASK, value),
|
||||
FIELD_GET(PLL_POSTDIV2_MASK, value));
|
||||
}
|
||||
|
||||
static bool pll_is_better_rate(unsigned long target, unsigned long now,
|
||||
unsigned long best)
|
||||
{
|
||||
return abs_diff(target, now) < abs_diff(target, best);
|
||||
}
|
||||
|
||||
static int sg2042_pll_compute_postdiv(const struct sg2044_pll_limit *limits,
|
||||
unsigned long target,
|
||||
unsigned long parent_rate,
|
||||
unsigned int refdiv,
|
||||
unsigned int fbdiv,
|
||||
unsigned int *postdiv1,
|
||||
unsigned int *postdiv2)
|
||||
{
|
||||
unsigned int div1, div2;
|
||||
unsigned long tmp, best_rate = 0;
|
||||
unsigned int best_div1 = 0, best_div2 = 0;
|
||||
|
||||
for_each_pll_limit_range(div2, &limits[PLL_LIMIT_POSTDIV2]) {
|
||||
for_each_pll_limit_range(div1, &limits[PLL_LIMIT_POSTDIV1]) {
|
||||
tmp = sg2044_pll_calc_rate(parent_rate,
|
||||
refdiv, fbdiv,
|
||||
div1, div2);
|
||||
|
||||
if (tmp > target)
|
||||
continue;
|
||||
|
||||
if (pll_is_better_rate(target, tmp, best_rate)) {
|
||||
best_div1 = div1;
|
||||
best_div2 = div2;
|
||||
best_rate = tmp;
|
||||
|
||||
if (tmp == target)
|
||||
goto find;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
find:
|
||||
if (best_rate) {
|
||||
*postdiv1 = best_div1;
|
||||
*postdiv2 = best_div2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int sg2044_compute_pll_setting(const struct sg2044_pll_limit *limits,
|
||||
unsigned long req_rate,
|
||||
unsigned long parent_rate,
|
||||
unsigned int *value)
|
||||
{
|
||||
unsigned int refdiv, fbdiv, postdiv1, postdiv2;
|
||||
unsigned int best_refdiv, best_fbdiv, best_postdiv1, best_postdiv2;
|
||||
unsigned long tmp, best_rate = 0;
|
||||
int ret;
|
||||
|
||||
for_each_pll_limit_range(fbdiv, &limits[PLL_LIMIT_FBDIV]) {
|
||||
for_each_pll_limit_range(refdiv, &limits[PLL_LIMIT_REFDIV]) {
|
||||
u64 vco = sg2044_pll_calc_vco_rate(parent_rate,
|
||||
refdiv, fbdiv);
|
||||
if (!sg2044_clk_fit_limit(vco, &limits[PLL_LIMIT_FOUTVCO]))
|
||||
continue;
|
||||
|
||||
ret = sg2042_pll_compute_postdiv(limits,
|
||||
req_rate, parent_rate,
|
||||
refdiv, fbdiv,
|
||||
&postdiv1, &postdiv2);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
tmp = sg2044_pll_calc_rate(parent_rate,
|
||||
refdiv, fbdiv,
|
||||
postdiv1, postdiv2);
|
||||
|
||||
if (pll_is_better_rate(req_rate, tmp, best_rate)) {
|
||||
best_refdiv = refdiv;
|
||||
best_fbdiv = fbdiv;
|
||||
best_postdiv1 = postdiv1;
|
||||
best_postdiv2 = postdiv2;
|
||||
best_rate = tmp;
|
||||
|
||||
if (tmp == req_rate)
|
||||
goto find;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
find:
|
||||
if (best_rate) {
|
||||
*value = FIELD_PREP(PLL_REFDIV_MASK, best_refdiv) |
|
||||
FIELD_PREP(PLL_FBDIV_MASK, best_fbdiv) |
|
||||
FIELD_PREP(PLL_POSTDIV1_MASK, best_postdiv1) |
|
||||
FIELD_PREP(PLL_POSTDIV2_MASK, best_postdiv2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int sg2044_pll_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
|
||||
unsigned int value;
|
||||
u64 target;
|
||||
int ret;
|
||||
|
||||
target = clamp(req->rate, pll->pll.limits[PLL_LIMIT_FOUT].min,
|
||||
pll->pll.limits[PLL_LIMIT_FOUT].max);
|
||||
|
||||
ret = sg2044_compute_pll_setting(pll->pll.limits, target,
|
||||
req->best_parent_rate, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
req->rate = sg2044_pll_calc_rate(req->best_parent_rate,
|
||||
FIELD_GET(PLL_REFDIV_MASK, value),
|
||||
FIELD_GET(PLL_FBDIV_MASK, value),
|
||||
FIELD_GET(PLL_POSTDIV1_MASK, value),
|
||||
FIELD_GET(PLL_POSTDIV2_MASK, value));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sg2044_pll_poll_update(struct sg2044_pll *pll)
|
||||
{
|
||||
int ret;
|
||||
unsigned int value;
|
||||
|
||||
ret = regmap_read_poll_timeout_atomic(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.status_offset,
|
||||
value,
|
||||
(value & BIT(pll->pll.status_lock_bit)),
|
||||
1, 100000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_read_poll_timeout_atomic(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.status_offset,
|
||||
value,
|
||||
(!(value & BIT(pll->pll.status_updating_bit))),
|
||||
1, 100000);
|
||||
}
|
||||
|
||||
static int sg2044_pll_enable(struct sg2044_pll *pll, bool en)
|
||||
{
|
||||
if (en) {
|
||||
if (sg2044_pll_poll_update(pll) < 0)
|
||||
pr_warn("%s: fail to lock pll\n", clk_hw_get_name(&pll->common.hw));
|
||||
|
||||
return regmap_set_bits(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.enable_offset,
|
||||
BIT(pll->pll.enable_bit));
|
||||
}
|
||||
|
||||
return regmap_clear_bits(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.enable_offset,
|
||||
BIT(pll->pll.enable_bit));
|
||||
}
|
||||
|
||||
static int sg2044_pll_update_vcosel(struct sg2044_pll *pll, u64 rate)
|
||||
{
|
||||
unsigned int sel;
|
||||
|
||||
if (rate < U64_C(2400000000))
|
||||
sel = PLL_VCOSEL_1G6;
|
||||
else
|
||||
sel = PLL_VCOSEL_2G4;
|
||||
|
||||
return regmap_write_bits(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.ctrl_offset,
|
||||
PLL_VCOSEL_MASK,
|
||||
FIELD_PREP(PLL_VCOSEL_MASK, sel));
|
||||
}
|
||||
|
||||
static int sg2044_pll_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
|
||||
unsigned int value;
|
||||
u64 vco;
|
||||
int ret;
|
||||
|
||||
ret = sg2044_compute_pll_setting(pll->pll.limits, rate,
|
||||
parent_rate, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
vco = sg2044_pll_calc_vco_rate(parent_rate,
|
||||
FIELD_GET(PLL_REFDIV_MASK, value),
|
||||
FIELD_GET(PLL_FBDIV_MASK, value));
|
||||
|
||||
value |= PLL_CALIBRATE_EN;
|
||||
value |= PLL_CALIBRATE_DEFAULT;
|
||||
value |= PLL_UPDATE_EN;
|
||||
|
||||
guard(spinlock_irqsave)(pll->common.lock);
|
||||
|
||||
ret = sg2044_pll_enable(pll, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sg2044_pll_update_vcosel(pll, vco);
|
||||
|
||||
regmap_write_bits(pll->common.regmap,
|
||||
pll->syscon_offset + pll->pll.ctrl_offset +
|
||||
PLL_HIGH_CTRL_OFFSET,
|
||||
PLL_HIGH_CTRL_MASK, value);
|
||||
|
||||
sg2044_pll_enable(pll, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct clk_ops sg2044_pll_ops = {
|
||||
.recalc_rate = sg2044_pll_recalc_rate,
|
||||
.determine_rate = sg2044_pll_determine_rate,
|
||||
.set_rate = sg2044_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops sg2044_pll_ro_ops = {
|
||||
.recalc_rate = sg2044_pll_recalc_rate,
|
||||
};
|
||||
|
||||
#define SG2044_CLK_COMMON_PDATA(_id, _name, _parents, _op, _flags) \
|
||||
{ \
|
||||
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents, \
|
||||
_op, (_flags)), \
|
||||
.id = (_id), \
|
||||
}
|
||||
|
||||
#define DEFINE_SG2044_PLL(_id, _name, _parent, _flags, \
|
||||
_ctrl_offset, \
|
||||
_status_offset, _status_lock_bit, \
|
||||
_status_updating_bit, \
|
||||
_enable_offset, _enable_bit, \
|
||||
_limits) \
|
||||
struct sg2044_pll _name = { \
|
||||
.common = SG2044_CLK_COMMON_PDATA(_id, #_name, _parent, \
|
||||
&sg2044_pll_ops, \
|
||||
(_flags)), \
|
||||
.pll = { \
|
||||
.ctrl_offset = (_ctrl_offset), \
|
||||
.status_offset = (_status_offset), \
|
||||
.enable_offset = (_enable_offset), \
|
||||
.status_lock_bit = (_status_lock_bit), \
|
||||
.status_updating_bit = (_status_updating_bit), \
|
||||
.enable_bit = (_enable_bit), \
|
||||
.limits = (_limits), \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define DEFINE_SG2044_PLL_RO(_id, _name, _parent, _flags, \
|
||||
_ctrl_offset, \
|
||||
_status_offset, _status_lock_bit, \
|
||||
_status_updating_bit, \
|
||||
_enable_offset, _enable_bit, \
|
||||
_limits) \
|
||||
struct sg2044_pll _name = { \
|
||||
.common = SG2044_CLK_COMMON_PDATA(_id, #_name, _parent, \
|
||||
&sg2044_pll_ro_ops, \
|
||||
(_flags)), \
|
||||
.pll = { \
|
||||
.ctrl_offset = (_ctrl_offset), \
|
||||
.status_offset = (_status_offset), \
|
||||
.enable_offset = (_enable_offset), \
|
||||
.status_lock_bit = (_status_lock_bit), \
|
||||
.status_updating_bit = (_status_updating_bit), \
|
||||
.enable_bit = (_enable_bit), \
|
||||
.limits = (_limits), \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const struct clk_parent_data osc_parents[] = {
|
||||
{ .index = 0 },
|
||||
};
|
||||
|
||||
static const struct sg2044_pll_limit pll_limits[] = {
|
||||
[PLL_LIMIT_FOUTVCO] = {
|
||||
.min = U64_C(1600000000),
|
||||
.max = U64_C(3200000000),
|
||||
},
|
||||
[PLL_LIMIT_FOUT] = {
|
||||
.min = U64_C(25000),
|
||||
.max = U64_C(3200000000),
|
||||
},
|
||||
[PLL_LIMIT_REFDIV] = {
|
||||
.min = U64_C(1),
|
||||
.max = U64_C(63),
|
||||
},
|
||||
[PLL_LIMIT_FBDIV] = {
|
||||
.min = U64_C(8),
|
||||
.max = U64_C(1066),
|
||||
},
|
||||
[PLL_LIMIT_POSTDIV1] = {
|
||||
.min = U64_C(0),
|
||||
.max = U64_C(7),
|
||||
},
|
||||
[PLL_LIMIT_POSTDIV2] = {
|
||||
.min = U64_C(0),
|
||||
.max = U64_C(7),
|
||||
},
|
||||
};
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_FPLL0, clk_fpll0, osc_parents, CLK_IS_CRITICAL,
|
||||
0x58, 0x00, 22, 6,
|
||||
0x04, 6, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_FPLL1, clk_fpll1, osc_parents, CLK_IS_CRITICAL,
|
||||
0x60, 0x00, 23, 7,
|
||||
0x04, 7, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_FPLL2, clk_fpll2, osc_parents, CLK_IS_CRITICAL,
|
||||
0x20, 0x08, 16, 0,
|
||||
0x0c, 0, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL0, clk_dpll0, osc_parents, CLK_IS_CRITICAL,
|
||||
0x68, 0x00, 24, 8,
|
||||
0x04, 8, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL1, clk_dpll1, osc_parents, CLK_IS_CRITICAL,
|
||||
0x70, 0x00, 25, 9,
|
||||
0x04, 9, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL2, clk_dpll2, osc_parents, CLK_IS_CRITICAL,
|
||||
0x78, 0x00, 26, 10,
|
||||
0x04, 10, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL3, clk_dpll3, osc_parents, CLK_IS_CRITICAL,
|
||||
0x80, 0x00, 27, 11,
|
||||
0x04, 11, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL4, clk_dpll4, osc_parents, CLK_IS_CRITICAL,
|
||||
0x88, 0x00, 28, 12,
|
||||
0x04, 12, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL5, clk_dpll5, osc_parents, CLK_IS_CRITICAL,
|
||||
0x90, 0x00, 29, 13,
|
||||
0x04, 13, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL6, clk_dpll6, osc_parents, CLK_IS_CRITICAL,
|
||||
0x98, 0x00, 30, 14,
|
||||
0x04, 14, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL_RO(CLK_DPLL7, clk_dpll7, osc_parents, CLK_IS_CRITICAL,
|
||||
0xa0, 0x00, 31, 15,
|
||||
0x04, 15, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL(CLK_MPLL0, clk_mpll0, osc_parents, CLK_IS_CRITICAL,
|
||||
0x28, 0x00, 16, 0,
|
||||
0x04, 0, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL(CLK_MPLL1, clk_mpll1, osc_parents, CLK_IS_CRITICAL,
|
||||
0x30, 0x00, 17, 1,
|
||||
0x04, 1, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL(CLK_MPLL2, clk_mpll2, osc_parents, CLK_IS_CRITICAL,
|
||||
0x38, 0x00, 18, 2,
|
||||
0x04, 2, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL(CLK_MPLL3, clk_mpll3, osc_parents, CLK_IS_CRITICAL,
|
||||
0x40, 0x00, 19, 3,
|
||||
0x04, 3, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL(CLK_MPLL4, clk_mpll4, osc_parents, CLK_IS_CRITICAL,
|
||||
0x48, 0x00, 20, 4,
|
||||
0x04, 4, pll_limits);
|
||||
|
||||
static DEFINE_SG2044_PLL(CLK_MPLL5, clk_mpll5, osc_parents, CLK_IS_CRITICAL,
|
||||
0x50, 0x00, 21, 5,
|
||||
0x04, 5, pll_limits);
|
||||
|
||||
static struct sg2044_clk_common * const sg2044_pll_commons[] = {
|
||||
&clk_fpll0.common,
|
||||
&clk_fpll1.common,
|
||||
&clk_fpll2.common,
|
||||
&clk_dpll0.common,
|
||||
&clk_dpll1.common,
|
||||
&clk_dpll2.common,
|
||||
&clk_dpll3.common,
|
||||
&clk_dpll4.common,
|
||||
&clk_dpll5.common,
|
||||
&clk_dpll6.common,
|
||||
&clk_dpll7.common,
|
||||
&clk_mpll0.common,
|
||||
&clk_mpll1.common,
|
||||
&clk_mpll2.common,
|
||||
&clk_mpll3.common,
|
||||
&clk_mpll4.common,
|
||||
&clk_mpll5.common,
|
||||
};
|
||||
|
||||
static int sg2044_pll_init_ctrl(struct device *dev, struct regmap *regmap,
|
||||
struct sg2044_pll_ctrl *ctrl,
|
||||
const struct sg2044_pll_desc_data *desc)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
spin_lock_init(&ctrl->lock);
|
||||
|
||||
for (i = 0; i < desc->num_pll; i++) {
|
||||
struct sg2044_clk_common *common = desc->pll[i];
|
||||
struct sg2044_pll *pll = hw_to_sg2044_pll(&common->hw);
|
||||
|
||||
common->lock = &ctrl->lock;
|
||||
common->regmap = regmap;
|
||||
pll->syscon_offset = SG2044_SYSCON_PLL_OFFSET;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &common->hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctrl->data.hws[common->id] = &common->hw;
|
||||
}
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
&ctrl->data);
|
||||
}
|
||||
|
||||
static int sg2044_pll_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct sg2044_pll_ctrl *ctrl;
|
||||
const struct sg2044_pll_desc_data *desc;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = device_node_to_regmap(pdev->dev.parent->of_node);
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap),
|
||||
"fail to get the regmap for PLL\n");
|
||||
|
||||
desc = (const struct sg2044_pll_desc_data *)platform_get_device_id(pdev)->driver_data;
|
||||
if (!desc)
|
||||
return dev_err_probe(dev, -EINVAL, "no match data for platform\n");
|
||||
|
||||
ctrl = devm_kzalloc(dev, struct_size(ctrl, data.hws, desc->num_pll), GFP_KERNEL);
|
||||
if (!ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
ctrl->data.num = desc->num_pll;
|
||||
|
||||
return sg2044_pll_init_ctrl(dev, regmap, ctrl, desc);
|
||||
}
|
||||
|
||||
static const struct sg2044_pll_desc_data sg2044_pll_desc_data = {
|
||||
.pll = sg2044_pll_commons,
|
||||
.num_pll = ARRAY_SIZE(sg2044_pll_commons),
|
||||
};
|
||||
|
||||
static const struct platform_device_id sg2044_pll_match[] = {
|
||||
{ .name = "sg2044-pll",
|
||||
.driver_data = (unsigned long)&sg2044_pll_desc_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, sg2044_pll_match);
|
||||
|
||||
static struct platform_driver sg2044_clk_driver = {
|
||||
.probe = sg2044_pll_probe,
|
||||
.driver = {
|
||||
.name = "sg2044-pll",
|
||||
},
|
||||
.id_table = sg2044_pll_match,
|
||||
};
|
||||
module_platform_driver(sg2044_clk_driver);
|
||||
|
||||
MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>");
|
||||
MODULE_DESCRIPTION("Sophgo SG2044 pll clock driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
1812
drivers/clk/sophgo/clk-sg2044.c
Normal file
1812
drivers/clk/sophgo/clk-sg2044.c
Normal file
File diff suppressed because it is too large
Load Diff
18
drivers/clk/spacemit/Kconfig
Normal file
18
drivers/clk/spacemit/Kconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config SPACEMIT_CCU
|
||||
tristate "Clock support for SpacemiT SoCs"
|
||||
depends on ARCH_SPACEMIT || COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Say Y to enable clock controller unit support for SpacemiT SoCs.
|
||||
|
||||
if SPACEMIT_CCU
|
||||
|
||||
config SPACEMIT_K1_CCU
|
||||
tristate "Support for SpacemiT K1 SoC"
|
||||
depends on ARCH_SPACEMIT || COMPILE_TEST
|
||||
help
|
||||
Support for clock controller unit in SpacemiT K1 SoC.
|
||||
|
||||
endif
|
||||
5
drivers/clk/spacemit/Makefile
Normal file
5
drivers/clk/spacemit/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_SPACEMIT_K1_CCU) = spacemit-ccu-k1.o
|
||||
spacemit-ccu-k1-y = ccu_pll.o ccu_mix.o ccu_ddn.o
|
||||
spacemit-ccu-k1-y += ccu-k1.o
|
||||
1164
drivers/clk/spacemit/ccu-k1.c
Normal file
1164
drivers/clk/spacemit/ccu-k1.c
Normal file
File diff suppressed because it is too large
Load Diff
48
drivers/clk/spacemit/ccu_common.h
Normal file
48
drivers/clk/spacemit/ccu_common.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*/
|
||||
|
||||
#ifndef _CCU_COMMON_H_
|
||||
#define _CCU_COMMON_H_
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct ccu_common {
|
||||
struct regmap *regmap;
|
||||
struct regmap *lock_regmap;
|
||||
|
||||
union {
|
||||
/* For DDN and MIX */
|
||||
struct {
|
||||
u32 reg_ctrl;
|
||||
u32 reg_fc;
|
||||
u32 mask_fc;
|
||||
};
|
||||
|
||||
/* For PLL */
|
||||
struct {
|
||||
u32 reg_swcr1;
|
||||
u32 reg_swcr3;
|
||||
};
|
||||
};
|
||||
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct ccu_common, hw);
|
||||
}
|
||||
|
||||
#define ccu_read(c, reg) \
|
||||
({ \
|
||||
u32 tmp; \
|
||||
regmap_read((c)->regmap, (c)->reg_##reg, &tmp); \
|
||||
tmp; \
|
||||
})
|
||||
#define ccu_update(c, reg, mask, val) \
|
||||
regmap_update_bits((c)->regmap, (c)->reg_##reg, mask, val)
|
||||
|
||||
#endif /* _CCU_COMMON_H_ */
|
||||
83
drivers/clk/spacemit/ccu_ddn.c
Normal file
83
drivers/clk/spacemit/ccu_ddn.c
Normal file
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*
|
||||
* DDN stands for "Divider Denominator Numerator", it's M/N clock with a
|
||||
* constant x2 factor. This clock hardware follows the equation below,
|
||||
*
|
||||
* numerator Fin
|
||||
* 2 * ------------- = -------
|
||||
* denominator Fout
|
||||
*
|
||||
* Thus, Fout could be calculated with,
|
||||
*
|
||||
* Fin denominator
|
||||
* Fout = ----- * -------------
|
||||
* 2 numerator
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/rational.h>
|
||||
|
||||
#include "ccu_ddn.h"
|
||||
|
||||
static unsigned long ccu_ddn_calc_rate(unsigned long prate,
|
||||
unsigned long num, unsigned long den)
|
||||
{
|
||||
return prate * den / 2 / num;
|
||||
}
|
||||
|
||||
static unsigned long ccu_ddn_calc_best_rate(struct ccu_ddn *ddn,
|
||||
unsigned long rate, unsigned long prate,
|
||||
unsigned long *num, unsigned long *den)
|
||||
{
|
||||
rational_best_approximation(rate, prate / 2,
|
||||
ddn->den_mask >> ddn->den_shift,
|
||||
ddn->num_mask >> ddn->num_shift,
|
||||
den, num);
|
||||
return ccu_ddn_calc_rate(prate, *num, *den);
|
||||
}
|
||||
|
||||
static long ccu_ddn_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
|
||||
unsigned long num, den;
|
||||
|
||||
return ccu_ddn_calc_best_rate(ddn, rate, *prate, &num, &den);
|
||||
}
|
||||
|
||||
static unsigned long ccu_ddn_recalc_rate(struct clk_hw *hw, unsigned long prate)
|
||||
{
|
||||
struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
|
||||
unsigned int val, num, den;
|
||||
|
||||
val = ccu_read(&ddn->common, ctrl);
|
||||
|
||||
num = (val & ddn->num_mask) >> ddn->num_shift;
|
||||
den = (val & ddn->den_mask) >> ddn->den_shift;
|
||||
|
||||
return ccu_ddn_calc_rate(prate, num, den);
|
||||
}
|
||||
|
||||
static int ccu_ddn_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
|
||||
unsigned long num, den;
|
||||
|
||||
ccu_ddn_calc_best_rate(ddn, rate, prate, &num, &den);
|
||||
|
||||
ccu_update(&ddn->common, ctrl,
|
||||
ddn->num_mask | ddn->den_mask,
|
||||
(num << ddn->num_shift) | (den << ddn->den_shift));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops spacemit_ccu_ddn_ops = {
|
||||
.recalc_rate = ccu_ddn_recalc_rate,
|
||||
.round_rate = ccu_ddn_round_rate,
|
||||
.set_rate = ccu_ddn_set_rate,
|
||||
};
|
||||
48
drivers/clk/spacemit/ccu_ddn.h
Normal file
48
drivers/clk/spacemit/ccu_ddn.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*/
|
||||
|
||||
#ifndef _CCU_DDN_H_
|
||||
#define _CCU_DDN_H_
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
|
||||
struct ccu_ddn {
|
||||
struct ccu_common common;
|
||||
unsigned int num_mask;
|
||||
unsigned int num_shift;
|
||||
unsigned int den_mask;
|
||||
unsigned int den_shift;
|
||||
};
|
||||
|
||||
#define CCU_DDN_INIT(_name, _parent, _flags) \
|
||||
CLK_HW_INIT_HW(#_name, &_parent.common.hw, &spacemit_ccu_ddn_ops, _flags)
|
||||
|
||||
#define CCU_DDN_DEFINE(_name, _parent, _reg_ctrl, _num_shift, _num_width, \
|
||||
_den_shift, _den_width, _flags) \
|
||||
static struct ccu_ddn _name = { \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
.hw.init = CCU_DDN_INIT(_name, _parent, _flags), \
|
||||
}, \
|
||||
.num_mask = GENMASK(_num_shift + _num_width - 1, _num_shift), \
|
||||
.num_shift = _num_shift, \
|
||||
.den_mask = GENMASK(_den_shift + _den_width - 1, _den_shift), \
|
||||
.den_shift = _den_shift, \
|
||||
}
|
||||
|
||||
static inline struct ccu_ddn *hw_to_ccu_ddn(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_common *common = hw_to_ccu_common(hw);
|
||||
|
||||
return container_of(common, struct ccu_ddn, common);
|
||||
}
|
||||
|
||||
extern const struct clk_ops spacemit_ccu_ddn_ops;
|
||||
|
||||
#endif
|
||||
268
drivers/clk/spacemit/ccu_mix.c
Normal file
268
drivers/clk/spacemit/ccu_mix.c
Normal file
@@ -0,0 +1,268 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*
|
||||
* MIX clock type is the combination of mux, factor or divider, and gate
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "ccu_mix.h"
|
||||
|
||||
#define MIX_FC_TIMEOUT_US 10000
|
||||
#define MIX_FC_DELAY_US 5
|
||||
|
||||
static void ccu_gate_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
|
||||
ccu_update(&mix->common, ctrl, mix->gate.mask, 0);
|
||||
}
|
||||
|
||||
static int ccu_gate_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
struct ccu_gate_config *gate = &mix->gate;
|
||||
|
||||
ccu_update(&mix->common, ctrl, gate->mask, gate->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccu_gate_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
struct ccu_gate_config *gate = &mix->gate;
|
||||
|
||||
return (ccu_read(&mix->common, ctrl) & gate->mask) == gate->mask;
|
||||
}
|
||||
|
||||
static unsigned long ccu_factor_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
|
||||
return parent_rate * mix->factor.mul / mix->factor.div;
|
||||
}
|
||||
|
||||
static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
struct ccu_div_config *div = &mix->div;
|
||||
unsigned long val;
|
||||
|
||||
val = ccu_read(&mix->common, ctrl) >> div->shift;
|
||||
val &= (1 << div->width) - 1;
|
||||
|
||||
return divider_recalc_rate(hw, parent_rate, val, NULL, 0, div->width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some clocks require a "FC" (frequency change) bit to be set after changing
|
||||
* their rates or reparenting. This bit will be automatically cleared by
|
||||
* hardware in MIX_FC_TIMEOUT_US, which indicates the operation is completed.
|
||||
*/
|
||||
static int ccu_mix_trigger_fc(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_common *common = hw_to_ccu_common(hw);
|
||||
unsigned int val;
|
||||
|
||||
if (common->reg_fc)
|
||||
return 0;
|
||||
|
||||
ccu_update(common, fc, common->mask_fc, common->mask_fc);
|
||||
|
||||
return regmap_read_poll_timeout_atomic(common->regmap, common->reg_fc,
|
||||
val, !(val & common->mask_fc),
|
||||
MIX_FC_DELAY_US,
|
||||
MIX_FC_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static long ccu_factor_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
return ccu_factor_recalc_rate(hw, *prate);
|
||||
}
|
||||
|
||||
static int ccu_factor_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
ccu_mix_calc_best_rate(struct clk_hw *hw, unsigned long rate,
|
||||
struct clk_hw **best_parent,
|
||||
unsigned long *best_parent_rate,
|
||||
u32 *div_val)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
unsigned int parent_num = clk_hw_get_num_parents(hw);
|
||||
struct ccu_div_config *div = &mix->div;
|
||||
u32 div_max = 1 << div->width;
|
||||
unsigned long best_rate = 0;
|
||||
|
||||
for (int i = 0; i < parent_num; i++) {
|
||||
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
|
||||
unsigned long parent_rate;
|
||||
|
||||
if (!parent)
|
||||
continue;
|
||||
|
||||
parent_rate = clk_hw_get_rate(parent);
|
||||
|
||||
for (int j = 1; j <= div_max; j++) {
|
||||
unsigned long tmp = DIV_ROUND_CLOSEST_ULL(parent_rate, j);
|
||||
|
||||
if (abs(tmp - rate) < abs(best_rate - rate)) {
|
||||
best_rate = tmp;
|
||||
|
||||
if (div_val)
|
||||
*div_val = j - 1;
|
||||
|
||||
if (best_parent) {
|
||||
*best_parent = parent;
|
||||
*best_parent_rate = parent_rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_rate;
|
||||
}
|
||||
|
||||
static int ccu_mix_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
req->rate = ccu_mix_calc_best_rate(hw, req->rate,
|
||||
&req->best_parent_hw,
|
||||
&req->best_parent_rate,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccu_mix_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
struct ccu_common *common = &mix->common;
|
||||
struct ccu_div_config *div = &mix->div;
|
||||
u32 current_div, target_div, mask;
|
||||
|
||||
ccu_mix_calc_best_rate(hw, rate, NULL, NULL, &target_div);
|
||||
|
||||
current_div = ccu_read(common, ctrl) >> div->shift;
|
||||
current_div &= (1 << div->width) - 1;
|
||||
|
||||
if (current_div == target_div)
|
||||
return 0;
|
||||
|
||||
mask = GENMASK(div->width + div->shift - 1, div->shift);
|
||||
|
||||
ccu_update(common, ctrl, mask, target_div << div->shift);
|
||||
|
||||
return ccu_mix_trigger_fc(hw);
|
||||
}
|
||||
|
||||
static u8 ccu_mux_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
struct ccu_mux_config *mux = &mix->mux;
|
||||
u8 parent;
|
||||
|
||||
parent = ccu_read(&mix->common, ctrl) >> mux->shift;
|
||||
parent &= (1 << mux->width) - 1;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct ccu_mix *mix = hw_to_ccu_mix(hw);
|
||||
struct ccu_mux_config *mux = &mix->mux;
|
||||
u32 mask;
|
||||
|
||||
mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
|
||||
|
||||
ccu_update(&mix->common, ctrl, mask, index << mux->shift);
|
||||
|
||||
return ccu_mix_trigger_fc(hw);
|
||||
}
|
||||
|
||||
const struct clk_ops spacemit_ccu_gate_ops = {
|
||||
.disable = ccu_gate_disable,
|
||||
.enable = ccu_gate_enable,
|
||||
.is_enabled = ccu_gate_is_enabled,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_factor_ops = {
|
||||
.round_rate = ccu_factor_round_rate,
|
||||
.recalc_rate = ccu_factor_recalc_rate,
|
||||
.set_rate = ccu_factor_set_rate,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_mux_ops = {
|
||||
.determine_rate = ccu_mix_determine_rate,
|
||||
.get_parent = ccu_mux_get_parent,
|
||||
.set_parent = ccu_mux_set_parent,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_div_ops = {
|
||||
.determine_rate = ccu_mix_determine_rate,
|
||||
.recalc_rate = ccu_div_recalc_rate,
|
||||
.set_rate = ccu_mix_set_rate,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_factor_gate_ops = {
|
||||
.disable = ccu_gate_disable,
|
||||
.enable = ccu_gate_enable,
|
||||
.is_enabled = ccu_gate_is_enabled,
|
||||
|
||||
.round_rate = ccu_factor_round_rate,
|
||||
.recalc_rate = ccu_factor_recalc_rate,
|
||||
.set_rate = ccu_factor_set_rate,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_mux_gate_ops = {
|
||||
.disable = ccu_gate_disable,
|
||||
.enable = ccu_gate_enable,
|
||||
.is_enabled = ccu_gate_is_enabled,
|
||||
|
||||
.determine_rate = ccu_mix_determine_rate,
|
||||
.get_parent = ccu_mux_get_parent,
|
||||
.set_parent = ccu_mux_set_parent,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_div_gate_ops = {
|
||||
.disable = ccu_gate_disable,
|
||||
.enable = ccu_gate_enable,
|
||||
.is_enabled = ccu_gate_is_enabled,
|
||||
|
||||
.determine_rate = ccu_mix_determine_rate,
|
||||
.recalc_rate = ccu_div_recalc_rate,
|
||||
.set_rate = ccu_mix_set_rate,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_mux_div_gate_ops = {
|
||||
.disable = ccu_gate_disable,
|
||||
.enable = ccu_gate_enable,
|
||||
.is_enabled = ccu_gate_is_enabled,
|
||||
|
||||
.get_parent = ccu_mux_get_parent,
|
||||
.set_parent = ccu_mux_set_parent,
|
||||
|
||||
.determine_rate = ccu_mix_determine_rate,
|
||||
.recalc_rate = ccu_div_recalc_rate,
|
||||
.set_rate = ccu_mix_set_rate,
|
||||
};
|
||||
|
||||
const struct clk_ops spacemit_ccu_mux_div_ops = {
|
||||
.get_parent = ccu_mux_get_parent,
|
||||
.set_parent = ccu_mux_set_parent,
|
||||
|
||||
.determine_rate = ccu_mix_determine_rate,
|
||||
.recalc_rate = ccu_div_recalc_rate,
|
||||
.set_rate = ccu_mix_set_rate,
|
||||
};
|
||||
218
drivers/clk/spacemit/ccu_mix.h
Normal file
218
drivers/clk/spacemit/ccu_mix.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*/
|
||||
|
||||
#ifndef _CCU_MIX_H_
|
||||
#define _CCU_MIX_H_
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
|
||||
/**
|
||||
* struct ccu_gate_config - Gate configuration
|
||||
*
|
||||
* @mask: Mask to enable the gate. Some clocks may have more than one bit
|
||||
* set in this field.
|
||||
*/
|
||||
struct ccu_gate_config {
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
struct ccu_factor_config {
|
||||
u32 div;
|
||||
u32 mul;
|
||||
};
|
||||
|
||||
struct ccu_mux_config {
|
||||
u8 shift;
|
||||
u8 width;
|
||||
};
|
||||
|
||||
struct ccu_div_config {
|
||||
u8 shift;
|
||||
u8 width;
|
||||
};
|
||||
|
||||
struct ccu_mix {
|
||||
struct ccu_factor_config factor;
|
||||
struct ccu_gate_config gate;
|
||||
struct ccu_div_config div;
|
||||
struct ccu_mux_config mux;
|
||||
struct ccu_common common;
|
||||
};
|
||||
|
||||
#define CCU_GATE_INIT(_mask) { .mask = _mask }
|
||||
#define CCU_FACTOR_INIT(_div, _mul) { .div = _div, .mul = _mul }
|
||||
#define CCU_MUX_INIT(_shift, _width) { .shift = _shift, .width = _width }
|
||||
#define CCU_DIV_INIT(_shift, _width) { .shift = _shift, .width = _width }
|
||||
|
||||
#define CCU_PARENT_HW(_parent) { .hw = &_parent.common.hw }
|
||||
#define CCU_PARENT_NAME(_name) { .fw_name = #_name }
|
||||
|
||||
#define CCU_MIX_INITHW(_name, _parent, _ops, _flags) \
|
||||
.hw.init = &(struct clk_init_data) { \
|
||||
.flags = _flags, \
|
||||
.name = #_name, \
|
||||
.parent_data = (const struct clk_parent_data[]) \
|
||||
{ _parent }, \
|
||||
.num_parents = 1, \
|
||||
.ops = &_ops, \
|
||||
}
|
||||
|
||||
#define CCU_MIX_INITHW_PARENTS(_name, _parents, _ops, _flags) \
|
||||
.hw.init = CLK_HW_INIT_PARENTS_DATA(#_name, _parents, &_ops, _flags)
|
||||
|
||||
#define CCU_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.gate = CCU_GATE_INIT(_mask_gate), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_gate_ops, _flags), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_FACTOR_DEFINE(_name, _parent, _div, _mul) \
|
||||
static struct ccu_mix _name = { \
|
||||
.factor = CCU_FACTOR_INIT(_div, _mul), \
|
||||
.common = { \
|
||||
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_ops, 0), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_MUX_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.mux = CCU_MUX_INIT(_shift, _width), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops, \
|
||||
_flags), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_DIV_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.div = CCU_DIV_INIT(_shift, _width), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_ops, _flags) \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \
|
||||
_mul) \
|
||||
static struct ccu_mix _name = { \
|
||||
.gate = CCU_GATE_INIT(_mask_gate), \
|
||||
.factor = CCU_FACTOR_INIT(_div, _mul), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, 0) \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, \
|
||||
_mask_gate, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.gate = CCU_GATE_INIT(_mask_gate), \
|
||||
.mux = CCU_MUX_INIT(_shift, _width), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
||||
spacemit_ccu_mux_gate_ops, _flags), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_DIV_GATE_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, \
|
||||
_mask_gate, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.gate = CCU_GATE_INIT(_mask_gate), \
|
||||
.div = CCU_DIV_INIT(_shift, _width), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_gate_ops, \
|
||||
_flags), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CCU_MUX_DIV_GATE_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth, \
|
||||
_muxshift, _muxwidth, _mask_gate, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.gate = CCU_GATE_INIT(_mask_gate), \
|
||||
.div = CCU_DIV_INIT(_mshift, _mwidth), \
|
||||
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
||||
spacemit_ccu_mux_div_gate_ops, _flags), \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_fc, \
|
||||
_mshift, _mwidth, _mask_fc, _muxshift, \
|
||||
_muxwidth, _mask_gate, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.gate = CCU_GATE_INIT(_mask_gate), \
|
||||
.div = CCU_DIV_INIT(_mshift, _mwidth), \
|
||||
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
.reg_fc = _reg_fc, \
|
||||
.mask_fc = _mask_fc, \
|
||||
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
||||
spacemit_ccu_mux_div_gate_ops, _flags), \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define CCU_MUX_DIV_GATE_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,\
|
||||
_mask_fc, _muxshift, _muxwidth, _mask_gate, \
|
||||
_flags) \
|
||||
CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_ctrl, _mshift,\
|
||||
_mwidth, _mask_fc, _muxshift, _muxwidth, \
|
||||
_mask_gate, _flags)
|
||||
|
||||
#define CCU_MUX_DIV_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth, \
|
||||
_mask_fc, _muxshift, _muxwidth, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.div = CCU_DIV_INIT(_mshift, _mwidth), \
|
||||
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
.reg_fc = _reg_ctrl, \
|
||||
.mask_fc = _mask_fc, \
|
||||
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
||||
spacemit_ccu_mux_div_ops, _flags), \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define CCU_MUX_FC_DEFINE(_name, _parents, _reg_ctrl, _mask_fc, _muxshift, \
|
||||
_muxwidth, _flags) \
|
||||
static struct ccu_mix _name = { \
|
||||
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
||||
.common = { \
|
||||
.reg_ctrl = _reg_ctrl, \
|
||||
.reg_fc = _reg_ctrl, \
|
||||
.mask_fc = _mask_fc, \
|
||||
CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops, \
|
||||
_flags) \
|
||||
}, \
|
||||
}
|
||||
|
||||
static inline struct ccu_mix *hw_to_ccu_mix(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_common *common = hw_to_ccu_common(hw);
|
||||
|
||||
return container_of(common, struct ccu_mix, common);
|
||||
}
|
||||
|
||||
extern const struct clk_ops spacemit_ccu_gate_ops;
|
||||
extern const struct clk_ops spacemit_ccu_factor_ops;
|
||||
extern const struct clk_ops spacemit_ccu_mux_ops;
|
||||
extern const struct clk_ops spacemit_ccu_div_ops;
|
||||
extern const struct clk_ops spacemit_ccu_factor_gate_ops;
|
||||
extern const struct clk_ops spacemit_ccu_div_gate_ops;
|
||||
extern const struct clk_ops spacemit_ccu_mux_gate_ops;
|
||||
extern const struct clk_ops spacemit_ccu_mux_div_ops;
|
||||
extern const struct clk_ops spacemit_ccu_mux_div_gate_ops;
|
||||
#endif /* _CCU_DIV_H_ */
|
||||
157
drivers/clk/spacemit/ccu_pll.c
Normal file
157
drivers/clk/spacemit/ccu_pll.c
Normal file
@@ -0,0 +1,157 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
#include "ccu_pll.h"
|
||||
|
||||
#define PLL_TIMEOUT_US 3000
|
||||
#define PLL_DELAY_US 5
|
||||
|
||||
#define PLL_SWCR3_EN ((u32)BIT(31))
|
||||
#define PLL_SWCR3_MASK GENMASK(30, 0)
|
||||
|
||||
static const struct ccu_pll_rate_tbl *ccu_pll_lookup_best_rate(struct ccu_pll *pll,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct ccu_pll_config *config = &pll->config;
|
||||
const struct ccu_pll_rate_tbl *best_entry;
|
||||
unsigned long best_delta = ULONG_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config->tbl_num; i++) {
|
||||
const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i];
|
||||
unsigned long delta = abs_diff(entry->rate, rate);
|
||||
|
||||
if (delta < best_delta) {
|
||||
best_delta = delta;
|
||||
best_entry = entry;
|
||||
}
|
||||
}
|
||||
|
||||
return best_entry;
|
||||
}
|
||||
|
||||
static const struct ccu_pll_rate_tbl *ccu_pll_lookup_matched_entry(struct ccu_pll *pll)
|
||||
{
|
||||
struct ccu_pll_config *config = &pll->config;
|
||||
u32 swcr1, swcr3;
|
||||
int i;
|
||||
|
||||
swcr1 = ccu_read(&pll->common, swcr1);
|
||||
swcr3 = ccu_read(&pll->common, swcr3);
|
||||
swcr3 &= PLL_SWCR3_MASK;
|
||||
|
||||
for (i = 0; i < config->tbl_num; i++) {
|
||||
const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i];
|
||||
|
||||
if (swcr1 == entry->swcr1 && swcr3 == entry->swcr3)
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ccu_pll_update_param(struct ccu_pll *pll, const struct ccu_pll_rate_tbl *entry)
|
||||
{
|
||||
struct ccu_common *common = &pll->common;
|
||||
|
||||
regmap_write(common->regmap, common->reg_swcr1, entry->swcr1);
|
||||
ccu_update(common, swcr3, PLL_SWCR3_MASK, entry->swcr3);
|
||||
}
|
||||
|
||||
static int ccu_pll_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_common *common = hw_to_ccu_common(hw);
|
||||
|
||||
return ccu_read(common, swcr3) & PLL_SWCR3_EN;
|
||||
}
|
||||
|
||||
static int ccu_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_pll *pll = hw_to_ccu_pll(hw);
|
||||
struct ccu_common *common = &pll->common;
|
||||
unsigned int tmp;
|
||||
|
||||
ccu_update(common, swcr3, PLL_SWCR3_EN, PLL_SWCR3_EN);
|
||||
|
||||
/* check lock status */
|
||||
return regmap_read_poll_timeout_atomic(common->lock_regmap,
|
||||
pll->config.reg_lock,
|
||||
tmp,
|
||||
tmp & pll->config.mask_lock,
|
||||
PLL_DELAY_US, PLL_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static void ccu_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_common *common = hw_to_ccu_common(hw);
|
||||
|
||||
ccu_update(common, swcr3, PLL_SWCR3_EN, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* PLLs must be gated before changing rate, which is ensured by
|
||||
* flag CLK_SET_RATE_GATE.
|
||||
*/
|
||||
static int ccu_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_pll *pll = hw_to_ccu_pll(hw);
|
||||
const struct ccu_pll_rate_tbl *entry;
|
||||
|
||||
entry = ccu_pll_lookup_best_rate(pll, rate);
|
||||
ccu_pll_update_param(pll, entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_pll *pll = hw_to_ccu_pll(hw);
|
||||
const struct ccu_pll_rate_tbl *entry;
|
||||
|
||||
entry = ccu_pll_lookup_matched_entry(pll);
|
||||
|
||||
WARN_ON_ONCE(!entry);
|
||||
|
||||
return entry ? entry->rate : -EINVAL;
|
||||
}
|
||||
|
||||
static long ccu_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct ccu_pll *pll = hw_to_ccu_pll(hw);
|
||||
|
||||
return ccu_pll_lookup_best_rate(pll, rate)->rate;
|
||||
}
|
||||
|
||||
static int ccu_pll_init(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_pll *pll = hw_to_ccu_pll(hw);
|
||||
|
||||
if (ccu_pll_lookup_matched_entry(pll))
|
||||
return 0;
|
||||
|
||||
ccu_pll_disable(hw);
|
||||
ccu_pll_update_param(pll, &pll->config.rate_tbl[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops spacemit_ccu_pll_ops = {
|
||||
.init = ccu_pll_init,
|
||||
.enable = ccu_pll_enable,
|
||||
.disable = ccu_pll_disable,
|
||||
.set_rate = ccu_pll_set_rate,
|
||||
.recalc_rate = ccu_pll_recalc_rate,
|
||||
.round_rate = ccu_pll_round_rate,
|
||||
.is_enabled = ccu_pll_is_enabled,
|
||||
};
|
||||
86
drivers/clk/spacemit/ccu_pll.h
Normal file
86
drivers/clk/spacemit/ccu_pll.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
||||
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
||||
*/
|
||||
|
||||
#ifndef _CCU_PLL_H_
|
||||
#define _CCU_PLL_H_
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
|
||||
/**
|
||||
* struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register
|
||||
* configuration.
|
||||
*
|
||||
* @rate: PLL rate
|
||||
* @swcr1: Register value of PLLX_SW1_CTRL (PLLx_SWCR1).
|
||||
* @swcr3: Register value of the PLLx_SW3_CTRL's lowest 31 bits of
|
||||
* PLLx_SW3_CTRL (PLLx_SWCR3). This highest bit is for enabling
|
||||
* the PLL and not contained in this field.
|
||||
*/
|
||||
struct ccu_pll_rate_tbl {
|
||||
unsigned long rate;
|
||||
u32 swcr1;
|
||||
u32 swcr3;
|
||||
};
|
||||
|
||||
struct ccu_pll_config {
|
||||
const struct ccu_pll_rate_tbl *rate_tbl;
|
||||
u32 tbl_num;
|
||||
u32 reg_lock;
|
||||
u32 mask_lock;
|
||||
};
|
||||
|
||||
#define CCU_PLL_RATE(_rate, _swcr1, _swcr3) \
|
||||
{ \
|
||||
.rate = _rate, \
|
||||
.swcr1 = _swcr1, \
|
||||
.swcr3 = _swcr3, \
|
||||
}
|
||||
|
||||
struct ccu_pll {
|
||||
struct ccu_common common;
|
||||
struct ccu_pll_config config;
|
||||
};
|
||||
|
||||
#define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \
|
||||
{ \
|
||||
.rate_tbl = _table, \
|
||||
.tbl_num = ARRAY_SIZE(_table), \
|
||||
.reg_lock = (_reg_lock), \
|
||||
.mask_lock = (_mask_lock), \
|
||||
}
|
||||
|
||||
#define CCU_PLL_HWINIT(_name, _flags) \
|
||||
(&(struct clk_init_data) { \
|
||||
.name = #_name, \
|
||||
.ops = &spacemit_ccu_pll_ops, \
|
||||
.parent_data = &(struct clk_parent_data) { .index = 0 }, \
|
||||
.num_parents = 1, \
|
||||
.flags = _flags, \
|
||||
})
|
||||
|
||||
#define CCU_PLL_DEFINE(_name, _table, _reg_swcr1, _reg_swcr3, _reg_lock, \
|
||||
_mask_lock, _flags) \
|
||||
static struct ccu_pll _name = { \
|
||||
.config = CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock), \
|
||||
.common = { \
|
||||
.reg_swcr1 = _reg_swcr1, \
|
||||
.reg_swcr3 = _reg_swcr3, \
|
||||
.hw.init = CCU_PLL_HWINIT(_name, _flags) \
|
||||
} \
|
||||
}
|
||||
|
||||
static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw)
|
||||
{
|
||||
struct ccu_common *common = hw_to_ccu_common(hw);
|
||||
|
||||
return container_of(common, struct ccu_pll, common);
|
||||
}
|
||||
|
||||
extern const struct clk_ops spacemit_ccu_pll_ops;
|
||||
|
||||
#endif
|
||||
@@ -9,123 +9,123 @@ if SUNXI_CCU
|
||||
|
||||
config SUNIV_F1C100S_CCU
|
||||
tristate "Support for the Allwinner newer F1C100s CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUNIV || COMPILE_TEST
|
||||
|
||||
config SUN20I_D1_CCU
|
||||
tristate "Support for the Allwinner D1/R528/T113 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || RISCV || COMPILE_TEST
|
||||
|
||||
config SUN20I_D1_R_CCU
|
||||
tristate "Support for the Allwinner D1/R528/T113 PRCM CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || RISCV || COMPILE_TEST
|
||||
|
||||
config SUN50I_A64_CCU
|
||||
tristate "Support for the Allwinner A64 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN50I_A100_CCU
|
||||
tristate "Support for the Allwinner A100 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN50I_A100_R_CCU
|
||||
tristate "Support for the Allwinner A100 PRCM CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN50I_H6_CCU
|
||||
tristate "Support for the Allwinner H6 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN50I_H616_CCU
|
||||
tristate "Support for the Allwinner H616 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN50I_H6_R_CCU
|
||||
tristate "Support for the Allwinner H6 and H616 PRCM CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN55I_A523_CCU
|
||||
tristate "Support for the Allwinner A523/T527 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN55I_A523_R_CCU
|
||||
tristate "Support for the Allwinner A523/T527 PRCM CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN4I_A10_CCU
|
||||
tristate "Support for the Allwinner A10/A20 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
|
||||
|
||||
config SUN5I_CCU
|
||||
bool "Support for the Allwinner sun5i family CCM"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN5I || COMPILE_TEST
|
||||
depends on SUNXI_CCU=y
|
||||
|
||||
config SUN6I_A31_CCU
|
||||
tristate "Support for the Allwinner A31/A31s CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN6I || COMPILE_TEST
|
||||
|
||||
config SUN6I_RTC_CCU
|
||||
tristate "Support for the Allwinner H616/R329 RTC CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || ARM64 || RISCV || COMPILE_TEST
|
||||
|
||||
config SUN8I_A23_CCU
|
||||
tristate "Support for the Allwinner A23 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN8I_A33_CCU
|
||||
tristate "Support for the Allwinner A33 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN8I_A83T_CCU
|
||||
tristate "Support for the Allwinner A83T CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN8I_H3_CCU
|
||||
tristate "Support for the Allwinner H3 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || ARM64 || COMPILE_TEST
|
||||
|
||||
config SUN8I_V3S_CCU
|
||||
tristate "Support for the Allwinner V3s CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN8I_DE2_CCU
|
||||
tristate "Support for the Allwinner SoCs DE2 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || ARM64 || RISCV || COMPILE_TEST
|
||||
|
||||
config SUN8I_R40_CCU
|
||||
tristate "Support for the Allwinner R40 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN9I_A80_CCU
|
||||
tristate "Support for the Allwinner A80 CCU"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN9I || COMPILE_TEST
|
||||
|
||||
config SUN8I_R_CCU
|
||||
tristate "Support for Allwinner SoCs' PRCM CCUs"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
depends on MACH_SUN8I || ARM64 || COMPILE_TEST
|
||||
|
||||
endif
|
||||
|
||||
@@ -1094,6 +1094,7 @@ static const struct ccu_reset_map sun50i_h616_ccu_resets[] = {
|
||||
[RST_BUS_TCON_LCD1] = { 0xb7c, BIT(17) },
|
||||
[RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
|
||||
[RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
|
||||
[RST_BUS_LVDS] = { 0xbac, BIT(16) },
|
||||
[RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) },
|
||||
[RST_BUS_TVE0] = { 0xbbc, BIT(17) },
|
||||
[RST_BUS_HDCP] = { 0xc4c, BIT(16) },
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -239,6 +240,16 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = {
|
||||
.num_resets = ARRAY_SIZE(sun50i_h5_de2_resets),
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = {
|
||||
.ccu_clks = sun8i_de2_ccu_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun8i_de2_ccu_clks),
|
||||
|
||||
.hw_clks = &sun8i_h3_de2_hw_clks,
|
||||
|
||||
.resets = sun50i_h5_de2_resets,
|
||||
.num_resets = ARRAY_SIZE(sun50i_h5_de2_resets),
|
||||
};
|
||||
|
||||
static int sunxi_de2_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *bus_clk, *mod_clk;
|
||||
@@ -291,6 +302,16 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev)
|
||||
goto err_disable_mod_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* The DE33 requires these additional (unknown) registers set
|
||||
* during initialisation.
|
||||
*/
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"allwinner,sun50i-h616-de33-clk")) {
|
||||
writel(0, reg + 0x24);
|
||||
writel(0x0000a980, reg + 0x28);
|
||||
}
|
||||
|
||||
ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
@@ -335,6 +356,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = {
|
||||
.compatible = "allwinner,sun50i-h6-de3-clk",
|
||||
.data = &sun50i_h5_de2_clk_desc,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun50i-h616-de33-clk",
|
||||
.data = &sun50i_h616_de33_clk_desc,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids);
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
menuconfig CLK_SUNXI
|
||||
bool "Legacy clock support for Allwinner SoCs"
|
||||
depends on (ARM && ARCH_SUNXI) || COMPILE_TEST
|
||||
default y
|
||||
default (ARM && ARCH_SUNXI)
|
||||
|
||||
if CLK_SUNXI
|
||||
|
||||
config CLK_SUNXI_CLOCKS
|
||||
bool "Legacy clock drivers"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
help
|
||||
Legacy clock drivers being used on older (A10, A13, A20,
|
||||
A23, A31, A80) SoCs. These drivers are kept around for
|
||||
@@ -19,14 +19,14 @@ config CLK_SUNXI_CLOCKS
|
||||
|
||||
config CLK_SUNXI_PRCM_SUN6I
|
||||
bool "Legacy A31 PRCM driver"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
help
|
||||
Legacy clock driver for the A31 PRCM clocks. Those are
|
||||
usually needed for the PMIC communication, mostly.
|
||||
|
||||
config CLK_SUNXI_PRCM_SUN8I
|
||||
bool "Legacy sun8i PRCM driver"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
help
|
||||
Legacy clock driver for the sun8i family PRCM clocks.
|
||||
Those are usually needed for the PMIC communication,
|
||||
@@ -34,7 +34,7 @@ config CLK_SUNXI_PRCM_SUN8I
|
||||
|
||||
config CLK_SUNXI_PRCM_SUN9I
|
||||
bool "Legacy A80 PRCM driver"
|
||||
default y
|
||||
default ARCH_SUNXI
|
||||
help
|
||||
Legacy clock driver for the A80 PRCM clocks. Those are
|
||||
usually needed for the PMIC communication, mostly.
|
||||
|
||||
@@ -847,6 +847,67 @@ static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", axi_aclk_pd, 0x20c, BIT(3), 0);
|
||||
static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", axi_aclk_pd, 0x20c, BIT(2), 0);
|
||||
static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", axi_aclk_pd, 0x20c, BIT(1), 0);
|
||||
|
||||
static CCU_GATE(CLK_AXI4_VO_ACLK, axi4_vo_aclk, "axi4-vo-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(0), 0);
|
||||
static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd,
|
||||
0x0, BIT(3), 0);
|
||||
static CCU_GATE(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(4), 0);
|
||||
static CCU_GATE(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk",
|
||||
video_pll_clk_pd, 0x0, BIT(5), 0);
|
||||
static CCU_GATE(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk",
|
||||
video_pll_clk_pd, 0x0, BIT(6), 0);
|
||||
static CCU_GATE(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_clk_pd, 0x0,
|
||||
BIT(7), 0);
|
||||
static CCU_GATE(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_clk_pd, 0x0,
|
||||
BIT(8), 0);
|
||||
static CCU_GATE(CLK_DPU_CCLK, dpu_cclk, "dpu-cclk", video_pll_clk_pd, 0x0,
|
||||
BIT(9), 0);
|
||||
static CCU_GATE(CLK_HDMI_SFR, hdmi_sfr_clk, "hdmi-sfr-clk", video_pll_clk_pd,
|
||||
0x0, BIT(10), 0);
|
||||
static CCU_GATE(CLK_HDMI_PCLK, hdmi_pclk, "hdmi-pclk", video_pll_clk_pd, 0x0,
|
||||
BIT(11), 0);
|
||||
static CCU_GATE(CLK_HDMI_CEC, hdmi_cec_clk, "hdmi-cec-clk", video_pll_clk_pd,
|
||||
0x0, BIT(12), 0);
|
||||
static CCU_GATE(CLK_MIPI_DSI0_PCLK, mipi_dsi0_pclk, "mipi-dsi0-pclk",
|
||||
video_pll_clk_pd, 0x0, BIT(13), 0);
|
||||
static CCU_GATE(CLK_MIPI_DSI1_PCLK, mipi_dsi1_pclk, "mipi-dsi1-pclk",
|
||||
video_pll_clk_pd, 0x0, BIT(14), 0);
|
||||
static CCU_GATE(CLK_MIPI_DSI0_CFG, mipi_dsi0_cfg_clk, "mipi-dsi0-cfg-clk",
|
||||
video_pll_clk_pd, 0x0, BIT(15), 0);
|
||||
static CCU_GATE(CLK_MIPI_DSI1_CFG, mipi_dsi1_cfg_clk, "mipi-dsi1-cfg-clk",
|
||||
video_pll_clk_pd, 0x0, BIT(16), 0);
|
||||
static CCU_GATE(CLK_MIPI_DSI0_REFCLK, mipi_dsi0_refclk, "mipi-dsi0-refclk",
|
||||
video_pll_clk_pd, 0x0, BIT(17), 0);
|
||||
static CCU_GATE(CLK_MIPI_DSI1_REFCLK, mipi_dsi1_refclk, "mipi-dsi1-refclk",
|
||||
video_pll_clk_pd, 0x0, BIT(18), 0);
|
||||
static CCU_GATE(CLK_HDMI_I2S, hdmi_i2s_clk, "hdmi-i2s-clk", video_pll_clk_pd,
|
||||
0x0, BIT(19), 0);
|
||||
static CCU_GATE(CLK_X2H_DPU1_ACLK, x2h_dpu1_aclk, "x2h-dpu1-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(20), 0);
|
||||
static CCU_GATE(CLK_X2H_DPU_ACLK, x2h_dpu_aclk, "x2h-dpu-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(21), 0);
|
||||
static CCU_GATE(CLK_AXI4_VO_PCLK, axi4_vo_pclk, "axi4-vo-pclk",
|
||||
video_pll_clk_pd, 0x0, BIT(22), 0);
|
||||
static CCU_GATE(CLK_IOPMP_VOSYS_DPU_PCLK, iopmp_vosys_dpu_pclk,
|
||||
"iopmp-vosys-dpu-pclk", video_pll_clk_pd, 0x0, BIT(23), 0);
|
||||
static CCU_GATE(CLK_IOPMP_VOSYS_DPU1_PCLK, iopmp_vosys_dpu1_pclk,
|
||||
"iopmp-vosys-dpu1-pclk", video_pll_clk_pd, 0x0, BIT(24), 0);
|
||||
static CCU_GATE(CLK_IOPMP_VOSYS_GPU_PCLK, iopmp_vosys_gpu_pclk,
|
||||
"iopmp-vosys-gpu-pclk", video_pll_clk_pd, 0x0, BIT(25), 0);
|
||||
static CCU_GATE(CLK_IOPMP_DPU1_ACLK, iopmp_dpu1_aclk, "iopmp-dpu1-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(27), 0);
|
||||
static CCU_GATE(CLK_IOPMP_DPU_ACLK, iopmp_dpu_aclk, "iopmp-dpu-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(28), 0);
|
||||
static CCU_GATE(CLK_IOPMP_GPU_ACLK, iopmp_gpu_aclk, "iopmp-gpu-aclk",
|
||||
video_pll_clk_pd, 0x0, BIT(29), 0);
|
||||
static CCU_GATE(CLK_MIPIDSI0_PIXCLK, mipi_dsi0_pixclk, "mipi-dsi0-pixclk",
|
||||
video_pll_clk_pd, 0x0, BIT(30), 0);
|
||||
static CCU_GATE(CLK_MIPIDSI1_PIXCLK, mipi_dsi1_pixclk, "mipi-dsi1-pixclk",
|
||||
video_pll_clk_pd, 0x0, BIT(31), 0);
|
||||
static CCU_GATE(CLK_HDMI_PIXCLK, hdmi_pixclk, "hdmi-pixclk", video_pll_clk_pd,
|
||||
0x4, BIT(0), 0);
|
||||
|
||||
static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m, "gmac-pll-clk-100m",
|
||||
&gmac_pll_clk.common.hw, 10, 1, 0);
|
||||
|
||||
@@ -963,7 +1024,38 @@ static struct ccu_common *th1520_gate_clks[] = {
|
||||
&sram3_clk.common,
|
||||
};
|
||||
|
||||
#define NR_CLKS (CLK_UART_SCLK + 1)
|
||||
static struct ccu_common *th1520_vo_gate_clks[] = {
|
||||
&axi4_vo_aclk.common,
|
||||
&gpu_core_clk.common,
|
||||
&gpu_cfg_aclk.common,
|
||||
&dpu0_pixelclk.common,
|
||||
&dpu1_pixelclk.common,
|
||||
&dpu_hclk.common,
|
||||
&dpu_aclk.common,
|
||||
&dpu_cclk.common,
|
||||
&hdmi_sfr_clk.common,
|
||||
&hdmi_pclk.common,
|
||||
&hdmi_cec_clk.common,
|
||||
&mipi_dsi0_pclk.common,
|
||||
&mipi_dsi1_pclk.common,
|
||||
&mipi_dsi0_cfg_clk.common,
|
||||
&mipi_dsi1_cfg_clk.common,
|
||||
&mipi_dsi0_refclk.common,
|
||||
&mipi_dsi1_refclk.common,
|
||||
&hdmi_i2s_clk.common,
|
||||
&x2h_dpu1_aclk.common,
|
||||
&x2h_dpu_aclk.common,
|
||||
&axi4_vo_pclk.common,
|
||||
&iopmp_vosys_dpu_pclk.common,
|
||||
&iopmp_vosys_dpu1_pclk.common,
|
||||
&iopmp_vosys_gpu_pclk.common,
|
||||
&iopmp_dpu1_aclk.common,
|
||||
&iopmp_dpu_aclk.common,
|
||||
&iopmp_gpu_aclk.common,
|
||||
&mipi_dsi0_pixclk.common,
|
||||
&mipi_dsi1_pixclk.common,
|
||||
&hdmi_pixclk.common
|
||||
};
|
||||
|
||||
static const struct regmap_config th1520_clk_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
@@ -972,8 +1064,44 @@ static const struct regmap_config th1520_clk_regmap_config = {
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
struct th1520_plat_data {
|
||||
struct ccu_common **th1520_pll_clks;
|
||||
struct ccu_common **th1520_div_clks;
|
||||
struct ccu_common **th1520_mux_clks;
|
||||
struct ccu_common **th1520_gate_clks;
|
||||
|
||||
int nr_clks;
|
||||
int nr_pll_clks;
|
||||
int nr_div_clks;
|
||||
int nr_mux_clks;
|
||||
int nr_gate_clks;
|
||||
};
|
||||
|
||||
static const struct th1520_plat_data th1520_ap_platdata = {
|
||||
.th1520_pll_clks = th1520_pll_clks,
|
||||
.th1520_div_clks = th1520_div_clks,
|
||||
.th1520_mux_clks = th1520_mux_clks,
|
||||
.th1520_gate_clks = th1520_gate_clks,
|
||||
|
||||
.nr_clks = CLK_UART_SCLK + 1,
|
||||
|
||||
.nr_pll_clks = ARRAY_SIZE(th1520_pll_clks),
|
||||
.nr_div_clks = ARRAY_SIZE(th1520_div_clks),
|
||||
.nr_mux_clks = ARRAY_SIZE(th1520_mux_clks),
|
||||
.nr_gate_clks = ARRAY_SIZE(th1520_gate_clks),
|
||||
};
|
||||
|
||||
static const struct th1520_plat_data th1520_vo_platdata = {
|
||||
.th1520_gate_clks = th1520_vo_gate_clks,
|
||||
|
||||
.nr_clks = CLK_HDMI_PIXCLK + 1,
|
||||
|
||||
.nr_gate_clks = ARRAY_SIZE(th1520_vo_gate_clks),
|
||||
};
|
||||
|
||||
static int th1520_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct th1520_plat_data *plat_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk_hw_onecell_data *priv;
|
||||
|
||||
@@ -982,11 +1110,16 @@ static int th1520_clk_probe(struct platform_device *pdev)
|
||||
struct clk_hw *hw;
|
||||
int ret, i;
|
||||
|
||||
priv = devm_kzalloc(dev, struct_size(priv, hws, NR_CLKS), GFP_KERNEL);
|
||||
plat_data = device_get_match_data(&pdev->dev);
|
||||
if (!plat_data)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
"No device match data found\n");
|
||||
|
||||
priv = devm_kzalloc(dev, struct_size(priv, hws, plat_data->nr_clks), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->num = NR_CLKS;
|
||||
priv->num = plat_data->nr_clks;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
@@ -996,35 +1129,35 @@ static int th1520_clk_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(th1520_pll_clks); i++) {
|
||||
struct ccu_pll *cp = hw_to_ccu_pll(&th1520_pll_clks[i]->hw);
|
||||
for (i = 0; i < plat_data->nr_pll_clks; i++) {
|
||||
struct ccu_pll *cp = hw_to_ccu_pll(&plat_data->th1520_pll_clks[i]->hw);
|
||||
|
||||
th1520_pll_clks[i]->map = map;
|
||||
plat_data->th1520_pll_clks[i]->map = map;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &th1520_pll_clks[i]->hw);
|
||||
ret = devm_clk_hw_register(dev, &plat_data->th1520_pll_clks[i]->hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->hws[cp->common.clkid] = &cp->common.hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(th1520_div_clks); i++) {
|
||||
struct ccu_div *cd = hw_to_ccu_div(&th1520_div_clks[i]->hw);
|
||||
for (i = 0; i < plat_data->nr_div_clks; i++) {
|
||||
struct ccu_div *cd = hw_to_ccu_div(&plat_data->th1520_div_clks[i]->hw);
|
||||
|
||||
th1520_div_clks[i]->map = map;
|
||||
plat_data->th1520_div_clks[i]->map = map;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &th1520_div_clks[i]->hw);
|
||||
ret = devm_clk_hw_register(dev, &plat_data->th1520_div_clks[i]->hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->hws[cd->common.clkid] = &cd->common.hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(th1520_mux_clks); i++) {
|
||||
struct ccu_mux *cm = hw_to_ccu_mux(&th1520_mux_clks[i]->hw);
|
||||
for (i = 0; i < plat_data->nr_mux_clks; i++) {
|
||||
struct ccu_mux *cm = hw_to_ccu_mux(&plat_data->th1520_mux_clks[i]->hw);
|
||||
const struct clk_init_data *init = cm->common.hw.init;
|
||||
|
||||
th1520_mux_clks[i]->map = map;
|
||||
plat_data->th1520_mux_clks[i]->map = map;
|
||||
hw = devm_clk_hw_register_mux_parent_data_table(dev,
|
||||
init->name,
|
||||
init->parent_data,
|
||||
@@ -1040,10 +1173,10 @@ static int th1520_clk_probe(struct platform_device *pdev)
|
||||
priv->hws[cm->common.clkid] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(th1520_gate_clks); i++) {
|
||||
struct ccu_gate *cg = hw_to_ccu_gate(&th1520_gate_clks[i]->hw);
|
||||
for (i = 0; i < plat_data->nr_gate_clks; i++) {
|
||||
struct ccu_gate *cg = hw_to_ccu_gate(&plat_data->th1520_gate_clks[i]->hw);
|
||||
|
||||
th1520_gate_clks[i]->map = map;
|
||||
plat_data->th1520_gate_clks[i]->map = map;
|
||||
|
||||
hw = devm_clk_hw_register_gate_parent_data(dev,
|
||||
cg->common.hw.init->name,
|
||||
@@ -1057,19 +1190,21 @@ static int th1520_clk_probe(struct platform_device *pdev)
|
||||
priv->hws[cg->common.clkid] = hw;
|
||||
}
|
||||
|
||||
ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
|
||||
if (plat_data == &th1520_ap_platdata) {
|
||||
ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
|
||||
ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);
|
||||
if (ret)
|
||||
@@ -1081,6 +1216,11 @@ static int th1520_clk_probe(struct platform_device *pdev)
|
||||
static const struct of_device_id th1520_clk_match[] = {
|
||||
{
|
||||
.compatible = "thead,th1520-clk-ap",
|
||||
.data = &th1520_ap_platdata,
|
||||
},
|
||||
{
|
||||
.compatible = "thead,th1520-clk-vo",
|
||||
.data = &th1520_vo_platdata,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
27
include/dt-bindings/clock/qcom,sm6350-videocc.h
Normal file
27
include/dt-bindings/clock/qcom,sm6350-videocc.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM6350_H
|
||||
#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM6350_H
|
||||
|
||||
/* VIDEO_CC clocks */
|
||||
#define VIDEO_PLL0 0
|
||||
#define VIDEO_PLL0_OUT_EVEN 1
|
||||
#define VIDEO_CC_IRIS_AHB_CLK 2
|
||||
#define VIDEO_CC_IRIS_CLK_SRC 3
|
||||
#define VIDEO_CC_MVS0_AXI_CLK 4
|
||||
#define VIDEO_CC_MVS0_CORE_CLK 5
|
||||
#define VIDEO_CC_MVSC_CORE_CLK 6
|
||||
#define VIDEO_CC_MVSC_CTL_AXI_CLK 7
|
||||
#define VIDEO_CC_SLEEP_CLK 8
|
||||
#define VIDEO_CC_SLEEP_CLK_SRC 9
|
||||
#define VIDEO_CC_VENUS_AHB_CLK 10
|
||||
|
||||
/* GDSCs */
|
||||
#define MVSC_GDSC 0
|
||||
#define MVS0_GDSC 1
|
||||
|
||||
#endif
|
||||
@@ -17,5 +17,8 @@
|
||||
#define R9A09G047_CM33_CLK0 6
|
||||
#define R9A09G047_CST_0_SWCLKTCK 7
|
||||
#define R9A09G047_IOTOP_0_SHCLK 8
|
||||
#define R9A09G047_SPI_CLK_SPI 9
|
||||
#define R9A09G047_GBETH_0_CLK_PTP_REF_I 10
|
||||
#define R9A09G047_GBETH_1_CLK_PTP_REF_I 11
|
||||
|
||||
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G047_CPG_H__ */
|
||||
|
||||
24
include/dt-bindings/clock/renesas,r9a09g056-cpg.h
Normal file
24
include/dt-bindings/clock/renesas,r9a09g056-cpg.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
*
|
||||
* Copyright (C) 2025 Renesas Electronics Corp.
|
||||
*/
|
||||
#ifndef __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__
|
||||
#define __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__
|
||||
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
|
||||
/* Core Clock list */
|
||||
#define R9A09G056_SYS_0_PCLK 0
|
||||
#define R9A09G056_CA55_0_CORE_CLK0 1
|
||||
#define R9A09G056_CA55_0_CORE_CLK1 2
|
||||
#define R9A09G056_CA55_0_CORE_CLK2 3
|
||||
#define R9A09G056_CA55_0_CORE_CLK3 4
|
||||
#define R9A09G056_CA55_0_PERIPHCLK 5
|
||||
#define R9A09G056_CM33_CLK0 6
|
||||
#define R9A09G056_CST_0_SWCLKTCK 7
|
||||
#define R9A09G056_IOTOP_0_SHCLK 8
|
||||
#define R9A09G056_USB2_0_CLK_CORE0 9
|
||||
#define R9A09G056_GBETH_0_CLK_PTP_REF_I 10
|
||||
#define R9A09G056_GBETH_1_CLK_PTP_REF_I 11
|
||||
|
||||
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__ */
|
||||
@@ -17,5 +17,9 @@
|
||||
#define R9A09G057_CM33_CLK0 6
|
||||
#define R9A09G057_CST_0_SWCLKTCK 7
|
||||
#define R9A09G057_IOTOP_0_SHCLK 8
|
||||
#define R9A09G057_USB2_0_CLK_CORE0 9
|
||||
#define R9A09G057_USB2_0_CLK_CORE1 10
|
||||
#define R9A09G057_GBETH_0_CLK_PTP_REF_I 11
|
||||
#define R9A09G057_GBETH_1_CLK_PTP_REF_I 12
|
||||
|
||||
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G057_CPG_H__ */
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#define SCLK_MACREF 152
|
||||
#define SCLK_MACPLL 153
|
||||
#define SCLK_SFC 160
|
||||
#define SCLK_USB480M 161
|
||||
|
||||
/* aclk gates */
|
||||
#define ACLK_DMAC2 194
|
||||
|
||||
@@ -414,6 +414,12 @@
|
||||
#define MCLK_I2S2_2CH_SAI_SRC_PRE 402
|
||||
#define MCLK_I2S3_8CH_SAI_SRC_PRE 403
|
||||
#define MCLK_SDPDIF_SRC_PRE 404
|
||||
#define SCLK_SDMMC_DRV 405
|
||||
#define SCLK_SDMMC_SAMPLE 406
|
||||
#define SCLK_SDIO0_DRV 407
|
||||
#define SCLK_SDIO0_SAMPLE 408
|
||||
#define SCLK_SDIO1_DRV 409
|
||||
#define SCLK_SDIO1_SAMPLE 410
|
||||
|
||||
/* scmi-clocks indices */
|
||||
#define SCMI_PCLK_KEYREADER 0
|
||||
|
||||
@@ -594,4 +594,14 @@
|
||||
#define SCMI_ARMCLK_B 11
|
||||
#define SCMI_CLK_GPU 456
|
||||
|
||||
/* IOC-controlled output clocks */
|
||||
#define CLK_SAI0_MCLKOUT_TO_IO 571
|
||||
#define CLK_SAI1_MCLKOUT_TO_IO 572
|
||||
#define CLK_SAI2_MCLKOUT_TO_IO 573
|
||||
#define CLK_SAI3_MCLKOUT_TO_IO 574
|
||||
#define CLK_SAI4_MCLKOUT_TO_IO 575
|
||||
#define CLK_SAI4_MCLKOUT_TO_IO 575
|
||||
#define CLK_FSPI0_TO_IO 576
|
||||
#define CLK_FSPI1_TO_IO 577
|
||||
|
||||
#endif
|
||||
|
||||
@@ -162,6 +162,57 @@
|
||||
#define DOUT_CLKCMU_TAA_NOC 146
|
||||
#define DOUT_TCXO_DIV2 147
|
||||
|
||||
/* CMU_CPUCL0 */
|
||||
#define CLK_FOUT_CPUCL0_PLL 1
|
||||
|
||||
#define CLK_MOUT_PLL_CPUCL0 2
|
||||
#define CLK_MOUT_CPUCL0_CLUSTER_USER 3
|
||||
#define CLK_MOUT_CPUCL0_DBG_USER 4
|
||||
#define CLK_MOUT_CPUCL0_SWITCH_USER 5
|
||||
#define CLK_MOUT_CPUCL0_CLUSTER 6
|
||||
#define CLK_MOUT_CPUCL0_CORE 7
|
||||
|
||||
#define CLK_DOUT_CLUSTER0_ACLK 8
|
||||
#define CLK_DOUT_CLUSTER0_ATCLK 9
|
||||
#define CLK_DOUT_CLUSTER0_MPCLK 10
|
||||
#define CLK_DOUT_CLUSTER0_PCLK 11
|
||||
#define CLK_DOUT_CLUSTER0_PERIPHCLK 12
|
||||
#define CLK_DOUT_CPUCL0_DBG_NOC 13
|
||||
#define CLK_DOUT_CPUCL0_DBG_PCLKDBG 14
|
||||
#define CLK_DOUT_CPUCL0_NOCP 15
|
||||
|
||||
/* CMU_CPUCL1 */
|
||||
#define CLK_FOUT_CPUCL1_PLL 1
|
||||
|
||||
#define CLK_MOUT_PLL_CPUCL1 2
|
||||
#define CLK_MOUT_CPUCL1_CLUSTER_USER 3
|
||||
#define CLK_MOUT_CPUCL1_SWITCH_USER 4
|
||||
#define CLK_MOUT_CPUCL1_CLUSTER 5
|
||||
#define CLK_MOUT_CPUCL1_CORE 6
|
||||
|
||||
#define CLK_DOUT_CLUSTER1_ACLK 7
|
||||
#define CLK_DOUT_CLUSTER1_ATCLK 8
|
||||
#define CLK_DOUT_CLUSTER1_MPCLK 9
|
||||
#define CLK_DOUT_CLUSTER1_PCLK 10
|
||||
#define CLK_DOUT_CLUSTER1_PERIPHCLK 11
|
||||
#define CLK_DOUT_CPUCL1_NOCP 12
|
||||
|
||||
/* CMU_CPUCL2 */
|
||||
#define CLK_FOUT_CPUCL2_PLL 1
|
||||
|
||||
#define CLK_MOUT_PLL_CPUCL2 2
|
||||
#define CLK_MOUT_CPUCL2_CLUSTER_USER 3
|
||||
#define CLK_MOUT_CPUCL2_SWITCH_USER 4
|
||||
#define CLK_MOUT_CPUCL2_CLUSTER 5
|
||||
#define CLK_MOUT_CPUCL2_CORE 6
|
||||
|
||||
#define CLK_DOUT_CLUSTER2_ACLK 7
|
||||
#define CLK_DOUT_CLUSTER2_ATCLK 8
|
||||
#define CLK_DOUT_CLUSTER2_MPCLK 9
|
||||
#define CLK_DOUT_CLUSTER2_PCLK 10
|
||||
#define CLK_DOUT_CLUSTER2_PERIPHCLK 11
|
||||
#define CLK_DOUT_CPUCL2_NOCP 12
|
||||
|
||||
/* CMU_PERIC0 */
|
||||
#define CLK_MOUT_PERIC0_IP_USER 1
|
||||
#define CLK_MOUT_PERIC0_NOC_USER 2
|
||||
|
||||
153
include/dt-bindings/clock/sophgo,sg2044-clk.h
Normal file
153
include/dt-bindings/clock/sophgo,sg2044-clk.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_SOPHGO_SG2044_CLK_H__
|
||||
#define __DT_BINDINGS_SOPHGO_SG2044_CLK_H__
|
||||
|
||||
#define CLK_DIV_AP_SYS_FIXED 0
|
||||
#define CLK_DIV_AP_SYS_MAIN 1
|
||||
#define CLK_DIV_RP_SYS_FIXED 2
|
||||
#define CLK_DIV_RP_SYS_MAIN 3
|
||||
#define CLK_DIV_TPU_SYS_FIXED 4
|
||||
#define CLK_DIV_TPU_SYS_MAIN 5
|
||||
#define CLK_DIV_NOC_SYS_FIXED 6
|
||||
#define CLK_DIV_NOC_SYS_MAIN 7
|
||||
#define CLK_DIV_VC_SRC0_FIXED 8
|
||||
#define CLK_DIV_VC_SRC0_MAIN 9
|
||||
#define CLK_DIV_VC_SRC1_FIXED 10
|
||||
#define CLK_DIV_VC_SRC1_MAIN 11
|
||||
#define CLK_DIV_CXP_MAC_FIXED 12
|
||||
#define CLK_DIV_CXP_MAC_MAIN 13
|
||||
#define CLK_DIV_DDR0_FIXED 14
|
||||
#define CLK_DIV_DDR0_MAIN 15
|
||||
#define CLK_DIV_DDR1_FIXED 16
|
||||
#define CLK_DIV_DDR1_MAIN 17
|
||||
#define CLK_DIV_DDR2_FIXED 18
|
||||
#define CLK_DIV_DDR2_MAIN 19
|
||||
#define CLK_DIV_DDR3_FIXED 20
|
||||
#define CLK_DIV_DDR3_MAIN 21
|
||||
#define CLK_DIV_DDR4_FIXED 22
|
||||
#define CLK_DIV_DDR4_MAIN 23
|
||||
#define CLK_DIV_DDR5_FIXED 24
|
||||
#define CLK_DIV_DDR5_MAIN 25
|
||||
#define CLK_DIV_DDR6_FIXED 26
|
||||
#define CLK_DIV_DDR6_MAIN 27
|
||||
#define CLK_DIV_DDR7_FIXED 28
|
||||
#define CLK_DIV_DDR7_MAIN 29
|
||||
#define CLK_DIV_TOP_50M 30
|
||||
#define CLK_DIV_TOP_AXI0 31
|
||||
#define CLK_DIV_TOP_AXI_HSPERI 32
|
||||
#define CLK_DIV_TIMER0 33
|
||||
#define CLK_DIV_TIMER1 34
|
||||
#define CLK_DIV_TIMER2 35
|
||||
#define CLK_DIV_TIMER3 36
|
||||
#define CLK_DIV_TIMER4 37
|
||||
#define CLK_DIV_TIMER5 38
|
||||
#define CLK_DIV_TIMER6 39
|
||||
#define CLK_DIV_TIMER7 40
|
||||
#define CLK_DIV_CXP_TEST_PHY 41
|
||||
#define CLK_DIV_CXP_TEST_ETH_PHY 42
|
||||
#define CLK_DIV_C2C0_TEST_PHY 43
|
||||
#define CLK_DIV_C2C1_TEST_PHY 44
|
||||
#define CLK_DIV_PCIE_1G 45
|
||||
#define CLK_DIV_UART_500M 46
|
||||
#define CLK_DIV_GPIO_DB 47
|
||||
#define CLK_DIV_SD 48
|
||||
#define CLK_DIV_SD_100K 49
|
||||
#define CLK_DIV_EMMC 50
|
||||
#define CLK_DIV_EMMC_100K 51
|
||||
#define CLK_DIV_EFUSE 52
|
||||
#define CLK_DIV_TX_ETH0 53
|
||||
#define CLK_DIV_PTP_REF_I_ETH0 54
|
||||
#define CLK_DIV_REF_ETH0 55
|
||||
#define CLK_DIV_PKA 56
|
||||
#define CLK_MUX_DDR0 57
|
||||
#define CLK_MUX_DDR1 58
|
||||
#define CLK_MUX_DDR2 59
|
||||
#define CLK_MUX_DDR3 60
|
||||
#define CLK_MUX_DDR4 61
|
||||
#define CLK_MUX_DDR5 62
|
||||
#define CLK_MUX_DDR6 63
|
||||
#define CLK_MUX_DDR7 64
|
||||
#define CLK_MUX_NOC_SYS 65
|
||||
#define CLK_MUX_TPU_SYS 66
|
||||
#define CLK_MUX_RP_SYS 67
|
||||
#define CLK_MUX_AP_SYS 68
|
||||
#define CLK_MUX_VC_SRC0 69
|
||||
#define CLK_MUX_VC_SRC1 70
|
||||
#define CLK_MUX_CXP_MAC 71
|
||||
#define CLK_GATE_AP_SYS 72
|
||||
#define CLK_GATE_RP_SYS 73
|
||||
#define CLK_GATE_TPU_SYS 74
|
||||
#define CLK_GATE_NOC_SYS 75
|
||||
#define CLK_GATE_VC_SRC0 76
|
||||
#define CLK_GATE_VC_SRC1 77
|
||||
#define CLK_GATE_DDR0 78
|
||||
#define CLK_GATE_DDR1 79
|
||||
#define CLK_GATE_DDR2 80
|
||||
#define CLK_GATE_DDR3 81
|
||||
#define CLK_GATE_DDR4 82
|
||||
#define CLK_GATE_DDR5 83
|
||||
#define CLK_GATE_DDR6 84
|
||||
#define CLK_GATE_DDR7 85
|
||||
#define CLK_GATE_TOP_50M 86
|
||||
#define CLK_GATE_SC_RX 87
|
||||
#define CLK_GATE_SC_RX_X0Y1 88
|
||||
#define CLK_GATE_TOP_AXI0 89
|
||||
#define CLK_GATE_INTC0 90
|
||||
#define CLK_GATE_INTC1 91
|
||||
#define CLK_GATE_INTC2 92
|
||||
#define CLK_GATE_INTC3 93
|
||||
#define CLK_GATE_MAILBOX0 94
|
||||
#define CLK_GATE_MAILBOX1 95
|
||||
#define CLK_GATE_MAILBOX2 96
|
||||
#define CLK_GATE_MAILBOX3 97
|
||||
#define CLK_GATE_TOP_AXI_HSPERI 98
|
||||
#define CLK_GATE_APB_TIMER 99
|
||||
#define CLK_GATE_TIMER0 100
|
||||
#define CLK_GATE_TIMER1 101
|
||||
#define CLK_GATE_TIMER2 102
|
||||
#define CLK_GATE_TIMER3 103
|
||||
#define CLK_GATE_TIMER4 104
|
||||
#define CLK_GATE_TIMER5 105
|
||||
#define CLK_GATE_TIMER6 106
|
||||
#define CLK_GATE_TIMER7 107
|
||||
#define CLK_GATE_CXP_CFG 108
|
||||
#define CLK_GATE_CXP_MAC 109
|
||||
#define CLK_GATE_CXP_TEST_PHY 110
|
||||
#define CLK_GATE_CXP_TEST_ETH_PHY 111
|
||||
#define CLK_GATE_PCIE_1G 112
|
||||
#define CLK_GATE_C2C0_TEST_PHY 113
|
||||
#define CLK_GATE_C2C1_TEST_PHY 114
|
||||
#define CLK_GATE_UART_500M 115
|
||||
#define CLK_GATE_APB_UART 116
|
||||
#define CLK_GATE_APB_SPI 117
|
||||
#define CLK_GATE_AHB_SPIFMC 118
|
||||
#define CLK_GATE_APB_I2C 119
|
||||
#define CLK_GATE_AXI_DBG_I2C 120
|
||||
#define CLK_GATE_GPIO_DB 121
|
||||
#define CLK_GATE_APB_GPIO_INTR 122
|
||||
#define CLK_GATE_APB_GPIO 123
|
||||
#define CLK_GATE_SD 124
|
||||
#define CLK_GATE_AXI_SD 125
|
||||
#define CLK_GATE_SD_100K 126
|
||||
#define CLK_GATE_EMMC 127
|
||||
#define CLK_GATE_AXI_EMMC 128
|
||||
#define CLK_GATE_EMMC_100K 129
|
||||
#define CLK_GATE_EFUSE 130
|
||||
#define CLK_GATE_APB_EFUSE 131
|
||||
#define CLK_GATE_SYSDMA_AXI 132
|
||||
#define CLK_GATE_TX_ETH0 133
|
||||
#define CLK_GATE_AXI_ETH0 134
|
||||
#define CLK_GATE_PTP_REF_I_ETH0 135
|
||||
#define CLK_GATE_REF_ETH0 136
|
||||
#define CLK_GATE_APB_RTC 137
|
||||
#define CLK_GATE_APB_PWM 138
|
||||
#define CLK_GATE_APB_WDT 139
|
||||
#define CLK_GATE_AXI_SRAM 140
|
||||
#define CLK_GATE_AHB_ROM 141
|
||||
#define CLK_GATE_PKA 142
|
||||
|
||||
#endif /* __DT_BINDINGS_SOPHGO_SG2044_CLK_H__ */
|
||||
27
include/dt-bindings/clock/sophgo,sg2044-pll.h
Normal file
27
include/dt-bindings/clock/sophgo,sg2044-pll.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_SOPHGO_SG2044_PLL_H__
|
||||
#define __DT_BINDINGS_SOPHGO_SG2044_PLL_H__
|
||||
|
||||
#define CLK_FPLL0 0
|
||||
#define CLK_FPLL1 1
|
||||
#define CLK_FPLL2 2
|
||||
#define CLK_DPLL0 3
|
||||
#define CLK_DPLL1 4
|
||||
#define CLK_DPLL2 5
|
||||
#define CLK_DPLL3 6
|
||||
#define CLK_DPLL4 7
|
||||
#define CLK_DPLL5 8
|
||||
#define CLK_DPLL6 9
|
||||
#define CLK_DPLL7 10
|
||||
#define CLK_MPLL0 11
|
||||
#define CLK_MPLL1 12
|
||||
#define CLK_MPLL2 13
|
||||
#define CLK_MPLL3 14
|
||||
#define CLK_MPLL4 15
|
||||
#define CLK_MPLL5 16
|
||||
|
||||
#endif /* __DT_BINDINGS_SOPHGO_SG2044_PLL_H__ */
|
||||
247
include/dt-bindings/clock/spacemit,k1-syscon.h
Normal file
247
include/dt-bindings/clock/spacemit,k1-syscon.h
Normal file
@@ -0,0 +1,247 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Haylen Chu <heylenay@outlook.com>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_SPACEMIT_CCU_H_
|
||||
#define _DT_BINDINGS_SPACEMIT_CCU_H_
|
||||
|
||||
/* APBS (PLL) clocks */
|
||||
#define CLK_PLL1 0
|
||||
#define CLK_PLL2 1
|
||||
#define CLK_PLL3 2
|
||||
#define CLK_PLL1_D2 3
|
||||
#define CLK_PLL1_D3 4
|
||||
#define CLK_PLL1_D4 5
|
||||
#define CLK_PLL1_D5 6
|
||||
#define CLK_PLL1_D6 7
|
||||
#define CLK_PLL1_D7 8
|
||||
#define CLK_PLL1_D8 9
|
||||
#define CLK_PLL1_D11 10
|
||||
#define CLK_PLL1_D13 11
|
||||
#define CLK_PLL1_D23 12
|
||||
#define CLK_PLL1_D64 13
|
||||
#define CLK_PLL1_D10_AUD 14
|
||||
#define CLK_PLL1_D100_AUD 15
|
||||
#define CLK_PLL2_D1 16
|
||||
#define CLK_PLL2_D2 17
|
||||
#define CLK_PLL2_D3 18
|
||||
#define CLK_PLL2_D4 19
|
||||
#define CLK_PLL2_D5 20
|
||||
#define CLK_PLL2_D6 21
|
||||
#define CLK_PLL2_D7 22
|
||||
#define CLK_PLL2_D8 23
|
||||
#define CLK_PLL3_D1 24
|
||||
#define CLK_PLL3_D2 25
|
||||
#define CLK_PLL3_D3 26
|
||||
#define CLK_PLL3_D4 27
|
||||
#define CLK_PLL3_D5 28
|
||||
#define CLK_PLL3_D6 29
|
||||
#define CLK_PLL3_D7 30
|
||||
#define CLK_PLL3_D8 31
|
||||
#define CLK_PLL3_80 32
|
||||
#define CLK_PLL3_40 33
|
||||
#define CLK_PLL3_20 34
|
||||
|
||||
/* MPMU clocks */
|
||||
#define CLK_PLL1_307P2 0
|
||||
#define CLK_PLL1_76P8 1
|
||||
#define CLK_PLL1_61P44 2
|
||||
#define CLK_PLL1_153P6 3
|
||||
#define CLK_PLL1_102P4 4
|
||||
#define CLK_PLL1_51P2 5
|
||||
#define CLK_PLL1_51P2_AP 6
|
||||
#define CLK_PLL1_57P6 7
|
||||
#define CLK_PLL1_25P6 8
|
||||
#define CLK_PLL1_12P8 9
|
||||
#define CLK_PLL1_12P8_WDT 10
|
||||
#define CLK_PLL1_6P4 11
|
||||
#define CLK_PLL1_3P2 12
|
||||
#define CLK_PLL1_1P6 13
|
||||
#define CLK_PLL1_0P8 14
|
||||
#define CLK_PLL1_409P6 15
|
||||
#define CLK_PLL1_204P8 16
|
||||
#define CLK_PLL1_491 17
|
||||
#define CLK_PLL1_245P76 18
|
||||
#define CLK_PLL1_614 19
|
||||
#define CLK_PLL1_47P26 20
|
||||
#define CLK_PLL1_31P5 21
|
||||
#define CLK_PLL1_819 22
|
||||
#define CLK_PLL1_1228 23
|
||||
#define CLK_SLOW_UART 24
|
||||
#define CLK_SLOW_UART1 25
|
||||
#define CLK_SLOW_UART2 26
|
||||
#define CLK_WDT 27
|
||||
#define CLK_RIPC 28
|
||||
#define CLK_I2S_SYSCLK 29
|
||||
#define CLK_I2S_BCLK 30
|
||||
#define CLK_APB 31
|
||||
#define CLK_WDT_BUS 32
|
||||
|
||||
/* APBC clocks */
|
||||
#define CLK_UART0 0
|
||||
#define CLK_UART2 1
|
||||
#define CLK_UART3 2
|
||||
#define CLK_UART4 3
|
||||
#define CLK_UART5 4
|
||||
#define CLK_UART6 5
|
||||
#define CLK_UART7 6
|
||||
#define CLK_UART8 7
|
||||
#define CLK_UART9 8
|
||||
#define CLK_GPIO 9
|
||||
#define CLK_PWM0 10
|
||||
#define CLK_PWM1 11
|
||||
#define CLK_PWM2 12
|
||||
#define CLK_PWM3 13
|
||||
#define CLK_PWM4 14
|
||||
#define CLK_PWM5 15
|
||||
#define CLK_PWM6 16
|
||||
#define CLK_PWM7 17
|
||||
#define CLK_PWM8 18
|
||||
#define CLK_PWM9 19
|
||||
#define CLK_PWM10 20
|
||||
#define CLK_PWM11 21
|
||||
#define CLK_PWM12 22
|
||||
#define CLK_PWM13 23
|
||||
#define CLK_PWM14 24
|
||||
#define CLK_PWM15 25
|
||||
#define CLK_PWM16 26
|
||||
#define CLK_PWM17 27
|
||||
#define CLK_PWM18 28
|
||||
#define CLK_PWM19 29
|
||||
#define CLK_SSP3 30
|
||||
#define CLK_RTC 31
|
||||
#define CLK_TWSI0 32
|
||||
#define CLK_TWSI1 33
|
||||
#define CLK_TWSI2 34
|
||||
#define CLK_TWSI4 35
|
||||
#define CLK_TWSI5 36
|
||||
#define CLK_TWSI6 37
|
||||
#define CLK_TWSI7 38
|
||||
#define CLK_TWSI8 39
|
||||
#define CLK_TIMERS1 40
|
||||
#define CLK_TIMERS2 41
|
||||
#define CLK_AIB 42
|
||||
#define CLK_ONEWIRE 43
|
||||
#define CLK_SSPA0 44
|
||||
#define CLK_SSPA1 45
|
||||
#define CLK_DRO 46
|
||||
#define CLK_IR 47
|
||||
#define CLK_TSEN 48
|
||||
#define CLK_IPC_AP2AUD 49
|
||||
#define CLK_CAN0 50
|
||||
#define CLK_CAN0_BUS 51
|
||||
#define CLK_UART0_BUS 52
|
||||
#define CLK_UART2_BUS 53
|
||||
#define CLK_UART3_BUS 54
|
||||
#define CLK_UART4_BUS 55
|
||||
#define CLK_UART5_BUS 56
|
||||
#define CLK_UART6_BUS 57
|
||||
#define CLK_UART7_BUS 58
|
||||
#define CLK_UART8_BUS 59
|
||||
#define CLK_UART9_BUS 60
|
||||
#define CLK_GPIO_BUS 61
|
||||
#define CLK_PWM0_BUS 62
|
||||
#define CLK_PWM1_BUS 63
|
||||
#define CLK_PWM2_BUS 64
|
||||
#define CLK_PWM3_BUS 65
|
||||
#define CLK_PWM4_BUS 66
|
||||
#define CLK_PWM5_BUS 67
|
||||
#define CLK_PWM6_BUS 68
|
||||
#define CLK_PWM7_BUS 69
|
||||
#define CLK_PWM8_BUS 70
|
||||
#define CLK_PWM9_BUS 71
|
||||
#define CLK_PWM10_BUS 72
|
||||
#define CLK_PWM11_BUS 73
|
||||
#define CLK_PWM12_BUS 74
|
||||
#define CLK_PWM13_BUS 75
|
||||
#define CLK_PWM14_BUS 76
|
||||
#define CLK_PWM15_BUS 77
|
||||
#define CLK_PWM16_BUS 78
|
||||
#define CLK_PWM17_BUS 79
|
||||
#define CLK_PWM18_BUS 80
|
||||
#define CLK_PWM19_BUS 81
|
||||
#define CLK_SSP3_BUS 82
|
||||
#define CLK_RTC_BUS 83
|
||||
#define CLK_TWSI0_BUS 84
|
||||
#define CLK_TWSI1_BUS 85
|
||||
#define CLK_TWSI2_BUS 86
|
||||
#define CLK_TWSI4_BUS 87
|
||||
#define CLK_TWSI5_BUS 88
|
||||
#define CLK_TWSI6_BUS 89
|
||||
#define CLK_TWSI7_BUS 90
|
||||
#define CLK_TWSI8_BUS 91
|
||||
#define CLK_TIMERS1_BUS 92
|
||||
#define CLK_TIMERS2_BUS 93
|
||||
#define CLK_AIB_BUS 94
|
||||
#define CLK_ONEWIRE_BUS 95
|
||||
#define CLK_SSPA0_BUS 96
|
||||
#define CLK_SSPA1_BUS 97
|
||||
#define CLK_TSEN_BUS 98
|
||||
#define CLK_IPC_AP2AUD_BUS 99
|
||||
|
||||
/* APMU clocks */
|
||||
#define CLK_CCI550 0
|
||||
#define CLK_CPU_C0_HI 1
|
||||
#define CLK_CPU_C0_CORE 2
|
||||
#define CLK_CPU_C0_ACE 3
|
||||
#define CLK_CPU_C0_TCM 4
|
||||
#define CLK_CPU_C1_HI 5
|
||||
#define CLK_CPU_C1_CORE 6
|
||||
#define CLK_CPU_C1_ACE 7
|
||||
#define CLK_CCIC_4X 8
|
||||
#define CLK_CCIC1PHY 9
|
||||
#define CLK_SDH_AXI 10
|
||||
#define CLK_SDH0 11
|
||||
#define CLK_SDH1 12
|
||||
#define CLK_SDH2 13
|
||||
#define CLK_USB_P1 14
|
||||
#define CLK_USB_AXI 15
|
||||
#define CLK_USB30 16
|
||||
#define CLK_QSPI 17
|
||||
#define CLK_QSPI_BUS 18
|
||||
#define CLK_DMA 19
|
||||
#define CLK_AES 20
|
||||
#define CLK_VPU 21
|
||||
#define CLK_GPU 22
|
||||
#define CLK_EMMC 23
|
||||
#define CLK_EMMC_X 24
|
||||
#define CLK_AUDIO 25
|
||||
#define CLK_HDMI 26
|
||||
#define CLK_PMUA_ACLK 27
|
||||
#define CLK_PCIE0_MASTER 28
|
||||
#define CLK_PCIE0_SLAVE 29
|
||||
#define CLK_PCIE0_DBI 30
|
||||
#define CLK_PCIE1_MASTER 31
|
||||
#define CLK_PCIE1_SLAVE 32
|
||||
#define CLK_PCIE1_DBI 33
|
||||
#define CLK_PCIE2_MASTER 34
|
||||
#define CLK_PCIE2_SLAVE 35
|
||||
#define CLK_PCIE2_DBI 36
|
||||
#define CLK_EMAC0_BUS 37
|
||||
#define CLK_EMAC0_PTP 38
|
||||
#define CLK_EMAC1_BUS 39
|
||||
#define CLK_EMAC1_PTP 40
|
||||
#define CLK_JPG 41
|
||||
#define CLK_CCIC2PHY 42
|
||||
#define CLK_CCIC3PHY 43
|
||||
#define CLK_CSI 44
|
||||
#define CLK_CAMM0 45
|
||||
#define CLK_CAMM1 46
|
||||
#define CLK_CAMM2 47
|
||||
#define CLK_ISP_CPP 48
|
||||
#define CLK_ISP_BUS 49
|
||||
#define CLK_ISP 50
|
||||
#define CLK_DPU_MCLK 51
|
||||
#define CLK_DPU_ESC 52
|
||||
#define CLK_DPU_BIT 53
|
||||
#define CLK_DPU_PXCLK 54
|
||||
#define CLK_DPU_HCLK 55
|
||||
#define CLK_DPU_SPI 56
|
||||
#define CLK_DPU_SPI_HBUS 57
|
||||
#define CLK_DPU_SPIBUS 58
|
||||
#define CLK_DPU_SPI_ACLK 59
|
||||
#define CLK_V2D 60
|
||||
#define CLK_EMMC_BUS 61
|
||||
|
||||
#endif /* _DT_BINDINGS_SPACEMIT_CCU_H_ */
|
||||
@@ -93,4 +93,38 @@
|
||||
#define CLK_SRAM3 83
|
||||
#define CLK_PLL_GMAC_100M 84
|
||||
#define CLK_UART_SCLK 85
|
||||
|
||||
/* VO clocks */
|
||||
#define CLK_AXI4_VO_ACLK 0
|
||||
#define CLK_GPU_MEM 1
|
||||
#define CLK_GPU_CORE 2
|
||||
#define CLK_GPU_CFG_ACLK 3
|
||||
#define CLK_DPU_PIXELCLK0 4
|
||||
#define CLK_DPU_PIXELCLK1 5
|
||||
#define CLK_DPU_HCLK 6
|
||||
#define CLK_DPU_ACLK 7
|
||||
#define CLK_DPU_CCLK 8
|
||||
#define CLK_HDMI_SFR 9
|
||||
#define CLK_HDMI_PCLK 10
|
||||
#define CLK_HDMI_CEC 11
|
||||
#define CLK_MIPI_DSI0_PCLK 12
|
||||
#define CLK_MIPI_DSI1_PCLK 13
|
||||
#define CLK_MIPI_DSI0_CFG 14
|
||||
#define CLK_MIPI_DSI1_CFG 15
|
||||
#define CLK_MIPI_DSI0_REFCLK 16
|
||||
#define CLK_MIPI_DSI1_REFCLK 17
|
||||
#define CLK_HDMI_I2S 18
|
||||
#define CLK_X2H_DPU1_ACLK 19
|
||||
#define CLK_X2H_DPU_ACLK 20
|
||||
#define CLK_AXI4_VO_PCLK 21
|
||||
#define CLK_IOPMP_VOSYS_DPU_PCLK 22
|
||||
#define CLK_IOPMP_VOSYS_DPU1_PCLK 23
|
||||
#define CLK_IOPMP_VOSYS_GPU_PCLK 24
|
||||
#define CLK_IOPMP_DPU1_ACLK 25
|
||||
#define CLK_IOPMP_DPU_ACLK 26
|
||||
#define CLK_IOPMP_GPU_ACLK 27
|
||||
#define CLK_MIPIDSI0_PIXCLK 28
|
||||
#define CLK_MIPIDSI1_PIXCLK 29
|
||||
#define CLK_HDMI_PIXCLK 30
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,5 +69,6 @@
|
||||
#define RST_BUS_GPADC 60
|
||||
#define RST_BUS_TCON_LCD0 61
|
||||
#define RST_BUS_TCON_LCD1 62
|
||||
#define RST_BUS_LVDS 63
|
||||
|
||||
#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
|
||||
|
||||
@@ -6,6 +6,7 @@ struct clk;
|
||||
struct clk_hw;
|
||||
struct device;
|
||||
struct device_node;
|
||||
struct of_phandle_args;
|
||||
struct kunit;
|
||||
|
||||
struct clk *
|
||||
|
||||
Reference in New Issue
Block a user