mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 12:52:30 +00:00
We have a couple patches in the framework core this time around but
they're mostly minor cleanups and some debugfs stuff. The real work that's in here is the typical pile of clk driver updates and new SoC support. Per usual (or maybe just recent trends), Qualcomm gains a handful of SoC drivers additions and has the largest diffstat. After that there are quite a few updates to the Allwinner (sunxi) drivers to support modular drivers and Renesas is heavily updated to add more support for various clks. Overall it looks pretty normal. New Drivers: - Add MDMA and BDMA clks to Ingenic JZ4760 and JZ4770 - MediaTek mt7986 SoC basic support - Clock and reset driver for Toshiba Visconti SoCs - Initial clock driver for the Exynos7885 SoC (Samsung Galaxy A8) - Allwinner D1 clks - Lan966x Generic Clock Controller driver and associated DT bindings - Qualcomm SDX65, SM8450, and MSM8976 GCC clks - Qualcomm SDX65 and SM8450 RPMh clks Updates: - Set suppress_bind_attrs to true for i.MX8ULP driver - Switch from do_div to div64_ul for throughout all i.MX drivers - Fix imx8mn_clko1_sels for i.MX8MN - Remove unused IPG_AUDIO_ROOT from i.MX8MP - Switch parent for audio_root_clk to audio ahb in i.MX8MP driver - Removal of all remaining uses of __clk_lookup() in drivers/clk/samsung - Refactoring of the CPU clocks registration to use common interface - An update of the Exynos850 driver (support for more clock domains) required by the E850-96 development board - Prep for runtime PM and generic power domains on Tegra - Support modular Allwinner clk drivers via platform bus - Lan966x clock driver extended to support clock gating - Add serial (SCI1), watchdog (WDT), timer (OSTM), SPI (RSPI), and thermal (TSU) clocks and resets on Renesas RZ/G2L - Rework SDHI clock handling in the Renesas R-Car Gen3 and RZ/G2 clock drivers, and in the Renesas SDHI driver - Make the Cortex-A55 (I) clock on Renesas RZ/G2L programmable - Document support for the new Renesas R-Car S4-8 (R8A779F0) SoC - Add support for the new Renesas R-Car S4-8 (R8A779F0) SoC - Add GPU clock and resets on Renesas RZ/G2L - Add clk-provider.h to various Qualcomm clk drivers - devm version of clk_hw_register_gate() - kerneldoc fixes in a couple drivers -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAmHfOa8RHHNib3lkQGtl cm5lbC5vcmcACgkQrQKIl8bklSX+Ew/9FaQLRh3ahN+qF8VMJ1K9qUciYBlU+UtC excKfTkJg+1JGMP8dGSRSi/aC/UyLPb0dJDRMKcSZPYIScP+wc3HJHm4i+CpxDcn /wXPW3tvY1CkVq1P7/baesoNiIle5zqpl4+0w9CN5KuoXctc35Pr1GqJ/C0XsDfQ DS3lpck65tr7Wy1muChT1ZR+7hGv6K7olR7FDYNVSDtfJcaOZENSLgbPF6eea0FR /dl+6o1COF23XAGF1GJg88DYRgnEqxLsfFTaC6Hz8DeQdKBVh9GF6tpgLhk7vsaG gcRZxU24KaUw0lNZGdzmagy8ZJ6aZhcuzXQKN9VecbTIhRYNTWmB1VsvbhhEVb1T 96kBAp/II1JZdh/8W7uOmg4Ahupap5+f6JKMfR3zD4aDXkNDsxyXBA5AXtC0GPGN 5340WiJsBz/dD9/YE+mQ7YZKhdvKaGEVbmVUpQHceapeTBk4EIHKSVIq5sKd7qiq ZHxOIizx5MgBJyoSeIxkB3j0KvwSTDNz6WM2F9gnNNtGfuSlA4NAnO1davINNQun +seP+deBviUl+P2u9iodRApfCiEuM3mA548KTba/Z1nJ7sN93/qrqr1FBAUSqY+k xNRXfXIzlOY9ifm6PlvU8QUK0XVtKjt0ld7pFzRkf6EU523DwzL2I2XIY2Eve2vA LaDihwcKyR0= =jB+l -----END PGP SIGNATURE----- Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux Pull clk updates from Stephen Boyd: "We have a couple patches in the framework core this time around but they're mostly minor cleanups and some debugfs stuff. The real work that's in here is the typical pile of clk driver updates and new SoC support. Per usual (or maybe just recent trends), Qualcomm gains a handful of SoC drivers additions and has the largest diffstat. After that there are quite a few updates to the Allwinner (sunxi) drivers to support modular drivers and Renesas is heavily updated to add more support for various clks. Overall it looks pretty normal. New Drivers: - Add MDMA and BDMA clks to Ingenic JZ4760 and JZ4770 - MediaTek mt7986 SoC basic support - Clock and reset driver for Toshiba Visconti SoCs - Initial clock driver for the Exynos7885 SoC (Samsung Galaxy A8) - Allwinner D1 clks - Lan966x Generic Clock Controller driver and associated DT bindings - Qualcomm SDX65, SM8450, and MSM8976 GCC clks - Qualcomm SDX65 and SM8450 RPMh clks Updates: - Set suppress_bind_attrs to true for i.MX8ULP driver - Switch from do_div to div64_ul for throughout all i.MX drivers - Fix imx8mn_clko1_sels for i.MX8MN - Remove unused IPG_AUDIO_ROOT from i.MX8MP - Switch parent for audio_root_clk to audio ahb in i.MX8MP driver - Removal of all remaining uses of __clk_lookup() in drivers/clk/samsung - Refactoring of the CPU clocks registration to use common interface - An update of the Exynos850 driver (support for more clock domains) required by the E850-96 development board - Prep for runtime PM and generic power domains on Tegra - Support modular Allwinner clk drivers via platform bus - Lan966x clock driver extended to support clock gating - Add serial (SCI1), watchdog (WDT), timer (OSTM), SPI (RSPI), and thermal (TSU) clocks and resets on Renesas RZ/G2L - Rework SDHI clock handling in the Renesas R-Car Gen3 and RZ/G2 clock drivers, and in the Renesas SDHI driver - Make the Cortex-A55 (I) clock on Renesas RZ/G2L programmable - Document support for the new Renesas R-Car S4-8 (R8A779F0) SoC - Add support for the new Renesas R-Car S4-8 (R8A779F0) SoC - Add GPU clock and resets on Renesas RZ/G2L - Add clk-provider.h to various Qualcomm clk drivers - devm version of clk_hw_register_gate() - kerneldoc fixes in a couple drivers" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (131 commits) clk: visconti: Remove pointless NULL check in visconti_pll_add_lookup() clk: mediatek: add mt7986 clock support clk: mediatek: add mt7986 clock IDs dt-bindings: clock: mediatek: document clk bindings for mediatek mt7986 SoC clk: mediatek: clk-gate: Use regmap_{set/clear}_bits helpers clk: mediatek: clk-gate: Shrink by adding clockgating bit check helper clk: x86: Fix clk_gate_flags for RV_CLK_GATE clk: x86: Use dynamic con_id string during clk registration ACPI: APD: Add a fmw property clk-name drivers: acpi: acpi_apd: Remove unused device property "is-rv" x86: clk: clk-fch: Add support for newer family of AMD's SOC clk: ingenic: Add MDMA and BDMA clocks dt-bindings: clk/ingenic: Add MDMA and BDMA clocks clk: bm1880: remove kfrees on static allocations clk: Drop unused COMMON_CLK_STM32MP157_SCMI config clk: st: clkgen-mux: search reg within node or parent clk: st: clkgen-fsyn: search reg within node or parent clk: Enable/Disable runtime PM for clk_summary MAINTAINERS: Add entries for Toshiba Visconti PLL and clock controller clk: visconti: Add support common clock driver and reset driver ...
This commit is contained in:
commit
455e73a07f
@ -14,6 +14,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-apmixedsys"
|
||||
- "mediatek,mt7623-apmixedsys", "mediatek,mt2701-apmixedsys"
|
||||
- "mediatek,mt7629-apmixedsys"
|
||||
- "mediatek,mt7986-apmixedsys"
|
||||
- "mediatek,mt8135-apmixedsys"
|
||||
- "mediatek,mt8167-apmixedsys", "syscon"
|
||||
- "mediatek,mt8173-apmixedsys"
|
||||
|
@ -10,6 +10,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-ethsys", "syscon"
|
||||
- "mediatek,mt7623-ethsys", "mediatek,mt2701-ethsys", "syscon"
|
||||
- "mediatek,mt7629-ethsys", "syscon"
|
||||
- "mediatek,mt7986-ethsys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
- #reset-cells: Must be 1
|
||||
|
||||
|
@ -15,6 +15,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-infracfg", "syscon"
|
||||
- "mediatek,mt7623-infracfg", "mediatek,mt2701-infracfg", "syscon"
|
||||
- "mediatek,mt7629-infracfg", "syscon"
|
||||
- "mediatek,mt7986-infracfg", "syscon"
|
||||
- "mediatek,mt8135-infracfg", "syscon"
|
||||
- "mediatek,mt8167-infracfg", "syscon"
|
||||
- "mediatek,mt8173-infracfg", "syscon"
|
||||
|
@ -8,6 +8,8 @@ Required Properties:
|
||||
- compatible: Should be:
|
||||
- "mediatek,mt7622-sgmiisys", "syscon"
|
||||
- "mediatek,mt7629-sgmiisys", "syscon"
|
||||
- "mediatek,mt7986-sgmiisys_0", "syscon"
|
||||
- "mediatek,mt7986-sgmiisys_1", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
The SGMIISYS controller uses the common clk binding from
|
||||
|
@ -14,6 +14,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-topckgen"
|
||||
- "mediatek,mt7623-topckgen", "mediatek,mt2701-topckgen"
|
||||
- "mediatek,mt7629-topckgen"
|
||||
- "mediatek,mt7986-topckgen", "syscon"
|
||||
- "mediatek,mt8135-topckgen"
|
||||
- "mediatek,mt8167-topckgen", "syscon"
|
||||
- "mediatek,mt8173-topckgen"
|
||||
|
@ -34,6 +34,8 @@ properties:
|
||||
- allwinner,sun8i-v3-ccu
|
||||
- allwinner,sun8i-v3s-ccu
|
||||
- allwinner,sun9i-a80-ccu
|
||||
- allwinner,sun20i-d1-ccu
|
||||
- allwinner,sun20i-d1-r-ccu
|
||||
- allwinner,sun50i-a64-ccu
|
||||
- allwinner,sun50i-a64-r-ccu
|
||||
- allwinner,sun50i-a100-ccu
|
||||
@ -79,6 +81,7 @@ if:
|
||||
enum:
|
||||
- allwinner,sun8i-a83t-r-ccu
|
||||
- allwinner,sun8i-h3-r-ccu
|
||||
- allwinner,sun20i-d1-r-ccu
|
||||
- allwinner,sun50i-a64-r-ccu
|
||||
- allwinner,sun50i-a100-r-ccu
|
||||
- allwinner,sun50i-h6-r-ccu
|
||||
@ -99,6 +102,7 @@ else:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun20i-d1-ccu
|
||||
- allwinner,sun50i-a100-ccu
|
||||
- allwinner,sun50i-h6-ccu
|
||||
- allwinner,sun50i-h616-ccu
|
||||
|
@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/microchip,lan966x-gck.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip LAN966X Generic Clock Controller
|
||||
|
||||
maintainers:
|
||||
- Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
|
||||
|
||||
description: |
|
||||
The LAN966X Generic clock controller contains 3 PLLs - cpu_clk,
|
||||
ddr_clk and sys_clk. This clock controller generates and supplies
|
||||
clock to various peripherals within the SoC.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,lan966x-gck
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Generic clock registers
|
||||
- description: Optional gate clock registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: CPU clock source
|
||||
- description: DDR clock source
|
||||
- description: System clock source
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: cpu
|
||||
- const: ddr
|
||||
- const: sys
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clks: clock-controller@e00c00a8 {
|
||||
compatible = "microchip,lan966x-gck";
|
||||
#clock-cells = <1>;
|
||||
clocks = <&cpu_clk>, <&ddr_clk>, <&sys_clk>;
|
||||
clock-names = "cpu", "ddr", "sys";
|
||||
reg = <0xe00c00a8 0x38>;
|
||||
};
|
||||
...
|
@ -0,0 +1,97 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8976.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Global Clock & Reset Controller Binding for MSM8976
|
||||
|
||||
maintainers:
|
||||
- Stephen Boyd <sboyd@kernel.org>
|
||||
- Taniya Das <tdas@codeaurora.org>
|
||||
|
||||
description: |
|
||||
Qualcomm global clock control module which supports the clocks, resets and
|
||||
power domains on MSM8976.
|
||||
|
||||
See also:
|
||||
- dt-bindings/clock/qcom,gcc-msm8976.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,gcc-msm8976
|
||||
- qcom,gcc-msm8976-v1.1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO source
|
||||
- description: Always-on XO source
|
||||
- description: Pixel clock from DSI PHY0
|
||||
- description: Byte clock from DSI PHY0
|
||||
- description: Pixel clock from DSI PHY1
|
||||
- description: Byte clock from DSI PHY1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
- const: xo_a
|
||||
- const: dsi0pll
|
||||
- const: dsi0pllbyte
|
||||
- const: dsi1pll
|
||||
- const: dsi1pllbyte
|
||||
|
||||
vdd_gfx-supply:
|
||||
description:
|
||||
Phandle to voltage regulator providing power to the GX domain.
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- vdd_gfx-supply
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
- '#power-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@1800000 {
|
||||
compatible = "qcom,gcc-msm8976";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
reg = <0x1800000 0x80000>;
|
||||
|
||||
clocks = <&xo_board>,
|
||||
<&xo_board>,
|
||||
<&dsi0_phy 1>,
|
||||
<&dsi0_phy 0>,
|
||||
<&dsi1_phy 1>,
|
||||
<&dsi1_phy 0>;
|
||||
|
||||
clock-names = "xo",
|
||||
"xo_a",
|
||||
"dsi0pll",
|
||||
"dsi0pllbyte",
|
||||
"dsi1pll",
|
||||
"dsi1pllbyte";
|
||||
|
||||
vdd_gfx-supply = <&pm8004_s5>;
|
||||
};
|
||||
...
|
@ -22,10 +22,12 @@ properties:
|
||||
- qcom,sc8180x-rpmh-clk
|
||||
- qcom,sdm845-rpmh-clk
|
||||
- qcom,sdx55-rpmh-clk
|
||||
- qcom,sdx65-rpmh-clk
|
||||
- qcom,sm6350-rpmh-clk
|
||||
- qcom,sm8150-rpmh-clk
|
||||
- qcom,sm8250-rpmh-clk
|
||||
- qcom,sm8350-rpmh-clk
|
||||
- qcom,sm8450-rpmh-clk
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
@ -48,6 +48,7 @@ properties:
|
||||
- renesas,r8a77990-cpg-mssr # R-Car E3
|
||||
- renesas,r8a77995-cpg-mssr # R-Car D3
|
||||
- renesas,r8a779a0-cpg-mssr # R-Car V3U
|
||||
- renesas,r8a779f0-cpg-mssr # R-Car S4-8
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -0,0 +1,166 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/samsung,exynos7885-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung Exynos7885 SoC clock controller
|
||||
|
||||
maintainers:
|
||||
- Dávid Virág <virag.david003@gmail.com>
|
||||
- Chanwoo Choi <cw00.choi@samsung.com>
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
- Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
- Tomasz Figa <tomasz.figa@gmail.com>
|
||||
|
||||
description: |
|
||||
Exynos7885 clock controller is comprised of several CMU units, generating
|
||||
clocks for different domains. Those CMU units are modeled as separate device
|
||||
tree nodes, and might depend on each other. The root clock in that root tree
|
||||
is an external clock: OSCCLK (26 MHz). This external clock must be defined
|
||||
as a fixed-rate clock in dts.
|
||||
|
||||
CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
|
||||
dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All clocks available for usage
|
||||
in clock consumer nodes are defined as preprocessor macros in
|
||||
'dt-bindings/clock/exynos7885.h' header.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- samsung,exynos7885-cmu-top
|
||||
- samsung,exynos7885-cmu-core
|
||||
- samsung,exynos7885-cmu-peri
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 10
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 10
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7885-cmu-top
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7885-cmu-core
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_CORE bus clock (from CMU_TOP)
|
||||
- description: CCI clock (from CMU_TOP)
|
||||
- description: G3D clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_core_bus
|
||||
- const: dout_core_cci
|
||||
- const: dout_core_g3d
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7885-cmu-peri
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_PERI bus clock (from CMU_TOP)
|
||||
- description: SPI0 clock (from CMU_TOP)
|
||||
- description: SPI1 clock (from CMU_TOP)
|
||||
- description: UART0 clock (from CMU_TOP)
|
||||
- description: UART1 clock (from CMU_TOP)
|
||||
- description: UART2 clock (from CMU_TOP)
|
||||
- description: USI0 clock (from CMU_TOP)
|
||||
- description: USI1 clock (from CMU_TOP)
|
||||
- description: USI2 clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_peri_bus
|
||||
- const: dout_peri_spi0
|
||||
- const: dout_peri_spi1
|
||||
- const: dout_peri_uart0
|
||||
- const: dout_peri_uart1
|
||||
- const: dout_peri_uart2
|
||||
- const: dout_peri_usi0
|
||||
- const: dout_peri_usi1
|
||||
- const: dout_peri_usi2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Clock controller node for CMU_PERI
|
||||
- |
|
||||
#include <dt-bindings/clock/exynos7885.h>
|
||||
|
||||
cmu_peri: clock-controller@10010000 {
|
||||
compatible = "samsung,exynos7885-cmu-peri";
|
||||
reg = <0x10010000 0x8000>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&oscclk>,
|
||||
<&cmu_top CLK_DOUT_PERI_BUS>,
|
||||
<&cmu_top CLK_DOUT_PERI_SPI0>,
|
||||
<&cmu_top CLK_DOUT_PERI_SPI1>,
|
||||
<&cmu_top CLK_DOUT_PERI_UART0>,
|
||||
<&cmu_top CLK_DOUT_PERI_UART1>,
|
||||
<&cmu_top CLK_DOUT_PERI_UART2>,
|
||||
<&cmu_top CLK_DOUT_PERI_USI0>,
|
||||
<&cmu_top CLK_DOUT_PERI_USI1>,
|
||||
<&cmu_top CLK_DOUT_PERI_USI2>;
|
||||
clock-names = "oscclk",
|
||||
"dout_peri_bus",
|
||||
"dout_peri_spi0",
|
||||
"dout_peri_spi1",
|
||||
"dout_peri_uart0",
|
||||
"dout_peri_uart1",
|
||||
"dout_peri_uart2",
|
||||
"dout_peri_usi0",
|
||||
"dout_peri_usi1",
|
||||
"dout_peri_usi2";
|
||||
};
|
||||
|
||||
...
|
@ -32,6 +32,8 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- samsung,exynos850-cmu-top
|
||||
- samsung,exynos850-cmu-apm
|
||||
- samsung,exynos850-cmu-cmgp
|
||||
- samsung,exynos850-cmu-core
|
||||
- samsung,exynos850-cmu-dpu
|
||||
- samsung,exynos850-cmu-hsi
|
||||
@ -68,6 +70,42 @@ allOf:
|
||||
items:
|
||||
- const: oscclk
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos850-cmu-apm
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_APM bus clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_clkcmu_apm_bus
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos850-cmu-cmgp
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_CMGP bus clock (from CMU_APM)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: gout_clkcmu_cmgp_bus
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -0,0 +1,57 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/toshiba,tmpv770x-pipllct.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Toshiba Visconti5 TMPV770X PLL Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
|
||||
description:
|
||||
Toshia Visconti5 PLL controller which supports the PLLs on TMPV770X.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: toshiba,tmpv7708-pipllct
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
description: External reference clock (OSC2)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
osc2_clk: osc2-clk {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <20000000>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pipllct: clock-controller@24220000 {
|
||||
compatible = "toshiba,tmpv7708-pipllct";
|
||||
reg = <0 0x24220000 0 0x820>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc2_clk>;
|
||||
};
|
||||
};
|
||||
...
|
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/toshiba,tmpv770x-pismu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Toshiba Visconti5 TMPV770x SMU controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
|
||||
description:
|
||||
Toshia Visconti5 SMU (System Management Unit) which supports the clock
|
||||
and resets on TMPV770x.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: toshiba,tmpv7708-pismu
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- "#reset-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pismu: syscon@24200000 {
|
||||
compatible = "toshiba,tmpv7708-pismu", "syscon";
|
||||
reg = <0 0x24200000 0 0x2140>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
12
MAINTAINERS
12
MAINTAINERS
@ -2807,12 +2807,15 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwamatsu/linux-visconti.git
|
||||
F: Documentation/devicetree/bindings/arm/toshiba.yaml
|
||||
F: Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pipllct.yaml
|
||||
F: Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pismu.yaml
|
||||
F: Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
|
||||
F: Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
|
||||
F: Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml
|
||||
F: Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
|
||||
F: arch/arm64/boot/dts/toshiba/
|
||||
F: drivers/clk/visconti/
|
||||
F: drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
|
||||
F: drivers/gpio/gpio-visconti.c
|
||||
F: drivers/pci/controller/dwc/pcie-visconti.c
|
||||
@ -15868,6 +15871,15 @@ F: Documentation/admin-guide/media/qcom_camss.rst
|
||||
F: Documentation/devicetree/bindings/media/*camss*
|
||||
F: drivers/media/platform/qcom/camss/
|
||||
|
||||
QUALCOMM CLOCK DRIVERS
|
||||
M: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
|
||||
F: Documentation/devicetree/bindings/clock/qcom,*
|
||||
F: drivers/clk/qcom/
|
||||
F: include/dt-bindings/clock/qcom,*
|
||||
|
||||
QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER
|
||||
M: Niklas Cassel <nks@flawful.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
|
@ -87,8 +87,15 @@ static int fch_misc_setup(struct apd_private_data *pdata)
|
||||
if (ret < 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (!acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, &obj))
|
||||
clk_data->is_rv = obj->integer.value;
|
||||
if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {
|
||||
clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,
|
||||
GFP_KERNEL);
|
||||
|
||||
strcpy(clk_data->name, obj->string.pointer);
|
||||
} else {
|
||||
/* Set default name to mclk if entry missing in firmware */
|
||||
clk_data->name = "mclk";
|
||||
}
|
||||
|
||||
list_for_each_entry(rentry, &resource_list, node) {
|
||||
clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,
|
||||
|
@ -169,6 +169,14 @@ config COMMON_CLK_CDCE706
|
||||
help
|
||||
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
|
||||
|
||||
config COMMON_CLK_TPS68470
|
||||
tristate "Clock Driver for TI TPS68470 PMIC"
|
||||
depends on I2C
|
||||
depends on INTEL_SKL_INT3472 || COMPILE_TEST
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports the clocks provided by the TPS68470 PMIC.
|
||||
|
||||
config COMMON_CLK_CDCE925
|
||||
tristate "Clock driver for TI CDCE913/925/937/949 devices"
|
||||
depends on I2C
|
||||
@ -221,6 +229,13 @@ config COMMON_CLK_GEMINI
|
||||
This driver supports the SoC clocks on the Cortina Systems Gemini
|
||||
platform, also known as SL3516 or CS3516.
|
||||
|
||||
config COMMON_CLK_LAN966X
|
||||
bool "Generic Clock Controller driver for LAN966X SoC"
|
||||
help
|
||||
This driver provides support for Generic Clock Controller(GCK) on
|
||||
LAN966X SoC. GCK generates and supplies clock to various peripherals
|
||||
within the SoC.
|
||||
|
||||
config COMMON_CLK_ASPEED
|
||||
bool "Clock driver for Aspeed BMC SoCs"
|
||||
depends on ARCH_ASPEED || COMPILE_TEST
|
||||
@ -339,16 +354,6 @@ config COMMON_CLK_STM32MP157
|
||||
help
|
||||
Support for stm32mp157 SoC family clocks
|
||||
|
||||
config COMMON_CLK_STM32MP157_SCMI
|
||||
bool "stm32mp157 Clock driver with Trusted Firmware"
|
||||
depends on COMMON_CLK_STM32MP157
|
||||
select COMMON_CLK_SCMI
|
||||
select ARM_SCMI_PROTOCOL
|
||||
default y
|
||||
help
|
||||
Support for stm32mp157 SoC family clocks with Trusted Firmware using
|
||||
SCMI protocol.
|
||||
|
||||
config COMMON_CLK_STM32F
|
||||
def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746)
|
||||
help
|
||||
@ -418,6 +423,7 @@ source "drivers/clk/sunxi-ng/Kconfig"
|
||||
source "drivers/clk/tegra/Kconfig"
|
||||
source "drivers/clk/ti/Kconfig"
|
||||
source "drivers/clk/uniphier/Kconfig"
|
||||
source "drivers/clk/visconti/Kconfig"
|
||||
source "drivers/clk/x86/Kconfig"
|
||||
source "drivers/clk/xilinx/Kconfig"
|
||||
source "drivers/clk/zynqmp/Kconfig"
|
||||
|
@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
|
||||
obj-$(CONFIG_COMMON_CLK_K210) += clk-k210.o
|
||||
obj-$(CONFIG_LMK04832) += clk-lmk04832.o
|
||||
obj-$(CONFIG_COMMON_CLK_LAN966X) += clk-lan966x.o
|
||||
obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o
|
||||
@ -63,6 +64,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
|
||||
obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
|
||||
obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
|
||||
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
|
||||
obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o
|
||||
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
|
||||
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
|
||||
obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o
|
||||
@ -111,12 +113,13 @@ obj-y += sprd/
|
||||
obj-$(CONFIG_ARCH_STI) += st/
|
||||
obj-$(CONFIG_SOC_STARFIVE) += starfive/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/
|
||||
obj-y += sunxi-ng/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-y += ti/
|
||||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||
obj-y += versatile/
|
||||
obj-$(CONFIG_COMMON_CLK_VISCONTI) += visconti/
|
||||
ifeq ($(CONFIG_COMMON_CLK), y)
|
||||
obj-$(CONFIG_X86) += x86/
|
||||
endif
|
||||
|
@ -522,14 +522,6 @@ static struct clk_hw *bm1880_clk_register_pll(struct bm1880_pll_hw_clock *pll_cl
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void bm1880_clk_unregister_pll(struct clk_hw *hw)
|
||||
{
|
||||
struct bm1880_pll_hw_clock *pll_hw = to_bm1880_pll_clk(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(pll_hw);
|
||||
}
|
||||
|
||||
static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,
|
||||
int num_clks,
|
||||
struct bm1880_clock_data *data)
|
||||
@ -555,7 +547,7 @@ static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,
|
||||
|
||||
err_clk:
|
||||
while (i--)
|
||||
bm1880_clk_unregister_pll(data->hw_data.hws[clks[i].pll.id]);
|
||||
clk_hw_unregister(data->hw_data.hws[clks[i].pll.id]);
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
@ -695,14 +687,6 @@ static struct clk_hw *bm1880_clk_register_div(struct bm1880_div_hw_clock *div_cl
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void bm1880_clk_unregister_div(struct clk_hw *hw)
|
||||
{
|
||||
struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(div_hw);
|
||||
}
|
||||
|
||||
static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,
|
||||
int num_clks,
|
||||
struct bm1880_clock_data *data)
|
||||
@ -729,7 +713,7 @@ static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,
|
||||
|
||||
err_clk:
|
||||
while (i--)
|
||||
bm1880_clk_unregister_div(data->hw_data.hws[clks[i].div.id]);
|
||||
clk_hw_unregister(data->hw_data.hws[clks[i].div.id]);
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
@ -222,3 +223,37 @@ void clk_hw_unregister_gate(struct clk_hw *hw)
|
||||
kfree(gate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_gate);
|
||||
|
||||
static void devm_clk_hw_release_gate(struct device *dev, void *res)
|
||||
{
|
||||
clk_hw_unregister_gate(*(struct clk_hw **)res);
|
||||
}
|
||||
|
||||
struct clk_hw *__devm_clk_hw_register_gate(struct device *dev,
|
||||
struct device_node *np, const char *name,
|
||||
const char *parent_name, const struct clk_hw *parent_hw,
|
||||
const struct clk_parent_data *parent_data,
|
||||
unsigned long flags,
|
||||
void __iomem *reg, u8 bit_idx,
|
||||
u8 clk_gate_flags, spinlock_t *lock)
|
||||
{
|
||||
struct clk_hw **ptr, *hw;
|
||||
|
||||
ptr = devres_alloc(devm_clk_hw_release_gate, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hw = __clk_hw_register_gate(dev, np, name, parent_name, parent_hw,
|
||||
parent_data, flags, reg, bit_idx,
|
||||
clk_gate_flags, lock);
|
||||
|
||||
if (!IS_ERR(hw)) {
|
||||
*ptr = hw;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_clk_hw_register_gate);
|
||||
|
@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(gemini_clk_lock);
|
||||
#define PCI_DLL_TAP_SEL_MASK 0x1f
|
||||
|
||||
/**
|
||||
* struct gemini_data_data - Gemini gated clocks
|
||||
* struct gemini_gate_data - Gemini gated clocks
|
||||
* @bit_idx: the bit used to gate this clock in the clock register
|
||||
* @name: the clock name
|
||||
* @parent_name: the name of the parent clock
|
||||
|
293
drivers/clk/clk-lan966x.c
Normal file
293
drivers/clk/clk-lan966x.c
Normal file
@ -0,0 +1,293 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Microchip LAN966x SoC Clock driver.
|
||||
*
|
||||
* Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
|
||||
*
|
||||
* Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/microchip,lan966x.h>
|
||||
|
||||
#define GCK_ENA BIT(0)
|
||||
#define GCK_SRC_SEL GENMASK(9, 8)
|
||||
#define GCK_PRESCALER GENMASK(23, 16)
|
||||
|
||||
#define DIV_MAX 255
|
||||
|
||||
static const char *clk_names[N_CLOCKS] = {
|
||||
"qspi0", "qspi1", "qspi2", "sdmmc0",
|
||||
"pi", "mcan0", "mcan1", "flexcom0",
|
||||
"flexcom1", "flexcom2", "flexcom3",
|
||||
"flexcom4", "timer1", "usb_refclk",
|
||||
};
|
||||
|
||||
struct lan966x_gck {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
};
|
||||
#define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw)
|
||||
|
||||
static const struct clk_parent_data lan966x_gck_pdata[] = {
|
||||
{ .fw_name = "cpu", },
|
||||
{ .fw_name = "ddr", },
|
||||
{ .fw_name = "sys", },
|
||||
};
|
||||
|
||||
static struct clk_init_data init = {
|
||||
.parent_data = lan966x_gck_pdata,
|
||||
.num_parents = ARRAY_SIZE(lan966x_gck_pdata),
|
||||
};
|
||||
|
||||
struct clk_gate_soc_desc {
|
||||
const char *name;
|
||||
int bit_idx;
|
||||
};
|
||||
|
||||
static const struct clk_gate_soc_desc clk_gate_desc[] = {
|
||||
{ "uhphs", 11 },
|
||||
{ "udphs", 10 },
|
||||
{ "mcramc", 9 },
|
||||
{ "hmatrix", 8 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(clk_gate_lock);
|
||||
static void __iomem *base;
|
||||
|
||||
static int lan966x_gck_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
val |= GCK_ENA;
|
||||
writel(val, gck->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lan966x_gck_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
val &= ~GCK_ENA;
|
||||
writel(val, gck->reg);
|
||||
}
|
||||
|
||||
static int lan966x_gck_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 div, val = readl(gck->reg);
|
||||
|
||||
if (rate == 0 || parent_rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set Prescalar */
|
||||
div = parent_rate / rate;
|
||||
val &= ~GCK_PRESCALER;
|
||||
val |= FIELD_PREP(GCK_PRESCALER, (div - 1));
|
||||
writel(val, gck->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long lan966x_gck_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
unsigned int div;
|
||||
|
||||
if (rate == 0 || *parent_rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (rate >= *parent_rate)
|
||||
return *parent_rate;
|
||||
|
||||
div = DIV_ROUND_CLOSEST(*parent_rate, rate);
|
||||
|
||||
return *parent_rate / div;
|
||||
}
|
||||
|
||||
static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 div, val = readl(gck->reg);
|
||||
|
||||
div = FIELD_GET(GCK_PRESCALER, val);
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static int lan966x_gck_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_hw *parent;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
|
||||
parent = clk_hw_get_parent_by_index(hw, i);
|
||||
if (!parent)
|
||||
continue;
|
||||
|
||||
/* Allowed prescaler divider range is 0-255 */
|
||||
if (clk_hw_get_rate(parent) / req->rate <= DIV_MAX) {
|
||||
req->best_parent_hw = parent;
|
||||
req->best_parent_rate = clk_hw_get_rate(parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static u8 lan966x_gck_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
return FIELD_GET(GCK_SRC_SEL, val);
|
||||
}
|
||||
|
||||
static int lan966x_gck_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
val &= ~GCK_SRC_SEL;
|
||||
val |= FIELD_PREP(GCK_SRC_SEL, index);
|
||||
writel(val, gck->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops lan966x_gck_ops = {
|
||||
.enable = lan966x_gck_enable,
|
||||
.disable = lan966x_gck_disable,
|
||||
.set_rate = lan966x_gck_set_rate,
|
||||
.round_rate = lan966x_gck_round_rate,
|
||||
.recalc_rate = lan966x_gck_recalc_rate,
|
||||
.determine_rate = lan966x_gck_determine_rate,
|
||||
.set_parent = lan966x_gck_set_parent,
|
||||
.get_parent = lan966x_gck_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
|
||||
{
|
||||
struct lan966x_gck *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
priv->reg = base + (i * 4);
|
||||
priv->hw.init = &init;
|
||||
ret = devm_clk_hw_register(dev, &priv->hw);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return &priv->hw;
|
||||
};
|
||||
|
||||
static int lan966x_gate_clk_register(struct device *dev,
|
||||
struct clk_hw_onecell_data *hw_data,
|
||||
void __iomem *gate_base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = GCK_GATE_UHPHS; i < N_CLOCKS; ++i) {
|
||||
int idx = i - GCK_GATE_UHPHS;
|
||||
|
||||
hw_data->hws[i] =
|
||||
devm_clk_hw_register_gate(dev, clk_gate_desc[idx].name,
|
||||
"lan966x", 0, base,
|
||||
clk_gate_desc[idx].bit_idx,
|
||||
0, &clk_gate_lock);
|
||||
|
||||
if (IS_ERR(hw_data->hws[i]))
|
||||
return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
|
||||
"failed to register %s clock\n",
|
||||
clk_gate_desc[idx].name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lan966x_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_hw_onecell_data *hw_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *gate_base;
|
||||
struct resource *res;
|
||||
int i, ret;
|
||||
|
||||
hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, N_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
if (!hw_data)
|
||||
return -ENOMEM;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
init.ops = &lan966x_gck_ops;
|
||||
|
||||
hw_data->num = GCK_GATE_UHPHS;
|
||||
|
||||
for (i = 0; i < GCK_GATE_UHPHS; i++) {
|
||||
init.name = clk_names[i];
|
||||
hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
|
||||
if (IS_ERR(hw_data->hws[i])) {
|
||||
dev_err(dev, "failed to register %s clock\n",
|
||||
init.name);
|
||||
return PTR_ERR(hw_data->hws[i]);
|
||||
}
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (res) {
|
||||
gate_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(gate_base))
|
||||
return PTR_ERR(gate_base);
|
||||
|
||||
hw_data->num = N_CLOCKS;
|
||||
|
||||
ret = lan966x_gate_clk_register(dev, hw_data, gate_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id lan966x_clk_dt_ids[] = {
|
||||
{ .compatible = "microchip,lan966x-gck", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);
|
||||
|
||||
static struct platform_driver lan966x_clk_driver = {
|
||||
.probe = lan966x_clk_probe,
|
||||
.driver = {
|
||||
.name = "lan966x-clk",
|
||||
.of_match_table = lan966x_clk_dt_ids,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(lan966x_clk_driver);
|
||||
|
||||
MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>");
|
||||
MODULE_DESCRIPTION("LAN966X clock driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
};
|
||||
|
||||
static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
|
||||
@ -211,7 +210,6 @@ static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
};
|
||||
|
||||
static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
|
||||
@ -286,7 +284,6 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
};
|
||||
|
||||
static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
|
||||
@ -364,7 +361,6 @@ static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" },
|
||||
};
|
||||
|
||||
|
@ -2253,8 +2253,6 @@ static int stm32_rcc_reset_init(struct device *dev, void __iomem *base,
|
||||
const struct stm32_rcc_match_data *data = match->data;
|
||||
struct stm32_reset_data *reset_data = NULL;
|
||||
|
||||
data = match->data;
|
||||
|
||||
reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
|
||||
if (!reset_data)
|
||||
return -ENOMEM;
|
||||
|
261
drivers/clk/clk-tps68470.c
Normal file
261
drivers/clk/clk-tps68470.c
Normal file
@ -0,0 +1,261 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Clock driver for TPS68470 PMIC
|
||||
*
|
||||
* Copyright (c) 2021 Red Hat Inc.
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Hans de Goede <hdegoede@redhat.com>
|
||||
* Zaikuo Wang <zaikuo.wang@intel.com>
|
||||
* Tianshu Qiu <tian.shu.qiu@intel.com>
|
||||
* Jian Xu Zheng <jian.xu.zheng@intel.com>
|
||||
* Yuning Pu <yuning.pu@intel.com>
|
||||
* Antti Laakso <antti.laakso@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/tps68470.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/tps68470.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define TPS68470_CLK_NAME "tps68470-clk"
|
||||
|
||||
#define to_tps68470_clkdata(clkd) \
|
||||
container_of(clkd, struct tps68470_clkdata, clkout_hw)
|
||||
|
||||
static struct tps68470_clkout_freqs {
|
||||
unsigned long freq;
|
||||
unsigned int xtaldiv;
|
||||
unsigned int plldiv;
|
||||
unsigned int postdiv;
|
||||
unsigned int buckdiv;
|
||||
unsigned int boostdiv;
|
||||
} clk_freqs[] = {
|
||||
/*
|
||||
* The PLL is used to multiply the crystal oscillator
|
||||
* frequency range of 3 MHz to 27 MHz by a programmable
|
||||
* factor of F = (M/N)*(1/P) such that the output
|
||||
* available at the HCLK_A or HCLK_B pins are in the range
|
||||
* of 4 MHz to 64 MHz in increments of 0.1 MHz.
|
||||
*
|
||||
* hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv)
|
||||
*
|
||||
* PLL_REF_CLK should be as close as possible to 100kHz
|
||||
* PLL_REF_CLK = input clk / XTALDIV[7:0] + 30)
|
||||
*
|
||||
* PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320))
|
||||
*
|
||||
* BOOST should be as close as possible to 2Mhz
|
||||
* BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) *
|
||||
*
|
||||
* BUCK should be as close as possible to 5.2Mhz
|
||||
* BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5)
|
||||
*
|
||||
* osc_in xtaldiv plldiv postdiv hclk_#
|
||||
* 20Mhz 170 32 1 19.2Mhz
|
||||
* 20Mhz 170 40 1 20Mhz
|
||||
* 20Mhz 170 80 1 24Mhz
|
||||
*/
|
||||
{ 19200000, 170, 32, 1, 2, 3 },
|
||||
{ 20000000, 170, 40, 1, 3, 4 },
|
||||
{ 24000000, 170, 80, 1, 4, 8 },
|
||||
};
|
||||
|
||||
struct tps68470_clkdata {
|
||||
struct clk_hw clkout_hw;
|
||||
struct regmap *regmap;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
||||
static int tps68470_clk_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
int val;
|
||||
|
||||
if (regmap_read(clkdata->regmap, TPS68470_REG_PLLCTL, &val))
|
||||
return 0;
|
||||
|
||||
return val & TPS68470_PLL_EN_MASK;
|
||||
}
|
||||
|
||||
static int tps68470_clk_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1,
|
||||
(TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_A_SHIFT) |
|
||||
(TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_B_SHIFT));
|
||||
|
||||
regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL,
|
||||
TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK);
|
||||
|
||||
/*
|
||||
* The PLLCTL reg lock bit is set by the PMIC after approx. 4ms and
|
||||
* does not indicate a true lock, so just wait 4 ms.
|
||||
*/
|
||||
usleep_range(4000, 5000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tps68470_clk_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
|
||||
/* Disable clock first ... */
|
||||
regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, 0);
|
||||
|
||||
/* ... and then tri-state the clock outputs. */
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, 0);
|
||||
}
|
||||
|
||||
static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
|
||||
return clkdata->rate;
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns the index of the clk_freqs[] cfg with the closest rate for
|
||||
* use in tps68470_clk_round_rate(). tps68470_clk_set_rate() checks that
|
||||
* the rate of the returned cfg is an exact match.
|
||||
*/
|
||||
static unsigned int tps68470_clk_cfg_lookup(unsigned long rate)
|
||||
{
|
||||
long diff, best_diff = LONG_MAX;
|
||||
unsigned int i, best_idx = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) {
|
||||
diff = clk_freqs[i].freq - rate;
|
||||
if (diff == 0)
|
||||
return i;
|
||||
|
||||
diff = abs(diff);
|
||||
if (diff < best_diff) {
|
||||
best_diff = diff;
|
||||
best_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
return best_idx;
|
||||
}
|
||||
|
||||
static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
unsigned int idx = tps68470_clk_cfg_lookup(rate);
|
||||
|
||||
return clk_freqs[idx].freq;
|
||||
}
|
||||
|
||||
static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
unsigned int idx = tps68470_clk_cfg_lookup(rate);
|
||||
|
||||
if (rate != clk_freqs[idx].freq)
|
||||
return -EINVAL;
|
||||
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, clk_freqs[idx].boostdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, clk_freqs[idx].buckdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, clk_freqs[idx].xtaldiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, clk_freqs[idx].plldiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, clk_freqs[idx].postdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV2, clk_freqs[idx].postdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA);
|
||||
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_PLLCTL,
|
||||
TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT |
|
||||
TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT);
|
||||
|
||||
clkdata->rate = rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops tps68470_clk_ops = {
|
||||
.is_prepared = tps68470_clk_is_prepared,
|
||||
.prepare = tps68470_clk_prepare,
|
||||
.unprepare = tps68470_clk_unprepare,
|
||||
.recalc_rate = tps68470_clk_recalc_rate,
|
||||
.round_rate = tps68470_clk_round_rate,
|
||||
.set_rate = tps68470_clk_set_rate,
|
||||
};
|
||||
|
||||
static int tps68470_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct clk_init_data tps68470_clk_initdata = {
|
||||
.name = TPS68470_CLK_NAME,
|
||||
.ops = &tps68470_clk_ops,
|
||||
/* Changing the dividers when the PLL is on is not allowed */
|
||||
.flags = CLK_SET_RATE_GATE,
|
||||
};
|
||||
struct tps68470_clkdata *tps68470_clkdata;
|
||||
int ret;
|
||||
|
||||
tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata),
|
||||
GFP_KERNEL);
|
||||
if (!tps68470_clkdata)
|
||||
return -ENOMEM;
|
||||
|
||||
tps68470_clkdata->regmap = dev_get_drvdata(pdev->dev.parent);
|
||||
tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata;
|
||||
|
||||
/* Set initial rate */
|
||||
tps68470_clk_set_rate(&tps68470_clkdata->clkout_hw, clk_freqs[0].freq, 0);
|
||||
|
||||
ret = devm_clk_hw_register(&pdev->dev, &tps68470_clkdata->clkout_hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_clk_hw_register_clkdev(&pdev->dev, &tps68470_clkdata->clkout_hw,
|
||||
TPS68470_CLK_NAME, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pdata) {
|
||||
ret = devm_clk_hw_register_clkdev(&pdev->dev,
|
||||
&tps68470_clkdata->clkout_hw,
|
||||
pdata->consumer_con_id,
|
||||
pdata->consumer_dev_name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver tps68470_clk_driver = {
|
||||
.driver = {
|
||||
.name = TPS68470_CLK_NAME,
|
||||
},
|
||||
.probe = tps68470_clk_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers
|
||||
* registering before the drivers for the camera-sensors which use them bind.
|
||||
* subsys_initcall() ensures this when the drivers are builtin.
|
||||
*/
|
||||
static int __init tps68470_clk_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps68470_clk_driver);
|
||||
}
|
||||
subsys_initcall(tps68470_clk_init);
|
||||
|
||||
static void __exit tps68470_clk_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps68470_clk_driver);
|
||||
}
|
||||
module_exit(tps68470_clk_exit);
|
||||
|
||||
MODULE_ALIAS("platform:tps68470-clk");
|
||||
MODULE_DESCRIPTION("clock driver for TPS68470 pmic");
|
||||
MODULE_LICENSE("GPL");
|
@ -424,19 +424,20 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
|
||||
|
||||
if (entry->hw) {
|
||||
parent = entry->hw->core;
|
||||
/*
|
||||
* We have a direct reference but it isn't registered yet?
|
||||
* Orphan it and let clk_reparent() update the orphan status
|
||||
* when the parent is registered.
|
||||
*/
|
||||
if (!parent)
|
||||
parent = ERR_PTR(-EPROBE_DEFER);
|
||||
} else {
|
||||
parent = clk_core_get(core, index);
|
||||
if (PTR_ERR(parent) == -ENOENT && entry->name)
|
||||
parent = clk_core_lookup(entry->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a direct reference but it isn't registered yet?
|
||||
* Orphan it and let clk_reparent() update the orphan status
|
||||
* when the parent is registered.
|
||||
*/
|
||||
if (!parent)
|
||||
parent = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
/* Only cache it if it's not an error */
|
||||
if (!IS_ERR(parent))
|
||||
entry->core = parent;
|
||||
@ -2965,7 +2966,9 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
|
||||
{
|
||||
struct clk_core *child;
|
||||
|
||||
clk_pm_runtime_get(c);
|
||||
clk_summary_show_one(s, c, level);
|
||||
clk_pm_runtime_put(c);
|
||||
|
||||
hlist_for_each_entry(child, &c->children, child_node)
|
||||
clk_summary_show_subtree(s, child, level + 1);
|
||||
@ -3217,6 +3220,42 @@ static int current_parent_show(struct seq_file *s, void *data)
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(current_parent);
|
||||
|
||||
#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
|
||||
static ssize_t current_parent_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
struct clk_core *core = s->private;
|
||||
struct clk_core *parent;
|
||||
u8 idx;
|
||||
int err;
|
||||
|
||||
err = kstrtou8_from_user(ubuf, count, 0, &idx);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
parent = clk_core_get_parent_by_index(core, idx);
|
||||
if (!parent)
|
||||
return -ENOENT;
|
||||
|
||||
clk_prepare_lock();
|
||||
err = clk_core_set_parent_nolock(core, parent);
|
||||
clk_prepare_unlock();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations current_parent_rw_fops = {
|
||||
.open = current_parent_open,
|
||||
.write = current_parent_write,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int clk_duty_cycle_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct clk_core *core = s->private;
|
||||
@ -3282,8 +3321,12 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
|
||||
#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
|
||||
debugfs_create_file("clk_prepare_enable", 0644, root, core,
|
||||
&clk_prepare_enable_fops);
|
||||
#endif
|
||||
|
||||
if (core->num_parents > 1)
|
||||
debugfs_create_file("clk_parent", 0644, root, core,
|
||||
¤t_parent_rw_fops);
|
||||
else
|
||||
#endif
|
||||
if (core->num_parents > 0)
|
||||
debugfs_create_file("clk_parent", 0444, root, core,
|
||||
¤t_parent_fops);
|
||||
@ -3343,6 +3386,24 @@ static int __init clk_debug_init(void)
|
||||
{
|
||||
struct clk_core *core;
|
||||
|
||||
#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
|
||||
pr_warn("\n");
|
||||
pr_warn("********************************************************************\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** WRITEABLE clk DebugFS SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** This means that this kernel is built to expose clk operations **\n");
|
||||
pr_warn("** such as parent or rate setting, enabling, disabling, etc. **\n");
|
||||
pr_warn("** to userspace, which may compromise security on your system. **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** If you see this message and you are not debugging the **\n");
|
||||
pr_warn("** kernel, report this immediately to your vendor! **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("********************************************************************\n");
|
||||
#endif
|
||||
|
||||
rootdir = debugfs_create_dir("clk", NULL);
|
||||
|
||||
debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
|
||||
@ -3413,9 +3474,6 @@ static int __clk_core_init(struct clk_core *core)
|
||||
unsigned long rate;
|
||||
int phase;
|
||||
|
||||
if (!core)
|
||||
return -EINVAL;
|
||||
|
||||
clk_prepare_lock();
|
||||
|
||||
/*
|
||||
|
@ -277,9 +277,9 @@ static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audi
|
||||
|
||||
static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
|
||||
|
||||
static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
|
||||
"sys_pll1_200m", "audio_pll2_out", "vpu_pll",
|
||||
"sys_pll1_80m", };
|
||||
static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy",
|
||||
"sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m",
|
||||
"dummy", "sys_pll1_80m", };
|
||||
static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
|
||||
"sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
|
||||
"video_pll1_out", "osc_32k", };
|
||||
|
@ -700,7 +700,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
|
||||
hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", ccm_base + 0x4620, 0);
|
||||
hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0);
|
||||
hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "ipg_root", ccm_base + 0x4650, 0);
|
||||
hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "audio_ahb", ccm_base + 0x4650, 0);
|
||||
|
||||
hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core",
|
||||
hws[IMX8MP_CLK_A53_CORE]->clk,
|
||||
|
@ -559,6 +559,7 @@ static struct platform_driver imx8ulp_clk_driver = {
|
||||
.probe = imx8ulp_clk_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = imx8ulp_clk_dt_ids,
|
||||
},
|
||||
};
|
||||
|
@ -8,20 +8,19 @@
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
/**
|
||||
* pll v1
|
||||
*
|
||||
* @clk_hw clock source
|
||||
* @parent the parent clock name
|
||||
* @base base address of pll registers
|
||||
*
|
||||
* PLL clock version 1, found on i.MX1/21/25/27/31/35
|
||||
*/
|
||||
|
||||
#define MFN_BITS (10)
|
||||
#define MFN_SIGN (BIT(MFN_BITS - 1))
|
||||
#define MFN_MASK (MFN_SIGN - 1)
|
||||
|
||||
/**
|
||||
* struct clk_pllv1 - IMX PLLv1 clock descriptor
|
||||
*
|
||||
* @hw: clock source
|
||||
* @base: base address of pll registers
|
||||
* @type: type of IMX_PLLV1
|
||||
*
|
||||
* PLL clock version 1, found on i.MX1/21/25/27/31/35
|
||||
*/
|
||||
struct clk_pllv1 {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
|
@ -247,7 +247,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
div = rate / parent_rate;
|
||||
temp64 = (u64) (rate - div * parent_rate);
|
||||
temp64 *= mfd;
|
||||
do_div(temp64, parent_rate);
|
||||
temp64 = div64_ul(temp64, parent_rate);
|
||||
mfn = temp64;
|
||||
|
||||
temp64 = (u64)parent_rate;
|
||||
@ -277,7 +277,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
div = rate / parent_rate;
|
||||
temp64 = (u64) (rate - div * parent_rate);
|
||||
temp64 *= mfd;
|
||||
do_div(temp64, parent_rate);
|
||||
temp64 = div64_ul(temp64, parent_rate);
|
||||
mfn = temp64;
|
||||
|
||||
val = readl_relaxed(pll->base);
|
||||
@ -334,7 +334,7 @@ static struct clk_pllv3_vf610_mf clk_pllv3_vf610_rate_to_mf(
|
||||
/* rate = parent_rate * (mfi + mfn/mfd) */
|
||||
temp64 = rate - parent_rate * mf.mfi;
|
||||
temp64 *= mf.mfd;
|
||||
do_div(temp64, parent_rate);
|
||||
temp64 = div64_ul(temp64, parent_rate);
|
||||
mf.mfn = temp64;
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,16 @@ static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = {
|
||||
.parents = { JZ4760_CLK_H2CLK, },
|
||||
.gate = { CGU_REG_CLKGR0, 21 },
|
||||
},
|
||||
[JZ4760_CLK_MDMA] = {
|
||||
"mdma", CGU_CLK_GATE,
|
||||
.parents = { JZ4760_CLK_HCLK, },
|
||||
.gate = { CGU_REG_CLKGR0, 25 },
|
||||
},
|
||||
[JZ4760_CLK_BDMA] = {
|
||||
"bdma", CGU_CLK_GATE,
|
||||
.parents = { JZ4760_CLK_HCLK, },
|
||||
.gate = { CGU_REG_CLKGR1, 0 },
|
||||
},
|
||||
[JZ4760_CLK_I2C0] = {
|
||||
"i2c0", CGU_CLK_GATE,
|
||||
.parents = { JZ4760_CLK_EXT, },
|
||||
|
@ -329,6 +329,11 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
|
||||
.parents = { JZ4770_CLK_H2CLK, },
|
||||
.gate = { CGU_REG_CLKGR0, 21 },
|
||||
},
|
||||
[JZ4770_CLK_BDMA] = {
|
||||
"bdma", CGU_CLK_GATE,
|
||||
.parents = { JZ4770_CLK_H2CLK, },
|
||||
.gate = { CGU_REG_CLKGR1, 0 },
|
||||
},
|
||||
[JZ4770_CLK_I2C0] = {
|
||||
"i2c0", CGU_CLK_GATE,
|
||||
.parents = { JZ4770_CLK_EXT, },
|
||||
|
@ -344,6 +344,23 @@ config COMMON_CLK_MT7629_HIFSYS
|
||||
This driver supports MediaTek MT7629 HIFSYS clocks providing
|
||||
to PCI-E and USB.
|
||||
|
||||
config COMMON_CLK_MT7986
|
||||
bool "Clock driver for MediaTek MT7986"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK
|
||||
help
|
||||
This driver supports MediaTek MT7986 basic clocks and clocks
|
||||
required for various peripherals found on MediaTek.
|
||||
|
||||
config COMMON_CLK_MT7986_ETHSYS
|
||||
bool "Clock driver for MediaTek MT7986 ETHSYS"
|
||||
depends on COMMON_CLK_MT7986
|
||||
default COMMON_CLK_MT7986
|
||||
help
|
||||
This driver adds support for clocks for Ethernet and SGMII
|
||||
required on MediaTek MT7986 SoC.
|
||||
|
||||
config COMMON_CLK_MT8135
|
||||
bool "Clock driver for MediaTek MT8135"
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
|
@ -46,6 +46,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o
|
||||
|
@ -16,28 +16,24 @@
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
|
||||
static u32 mtk_get_clockgating(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 val;
|
||||
|
||||
regmap_read(cg->regmap, cg->sta_ofs, &val);
|
||||
|
||||
val &= BIT(cg->bit);
|
||||
return val & BIT(cg->bit);
|
||||
}
|
||||
|
||||
return val == 0;
|
||||
static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
|
||||
{
|
||||
return mtk_get_clockgating(hw) == 0;
|
||||
}
|
||||
|
||||
static int mtk_cg_bit_is_set(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 val;
|
||||
|
||||
regmap_read(cg->regmap, cg->sta_ofs, &val);
|
||||
|
||||
val &= BIT(cg->bit);
|
||||
|
||||
return val != 0;
|
||||
return mtk_get_clockgating(hw) != 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_set_bit(struct clk_hw *hw)
|
||||
@ -57,17 +53,15 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
|
||||
static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 cgbit = BIT(cg->bit);
|
||||
|
||||
regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
|
||||
regmap_set_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 cgbit = BIT(cg->bit);
|
||||
|
||||
regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
|
||||
regmap_clear_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static int mtk_cg_enable(struct clk_hw *hw)
|
||||
|
100
drivers/clk/mediatek/clk-mt7986-apmixed.c
Normal file
100
drivers/clk/mediatek/clk-mt7986-apmixed.c
Normal file
@ -0,0 +1,100 @@
|
||||
// SPDX-License-Identifier: GPL-1.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#define MT7986_PLL_FMAX (2500UL * MHZ)
|
||||
#define CON0_MT7986_RST_BAR BIT(27)
|
||||
|
||||
#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
|
||||
_div_table, _parent_name) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, .flags = _flags, \
|
||||
.rst_bar_mask = CON0_MT7986_RST_BAR, .fmax = MT7986_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, .div_table = _div_table, \
|
||||
.parent_name = _parent_name, \
|
||||
}
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
|
||||
_pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \
|
||||
PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \
|
||||
"clkxtal")
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, 0, 32,
|
||||
0x0200, 4, 0, 0x0204, 0),
|
||||
PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32,
|
||||
0x0210, 4, 0, 0x0214, 0),
|
||||
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32,
|
||||
0x0220, 4, 0, 0x0224, 0),
|
||||
PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x00000001, 0, 32,
|
||||
0x0230, 4, 0, 0x0234, 0),
|
||||
PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x00000001, 0,
|
||||
32, 0x0240, 4, 0, 0x0244, 0),
|
||||
PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x00000001, 0, 32,
|
||||
0x0250, 4, 0, 0x0254, 0),
|
||||
PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, 0x0260,
|
||||
4, 0, 0x0264, 0),
|
||||
PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32,
|
||||
0x0278, 4, 0, 0x027c, 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7986_apmixed[] = {
|
||||
{ .compatible = "mediatek,mt7986-apmixedsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt7986_apmixed_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r) {
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
goto free_apmixed_data;
|
||||
}
|
||||
return r;
|
||||
|
||||
free_apmixed_data:
|
||||
mtk_free_clk_data(clk_data);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt7986_apmixed_drv = {
|
||||
.probe = clk_mt7986_apmixed_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7986-apmixed",
|
||||
.of_match_table = of_match_clk_mt7986_apmixed,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_mt7986_apmixed_drv);
|
132
drivers/clk/mediatek/clk-mt7986-eth.c
Normal file
132
drivers/clk/mediatek/clk-mt7986-eth.c
Normal file
@ -0,0 +1,132 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs sgmii0_cg_regs = {
|
||||
.set_ofs = 0xe4,
|
||||
.clr_ofs = 0xe4,
|
||||
.sta_ofs = 0xe4,
|
||||
};
|
||||
|
||||
#define GATE_SGMII0(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &sgmii0_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate sgmii0_clks[] __initconst = {
|
||||
GATE_SGMII0(CLK_SGMII0_TX250M_EN, "sgmii0_tx250m_en", "top_xtal", 2),
|
||||
GATE_SGMII0(CLK_SGMII0_RX250M_EN, "sgmii0_rx250m_en", "top_xtal", 3),
|
||||
GATE_SGMII0(CLK_SGMII0_CDR_REF, "sgmii0_cdr_ref", "top_xtal", 4),
|
||||
GATE_SGMII0(CLK_SGMII0_CDR_FB, "sgmii0_cdr_fb", "top_xtal", 5),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs sgmii1_cg_regs = {
|
||||
.set_ofs = 0xe4,
|
||||
.clr_ofs = 0xe4,
|
||||
.sta_ofs = 0xe4,
|
||||
};
|
||||
|
||||
#define GATE_SGMII1(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &sgmii1_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate sgmii1_clks[] __initconst = {
|
||||
GATE_SGMII1(CLK_SGMII1_TX250M_EN, "sgmii1_tx250m_en", "top_xtal", 2),
|
||||
GATE_SGMII1(CLK_SGMII1_RX250M_EN, "sgmii1_rx250m_en", "top_xtal", 3),
|
||||
GATE_SGMII1(CLK_SGMII1_CDR_REF, "sgmii1_cdr_ref", "top_xtal", 4),
|
||||
GATE_SGMII1(CLK_SGMII1_CDR_FB, "sgmii1_cdr_fb", "top_xtal", 5),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs eth_cg_regs = {
|
||||
.set_ofs = 0x30,
|
||||
.clr_ofs = 0x30,
|
||||
.sta_ofs = 0x30,
|
||||
};
|
||||
|
||||
#define GATE_ETH(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = ð_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate eth_clks[] __initconst = {
|
||||
GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x_sel", 6),
|
||||
GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m_sel", 7),
|
||||
GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m_sel", 8),
|
||||
GATE_ETH(CLK_ETH_WOCPU1_EN, "eth_wocpu1_en", "netsys_mcu_sel", 14),
|
||||
GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_mcu_sel", 15),
|
||||
};
|
||||
|
||||
static void __init mtk_sgmiisys_0_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks));
|
||||
|
||||
mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7986-sgmiisys_0",
|
||||
mtk_sgmiisys_0_init);
|
||||
|
||||
static void __init mtk_sgmiisys_1_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks));
|
||||
|
||||
mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7986-sgmiisys_1",
|
||||
mtk_sgmiisys_1_init);
|
||||
|
||||
static void __init mtk_ethsys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks));
|
||||
|
||||
mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys_ck", mtk_ethsys_init);
|
224
drivers/clk/mediatek/clk-mt7986-infracfg.c
Normal file
224
drivers/clk/mediatek/clk-mt7986-infracfg.c
Normal file
@ -0,0 +1,224 @@
|
||||
// SPDX-License-Identifier: GPL-1.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7986_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_factor infra_divs[] = {
|
||||
FACTOR(CLK_INFRA_SYSAXI_D2, "infra_sysaxi_d2", "sysaxi_sel", 1, 2),
|
||||
};
|
||||
|
||||
static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel",
|
||||
"uart_sel" };
|
||||
|
||||
static const char *const infra_spi_parents[] __initconst = { "i2c_sel",
|
||||
"spi_sel" };
|
||||
|
||||
static const char *const infra_pwm_bsel_parents[] __initconst = {
|
||||
"top_rtc_32p7k", "csw_f26m_sel", "infra_sysaxi_d2", "pwm_sel"
|
||||
};
|
||||
|
||||
static const char *const infra_pcie_parents[] __initconst = {
|
||||
"top_rtc_32p7k", "csw_f26m_sel", "top_xtal", "pextp_tl_ck_sel"
|
||||
};
|
||||
|
||||
static const struct mtk_mux infra_muxes[] = {
|
||||
/* MODULE_CLK_SEL_0 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel",
|
||||
infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel",
|
||||
infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel",
|
||||
infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel",
|
||||
infra_spi_parents, 0x0018, 0x0010, 0x0014, 4, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel",
|
||||
infra_spi_parents, 0x0018, 0x0010, 0x0014, 5, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel",
|
||||
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 9,
|
||||
2, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel",
|
||||
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 11,
|
||||
2, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel",
|
||||
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13,
|
||||
2, -1, -1, -1),
|
||||
/* MODULE_CLK_SEL_1 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel",
|
||||
infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2,
|
||||
-1, -1, -1),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra0_cg_regs = {
|
||||
.set_ofs = 0x40,
|
||||
.clr_ofs = 0x44,
|
||||
.sta_ofs = 0x48,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra1_cg_regs = {
|
||||
.set_ofs = 0x50,
|
||||
.clr_ofs = 0x54,
|
||||
.sta_ofs = 0x58,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra2_cg_regs = {
|
||||
.set_ofs = 0x60,
|
||||
.clr_ofs = 0x64,
|
||||
.sta_ofs = 0x68,
|
||||
};
|
||||
|
||||
#define GATE_INFRA0(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra0_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA1(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra1_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA2(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra2_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] = {
|
||||
/* INFRA0 */
|
||||
GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_sysaxi_d2", 0),
|
||||
GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_sysaxi_d2", 1),
|
||||
GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2),
|
||||
GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3),
|
||||
GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4),
|
||||
GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi_sel", 6),
|
||||
GATE_INFRA0(CLK_INFRA_EIP97_CK, "infra_eip97", "eip_b_sel", 7),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi_sel", 8),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l_sel", 10),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys_sel", 11),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner_sel", 13),
|
||||
GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel",
|
||||
14),
|
||||
GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_sysaxi_d2", 15),
|
||||
GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_sysaxi_d2", 16),
|
||||
GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_sysaxi_d2", 24),
|
||||
GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25),
|
||||
GATE_INFRA0(CLK_INFRA_TRNG_CK, "infra_trng", "sysaxi_sel", 26),
|
||||
/* INFRA1 */
|
||||
GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0),
|
||||
GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_sel", 1),
|
||||
GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2),
|
||||
GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3),
|
||||
GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4),
|
||||
GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x_sel", 8),
|
||||
GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_sel", 9),
|
||||
GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_sysaxi_d2",
|
||||
10),
|
||||
GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11),
|
||||
GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12),
|
||||
GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_sysaxi_d2",
|
||||
13),
|
||||
GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_sysaxi_d2",
|
||||
14),
|
||||
GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "top_rtc_32k", 15),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_416m_sel", 16),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_250m_sel",
|
||||
17),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi_sel",
|
||||
18),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2",
|
||||
19),
|
||||
GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "csw_f26m_sel", 20),
|
||||
GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21),
|
||||
GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23),
|
||||
/* INFRA2 */
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi_sel", 0),
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "infra_sysaxi_d2",
|
||||
1),
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys_sel", 2),
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_sel", 3),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl_ck_sel", 12),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "top_xtal",
|
||||
13),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m_sel", 14),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi_sel", 15),
|
||||
};
|
||||
|
||||
static int clk_mt7986_infracfg_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) +
|
||||
ARRAY_SIZE(infra_clks);
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(nr);
|
||||
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
|
||||
mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node,
|
||||
&mt7986_clk_lock, clk_data);
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r) {
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
goto free_infracfg_data;
|
||||
}
|
||||
return r;
|
||||
|
||||
free_infracfg_data:
|
||||
mtk_free_clk_data(clk_data);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7986_infracfg[] = {
|
||||
{ .compatible = "mediatek,mt7986-infracfg", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt7986_infracfg_drv = {
|
||||
.probe = clk_mt7986_infracfg_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7986-infracfg",
|
||||
.of_match_table = of_match_clk_mt7986_infracfg,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_mt7986_infracfg_drv);
|
342
drivers/clk/mediatek/clk-mt7986-topckgen.c
Normal file
342
drivers/clk/mediatek/clk-mt7986-topckgen.c
Normal file
@ -0,0 +1,342 @@
|
||||
// SPDX-License-Identifier: GPL-1.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7986_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_clk top_fixed_clks[] = {
|
||||
FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000),
|
||||
FIXED_CLK(CLK_TOP_JTAG, "top_jtag", "clkxtal", 50000000),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_factor top_divs[] = {
|
||||
/* XTAL */
|
||||
FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2),
|
||||
FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250),
|
||||
FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220),
|
||||
/* MPLL */
|
||||
FACTOR(CLK_TOP_MPLL_D2, "top_mpll_d2", "mpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MPLL_D4, "top_mpll_d4", "mpll", 1, 4),
|
||||
FACTOR(CLK_TOP_MPLL_D8, "top_mpll_d8", "mpll", 1, 8),
|
||||
FACTOR(CLK_TOP_MPLL_D8_D2, "top_mpll_d8_d2", "mpll", 1, 16),
|
||||
FACTOR(CLK_TOP_MPLL_D3_D2, "top_mpll_d3_d2", "mpll", 1, 6),
|
||||
/* MMPLL */
|
||||
FACTOR(CLK_TOP_MMPLL_D2, "top_mmpll_d2", "mmpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MMPLL_D4, "top_mmpll_d4", "mmpll", 1, 4),
|
||||
FACTOR(CLK_TOP_MMPLL_D8, "top_mmpll_d8", "mmpll", 1, 8),
|
||||
FACTOR(CLK_TOP_MMPLL_D8_D2, "top_mmpll_d8_d2", "mmpll", 1, 16),
|
||||
FACTOR(CLK_TOP_MMPLL_D3_D8, "top_mmpll_d3_d8", "mmpll", 1, 24),
|
||||
FACTOR(CLK_TOP_MMPLL_U2PHY, "top_mmpll_u2phy", "mmpll", 1, 30),
|
||||
/* APLL2 */
|
||||
FACTOR(CLK_TOP_APLL2_D4, "top_apll2_d4", "apll2", 1, 4),
|
||||
/* NET1PLL */
|
||||
FACTOR(CLK_TOP_NET1PLL_D4, "top_net1pll_d4", "net1pll", 1, 4),
|
||||
FACTOR(CLK_TOP_NET1PLL_D5, "top_net1pll_d5", "net1pll", 1, 5),
|
||||
FACTOR(CLK_TOP_NET1PLL_D5_D2, "top_net1pll_d5_d2", "net1pll", 1, 10),
|
||||
FACTOR(CLK_TOP_NET1PLL_D5_D4, "top_net1pll_d5_d4", "net1pll", 1, 20),
|
||||
FACTOR(CLK_TOP_NET1PLL_D8_D2, "top_net1pll_d8_d2", "net1pll", 1, 16),
|
||||
FACTOR(CLK_TOP_NET1PLL_D8_D4, "top_net1pll_d8_d4", "net1pll", 1, 32),
|
||||
/* NET2PLL */
|
||||
FACTOR(CLK_TOP_NET2PLL_D4, "top_net2pll_d4", "net2pll", 1, 4),
|
||||
FACTOR(CLK_TOP_NET2PLL_D4_D2, "top_net2pll_d4_d2", "net2pll", 1, 8),
|
||||
FACTOR(CLK_TOP_NET2PLL_D3_D2, "top_net2pll_d3_d2", "net2pll", 1, 2),
|
||||
/* WEDMCUPLL */
|
||||
FACTOR(CLK_TOP_WEDMCUPLL_D5_D2, "top_wedmcupll_d5_d2", "wedmcupll", 1,
|
||||
10),
|
||||
};
|
||||
|
||||
static const char *const nfi1x_parents[] __initconst = { "top_xtal",
|
||||
"top_mmpll_d8",
|
||||
"top_net1pll_d8_d2",
|
||||
"top_net2pll_d3_d2",
|
||||
"top_mpll_d4",
|
||||
"top_mmpll_d8_d2",
|
||||
"top_wedmcupll_d5_d2",
|
||||
"top_mpll_d8" };
|
||||
|
||||
static const char *const spinfi_parents[] __initconst = {
|
||||
"top_xtal_d2", "top_xtal", "top_net1pll_d5_d4",
|
||||
"top_mpll_d4", "top_mmpll_d8_d2", "top_wedmcupll_d5_d2",
|
||||
"top_mmpll_d3_d8", "top_mpll_d8"
|
||||
};
|
||||
|
||||
static const char *const spi_parents[] __initconst = {
|
||||
"top_xtal", "top_mpll_d2", "top_mmpll_d8",
|
||||
"top_net1pll_d8_d2", "top_net2pll_d3_d2", "top_net1pll_d5_d4",
|
||||
"top_mpll_d4", "top_wedmcupll_d5_d2"
|
||||
};
|
||||
|
||||
static const char *const uart_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d8",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const pwm_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d8_d2", "top_net1pll_d5_d4", "top_mpll_d4"
|
||||
};
|
||||
|
||||
static const char *const i2c_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d4", "top_mpll_d4", "top_net1pll_d8_d4"
|
||||
};
|
||||
|
||||
static const char *const pextp_tl_ck_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d4", "top_net2pll_d4_d2", "top_rtc_32k"
|
||||
};
|
||||
|
||||
static const char *const emmc_250m_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d2"
|
||||
};
|
||||
|
||||
static const char *const emmc_416m_parents[] __initconst = { "top_xtal",
|
||||
"mpll" };
|
||||
|
||||
static const char *const f_26m_adc_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const dramc_md32_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d2" };
|
||||
|
||||
static const char *const sysaxi_parents[] __initconst = { "top_xtal",
|
||||
"top_net1pll_d8_d2",
|
||||
"top_net2pll_d4" };
|
||||
|
||||
static const char *const sysapb_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d3_d2",
|
||||
"top_net2pll_d4_d2" };
|
||||
|
||||
static const char *const arm_db_main_parents[] __initconst = {
|
||||
"top_xtal", "top_net2pll_d3_d2"
|
||||
};
|
||||
|
||||
static const char *const arm_db_jtsel_parents[] __initconst = { "top_jtag",
|
||||
"top_xtal" };
|
||||
|
||||
static const char *const netsys_parents[] __initconst = { "top_xtal",
|
||||
"top_mmpll_d4" };
|
||||
|
||||
static const char *const netsys_500m_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5"
|
||||
};
|
||||
|
||||
static const char *const netsys_mcu_parents[] __initconst = {
|
||||
"top_xtal", "wedmcupll", "top_mmpll_d2", "top_net1pll_d4",
|
||||
"top_net1pll_d5"
|
||||
};
|
||||
|
||||
static const char *const netsys_2x_parents[] __initconst = {
|
||||
"top_xtal", "net2pll", "wedmcupll", "top_mmpll_d2"
|
||||
};
|
||||
|
||||
static const char *const sgm_325m_parents[] __initconst = { "top_xtal",
|
||||
"sgmpll" };
|
||||
|
||||
static const char *const sgm_reg_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d8_d4"
|
||||
};
|
||||
|
||||
static const char *const a1sys_parents[] __initconst = { "top_xtal",
|
||||
"top_apll2_d4" };
|
||||
|
||||
static const char *const conn_mcusys_parents[] __initconst = { "top_xtal",
|
||||
"top_mmpll_d2" };
|
||||
|
||||
static const char *const eip_b_parents[] __initconst = { "top_xtal",
|
||||
"net2pll" };
|
||||
|
||||
static const char *const aud_l_parents[] __initconst = { "top_xtal", "apll2",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const a_tuner_parents[] __initconst = { "top_xtal",
|
||||
"top_apll2_d4",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const u2u3_sys_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d4"
|
||||
};
|
||||
|
||||
static const char *const da_u2_refsel_parents[] __initconst = {
|
||||
"top_xtal", "top_mmpll_u2phy"
|
||||
};
|
||||
|
||||
static const struct mtk_mux top_muxes[] = {
|
||||
/* CLK_CFG_0 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents,
|
||||
0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents,
|
||||
0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000,
|
||||
0x004, 0x008, 16, 3, 23, 0x1C0, 2),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents,
|
||||
0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3),
|
||||
/* CLK_CFG_1 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010,
|
||||
0x014, 0x018, 0, 2, 7, 0x1C0, 4),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010,
|
||||
0x014, 0x018, 8, 2, 15, 0x1C0, 5),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010,
|
||||
0x014, 0x018, 16, 2, 23, 0x1C0, 6),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel",
|
||||
pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2,
|
||||
31, 0x1C0, 7),
|
||||
/* CLK_CFG_2 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
|
||||
emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7,
|
||||
0x1C0, 8),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel",
|
||||
emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15,
|
||||
0x1C0, 9),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel",
|
||||
f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23,
|
||||
0x1C0, 10),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents,
|
||||
0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11),
|
||||
/* CLK_CFG_3 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel",
|
||||
dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7,
|
||||
0x1C0, 12),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents,
|
||||
0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents,
|
||||
0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel",
|
||||
arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1,
|
||||
31, 0x1C0, 15),
|
||||
/* CLK_CFG_4 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_JTSEL, "arm_db_jtsel",
|
||||
arm_db_jtsel_parents, 0x040, 0x044, 0x048, 0, 1, 7,
|
||||
0x1C0, 16),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents,
|
||||
0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel",
|
||||
netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1,
|
||||
23, 0x1C0, 18),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel",
|
||||
netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31,
|
||||
0x1C0, 19),
|
||||
/* CLK_CFG_5 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel",
|
||||
netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7,
|
||||
0x1C0, 20),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel",
|
||||
sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15,
|
||||
0x1C0, 21),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel",
|
||||
sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23,
|
||||
0x1C0, 22),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents,
|
||||
0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23),
|
||||
/* CLK_CFG_6 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel",
|
||||
conn_mcusys_parents, 0x060, 0x064, 0x068, 0, 1, 7,
|
||||
0x1C0, 24),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents,
|
||||
0x060, 0x064, 0x068, 8, 1, 15, 0x1C0, 25),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_PHY_SEL, "pcie_phy_sel",
|
||||
f_26m_adc_parents, 0x060, 0x064, 0x068, 16, 1, 23,
|
||||
0x1C0, 26),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel",
|
||||
f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31,
|
||||
0x1C0, 27),
|
||||
/* CLK_CFG_7 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel",
|
||||
f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7,
|
||||
0x1C0, 28),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents,
|
||||
0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel",
|
||||
a_tuner_parents, 0x070, 0x074, 0x078, 16, 2, 23,
|
||||
0x1C0, 30),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents,
|
||||
0x070, 0x074, 0x078, 24, 1, 31, 0x1C4, 0),
|
||||
/* CLK_CFG_8 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel",
|
||||
u2u3_sys_parents, 0x080, 0x084, 0x088, 0, 1, 7,
|
||||
0x1C4, 1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel",
|
||||
u2u3_sys_parents, 0x080, 0x084, 0x088, 8, 1, 15,
|
||||
0x1C4, 2),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_REFSEL, "da_u2_refsel",
|
||||
da_u2_refsel_parents, 0x080, 0x084, 0x088, 16, 1,
|
||||
23, 0x1C4, 3),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel",
|
||||
da_u2_refsel_parents, 0x080, 0x084, 0x088, 24, 1,
|
||||
31, 0x1C4, 4),
|
||||
/* CLK_CFG_9 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel",
|
||||
sgm_reg_parents, 0x090, 0x094, 0x098, 0, 1, 7,
|
||||
0x1C4, 5),
|
||||
};
|
||||
|
||||
static int clk_mt7986_topckgen_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) +
|
||||
ARRAY_SIZE(top_muxes);
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(nr);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
|
||||
clk_data);
|
||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
|
||||
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
|
||||
&mt7986_clk_lock, clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAXI_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAPB_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_MD32_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_F26M_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_SGM_REG_SEL]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r) {
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
goto free_topckgen_data;
|
||||
}
|
||||
return r;
|
||||
|
||||
free_topckgen_data:
|
||||
mtk_free_clk_data(clk_data);
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7986_topckgen[] = {
|
||||
{ .compatible = "mediatek,mt7986-topckgen", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt7986_topckgen_drv = {
|
||||
.probe = clk_mt7986_topckgen_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7986-topckgen",
|
||||
.of_match_table = of_match_clk_mt7986_topckgen,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_mt7986_topckgen_drv);
|
@ -713,6 +713,35 @@ static struct clk_regmap gxbb_mpll_prediv = {
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_mpll0_div = {
|
||||
.data = &(struct meson_clk_mpll_data){
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL,
|
||||
.shift = 25,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.lock = &meson_clk_lock,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0_div",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&gxbb_mpll_prediv.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxl_mpll0_div = {
|
||||
.data = &(struct meson_clk_mpll_data){
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
@ -749,7 +778,16 @@ static struct clk_regmap gxbb_mpll0 = {
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw },
|
||||
.parent_data = &(const struct clk_parent_data) {
|
||||
/*
|
||||
* Note:
|
||||
* GXL and GXBB have different SDM_EN registers. We
|
||||
* fallback to the global naming string mechanism so
|
||||
* mpll0_div picks up the appropriate one.
|
||||
*/
|
||||
.name = "mpll0_div",
|
||||
.index = -1,
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
@ -3044,7 +3082,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
|
||||
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
|
||||
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
|
||||
[CLKID_VAPB] = &gxbb_vapb.hw,
|
||||
[CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw,
|
||||
[CLKID_MPLL0_DIV] = &gxl_mpll0_div.hw,
|
||||
[CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
|
||||
[CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
|
||||
[CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
|
||||
@ -3439,7 +3477,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = {
|
||||
&gxbb_mpll0,
|
||||
&gxbb_mpll1,
|
||||
&gxbb_mpll2,
|
||||
&gxbb_mpll0_div,
|
||||
&gxl_mpll0_div,
|
||||
&gxbb_mpll1_div,
|
||||
&gxbb_mpll2_div,
|
||||
&gxbb_cts_amclk_div,
|
||||
|
@ -265,6 +265,14 @@ config MSM_MMCC_8974
|
||||
Say Y if you want to support multimedia devices such as display,
|
||||
graphics, video encode/decode, camera, etc.
|
||||
|
||||
config MSM_GCC_8976
|
||||
tristate "MSM8956/76 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on msm8956/76 devices.
|
||||
Say Y if you want to use peripheral devices such as UART, SPI,
|
||||
i2c, USB, SD/eMMC, SATA, PCIe, etc.
|
||||
|
||||
config MSM_MMCC_8994
|
||||
tristate "MSM8994 Multimedia Clock Controller"
|
||||
select MSM_GCC_8994
|
||||
@ -564,6 +572,14 @@ config SM_CAMCC_8250
|
||||
Support for the camera clock controller on SM8250 devices.
|
||||
Say Y if you want to support camera devices and camera functionality.
|
||||
|
||||
config SDX_GCC_65
|
||||
tristate "SDX65 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on SDX65 devices.
|
||||
Say Y if you want to use peripheral devices such as UART,
|
||||
SPI, I2C, USB, SD/UFS, PCIe etc.
|
||||
|
||||
config SM_DISPCC_8250
|
||||
tristate "SM8150 and SM8250 Display Clock Controller"
|
||||
depends on SM_GCC_8150 || SM_GCC_8250
|
||||
@ -618,6 +634,14 @@ config SM_GCC_8350
|
||||
Say Y if you want to use peripheral devices such as UART,
|
||||
SPI, I2C, USB, SD/UFS, PCIe etc.
|
||||
|
||||
config SM_GCC_8450
|
||||
tristate "SM8450 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on SM8450 devices.
|
||||
Say Y if you want to use peripheral devices such as UART,
|
||||
SPI, I2C, USB, SD/UFS, PCIe etc.
|
||||
|
||||
config SM_GPUCC_8150
|
||||
tristate "SM8150 Graphics Clock Controller"
|
||||
select SM_GCC_8150
|
||||
|
@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_GCC_8939) += gcc-msm8939.o
|
||||
obj-$(CONFIG_MSM_GCC_8953) += gcc-msm8953.o
|
||||
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
|
||||
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
|
||||
obj-$(CONFIG_MSM_GCC_8976) += gcc-msm8976.o
|
||||
obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
|
||||
obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
|
||||
obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
|
||||
@ -83,6 +84,7 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
|
||||
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
|
||||
obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o
|
||||
obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o
|
||||
obj-$(CONFIG_SDX_GCC_65) += gcc-sdx65.o
|
||||
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
|
||||
obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o
|
||||
obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o
|
||||
@ -90,6 +92,7 @@ obj-$(CONFIG_SM_GCC_6350) += gcc-sm6350.o
|
||||
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
|
||||
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
|
||||
obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o
|
||||
obj-$(CONFIG_SM_GCC_8450) += gcc-sm8450.o
|
||||
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
|
||||
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
|
||||
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -139,6 +140,20 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
|
||||
[PLL_OFF_OPMODE] = 0x28,
|
||||
[PLL_OFF_STATUS] = 0x38,
|
||||
},
|
||||
[CLK_ALPHA_PLL_TYPE_LUCID_EVO] = {
|
||||
[PLL_OFF_OPMODE] = 0x04,
|
||||
[PLL_OFF_STATUS] = 0x0c,
|
||||
[PLL_OFF_L_VAL] = 0x10,
|
||||
[PLL_OFF_ALPHA_VAL] = 0x14,
|
||||
[PLL_OFF_USER_CTL] = 0x18,
|
||||
[PLL_OFF_USER_CTL_U] = 0x1c,
|
||||
[PLL_OFF_CONFIG_CTL] = 0x20,
|
||||
[PLL_OFF_CONFIG_CTL_U] = 0x24,
|
||||
[PLL_OFF_CONFIG_CTL_U1] = 0x28,
|
||||
[PLL_OFF_TEST_CTL] = 0x2c,
|
||||
[PLL_OFF_TEST_CTL_U] = 0x30,
|
||||
[PLL_OFF_TEST_CTL_U1] = 0x34,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
||||
|
||||
@ -175,6 +190,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
||||
#define LUCID_5LPE_PLL_LATCH_INPUT BIT(14)
|
||||
#define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21)
|
||||
|
||||
/* LUCID EVO PLL specific settings and offsets */
|
||||
#define LUCID_EVO_ENABLE_VOTE_RUN BIT(25)
|
||||
#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)
|
||||
|
||||
/* ZONDA PLL specific */
|
||||
#define ZONDA_PLL_OUT_MASK 0xf
|
||||
#define ZONDA_STAY_IN_CFA BIT(16)
|
||||
@ -204,7 +223,7 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (count = 100; count > 0; count--) {
|
||||
for (count = 200; count > 0; count--) {
|
||||
ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1750,24 +1769,32 @@ static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
LUCID_5LPE_ALPHA_PLL_ACK_LATCH);
|
||||
}
|
||||
|
||||
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
static int __clk_lucid_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate,
|
||||
unsigned long enable_vote_run)
|
||||
{
|
||||
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
|
||||
int i, val = 0, div, ret;
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
int i, val, div, ret;
|
||||
u32 mask;
|
||||
|
||||
/*
|
||||
* If the PLL is in FSM mode, then treat set_rate callback as a
|
||||
* no-operation.
|
||||
*/
|
||||
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
|
||||
ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & LUCID_5LPE_ENABLE_VOTE_RUN)
|
||||
if (val & enable_vote_run)
|
||||
return 0;
|
||||
|
||||
if (!pll->post_div_table) {
|
||||
pr_err("Missing the post_div_table for the %s PLL\n",
|
||||
clk_hw_get_name(&pll->clkr.hw));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||
for (i = 0; i < pll->num_post_div; i++) {
|
||||
if (pll->post_div_table[i].div == div) {
|
||||
@ -1781,6 +1808,12 @@ static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long
|
||||
mask, val << pll->post_div_shift);
|
||||
}
|
||||
|
||||
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_5LPE_ENABLE_VOTE_RUN);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
|
||||
.prepare = alpha_pll_lucid_5lpe_prepare,
|
||||
.enable = alpha_pll_lucid_5lpe_enable,
|
||||
@ -1960,3 +1993,124 @@ const struct clk_ops clk_alpha_pll_zonda_ops = {
|
||||
.set_rate = clk_zonda_pll_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL(clk_alpha_pll_zonda_ops);
|
||||
|
||||
static int alpha_pll_lucid_evo_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If in FSM mode, just vote for it */
|
||||
if (val & LUCID_EVO_ENABLE_VOTE_RUN) {
|
||||
ret = clk_enable_regmap(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
return wait_for_pll_enable_lock(pll);
|
||||
}
|
||||
|
||||
/* Check if PLL is already enabled */
|
||||
ret = trion_pll_is_enabled(pll, regmap);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else if (ret) {
|
||||
pr_warn("%s PLL is already enabled\n", clk_hw_get_name(&pll->clkr.hw));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set operation mode to RUN */
|
||||
regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);
|
||||
|
||||
ret = wait_for_pll_enable_lock(pll);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable the PLL outputs */
|
||||
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable the global PLL outputs */
|
||||
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Ensure that the write above goes through before returning. */
|
||||
mb();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void alpha_pll_lucid_evo_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* If in FSM mode, just unvote it */
|
||||
if (val & LUCID_EVO_ENABLE_VOTE_RUN) {
|
||||
clk_disable_regmap(hw);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable the global PLL output */
|
||||
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* Disable the PLL outputs */
|
||||
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* Place the PLL mode in STANDBY */
|
||||
regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
|
||||
}
|
||||
|
||||
static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 l, frac;
|
||||
|
||||
regmap_read(regmap, PLL_L_VAL(pll), &l);
|
||||
l &= LUCID_EVO_PLL_L_VAL_MASK;
|
||||
regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);
|
||||
|
||||
return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll));
|
||||
}
|
||||
|
||||
static int clk_lucid_evo_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_EVO_ENABLE_VOTE_RUN);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops = {
|
||||
.enable = alpha_pll_lucid_evo_enable,
|
||||
.disable = alpha_pll_lucid_evo_disable,
|
||||
.is_enabled = clk_trion_pll_is_enabled,
|
||||
.recalc_rate = alpha_pll_lucid_evo_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_round_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_evo_ops);
|
||||
|
||||
const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops = {
|
||||
.recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_postdiv_fabia_round_rate,
|
||||
.set_rate = clk_lucid_evo_pll_postdiv_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_evo_ops);
|
||||
|
@ -17,6 +17,7 @@ enum {
|
||||
CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
|
||||
CLK_ALPHA_PLL_TYPE_AGERA,
|
||||
CLK_ALPHA_PLL_TYPE_ZONDA,
|
||||
CLK_ALPHA_PLL_TYPE_LUCID_EVO,
|
||||
CLK_ALPHA_PLL_TYPE_MAX,
|
||||
};
|
||||
|
||||
@ -151,6 +152,8 @@ extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
|
||||
|
||||
extern const struct clk_ops clk_alpha_pll_zonda_ops;
|
||||
#define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops
|
||||
extern const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops;
|
||||
|
||||
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config);
|
||||
|
@ -515,6 +515,32 @@ static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
|
||||
/* Resource name must match resource id present in cmd-db */
|
||||
DEFINE_CLK_RPMH_ARC(sc7280, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 4);
|
||||
|
||||
DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
|
||||
DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 4);
|
||||
|
||||
static struct clk_hw *sm8450_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
|
||||
[RPMH_LN_BB_CLK1] = &sm8450_ln_bb_clk1.hw,
|
||||
[RPMH_LN_BB_CLK1_A] = &sm8450_ln_bb_clk1_ao.hw,
|
||||
[RPMH_LN_BB_CLK2] = &sm8450_ln_bb_clk2.hw,
|
||||
[RPMH_LN_BB_CLK2_A] = &sm8450_ln_bb_clk2_ao.hw,
|
||||
[RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
|
||||
[RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
|
||||
[RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
|
||||
[RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
|
||||
[RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
|
||||
[RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
|
||||
[RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
|
||||
[RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
|
||||
[RPMH_IPA_CLK] = &sdm845_ipa.hw,
|
||||
};
|
||||
|
||||
static const struct clk_rpmh_desc clk_rpmh_sm8450 = {
|
||||
.clks = sm8450_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sm8450_rpmh_clocks),
|
||||
};
|
||||
|
||||
static struct clk_hw *sc7280_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
|
||||
@ -556,6 +582,30 @@ static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
|
||||
.num_clks = ARRAY_SIZE(sm6350_rpmh_clocks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_RPMH_VRM(sdx65, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
|
||||
|
||||
static struct clk_hw *sdx65_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
|
||||
[RPMH_LN_BB_CLK1] = &sdx65_ln_bb_clk1.hw,
|
||||
[RPMH_LN_BB_CLK1_A] = &sdx65_ln_bb_clk1_ao.hw,
|
||||
[RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
|
||||
[RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
|
||||
[RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
|
||||
[RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
|
||||
[RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
|
||||
[RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
|
||||
[RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
|
||||
[RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
|
||||
[RPMH_IPA_CLK] = &sdm845_ipa.hw,
|
||||
[RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
|
||||
};
|
||||
|
||||
static const struct clk_rpmh_desc clk_rpmh_sdx65 = {
|
||||
.clks = sdx65_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sdx65_rpmh_clocks),
|
||||
};
|
||||
|
||||
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
@ -643,10 +693,12 @@ static const struct of_device_id clk_rpmh_match_table[] = {
|
||||
{ .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
|
||||
{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
|
||||
{ .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
|
||||
{ .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65},
|
||||
{ .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
|
||||
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
|
||||
{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
|
||||
{ .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
|
||||
{ .compatible = "qcom,sm8450-rpmh-clk", .data = &clk_rpmh_sm8450},
|
||||
{ .compatible = "qcom,sc7280-rpmh-clk", .data = &clk_rpmh_sc7280},
|
||||
{ }
|
||||
};
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/soc/qcom/smd-rpm.h>
|
||||
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/mfd/qcom-rpm.h>
|
||||
|
||||
#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
|
||||
#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
|
||||
@ -151,12 +150,6 @@ struct clk_smd_rpm_req {
|
||||
__le32 value;
|
||||
};
|
||||
|
||||
struct rpm_cc {
|
||||
struct qcom_rpm *rpm;
|
||||
struct clk_smd_rpm **clks;
|
||||
size_t num_clks;
|
||||
};
|
||||
|
||||
struct rpm_smd_clk_desc {
|
||||
struct clk_smd_rpm **clks;
|
||||
size_t num_clks;
|
||||
@ -196,10 +189,6 @@ static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,
|
||||
.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
|
||||
};
|
||||
|
||||
/* Buffered clock needs a binary value */
|
||||
if (r->rpm_res_type == QCOM_SMD_RPM_CLK_BUF_A)
|
||||
req.value = cpu_to_le32(!!req.value);
|
||||
|
||||
return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
r->rpm_res_type, r->rpm_clk_id, &req,
|
||||
sizeof(req));
|
||||
@ -214,10 +203,6 @@ static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,
|
||||
.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
|
||||
};
|
||||
|
||||
/* Buffered clock needs a binary value */
|
||||
if (r->rpm_res_type == QCOM_SMD_RPM_CLK_BUF_A)
|
||||
req.value = cpu_to_le32(!!req.value);
|
||||
|
||||
return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
|
||||
r->rpm_res_type, r->rpm_clk_id, &req,
|
||||
sizeof(req));
|
||||
@ -1159,20 +1144,19 @@ MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
|
||||
static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
struct rpm_cc *rcc = data;
|
||||
const struct rpm_smd_clk_desc *desc = data;
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx >= rcc->num_clks) {
|
||||
if (idx >= desc->num_clks) {
|
||||
pr_err("%s: invalid index %u\n", __func__, idx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
|
||||
return desc->clks[idx] ? &desc->clks[idx]->hw : ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
static int rpm_smd_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rpm_cc *rcc;
|
||||
int ret;
|
||||
size_t num_clks, i;
|
||||
struct qcom_smd_rpm *rpm;
|
||||
@ -1192,13 +1176,6 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
|
||||
rpm_smd_clks = desc->clks;
|
||||
num_clks = desc->num_clks;
|
||||
|
||||
rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
|
||||
if (!rcc)
|
||||
return -ENOMEM;
|
||||
|
||||
rcc->clks = rpm_smd_clks;
|
||||
rcc->num_clks = num_clks;
|
||||
|
||||
for (i = 0; i < num_clks; i++) {
|
||||
if (!rpm_smd_clks[i])
|
||||
continue;
|
||||
@ -1224,7 +1201,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get,
|
||||
rcc);
|
||||
(void *)desc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
4155
drivers/clk/qcom/gcc-msm8976.c
Normal file
4155
drivers/clk/qcom/gcc-msm8976.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -2917,7 +2917,7 @@ static struct clk_branch gcc_cfg_noc_lpass_clk = {
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_cfg_noc_lpass_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
.ops = &clk_branch2_aon_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
1611
drivers/clk/qcom/gcc-sdx65.c
Normal file
1611
drivers/clk/qcom/gcc-sdx65.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2020-2021, Linaro Limited
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
3304
drivers/clk/qcom/gcc-sm8450.c
Normal file
3304
drivers/clk/qcom/gcc-sm8450.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -31,6 +31,7 @@ config CLK_RENESAS
|
||||
select CLK_R8A77990 if ARCH_R8A77990
|
||||
select CLK_R8A77995 if ARCH_R8A77995
|
||||
select CLK_R8A779A0 if ARCH_R8A779A0
|
||||
select CLK_R8A779F0 if ARCH_R8A779F0
|
||||
select CLK_R9A06G032 if ARCH_R9A06G032
|
||||
select CLK_R9A07G044 if ARCH_R9A07G044
|
||||
select CLK_SH73A0 if ARCH_SH73A0
|
||||
@ -149,8 +150,11 @@ config CLK_R8A77995
|
||||
|
||||
config CLK_R8A779A0
|
||||
bool "R-Car V3U clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_CPG_LIB
|
||||
select CLK_RENESAS_CPG_MSSR
|
||||
select CLK_RCAR_GEN4_CPG
|
||||
|
||||
config CLK_R8A779F0
|
||||
bool "R-Car S4-8 clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_GEN4_CPG
|
||||
|
||||
config CLK_R9A06G032
|
||||
bool "RZ/N1D clock support" if COMPILE_TEST
|
||||
@ -178,6 +182,11 @@ config CLK_RCAR_GEN3_CPG
|
||||
select CLK_RCAR_CPG_LIB
|
||||
select CLK_RENESAS_CPG_MSSR
|
||||
|
||||
config CLK_RCAR_GEN4_CPG
|
||||
bool "R-Car Gen4 clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_CPG_LIB
|
||||
select CLK_RENESAS_CPG_MSSR
|
||||
|
||||
config CLK_RCAR_USB2_CLOCK_SEL
|
||||
bool "Renesas R-Car USB2 clock selector support"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
|
@ -28,6 +28,7 @@ obj-$(CONFIG_CLK_R8A77980) += r8a77980-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
|
||||
obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
|
||||
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
|
||||
@ -36,6 +37,7 @@ obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
|
||||
obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o
|
||||
obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o
|
||||
obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o
|
||||
obj-$(CONFIG_CLK_RCAR_GEN4_CPG) += rcar-gen4-cpg.o
|
||||
obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o
|
||||
obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o
|
||||
|
||||
|
@ -100,10 +100,14 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A774A1_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A774A1_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A774A1_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A774A1_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A774A1_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A774A1_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SDH("sd0h", R8A774A1_CLK_SD0H, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SDH("sd1h", R8A774A1_CLK_SD1H, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SDH("sd2h", R8A774A1_CLK_SD2H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd3h", R8A774A1_CLK_SD3H, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SD("sd0", R8A774A1_CLK_SD0, R8A774A1_CLK_SD0H, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A774A1_CLK_SD1, R8A774A1_CLK_SD1H, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A774A1_CLK_SD2, R8A774A1_CLK_SD2H, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A774A1_CLK_SD3, R8A774A1_CLK_SD3H, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A774A1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A774A1_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
@ -97,10 +97,14 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A774B1_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A774B1_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A774B1_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A774B1_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A774B1_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A774B1_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SDH("sd0h", R8A774B1_CLK_SD0H, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SDH("sd1h", R8A774B1_CLK_SD1H, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SDH("sd2h", R8A774B1_CLK_SD2H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd3h", R8A774B1_CLK_SD3H, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SD("sd0", R8A774B1_CLK_SD0, R8A774B1_CLK_SD0H, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A774B1_CLK_SD1, R8A774B1_CLK_SD1H, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A774B1_CLK_SD2, R8A774B1_CLK_SD2H, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A774B1_CLK_SD3, R8A774B1_CLK_SD3H, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A774B1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A774B1_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
@ -108,9 +108,12 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A774C0_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A774C0_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A774C0_CLK_SD0, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A774C0_CLK_SD1, CLK_SDSRC, 0x0078),
|
||||
DEF_GEN3_SD("sd3", R8A774C0_CLK_SD3, CLK_SDSRC, 0x026c),
|
||||
DEF_GEN3_SDH("sd0h", R8A774C0_CLK_SD0H, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SDH("sd1h", R8A774C0_CLK_SD1H, CLK_SDSRC, 0x0078),
|
||||
DEF_GEN3_SDH("sd3h", R8A774C0_CLK_SD3H, CLK_SDSRC, 0x026c),
|
||||
DEF_GEN3_SD("sd0", R8A774C0_CLK_SD0, R8A774C0_CLK_SD0H, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A774C0_CLK_SD1, R8A774C0_CLK_SD1H, 0x0078),
|
||||
DEF_GEN3_SD("sd3", R8A774C0_CLK_SD3, R8A774C0_CLK_SD3H, 0x026c),
|
||||
|
||||
DEF_FIXED("cl", R8A774C0_CLK_CL, CLK_PLL1, 48, 1),
|
||||
DEF_FIXED("cp", R8A774C0_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
@ -100,10 +100,14 @@ static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A774E1_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A774E1_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A774E1_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A774E1_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A774E1_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A774E1_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SDH("sd0h", R8A774E1_CLK_SD0H, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SDH("sd1h", R8A774E1_CLK_SD1H, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SDH("sd2h", R8A774E1_CLK_SD2H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd3h", R8A774E1_CLK_SD3H, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SD("sd0", R8A774E1_CLK_SD0, R8A774E1_CLK_SD0H, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A774E1_CLK_SD1, R8A774E1_CLK_SD1H, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A774E1_CLK_SD2, R8A774E1_CLK_SD2H, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A774E1_CLK_SD3, R8A774E1_CLK_SD3H, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A774E1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cr", R8A774E1_CLK_CR, CLK_PLL1_DIV4, 2, 1),
|
||||
|
@ -104,10 +104,14 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
|
||||
DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SDH("sd0h", R8A7795_CLK_SD0H, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SDH("sd1h", R8A7795_CLK_SD1H, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SDH("sd2h", R8A7795_CLK_SD2H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd3h", R8A7795_CLK_SD3H, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, R8A7795_CLK_SD0H, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, R8A7795_CLK_SD1H, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, R8A7795_CLK_SD2H, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, R8A7795_CLK_SD3H, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cr", R8A7795_CLK_CR, CLK_PLL1_DIV4, 2, 1),
|
||||
|
@ -106,10 +106,14 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SDH("sd0h", R8A7796_CLK_SD0H, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SDH("sd1h", R8A7796_CLK_SD1H, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SDH("sd2h", R8A7796_CLK_SD2H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd3h", R8A7796_CLK_SD3H, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, R8A7796_CLK_SD0H, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, R8A7796_CLK_SD1H, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, R8A7796_CLK_SD2H, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, R8A7796_CLK_SD3H, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cr", R8A7796_CLK_CR, CLK_PLL1_DIV4, 2, 1),
|
||||
|
@ -101,10 +101,14 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A77965_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A77965_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A77965_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A77965_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A77965_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A77965_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SDH("sd0h", R8A77965_CLK_SD0H, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SDH("sd1h", R8A77965_CLK_SD1H, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SDH("sd2h", R8A77965_CLK_SD2H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd3h", R8A77965_CLK_SD3H, CLK_SDSRC, 0x26c),
|
||||
DEF_GEN3_SD("sd0", R8A77965_CLK_SD0, R8A77965_CLK_SD0H, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A77965_CLK_SD1, R8A77965_CLK_SD1H, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A77965_CLK_SD2, R8A77965_CLK_SD2H, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A77965_CLK_SD3, R8A77965_CLK_SD3H, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A77965_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cr", R8A77965_CLK_CR, CLK_PLL1_DIV4, 2, 1),
|
||||
|
@ -96,7 +96,8 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A77980_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A77980_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A77980_CLK_SD0, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SDH("sd0h", R8A77980_CLK_SD0H, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SD("sd0", R8A77980_CLK_SD0, R8A77980_CLK_SD0H, 0x0074),
|
||||
|
||||
DEF_FIXED("cl", R8A77980_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A77980_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
@ -100,9 +100,12 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
|
||||
DEF_FIXED("s3d2", R8A77990_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A77990_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A77990_CLK_SD0, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A77990_CLK_SD1, CLK_SDSRC, 0x0078),
|
||||
DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, CLK_SDSRC, 0x026c),
|
||||
DEF_GEN3_SDH("sd0h", R8A77990_CLK_SD0H, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SDH("sd1h", R8A77990_CLK_SD1H, CLK_SDSRC, 0x0078),
|
||||
DEF_GEN3_SDH("sd3h", R8A77990_CLK_SD3H, CLK_SDSRC, 0x026c),
|
||||
DEF_GEN3_SD("sd0", R8A77990_CLK_SD0, R8A77990_CLK_SD0H, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A77990_CLK_SD1, R8A77990_CLK_SD1H, 0x0078),
|
||||
DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, R8A77990_CLK_SD3H, 0x026c),
|
||||
|
||||
DEF_FIXED("cl", R8A77990_CLK_CL, CLK_PLL1, 48, 1),
|
||||
DEF_FIXED("cr", R8A77990_CLK_CR, CLK_PLL1D2, 2, 1),
|
||||
|
@ -103,7 +103,8 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
|
||||
DEF_GEN3_PE("s3d2c", R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
|
||||
DEF_GEN3_PE("s3d4c", R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SDH("sd0h", R8A77995_CLK_SD0H, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, R8A77995_CLK_SD0H, 0x268),
|
||||
|
||||
DEF_DIV6P1("canfd", R8A77995_CLK_CANFD, CLK_PLL0D3, 0x244),
|
||||
DEF_DIV6P1("mso", R8A77995_CLK_MSO, CLK_PLL1D2, 0x014),
|
||||
|
@ -10,46 +10,19 @@
|
||||
* Copyright (C) 2015 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/renesas/rcar-rst.h>
|
||||
|
||||
#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
|
||||
|
||||
#include "rcar-cpg-lib.h"
|
||||
#include "renesas-cpg-mssr.h"
|
||||
|
||||
enum rcar_r8a779a0_clk_types {
|
||||
CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM,
|
||||
CLK_TYPE_R8A779A0_PLL1,
|
||||
CLK_TYPE_R8A779A0_PLL2X_3X, /* PLL[23][01] */
|
||||
CLK_TYPE_R8A779A0_PLL5,
|
||||
CLK_TYPE_R8A779A0_Z,
|
||||
CLK_TYPE_R8A779A0_SD,
|
||||
CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */
|
||||
CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */
|
||||
CLK_TYPE_R8A779A0_RPCSRC,
|
||||
CLK_TYPE_R8A779A0_RPC,
|
||||
CLK_TYPE_R8A779A0_RPCD2,
|
||||
};
|
||||
|
||||
struct rcar_r8a779a0_cpg_pll_config {
|
||||
u8 extal_div;
|
||||
u8 pll1_mult;
|
||||
u8 pll1_div;
|
||||
u8 pll5_mult;
|
||||
u8 pll5_div;
|
||||
u8 osc_prediv;
|
||||
};
|
||||
#include "rcar-gen4-cpg.h"
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
@ -85,33 +58,18 @@ enum clk_ids {
|
||||
};
|
||||
|
||||
#define DEF_PLL(_name, _id, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL2X_3X, CLK_MAIN, \
|
||||
.offset = _offset)
|
||||
|
||||
#define DEF_Z(_name, _id, _parent, _div, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_Z, _parent, .div = _div, \
|
||||
.offset = _offset)
|
||||
|
||||
#define DEF_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset)
|
||||
|
||||
#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL, \
|
||||
(_parent0) << 16 | (_parent1), \
|
||||
.div = (_div0) << 16 | (_div1), .offset = _md)
|
||||
|
||||
#define DEF_OSC(_name, _id, _parent, _div) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div)
|
||||
|
||||
static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_R8A779A0_MAIN, CLK_EXTAL),
|
||||
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_R8A779A0_PLL1, CLK_MAIN),
|
||||
DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_R8A779A0_PLL5, CLK_MAIN),
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
|
||||
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
|
||||
DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
|
||||
DEF_PLL(".pll20", CLK_PLL20, 0x0834),
|
||||
DEF_PLL(".pll21", CLK_PLL21, 0x0838),
|
||||
DEF_PLL(".pll30", CLK_PLL30, 0x083c),
|
||||
@ -128,14 +86,14 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1),
|
||||
DEF_RATE(".oco", CLK_OCO, 32768),
|
||||
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_R8A779A0_RPCSRC, CLK_PLL5),
|
||||
DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_R8A779A0_RPC, CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A779A0_CLK_RPCD2, CLK_TYPE_R8A779A0_RPCD2,
|
||||
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
|
||||
DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A779A0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2,
|
||||
R8A779A0_CLK_RPC),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
DEF_Z("z0", R8A779A0_CLK_Z0, CLK_PLL20, 2, 0),
|
||||
DEF_Z("z1", R8A779A0_CLK_Z1, CLK_PLL21, 2, 8),
|
||||
DEF_GEN4_Z("z0", R8A779A0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL20, 2, 0),
|
||||
DEF_GEN4_Z("z1", R8A779A0_CLK_Z1, CLK_TYPE_GEN4_Z, CLK_PLL21, 2, 8),
|
||||
DEF_FIXED("zx", R8A779A0_CLK_ZX, CLK_PLL20_DIV2, 2, 1),
|
||||
DEF_FIXED("s1d1", R8A779A0_CLK_S1D1, CLK_S1, 1, 1),
|
||||
DEF_FIXED("s1d2", R8A779A0_CLK_S1D2, CLK_S1, 2, 1),
|
||||
@ -159,15 +117,16 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
||||
DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
DEF_FIXED("cl16mck", R8A779A0_CLK_CL16MCK, CLK_PLL1_DIV2, 64, 1),
|
||||
|
||||
DEF_SD("sd0", R8A779A0_CLK_SD0, CLK_SDSRC, 0x870),
|
||||
DEF_GEN4_SDH("sdh0", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870),
|
||||
DEF_GEN4_SD("sd0", R8A779A0_CLK_SD0, R8A779A0_CLK_SD0H, 0x870),
|
||||
|
||||
DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
|
||||
DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878),
|
||||
DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880),
|
||||
DEF_DIV6P1("dsi", R8A779A0_CLK_DSI, CLK_PLL5_DIV4, 0x884),
|
||||
|
||||
DEF_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8),
|
||||
DEF_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
|
||||
DEF_GEN4_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8),
|
||||
DEF_GEN4_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
|
||||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
|
||||
@ -271,256 +230,6 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
|
||||
DEF_MOD("vspx3", 1031, R8A779A0_CLK_S1D1),
|
||||
};
|
||||
|
||||
static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
|
||||
/*
|
||||
* Z0 Clock & Z1 Clock
|
||||
*/
|
||||
#define CPG_FRQCRB 0x00000804
|
||||
#define CPG_FRQCRB_KICK BIT(31)
|
||||
#define CPG_FRQCRC 0x00000808
|
||||
|
||||
struct cpg_z_clk {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
void __iomem *kick_reg;
|
||||
unsigned long max_rate; /* Maximum rate for normal mode */
|
||||
unsigned int fixed_div;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
|
||||
|
||||
static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int mult;
|
||||
u32 val;
|
||||
|
||||
val = readl(zclk->reg) & zclk->mask;
|
||||
mult = 32 - (val >> __ffs(zclk->mask));
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
|
||||
32 * zclk->fixed_div);
|
||||
}
|
||||
|
||||
static int cpg_z_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int min_mult, max_mult, mult;
|
||||
unsigned long rate, prate;
|
||||
|
||||
rate = min(req->rate, req->max_rate);
|
||||
if (rate <= zclk->max_rate) {
|
||||
/* Set parent rate to initial value for normal modes */
|
||||
prate = zclk->max_rate;
|
||||
} else {
|
||||
/* Set increased parent rate for boost modes */
|
||||
prate = rate;
|
||||
}
|
||||
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||
prate * zclk->fixed_div);
|
||||
|
||||
prate = req->best_parent_rate / zclk->fixed_div;
|
||||
min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
|
||||
max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
|
||||
if (max_mult < min_mult)
|
||||
return -EINVAL;
|
||||
|
||||
mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
|
||||
mult = clamp(mult, min_mult, max_mult);
|
||||
|
||||
req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int mult;
|
||||
unsigned int i;
|
||||
|
||||
mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
|
||||
parent_rate);
|
||||
mult = clamp(mult, 1U, 32U);
|
||||
|
||||
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
|
||||
return -EBUSY;
|
||||
|
||||
cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
|
||||
|
||||
/*
|
||||
* Set KICK bit in FRQCRB to update hardware setting and wait for
|
||||
* clock change completion.
|
||||
*/
|
||||
cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
|
||||
|
||||
/*
|
||||
* Note: There is no HW information about the worst case latency.
|
||||
*
|
||||
* Using experimental measurements, it seems that no more than
|
||||
* ~10 iterations are needed, independently of the CPU rate.
|
||||
* Since this value might be dependent on external xtal rate, pll1
|
||||
* rate or even the other emulation clocks rate, use 1000 as a
|
||||
* "super" safe value.
|
||||
*/
|
||||
for (i = 1000; i; i--) {
|
||||
if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
|
||||
return 0;
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_z_clk_ops = {
|
||||
.recalc_rate = cpg_z_clk_recalc_rate,
|
||||
.determine_rate = cpg_z_clk_determine_rate,
|
||||
.set_rate = cpg_z_clk_set_rate,
|
||||
};
|
||||
|
||||
static struct clk * __init cpg_z_clk_register(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
unsigned int div,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct clk_init_data init = {};
|
||||
struct cpg_z_clk *zclk;
|
||||
struct clk *clk;
|
||||
|
||||
zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
|
||||
if (!zclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_z_clk_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
zclk->reg = reg + CPG_FRQCRC;
|
||||
zclk->kick_reg = reg + CPG_FRQCRB;
|
||||
zclk->hw.init = &init;
|
||||
zclk->mask = GENMASK(offset + 4, offset);
|
||||
zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
|
||||
|
||||
clk = clk_register(NULL, &zclk->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(zclk);
|
||||
return clk;
|
||||
}
|
||||
|
||||
zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
|
||||
zclk->fixed_div;
|
||||
return clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* RPC Clocks
|
||||
*/
|
||||
#define CPG_RPCCKCR 0x874
|
||||
|
||||
static const struct clk_div_table cpg_rpcsrc_div_table[] = {
|
||||
{ 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
|
||||
};
|
||||
|
||||
static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
const struct clk *parent;
|
||||
unsigned int mult = 1;
|
||||
unsigned int div = 1;
|
||||
u32 value;
|
||||
|
||||
parent = clks[core->parent & 0xffff]; /* some types use high bits */
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
|
||||
switch (core->type) {
|
||||
case CLK_TYPE_R8A779A0_MAIN:
|
||||
div = cpg_pll_config->extal_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_PLL1:
|
||||
mult = cpg_pll_config->pll1_mult;
|
||||
div = cpg_pll_config->pll1_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_PLL2X_3X:
|
||||
value = readl(base + core->offset);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_PLL5:
|
||||
mult = cpg_pll_config->pll5_mult;
|
||||
div = cpg_pll_config->pll5_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_Z:
|
||||
return cpg_z_clk_register(core->name, __clk_get_name(parent),
|
||||
base, core->div, core->offset);
|
||||
|
||||
case CLK_TYPE_R8A779A0_SD:
|
||||
return cpg_sd_clk_register(core->name, base, core->offset,
|
||||
__clk_get_name(parent), notifiers,
|
||||
false);
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_MDSEL:
|
||||
/*
|
||||
* Clock selectable between two parents and two fixed dividers
|
||||
* using a mode pin
|
||||
*/
|
||||
if (cpg_mode & BIT(core->offset)) {
|
||||
div = core->div & 0xffff;
|
||||
} else {
|
||||
parent = clks[core->parent >> 16];
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
div = core->div >> 16;
|
||||
}
|
||||
mult = 1;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_OSC:
|
||||
/*
|
||||
* Clock combining OSC EXTAL predivider and a fixed divider
|
||||
*/
|
||||
div = cpg_pll_config->osc_prediv * core->div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_RPCSRC:
|
||||
return clk_register_divider_table(NULL, core->name,
|
||||
__clk_get_name(parent), 0,
|
||||
base + CPG_RPCCKCR, 3, 2, 0,
|
||||
cpg_rpcsrc_div_table,
|
||||
&cpg_lock);
|
||||
|
||||
case CLK_TYPE_R8A779A0_RPC:
|
||||
return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent), notifiers);
|
||||
|
||||
case CLK_TYPE_R8A779A0_RPCD2:
|
||||
return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent));
|
||||
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return clk_register_fixed_factor(NULL, core->name,
|
||||
__clk_get_name(parent), 0, mult, div);
|
||||
}
|
||||
|
||||
static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
|
||||
MOD_CLK_ID(907), /* RWDT */
|
||||
};
|
||||
@ -539,17 +248,19 @@ static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
|
||||
*/
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
|
||||
(((md) & BIT(13)) >> 13))
|
||||
|
||||
static const struct rcar_r8a779a0_cpg_pll_config cpg_pll_configs[4] = {
|
||||
/* EXTAL div PLL1 mult/div PLL5 mult/div OSC prediv */
|
||||
{ 1, 128, 1, 192, 1, 16, },
|
||||
{ 1, 106, 1, 160, 1, 19, },
|
||||
{ 0, 0, 0, 0, 0, 0, },
|
||||
{ 2, 128, 1, 192, 1, 32, },
|
||||
static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
|
||||
/* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
|
||||
{ 1, 128, 1, 0, 0, 0, 0, 192, 1, 0, 0, 16, },
|
||||
{ 1, 106, 1, 0, 0, 0, 0, 160, 1, 0, 0, 19, },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
|
||||
{ 2, 128, 1, 0, 0, 0, 0, 192, 1, 0, 0, 32, },
|
||||
};
|
||||
|
||||
|
||||
static int __init r8a779a0_cpg_mssr_init(struct device *dev)
|
||||
{
|
||||
const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
|
||||
u32 cpg_mode;
|
||||
int error;
|
||||
|
||||
error = rcar_rst_read_mode_pins(&cpg_mode);
|
||||
@ -557,10 +268,8 @@ static int __init r8a779a0_cpg_mssr_init(struct device *dev)
|
||||
return error;
|
||||
|
||||
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
|
||||
cpg_clk_extalr = CLK_EXTALR;
|
||||
spin_lock_init(&cpg_lock);
|
||||
|
||||
return 0;
|
||||
return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
|
||||
}
|
||||
|
||||
const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
|
||||
@ -581,7 +290,7 @@ const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
|
||||
|
||||
/* Callbacks */
|
||||
.init = r8a779a0_cpg_mssr_init,
|
||||
.cpg_clk_register = rcar_r8a779a0_cpg_clk_register,
|
||||
.cpg_clk_register = rcar_gen4_cpg_clk_register,
|
||||
|
||||
.reg_layout = CLK_REG_LAYOUT_RCAR_V3U,
|
||||
.reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
|
||||
};
|
||||
|
183
drivers/clk/renesas/r8a779f0-cpg-mssr.c
Normal file
183
drivers/clk/renesas/r8a779f0-cpg-mssr.c
Normal file
@ -0,0 +1,183 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* r8a779f0 Clock Pulse Generator / Module Standby and Software Reset
|
||||
*
|
||||
* Copyright (C) 2021 Renesas Electronics Corp.
|
||||
*
|
||||
* Based on r8a779a0-cpg-mssr.c
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/soc/renesas/rcar-rst.h>
|
||||
|
||||
#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
#include "rcar-gen4-cpg.h"
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R8A779F0_CLK_R,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_EXTAL,
|
||||
CLK_EXTALR,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_MAIN,
|
||||
CLK_PLL1,
|
||||
CLK_PLL2,
|
||||
CLK_PLL3,
|
||||
CLK_PLL5,
|
||||
CLK_PLL6,
|
||||
CLK_PLL1_DIV2,
|
||||
CLK_PLL2_DIV2,
|
||||
CLK_PLL3_DIV2,
|
||||
CLK_PLL5_DIV2,
|
||||
CLK_PLL5_DIV4,
|
||||
CLK_PLL6_DIV2,
|
||||
CLK_S0,
|
||||
CLK_SDSRC,
|
||||
CLK_RPCSRC,
|
||||
CLK_OCO,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE
|
||||
};
|
||||
|
||||
static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
|
||||
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
|
||||
DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN),
|
||||
DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN),
|
||||
DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
|
||||
DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN),
|
||||
|
||||
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
|
||||
DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
|
||||
DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
|
||||
DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
|
||||
DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
|
||||
DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
|
||||
DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
|
||||
DEF_RATE(".oco", CLK_OCO, 32768),
|
||||
|
||||
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
|
||||
DEF_BASE(".rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A779F0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
DEF_FIXED("s0d2", R8A779F0_CLK_S0D2, CLK_S0, 2, 1),
|
||||
DEF_FIXED("s0d3", R8A779F0_CLK_S0D3, CLK_S0, 3, 1),
|
||||
DEF_FIXED("s0d4", R8A779F0_CLK_S0D4, CLK_S0, 4, 1),
|
||||
DEF_FIXED("cl16m", R8A779F0_CLK_CL16M, CLK_S0, 48, 1),
|
||||
DEF_FIXED("s0d2_mm", R8A779F0_CLK_S0D2_MM, CLK_S0, 2, 1),
|
||||
DEF_FIXED("s0d3_mm", R8A779F0_CLK_S0D3_MM, CLK_S0, 3, 1),
|
||||
DEF_FIXED("s0d4_mm", R8A779F0_CLK_S0D4_MM, CLK_S0, 4, 1),
|
||||
DEF_FIXED("cl16m_mm", R8A779F0_CLK_CL16M_MM, CLK_S0, 48, 1),
|
||||
DEF_FIXED("s0d2_rt", R8A779F0_CLK_S0D2_RT, CLK_S0, 2, 1),
|
||||
DEF_FIXED("s0d3_rt", R8A779F0_CLK_S0D3_RT, CLK_S0, 3, 1),
|
||||
DEF_FIXED("s0d4_rt", R8A779F0_CLK_S0D4_RT, CLK_S0, 4, 1),
|
||||
DEF_FIXED("s0d6_rt", R8A779F0_CLK_S0D6_RT, CLK_S0, 6, 1),
|
||||
DEF_FIXED("cl16m_rt", R8A779F0_CLK_CL16M_RT, CLK_S0, 48, 1),
|
||||
DEF_FIXED("s0d3_per", R8A779F0_CLK_S0D3_PER, CLK_S0, 3, 1),
|
||||
DEF_FIXED("s0d6_per", R8A779F0_CLK_S0D6_PER, CLK_S0, 6, 1),
|
||||
DEF_FIXED("s0d12_per", R8A779F0_CLK_S0D12_PER, CLK_S0, 12, 1),
|
||||
DEF_FIXED("s0d24_per", R8A779F0_CLK_S0D24_PER, CLK_S0, 24, 1),
|
||||
DEF_FIXED("cl16m_per", R8A779F0_CLK_CL16M_PER, CLK_S0, 48, 1),
|
||||
DEF_FIXED("s0d2_hsc", R8A779F0_CLK_S0D2_HSC, CLK_S0, 2, 1),
|
||||
DEF_FIXED("s0d3_hsc", R8A779F0_CLK_S0D3_HSC, CLK_S0, 3, 1),
|
||||
DEF_FIXED("s0d4_hsc", R8A779F0_CLK_S0D4_HSC, CLK_S0, 4, 1),
|
||||
DEF_FIXED("s0d6_hsc", R8A779F0_CLK_S0D6_HSC, CLK_S0, 6, 1),
|
||||
DEF_FIXED("s0d12_hsc", R8A779F0_CLK_S0D12_HSC, CLK_S0, 12, 1),
|
||||
DEF_FIXED("cl16m_hsc", R8A779F0_CLK_CL16M_HSC, CLK_S0, 48, 1),
|
||||
DEF_FIXED("s0d2_cc", R8A779F0_CLK_S0D2_CC, CLK_S0, 2, 1),
|
||||
DEF_FIXED("rsw2", R8A779F0_CLK_RSW2, CLK_PLL5, 2, 1),
|
||||
DEF_FIXED("cbfusa", R8A779F0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
|
||||
DEF_FIXED("cpex", R8A779F0_CLK_CPEX, CLK_EXTAL, 2, 1),
|
||||
|
||||
DEF_GEN4_SD("sd0", R8A779F0_CLK_SD0, CLK_SDSRC, 0x870),
|
||||
DEF_DIV6P1("mso", R8A779F0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
|
||||
|
||||
DEF_GEN4_OSC("osc", R8A779F0_CLK_OSC, CLK_EXTAL, 8),
|
||||
DEF_GEN4_MDSEL("r", R8A779F0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
|
||||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
|
||||
DEF_MOD("scif0", 702, R8A779F0_CLK_S0D12_PER),
|
||||
DEF_MOD("scif1", 703, R8A779F0_CLK_S0D12_PER),
|
||||
DEF_MOD("scif3", 704, R8A779F0_CLK_S0D12_PER),
|
||||
DEF_MOD("scif4", 705, R8A779F0_CLK_S0D12_PER),
|
||||
};
|
||||
|
||||
/*
|
||||
* CPG Clock Data
|
||||
*/
|
||||
/*
|
||||
* MD EXTAL PLL1 PLL2 PLL3 PLL5 PLL6 OSC
|
||||
* 14 13 (MHz)
|
||||
* ----------------------------------------------------------------
|
||||
* 0 0 16 / 1 x200 x150 x200 x200 x134 /15
|
||||
* 0 1 20 / 1 x160 x120 x160 x160 x106 /19
|
||||
* 1 0 Prohibited setting
|
||||
* 1 1 40 / 2 x160 x120 x160 x160 x106 /38
|
||||
*/
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
|
||||
(((md) & BIT(13)) >> 13))
|
||||
|
||||
static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
|
||||
/* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
|
||||
{ 1, 200, 1, 150, 1, 200, 1, 200, 1, 134, 1, 15, },
|
||||
{ 1, 160, 1, 120, 1, 160, 1, 160, 1, 106, 1, 19, },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
|
||||
{ 2, 160, 1, 120, 1, 160, 1, 160, 1, 106, 1, 38, },
|
||||
};
|
||||
|
||||
static int __init r8a779f0_cpg_mssr_init(struct device *dev)
|
||||
{
|
||||
const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
|
||||
u32 cpg_mode;
|
||||
int error;
|
||||
|
||||
error = rcar_rst_read_mode_pins(&cpg_mode);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
|
||||
if (!cpg_pll_config->extal_div) {
|
||||
dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
|
||||
}
|
||||
|
||||
const struct cpg_mssr_info r8a779f0_cpg_mssr_info __initconst = {
|
||||
/* Core Clocks */
|
||||
.core_clks = r8a779f0_core_clks,
|
||||
.num_core_clks = ARRAY_SIZE(r8a779f0_core_clks),
|
||||
.last_dt_core_clk = LAST_DT_CORE_CLK,
|
||||
.num_total_core_clks = MOD_CLK_BASE,
|
||||
|
||||
/* Module Clocks */
|
||||
.mod_clks = r8a779f0_mod_clks,
|
||||
.num_mod_clks = ARRAY_SIZE(r8a779f0_mod_clks),
|
||||
.num_hw_mod_clks = 28 * 32,
|
||||
|
||||
/* Callbacks */
|
||||
.init = r8a779f0_cpg_mssr_init,
|
||||
.cpg_clk_register = rcar_gen4_cpg_clk_register,
|
||||
|
||||
.reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
|
||||
};
|
@ -26,15 +26,15 @@ enum clk_ids {
|
||||
CLK_PLL1,
|
||||
CLK_PLL2,
|
||||
CLK_PLL2_DIV2,
|
||||
CLK_PLL2_DIV16,
|
||||
CLK_PLL2_DIV20,
|
||||
CLK_PLL2_DIV2_8,
|
||||
CLK_PLL2_DIV2_10,
|
||||
CLK_PLL3,
|
||||
CLK_PLL3_400,
|
||||
CLK_PLL3_533,
|
||||
CLK_PLL3_DIV2,
|
||||
CLK_PLL3_DIV2_2,
|
||||
CLK_PLL3_DIV2_4,
|
||||
CLK_PLL3_DIV2_4_2,
|
||||
CLK_PLL3_DIV4,
|
||||
CLK_SEL_PLL3_3,
|
||||
CLK_DIV_PLL3_C,
|
||||
CLK_PLL4,
|
||||
@ -50,12 +50,21 @@ enum clk_ids {
|
||||
CLK_PLL2_SDHI_266,
|
||||
CLK_SD0_DIV4,
|
||||
CLK_SD1_DIV4,
|
||||
CLK_SEL_GPU2,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE,
|
||||
};
|
||||
|
||||
/* Divider tables */
|
||||
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_1_32[] = {
|
||||
{0, 1},
|
||||
{1, 2},
|
||||
@ -69,6 +78,7 @@ static const struct clk_div_table dtable_1_32[] = {
|
||||
static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
|
||||
static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
|
||||
static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
|
||||
static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
|
||||
|
||||
static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
@ -94,13 +104,13 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2),
|
||||
DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2),
|
||||
|
||||
DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16),
|
||||
DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20),
|
||||
DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
|
||||
DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10),
|
||||
|
||||
DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
|
||||
DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2),
|
||||
DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
|
||||
DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2),
|
||||
DEF_FIXED(".pll3_div4", CLK_PLL3_DIV4, CLK_PLL3, 1, 4),
|
||||
DEF_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3,
|
||||
sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY),
|
||||
DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3,
|
||||
@ -108,13 +118,16 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
|
||||
DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2),
|
||||
DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
|
||||
DEF_MUX(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2,
|
||||
sel_gpu2, ARRAY_SIZE(sel_gpu2), 0, CLK_MUX_READ_ONLY),
|
||||
|
||||
/* Core output clk */
|
||||
DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1),
|
||||
DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A,
|
||||
DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8,
|
||||
CLK_DIVIDER_HIWORD_MASK),
|
||||
DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A,
|
||||
dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
|
||||
DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2),
|
||||
DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV20, 1, 1),
|
||||
DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1),
|
||||
DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4,
|
||||
DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
|
||||
DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2),
|
||||
@ -132,6 +145,8 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
sel_shdi, ARRAY_SIZE(sel_shdi)),
|
||||
DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
|
||||
DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
|
||||
DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8,
|
||||
CLK_DIVIDER_HIWORD_MASK),
|
||||
};
|
||||
|
||||
static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
@ -145,6 +160,24 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
0x52c, 0),
|
||||
DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
|
||||
0x52c, 1),
|
||||
DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0,
|
||||
0x534, 0),
|
||||
DEF_MOD("ostm1_clk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0,
|
||||
0x534, 1),
|
||||
DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0,
|
||||
0x534, 2),
|
||||
DEF_MOD("wdt0_pclk", R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0,
|
||||
0x548, 0),
|
||||
DEF_MOD("wdt0_clk", R9A07G044_WDT0_CLK, R9A07G044_OSCCLK,
|
||||
0x548, 1),
|
||||
DEF_MOD("wdt1_pclk", R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0,
|
||||
0x548, 2),
|
||||
DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK,
|
||||
0x548, 3),
|
||||
DEF_MOD("wdt2_pclk", R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0,
|
||||
0x548, 4),
|
||||
DEF_MOD("wdt2_clk", R9A07G044_WDT2_CLK, R9A07G044_OSCCLK,
|
||||
0x548, 5),
|
||||
DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
|
||||
0x550, 0),
|
||||
DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
|
||||
@ -165,6 +198,12 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
0x554, 6),
|
||||
DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1,
|
||||
0x554, 7),
|
||||
DEF_MOD("gpu_clk", R9A07G044_GPU_CLK, R9A07G044_CLK_G,
|
||||
0x558, 0),
|
||||
DEF_MOD("gpu_axi_clk", R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1,
|
||||
0x558, 1),
|
||||
DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1,
|
||||
0x558, 2),
|
||||
DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
|
||||
0x570, 0),
|
||||
DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
|
||||
@ -217,6 +256,14 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
0x584, 4),
|
||||
DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0,
|
||||
0x588, 0),
|
||||
DEF_MOD("sci1", R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0,
|
||||
0x588, 1),
|
||||
DEF_MOD("rspi0", R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0,
|
||||
0x590, 0),
|
||||
DEF_MOD("rspi1", R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0,
|
||||
0x590, 1),
|
||||
DEF_MOD("rspi2", R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0,
|
||||
0x590, 2),
|
||||
DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0,
|
||||
0x594, 0),
|
||||
DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK,
|
||||
@ -225,6 +272,8 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
0x5a8, 0),
|
||||
DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0,
|
||||
0x5a8, 1),
|
||||
DEF_MOD("tsu_pclk", R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU,
|
||||
0x5ac, 0),
|
||||
};
|
||||
|
||||
static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
@ -233,9 +282,18 @@ static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0),
|
||||
DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0),
|
||||
DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1),
|
||||
DEF_RST(R9A07G044_OSTM0_PRESETZ, 0x834, 0),
|
||||
DEF_RST(R9A07G044_OSTM1_PRESETZ, 0x834, 1),
|
||||
DEF_RST(R9A07G044_OSTM2_PRESETZ, 0x834, 2),
|
||||
DEF_RST(R9A07G044_WDT0_PRESETN, 0x848, 0),
|
||||
DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1),
|
||||
DEF_RST(R9A07G044_WDT2_PRESETN, 0x848, 2),
|
||||
DEF_RST(R9A07G044_SPI_RST, 0x850, 0),
|
||||
DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0),
|
||||
DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1),
|
||||
DEF_RST(R9A07G044_GPU_RESETN, 0x858, 0),
|
||||
DEF_RST(R9A07G044_GPU_AXI_RESETN, 0x858, 1),
|
||||
DEF_RST(R9A07G044_GPU_ACE_RESETN, 0x858, 2),
|
||||
DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0),
|
||||
DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1),
|
||||
DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2),
|
||||
@ -256,6 +314,10 @@ static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
DEF_RST(R9A07G044_SCIF3_RST_SYSTEM_N, 0x884, 3),
|
||||
DEF_RST(R9A07G044_SCIF4_RST_SYSTEM_N, 0x884, 4),
|
||||
DEF_RST(R9A07G044_SCI0_RST, 0x888, 0),
|
||||
DEF_RST(R9A07G044_SCI1_RST, 0x888, 1),
|
||||
DEF_RST(R9A07G044_RSPI0_RST, 0x890, 0),
|
||||
DEF_RST(R9A07G044_RSPI1_RST, 0x890, 1),
|
||||
DEF_RST(R9A07G044_RSPI2_RST, 0x890, 2),
|
||||
DEF_RST(R9A07G044_CANFD_RSTP_N, 0x894, 0),
|
||||
DEF_RST(R9A07G044_CANFD_RSTC_N, 0x894, 1),
|
||||
DEF_RST(R9A07G044_GPIO_RSTN, 0x898, 0),
|
||||
@ -263,6 +325,7 @@ static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
DEF_RST(R9A07G044_GPIO_SPARE_RESETN, 0x898, 2),
|
||||
DEF_RST(R9A07G044_ADC_PRESETN, 0x8a8, 0),
|
||||
DEF_RST(R9A07G044_ADC_ADRST_N, 0x8a8, 1),
|
||||
DEF_RST(R9A07G044_TSU_PRESETN, 0x8ac, 0),
|
||||
};
|
||||
|
||||
static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
|
||||
|
@ -65,206 +65,49 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
|
||||
/*
|
||||
* SDn Clock
|
||||
*/
|
||||
#define CPG_SD_STP_HCK BIT(9)
|
||||
#define CPG_SD_STP_CK BIT(8)
|
||||
|
||||
#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
|
||||
#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
|
||||
#define SDnSRCFC_SHIFT 2
|
||||
#define STPnHCK BIT(9 - SDnSRCFC_SHIFT)
|
||||
|
||||
#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
|
||||
{ \
|
||||
.val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
|
||||
((sd_srcfc) << 2) | \
|
||||
((sd_fc) << 0), \
|
||||
.div = (sd_div), \
|
||||
}
|
||||
|
||||
struct sd_div_table {
|
||||
u32 val;
|
||||
unsigned int div;
|
||||
static const struct clk_div_table cpg_sdh_div_table[] = {
|
||||
{ 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
|
||||
{ STPnHCK | 4, 16 }, { 0, 0 },
|
||||
};
|
||||
|
||||
struct sd_clock {
|
||||
struct clk_hw hw;
|
||||
const struct sd_div_table *div_table;
|
||||
struct cpg_simple_notifier csn;
|
||||
unsigned int div_num;
|
||||
unsigned int cur_div_idx;
|
||||
};
|
||||
|
||||
/* SDn divider
|
||||
* sd_srcfc sd_fc div
|
||||
* stp_hck (div) (div) = sd_srcfc x sd_fc
|
||||
*---------------------------------------------------------
|
||||
* 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP)
|
||||
* 0 1 (2) 1 (4) 8 : SDR50
|
||||
* 1 2 (4) 1 (4) 16 : HS / SDR25
|
||||
* 1 3 (8) 1 (4) 32 : NS / SDR12
|
||||
* 1 4 (16) 1 (4) 64
|
||||
* 0 0 (1) 0 (2) 2
|
||||
* 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP)
|
||||
* 1 2 (4) 0 (2) 8
|
||||
* 1 3 (8) 0 (2) 16
|
||||
* 1 4 (16) 0 (2) 32
|
||||
*
|
||||
* NOTE: There is a quirk option to ignore the first row of the dividers
|
||||
* table when searching for suitable settings. This is because HS400 on
|
||||
* early ES versions of H3 and M3-W requires a specific setting to work.
|
||||
*/
|
||||
static const struct sd_div_table cpg_sd_div_table[] = {
|
||||
/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */
|
||||
CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32),
|
||||
};
|
||||
|
||||
#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
|
||||
|
||||
static int cpg_sd_clock_enable(struct clk_hw *hw)
|
||||
struct clk * __init cpg_sdh_clk_register(const char *name,
|
||||
void __iomem *sdnckcr, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
struct cpg_simple_notifier *csn;
|
||||
struct clk *clk;
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
|
||||
clock->div_table[clock->cur_div_idx].val &
|
||||
CPG_SD_STP_MASK);
|
||||
csn = kzalloc(sizeof(*csn), GFP_KERNEL);
|
||||
if (!csn)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
csn->reg = sdnckcr;
|
||||
|
||||
static void cpg_sd_clock_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return DIV_ROUND_CLOSEST(parent_rate,
|
||||
clock->div_table[clock->cur_div_idx].div);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
unsigned long calc_rate, diff;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clock->div_num; i++) {
|
||||
calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
|
||||
clock->div_table[i].div);
|
||||
if (calc_rate < req->min_rate || calc_rate > req->max_rate)
|
||||
continue;
|
||||
|
||||
diff = calc_rate > req->rate ? calc_rate - req->rate
|
||||
: req->rate - calc_rate;
|
||||
if (diff < diff_min) {
|
||||
best_rate = calc_rate;
|
||||
diff_min = diff;
|
||||
}
|
||||
clk = clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
|
||||
SDnSRCFC_SHIFT, 8, 0, cpg_sdh_div_table,
|
||||
&cpg_lock);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(csn);
|
||||
return clk;
|
||||
}
|
||||
|
||||
if (best_rate == ULONG_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
req->rate = best_rate;
|
||||
return 0;
|
||||
cpg_simple_notifier_register(notifiers, csn);
|
||||
return clk;
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clock->div_num; i++)
|
||||
if (rate == DIV_ROUND_CLOSEST(parent_rate,
|
||||
clock->div_table[i].div))
|
||||
break;
|
||||
|
||||
if (i >= clock->div_num)
|
||||
return -EINVAL;
|
||||
|
||||
clock->cur_div_idx = i;
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
|
||||
clock->div_table[i].val &
|
||||
(CPG_SD_STP_MASK | CPG_SD_FC_MASK));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_sd_clock_ops = {
|
||||
.enable = cpg_sd_clock_enable,
|
||||
.disable = cpg_sd_clock_disable,
|
||||
.is_enabled = cpg_sd_clock_is_enabled,
|
||||
.recalc_rate = cpg_sd_clock_recalc_rate,
|
||||
.determine_rate = cpg_sd_clock_determine_rate,
|
||||
.set_rate = cpg_sd_clock_set_rate,
|
||||
static const struct clk_div_table cpg_sd_div_table[] = {
|
||||
{ 0, 2 }, { 1, 4 }, { 0, 0 },
|
||||
};
|
||||
|
||||
struct clk * __init cpg_sd_clk_register(const char *name,
|
||||
void __iomem *base, unsigned int offset, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers, bool skip_first)
|
||||
void __iomem *sdnckcr, const char *parent_name)
|
||||
{
|
||||
struct clk_init_data init = {};
|
||||
struct sd_clock *clock;
|
||||
struct clk *clk;
|
||||
u32 val;
|
||||
|
||||
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
|
||||
if (!clock)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_sd_clock_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clock->csn.reg = base + offset;
|
||||
clock->hw.init = &init;
|
||||
clock->div_table = cpg_sd_div_table;
|
||||
clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
|
||||
|
||||
if (skip_first) {
|
||||
clock->div_table++;
|
||||
clock->div_num--;
|
||||
}
|
||||
|
||||
val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
|
||||
val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
|
||||
writel(val, clock->csn.reg);
|
||||
|
||||
clk = clk_register(NULL, &clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
goto free_clock;
|
||||
|
||||
cpg_simple_notifier_register(notifiers, &clock->csn);
|
||||
return clk;
|
||||
|
||||
free_clock:
|
||||
kfree(clock);
|
||||
return clk;
|
||||
return clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
|
||||
0, 2, 0, cpg_sd_div_table, &cpg_lock);
|
||||
}
|
||||
|
||||
struct rpc_clock {
|
||||
|
@ -26,9 +26,12 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
|
||||
|
||||
void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set);
|
||||
|
||||
struct clk * __init cpg_sdh_clk_register(const char *name,
|
||||
void __iomem *sdnckcr, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers);
|
||||
|
||||
struct clk * __init cpg_sd_clk_register(const char *name,
|
||||
void __iomem *base, unsigned int offset, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers, bool skip_first);
|
||||
void __iomem *sdnckcr, const char *parent_name);
|
||||
|
||||
struct clk * __init cpg_rpc_clk_register(const char *name,
|
||||
void __iomem *rpcckcr, const char *parent_name,
|
||||
|
@ -312,29 +312,20 @@ static u32 cpg_quirks __initdata;
|
||||
|
||||
#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
|
||||
#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
|
||||
#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */
|
||||
|
||||
|
||||
static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
|
||||
{
|
||||
.soc_id = "r8a7795", .revision = "ES1.0",
|
||||
.data = (void *)(PLL_ERRATA | RCKCR_CKSEL | SD_SKIP_FIRST),
|
||||
.data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7795", .revision = "ES1.*",
|
||||
.data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7795", .revision = "ES2.0",
|
||||
.data = (void *)SD_SKIP_FIRST,
|
||||
.data = (void *)(RCKCR_CKSEL),
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7796", .revision = "ES1.0",
|
||||
.data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7796", .revision = "ES1.1",
|
||||
.data = (void *)SD_SKIP_FIRST,
|
||||
.data = (void *)(RCKCR_CKSEL),
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
@ -401,10 +392,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
||||
mult *= 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_SDH:
|
||||
return cpg_sdh_clk_register(core->name, base + core->offset,
|
||||
__clk_get_name(parent), notifiers);
|
||||
|
||||
case CLK_TYPE_GEN3_SD:
|
||||
return cpg_sd_clk_register(core->name, base, core->offset,
|
||||
__clk_get_name(parent), notifiers,
|
||||
cpg_quirks & SD_SKIP_FIRST);
|
||||
return cpg_sd_clk_register(core->name, base + core->offset,
|
||||
__clk_get_name(parent));
|
||||
|
||||
case CLK_TYPE_GEN3_R:
|
||||
if (cpg_quirks & RCKCR_CKSEL) {
|
||||
|
@ -17,6 +17,7 @@ enum rcar_gen3_clk_types {
|
||||
CLK_TYPE_GEN3_PLL2,
|
||||
CLK_TYPE_GEN3_PLL3,
|
||||
CLK_TYPE_GEN3_PLL4,
|
||||
CLK_TYPE_GEN3_SDH,
|
||||
CLK_TYPE_GEN3_SD,
|
||||
CLK_TYPE_GEN3_R,
|
||||
CLK_TYPE_GEN3_MDSEL, /* Select parent/divider using mode pin */
|
||||
@ -32,6 +33,9 @@ enum rcar_gen3_clk_types {
|
||||
CLK_TYPE_GEN3_SOC_BASE,
|
||||
};
|
||||
|
||||
#define DEF_GEN3_SDH(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN3_SDH, _parent, .offset = _offset)
|
||||
|
||||
#define DEF_GEN3_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
|
||||
|
||||
|
305
drivers/clk/renesas/rcar-gen4-cpg.c
Normal file
305
drivers/clk/renesas/rcar-gen4-cpg.c
Normal file
@ -0,0 +1,305 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* R-Car Gen4 Clock Pulse Generator
|
||||
*
|
||||
* Copyright (C) 2021 Renesas Electronics Corp.
|
||||
*
|
||||
* Based on rcar-gen3-cpg.c
|
||||
*
|
||||
* Copyright (C) 2015-2018 Glider bvba
|
||||
* Copyright (C) 2019 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
#include "rcar-gen4-cpg.h"
|
||||
#include "rcar-cpg-lib.h"
|
||||
|
||||
static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initconst;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
|
||||
/*
|
||||
* Z0 Clock & Z1 Clock
|
||||
*/
|
||||
#define CPG_FRQCRB 0x00000804
|
||||
#define CPG_FRQCRB_KICK BIT(31)
|
||||
#define CPG_FRQCRC 0x00000808
|
||||
|
||||
struct cpg_z_clk {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
void __iomem *kick_reg;
|
||||
unsigned long max_rate; /* Maximum rate for normal mode */
|
||||
unsigned int fixed_div;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
|
||||
|
||||
static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int mult;
|
||||
u32 val;
|
||||
|
||||
val = readl(zclk->reg) & zclk->mask;
|
||||
mult = 32 - (val >> __ffs(zclk->mask));
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
|
||||
32 * zclk->fixed_div);
|
||||
}
|
||||
|
||||
static int cpg_z_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int min_mult, max_mult, mult;
|
||||
unsigned long rate, prate;
|
||||
|
||||
rate = min(req->rate, req->max_rate);
|
||||
if (rate <= zclk->max_rate) {
|
||||
/* Set parent rate to initial value for normal modes */
|
||||
prate = zclk->max_rate;
|
||||
} else {
|
||||
/* Set increased parent rate for boost modes */
|
||||
prate = rate;
|
||||
}
|
||||
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||
prate * zclk->fixed_div);
|
||||
|
||||
prate = req->best_parent_rate / zclk->fixed_div;
|
||||
min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
|
||||
max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
|
||||
if (max_mult < min_mult)
|
||||
return -EINVAL;
|
||||
|
||||
mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
|
||||
mult = clamp(mult, min_mult, max_mult);
|
||||
|
||||
req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int mult;
|
||||
unsigned int i;
|
||||
|
||||
mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
|
||||
parent_rate);
|
||||
mult = clamp(mult, 1U, 32U);
|
||||
|
||||
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
|
||||
return -EBUSY;
|
||||
|
||||
cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
|
||||
|
||||
/*
|
||||
* Set KICK bit in FRQCRB to update hardware setting and wait for
|
||||
* clock change completion.
|
||||
*/
|
||||
cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
|
||||
|
||||
/*
|
||||
* Note: There is no HW information about the worst case latency.
|
||||
*
|
||||
* Using experimental measurements, it seems that no more than
|
||||
* ~10 iterations are needed, independently of the CPU rate.
|
||||
* Since this value might be dependent on external xtal rate, pll1
|
||||
* rate or even the other emulation clocks rate, use 1000 as a
|
||||
* "super" safe value.
|
||||
*/
|
||||
for (i = 1000; i; i--) {
|
||||
if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
|
||||
return 0;
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_z_clk_ops = {
|
||||
.recalc_rate = cpg_z_clk_recalc_rate,
|
||||
.determine_rate = cpg_z_clk_determine_rate,
|
||||
.set_rate = cpg_z_clk_set_rate,
|
||||
};
|
||||
|
||||
static struct clk * __init cpg_z_clk_register(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
unsigned int div,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct clk_init_data init = {};
|
||||
struct cpg_z_clk *zclk;
|
||||
struct clk *clk;
|
||||
|
||||
zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
|
||||
if (!zclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_z_clk_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
zclk->reg = reg + CPG_FRQCRC;
|
||||
zclk->kick_reg = reg + CPG_FRQCRB;
|
||||
zclk->hw.init = &init;
|
||||
zclk->mask = GENMASK(offset + 4, offset);
|
||||
zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
|
||||
|
||||
clk = clk_register(NULL, &zclk->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(zclk);
|
||||
return clk;
|
||||
}
|
||||
|
||||
zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
|
||||
zclk->fixed_div;
|
||||
return clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* RPC Clocks
|
||||
*/
|
||||
static const struct clk_div_table cpg_rpcsrc_div_table[] = {
|
||||
{ 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
|
||||
};
|
||||
|
||||
struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
const struct clk *parent;
|
||||
unsigned int mult = 1;
|
||||
unsigned int div = 1;
|
||||
u32 value;
|
||||
|
||||
parent = clks[core->parent & 0xffff]; /* some types use high bits */
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
|
||||
switch (core->type) {
|
||||
case CLK_TYPE_GEN4_MAIN:
|
||||
div = cpg_pll_config->extal_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_PLL1:
|
||||
mult = cpg_pll_config->pll1_mult;
|
||||
div = cpg_pll_config->pll1_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_PLL2:
|
||||
mult = cpg_pll_config->pll2_mult;
|
||||
div = cpg_pll_config->pll2_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_PLL3:
|
||||
mult = cpg_pll_config->pll3_mult;
|
||||
div = cpg_pll_config->pll3_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_PLL5:
|
||||
mult = cpg_pll_config->pll5_mult;
|
||||
div = cpg_pll_config->pll5_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_PLL6:
|
||||
mult = cpg_pll_config->pll6_mult;
|
||||
div = cpg_pll_config->pll6_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_PLL2X_3X:
|
||||
value = readl(base + core->offset);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_Z:
|
||||
return cpg_z_clk_register(core->name, __clk_get_name(parent),
|
||||
base, core->div, core->offset);
|
||||
|
||||
case CLK_TYPE_GEN4_SDSRC:
|
||||
div = ((readl(base + SD0CKCR1) >> 29) & 0x03) + 4;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_SDH:
|
||||
return cpg_sdh_clk_register(core->name, base + core->offset,
|
||||
__clk_get_name(parent), notifiers);
|
||||
|
||||
case CLK_TYPE_GEN4_SD:
|
||||
return cpg_sd_clk_register(core->name, base + core->offset,
|
||||
__clk_get_name(parent));
|
||||
|
||||
case CLK_TYPE_GEN4_MDSEL:
|
||||
/*
|
||||
* Clock selectable between two parents and two fixed dividers
|
||||
* using a mode pin
|
||||
*/
|
||||
if (cpg_mode & BIT(core->offset)) {
|
||||
div = core->div & 0xffff;
|
||||
} else {
|
||||
parent = clks[core->parent >> 16];
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
div = core->div >> 16;
|
||||
}
|
||||
mult = 1;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_OSC:
|
||||
/*
|
||||
* Clock combining OSC EXTAL predivider and a fixed divider
|
||||
*/
|
||||
div = cpg_pll_config->osc_prediv * core->div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN4_RPCSRC:
|
||||
return clk_register_divider_table(NULL, core->name,
|
||||
__clk_get_name(parent), 0,
|
||||
base + CPG_RPCCKCR, 3, 2, 0,
|
||||
cpg_rpcsrc_div_table,
|
||||
&cpg_lock);
|
||||
|
||||
case CLK_TYPE_GEN4_RPC:
|
||||
return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent), notifiers);
|
||||
|
||||
case CLK_TYPE_GEN4_RPCD2:
|
||||
return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent));
|
||||
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return clk_register_fixed_factor(NULL, core->name,
|
||||
__clk_get_name(parent), 0, mult, div);
|
||||
}
|
||||
|
||||
int __init rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
|
||||
unsigned int clk_extalr, u32 mode)
|
||||
{
|
||||
cpg_pll_config = config;
|
||||
cpg_clk_extalr = clk_extalr;
|
||||
cpg_mode = mode;
|
||||
|
||||
spin_lock_init(&cpg_lock);
|
||||
|
||||
return 0;
|
||||
}
|
76
drivers/clk/renesas/rcar-gen4-cpg.h
Normal file
76
drivers/clk/renesas/rcar-gen4-cpg.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* R-Car Gen4 Clock Pulse Generator
|
||||
*
|
||||
* Copyright (C) 2021 Renesas Electronics Corp.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CLK_RENESAS_RCAR_GEN4_CPG_H__
|
||||
#define __CLK_RENESAS_RCAR_GEN4_CPG_H__
|
||||
|
||||
enum rcar_gen4_clk_types {
|
||||
CLK_TYPE_GEN4_MAIN = CLK_TYPE_CUSTOM,
|
||||
CLK_TYPE_GEN4_PLL1,
|
||||
CLK_TYPE_GEN4_PLL2,
|
||||
CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */
|
||||
CLK_TYPE_GEN4_PLL3,
|
||||
CLK_TYPE_GEN4_PLL5,
|
||||
CLK_TYPE_GEN4_PLL6,
|
||||
CLK_TYPE_GEN4_SDSRC,
|
||||
CLK_TYPE_GEN4_SDH,
|
||||
CLK_TYPE_GEN4_SD,
|
||||
CLK_TYPE_GEN4_MDSEL, /* Select parent/divider using mode pin */
|
||||
CLK_TYPE_GEN4_Z,
|
||||
CLK_TYPE_GEN4_OSC, /* OSC EXTAL predivider and fixed divider */
|
||||
CLK_TYPE_GEN4_RPCSRC,
|
||||
CLK_TYPE_GEN4_RPC,
|
||||
CLK_TYPE_GEN4_RPCD2,
|
||||
|
||||
/* SoC specific definitions start here */
|
||||
CLK_TYPE_GEN4_SOC_BASE,
|
||||
};
|
||||
|
||||
#define DEF_GEN4_SDH(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN4_SDH, _parent, .offset = _offset)
|
||||
|
||||
#define DEF_GEN4_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN4_SD, _parent, .offset = _offset)
|
||||
|
||||
#define DEF_GEN4_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN4_MDSEL, \
|
||||
(_parent0) << 16 | (_parent1), \
|
||||
.div = (_div0) << 16 | (_div1), .offset = _md)
|
||||
|
||||
#define DEF_GEN4_OSC(_name, _id, _parent, _div) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN4_OSC, _parent, .div = _div)
|
||||
|
||||
#define DEF_GEN4_Z(_name, _id, _type, _parent, _div, _offset) \
|
||||
DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
|
||||
|
||||
struct rcar_gen4_cpg_pll_config {
|
||||
u8 extal_div;
|
||||
u8 pll1_mult;
|
||||
u8 pll1_div;
|
||||
u8 pll2_mult;
|
||||
u8 pll2_div;
|
||||
u8 pll3_mult;
|
||||
u8 pll3_div;
|
||||
u8 pll5_mult;
|
||||
u8 pll5_div;
|
||||
u8 pll6_mult;
|
||||
u8 pll6_div;
|
||||
u8 osc_prediv;
|
||||
};
|
||||
|
||||
#define CPG_RPCCKCR 0x874
|
||||
#define SD0CKCR1 0x8a4
|
||||
|
||||
struct clk *rcar_gen4_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers);
|
||||
int rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
|
||||
unsigned int clk_extalr, u32 mode);
|
||||
|
||||
#endif
|
@ -57,9 +57,11 @@ static const u16 mstpsr[] = {
|
||||
0x9A0, 0x9A4, 0x9A8, 0x9AC,
|
||||
};
|
||||
|
||||
static const u16 mstpsr_for_v3u[] = {
|
||||
static const u16 mstpsr_for_gen4[] = {
|
||||
0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
|
||||
0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38,
|
||||
0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, 0x2E3C,
|
||||
0x2E40, 0x2E44, 0x2E48, 0x2E4C, 0x2E50, 0x2E54, 0x2E58, 0x2E5C,
|
||||
0x2E60, 0x2E64, 0x2E68, 0x2E6C,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -71,9 +73,11 @@ static const u16 smstpcr[] = {
|
||||
0x990, 0x994, 0x998, 0x99C,
|
||||
};
|
||||
|
||||
static const u16 mstpcr_for_v3u[] = {
|
||||
static const u16 mstpcr_for_gen4[] = {
|
||||
0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
|
||||
0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38,
|
||||
0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, 0x2D3C,
|
||||
0x2D40, 0x2D44, 0x2D48, 0x2D4C, 0x2D50, 0x2D54, 0x2D58, 0x2D5C,
|
||||
0x2D60, 0x2D64, 0x2D68, 0x2D6C,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -95,9 +99,11 @@ static const u16 srcr[] = {
|
||||
0x920, 0x924, 0x928, 0x92C,
|
||||
};
|
||||
|
||||
static const u16 srcr_for_v3u[] = {
|
||||
static const u16 srcr_for_gen4[] = {
|
||||
0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
|
||||
0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38,
|
||||
0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, 0x2C3C,
|
||||
0x2C40, 0x2C44, 0x2C48, 0x2C4C, 0x2C50, 0x2C54, 0x2C58, 0x2C5C,
|
||||
0x2C60, 0x2C64, 0x2C68, 0x2C6C,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -109,9 +115,11 @@ static const u16 srstclr[] = {
|
||||
0x960, 0x964, 0x968, 0x96C,
|
||||
};
|
||||
|
||||
static const u16 srstclr_for_v3u[] = {
|
||||
static const u16 srstclr_for_gen4[] = {
|
||||
0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
|
||||
0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8,
|
||||
0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, 0x2CBC,
|
||||
0x2CC0, 0x2CC4, 0x2CC8, 0x2CCC, 0x2CD0, 0x2CD4, 0x2CD8, 0x2CDC,
|
||||
0x2CE0, 0x2CE4, 0x2CE8, 0x2CEC,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -158,7 +166,7 @@ struct cpg_mssr_priv {
|
||||
struct {
|
||||
u32 mask;
|
||||
u32 val;
|
||||
} smstpcr_saved[ARRAY_SIZE(mstpsr_for_v3u)];
|
||||
} smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
|
||||
|
||||
struct clk *clks[];
|
||||
};
|
||||
@ -552,6 +560,11 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
|
||||
pm_clk_destroy(dev);
|
||||
}
|
||||
|
||||
static void cpg_mssr_genpd_remove(void *data)
|
||||
{
|
||||
pm_genpd_remove(data);
|
||||
}
|
||||
|
||||
static int __init cpg_mssr_add_clk_domain(struct device *dev,
|
||||
const unsigned int *core_pm_clks,
|
||||
unsigned int num_core_pm_clks)
|
||||
@ -560,6 +573,7 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
|
||||
struct generic_pm_domain *genpd;
|
||||
struct cpg_mssr_clk_domain *pd;
|
||||
size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
|
||||
int ret;
|
||||
|
||||
pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
|
||||
if (!pd)
|
||||
@ -574,11 +588,17 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
|
||||
GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
genpd->attach_dev = cpg_mssr_attach_dev;
|
||||
genpd->detach_dev = cpg_mssr_detach_dev;
|
||||
pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
|
||||
ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, cpg_mssr_genpd_remove, genpd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cpg_mssr_clk_domain = pd;
|
||||
|
||||
of_genpd_add_provider_simple(np, genpd);
|
||||
return 0;
|
||||
return of_genpd_add_provider_simple(np, genpd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
@ -827,6 +847,12 @@ static const struct of_device_id cpg_mssr_match[] = {
|
||||
.compatible = "renesas,r8a779a0-cpg-mssr",
|
||||
.data = &r8a779a0_cpg_mssr_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CLK_R8A779F0
|
||||
{
|
||||
.compatible = "renesas,r8a779f0-cpg-mssr",
|
||||
.data = &r8a779f0_cpg_mssr_info,
|
||||
},
|
||||
#endif
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
@ -970,11 +996,11 @@ static int __init cpg_mssr_common_init(struct device *dev,
|
||||
priv->reset_clear_regs = srstclr;
|
||||
} else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
|
||||
priv->control_regs = stbcr;
|
||||
} else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
|
||||
priv->status_regs = mstpsr_for_v3u;
|
||||
priv->control_regs = mstpcr_for_v3u;
|
||||
priv->reset_regs = srcr_for_v3u;
|
||||
priv->reset_clear_regs = srstclr_for_v3u;
|
||||
} else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
|
||||
priv->status_regs = mstpsr_for_gen4;
|
||||
priv->control_regs = mstpcr_for_gen4;
|
||||
priv->reset_regs = srcr_for_gen4;
|
||||
priv->reset_clear_regs = srstclr_for_gen4;
|
||||
} else {
|
||||
error = -EINVAL;
|
||||
goto out_err;
|
||||
|
@ -88,7 +88,7 @@ struct device_node;
|
||||
enum clk_reg_layout {
|
||||
CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
|
||||
CLK_REG_LAYOUT_RZ_A,
|
||||
CLK_REG_LAYOUT_RCAR_V3U,
|
||||
CLK_REG_LAYOUT_RCAR_GEN4,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -178,6 +178,7 @@ extern const struct cpg_mssr_info r8a77980_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a77990_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a779a0_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a779f0_cpg_mssr_info;
|
||||
|
||||
void __init cpg_mssr_early_init(struct device_node *np,
|
||||
const struct cpg_mssr_info *info);
|
||||
|
@ -74,6 +74,7 @@ struct sd_hw_data {
|
||||
* @clks: Array containing all Core and Module Clocks
|
||||
* @num_core_clks: Number of Core Clocks in clks[]
|
||||
* @num_mod_clks: Number of Module Clocks in clks[]
|
||||
* @num_resets: Number of Module Resets in info->resets[]
|
||||
* @last_dt_core_clk: ID of the last Core Clock exported to DT
|
||||
* @notifiers: Notifier chain to save/restore clock state for system resume
|
||||
* @info: Pointer to platform data
|
||||
@ -850,10 +851,16 @@ static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device
|
||||
pm_clk_destroy(dev);
|
||||
}
|
||||
|
||||
static void rzg2l_cpg_genpd_remove(void *data)
|
||||
{
|
||||
pm_genpd_remove(data);
|
||||
}
|
||||
|
||||
static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct generic_pm_domain *genpd;
|
||||
int ret;
|
||||
|
||||
genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL);
|
||||
if (!genpd)
|
||||
@ -864,10 +871,15 @@ static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
|
||||
GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
genpd->attach_dev = rzg2l_cpg_attach_dev;
|
||||
genpd->detach_dev = rzg2l_cpg_detach_dev;
|
||||
pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
|
||||
ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
of_genpd_add_provider_simple(np, genpd);
|
||||
return 0;
|
||||
ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, genpd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return of_genpd_add_provider_simple(np, genpd);
|
||||
}
|
||||
|
||||
static int __init rzg2l_cpg_probe(struct platform_device *pdev)
|
||||
|
@ -9,11 +9,14 @@
|
||||
#ifndef __RENESAS_RZG2L_CPG_H__
|
||||
#define __RENESAS_RZG2L_CPG_H__
|
||||
|
||||
#define CPG_PL1_DDIV (0x200)
|
||||
#define CPG_PL2_DDIV (0x204)
|
||||
#define CPG_PL3A_DDIV (0x208)
|
||||
#define CPG_PL6_DDIV (0x210)
|
||||
#define CPG_PL2SDHI_DSEL (0x218)
|
||||
#define CPG_CLKSTATUS (0x280)
|
||||
#define CPG_PL3_SSEL (0x408)
|
||||
#define CPG_PL6_SSEL (0x414)
|
||||
#define CPG_PL6_ETH_SSEL (0x418)
|
||||
|
||||
#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
|
||||
@ -29,16 +32,19 @@
|
||||
|
||||
#define DDIV_PACK(offset, bitpos, size) \
|
||||
(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
|
||||
#define DIVPL1A DDIV_PACK(CPG_PL1_DDIV, 0, 2)
|
||||
#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3)
|
||||
#define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3)
|
||||
#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3)
|
||||
#define DIVPL3C DDIV_PACK(CPG_PL3A_DDIV, 8, 3)
|
||||
#define DIVGPU DDIV_PACK(CPG_PL6_DDIV, 0, 2)
|
||||
|
||||
#define SEL_PLL_PACK(offset, bitpos, size) \
|
||||
(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
|
||||
|
||||
#define SEL_PLL3_3 SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1)
|
||||
#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
|
||||
#define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
|
||||
|
||||
#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
|
||||
#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
|
||||
@ -168,6 +174,9 @@ struct rzg2l_reset {
|
||||
* @num_mod_clks: Number of entries in mod_clks[]
|
||||
* @num_hw_mod_clks: Number of Module Clocks supported by the hardware
|
||||
*
|
||||
* @resets: Array of Module Reset definitions
|
||||
* @num_resets: Number of entries in resets[]
|
||||
*
|
||||
* @crit_mod_clks: Array with Module Clock IDs of critical clocks that
|
||||
* should not be disabled without a knowledgeable driver
|
||||
* @num_crit_mod_clks: Number of entries in crit_mod_clks[]
|
||||
|
@ -16,7 +16,9 @@ obj-$(CONFIG_EXYNOS_5420_COMMON_CLK) += clk-exynos5-subcmu.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
|
||||
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
|
||||
obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos-arm64.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7885.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o
|
||||
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
|
||||
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
|
||||
|
@ -400,7 +400,7 @@ static int exynos5433_cpuclk_notifier_cb(struct notifier_block *nb,
|
||||
}
|
||||
|
||||
/* helper function to register a CPU clock */
|
||||
int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
||||
static int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
||||
unsigned int lookup_id, const char *name,
|
||||
const struct clk_hw *parent, const struct clk_hw *alt_parent,
|
||||
unsigned long offset, const struct exynos_cpuclk_cfg_data *cfg,
|
||||
|
@ -62,11 +62,4 @@ struct exynos_cpuclk {
|
||||
#define CLK_CPU_HAS_E5433_REGS_LAYOUT (1 << 2)
|
||||
};
|
||||
|
||||
int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
||||
unsigned int lookup_id, const char *name,
|
||||
const struct clk_hw *parent, const struct clk_hw *alt_parent,
|
||||
unsigned long offset,
|
||||
const struct exynos_cpuclk_cfg_data *cfg,
|
||||
unsigned long num_cfgs, unsigned long flags);
|
||||
|
||||
#endif /* __SAMSUNG_CLK_CPU_H */
|
||||
|
94
drivers/clk/samsung/clk-exynos-arm64.c
Normal file
94
drivers/clk/samsung/clk-exynos-arm64.c
Normal file
@ -0,0 +1,94 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2021 Linaro Ltd.
|
||||
* Copyright (C) 2021 Dávid Virág <virag.david003@gmail.com>
|
||||
* Author: Sam Protsenko <semen.protsenko@linaro.org>
|
||||
* Author: Dávid Virág <virag.david003@gmail.com>
|
||||
*
|
||||
* This file contains shared functions used by some arm64 Exynos SoCs,
|
||||
* such as Exynos7885 or Exynos850 to register and init CMUs.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "clk-exynos-arm64.h"
|
||||
|
||||
/* Gate register bits */
|
||||
#define GATE_MANUAL BIT(20)
|
||||
#define GATE_ENABLE_HWACG BIT(28)
|
||||
|
||||
/* Gate register offsets range */
|
||||
#define GATE_OFF_START 0x2000
|
||||
#define GATE_OFF_END 0x2fff
|
||||
|
||||
/**
|
||||
* exynos_arm64_init_clocks - Set clocks initial configuration
|
||||
* @np: CMU device tree node with "reg" property (CMU addr)
|
||||
* @reg_offs: Register offsets array for clocks to init
|
||||
* @reg_offs_len: Number of register offsets in reg_offs array
|
||||
*
|
||||
* Set manual control mode for all gate clocks.
|
||||
*/
|
||||
static void __init exynos_arm64_init_clocks(struct device_node *np,
|
||||
const unsigned long *reg_offs, size_t reg_offs_len)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
size_t i;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
|
||||
for (i = 0; i < reg_offs_len; ++i) {
|
||||
void __iomem *reg = reg_base + reg_offs[i];
|
||||
u32 val;
|
||||
|
||||
/* Modify only gate clock registers */
|
||||
if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END)
|
||||
continue;
|
||||
|
||||
val = readl(reg);
|
||||
val |= GATE_MANUAL;
|
||||
val &= ~GATE_ENABLE_HWACG;
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
iounmap(reg_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos_arm64_register_cmu - Register specified Exynos CMU domain
|
||||
* @dev: Device object; may be NULL if this function is not being
|
||||
* called from platform driver probe function
|
||||
* @np: CMU device tree node
|
||||
* @cmu: CMU data
|
||||
*
|
||||
* Register specified CMU domain, which includes next steps:
|
||||
*
|
||||
* 1. Enable parent clock of @cmu CMU
|
||||
* 2. Set initial registers configuration for @cmu CMU clocks
|
||||
* 3. Register @cmu CMU clocks using Samsung clock framework API
|
||||
*/
|
||||
void __init exynos_arm64_register_cmu(struct device *dev,
|
||||
struct device_node *np, const struct samsung_cmu_info *cmu)
|
||||
{
|
||||
/* Keep CMU parent clock running (needed for CMU registers access) */
|
||||
if (cmu->clk_name) {
|
||||
struct clk *parent_clk;
|
||||
|
||||
if (dev)
|
||||
parent_clk = clk_get(dev, cmu->clk_name);
|
||||
else
|
||||
parent_clk = of_clk_get_by_name(np, cmu->clk_name);
|
||||
|
||||
if (IS_ERR(parent_clk)) {
|
||||
pr_err("%s: could not find bus clock %s; err = %ld\n",
|
||||
__func__, cmu->clk_name, PTR_ERR(parent_clk));
|
||||
} else {
|
||||
clk_prepare_enable(parent_clk);
|
||||
}
|
||||
}
|
||||
|
||||
exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs);
|
||||
samsung_cmu_register_one(np, cmu);
|
||||
}
|
20
drivers/clk/samsung/clk-exynos-arm64.h
Normal file
20
drivers/clk/samsung/clk-exynos-arm64.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2021 Linaro Ltd.
|
||||
* Copyright (C) 2021 Dávid Virág <virag.david003@gmail.com>
|
||||
* Author: Sam Protsenko <semen.protsenko@linaro.org>
|
||||
* Author: Dávid Virág <virag.david003@gmail.com>
|
||||
*
|
||||
* This file contains shared functions used by some arm64 Exynos SoCs,
|
||||
* such as Exynos7885 or Exynos850 to register and init CMUs.
|
||||
*/
|
||||
|
||||
#ifndef __CLK_EXYNOS_ARM64_H
|
||||
#define __CLK_EXYNOS_ARM64_H
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
void exynos_arm64_register_cmu(struct device *dev,
|
||||
struct device_node *np, const struct samsung_cmu_info *cmu);
|
||||
|
||||
#endif /* __CLK_EXYNOS_ARM64_H */
|
@ -748,6 +748,31 @@ static const struct samsung_pll_clock exynos3250_plls[] __initconst = {
|
||||
UPLL_LOCK, UPLL_CON0, exynos3250_pll_rates),
|
||||
};
|
||||
|
||||
#define E3250_CPU_DIV0(apll, pclk_dbg, atb, corem) \
|
||||
(((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
|
||||
((corem) << 4))
|
||||
#define E3250_CPU_DIV1(hpm, copy) \
|
||||
(((hpm) << 4) | ((copy) << 0))
|
||||
|
||||
static const struct exynos_cpuclk_cfg_data e3250_armclk_d[] __initconst = {
|
||||
{ 1000000, E3250_CPU_DIV0(1, 7, 4, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 900000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 800000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 700000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 600000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 500000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 400000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 300000, E3250_CPU_DIV0(1, 5, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 200000, E3250_CPU_DIV0(1, 3, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 100000, E3250_CPU_DIV0(1, 1, 1, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct samsung_cpu_clock exynos3250_cpu_clks[] __initconst = {
|
||||
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL_USER_C,
|
||||
CLK_CPU_HAS_DIV1, 0x14200, e3250_armclk_d),
|
||||
};
|
||||
|
||||
static void __init exynos3_core_down_clock(void __iomem *reg_base)
|
||||
{
|
||||
unsigned int tmp;
|
||||
@ -780,46 +805,21 @@ static const struct samsung_cmu_info cmu_info __initconst = {
|
||||
.nr_gate_clks = ARRAY_SIZE(gate_clks),
|
||||
.fixed_factor_clks = fixed_factor_clks,
|
||||
.nr_fixed_factor_clks = ARRAY_SIZE(fixed_factor_clks),
|
||||
.cpu_clks = exynos3250_cpu_clks,
|
||||
.nr_cpu_clks = ARRAY_SIZE(exynos3250_cpu_clks),
|
||||
.nr_clk_ids = CLK_NR_CLKS,
|
||||
.clk_regs = exynos3250_cmu_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(exynos3250_cmu_clk_regs),
|
||||
};
|
||||
|
||||
#define E3250_CPU_DIV0(apll, pclk_dbg, atb, corem) \
|
||||
(((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
|
||||
((corem) << 4))
|
||||
#define E3250_CPU_DIV1(hpm, copy) \
|
||||
(((hpm) << 4) | ((copy) << 0))
|
||||
|
||||
static const struct exynos_cpuclk_cfg_data e3250_armclk_d[] __initconst = {
|
||||
{ 1000000, E3250_CPU_DIV0(1, 7, 4, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 900000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 800000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 700000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 600000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 500000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 400000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 300000, E3250_CPU_DIV0(1, 5, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 200000, E3250_CPU_DIV0(1, 3, 3, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 100000, E3250_CPU_DIV0(1, 1, 1, 1), E3250_CPU_DIV1(7, 7), },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void __init exynos3250_cmu_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct clk_hw **hws;
|
||||
|
||||
ctx = samsung_cmu_register_one(np, &cmu_info);
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
hws = ctx->clk_data.hws;
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL_USER_C],
|
||||
0x14200, e3250_armclk_d, ARRAY_SIZE(e3250_armclk_d),
|
||||
CLK_CPU_HAS_DIV1);
|
||||
|
||||
exynos3_core_down_clock(ctx->reg_base);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
|
||||
|
@ -437,7 +437,7 @@ static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = {
|
||||
|
||||
/* list of mux clocks supported in exynos4210 soc */
|
||||
static const struct samsung_mux_clock exynos4210_mux_early[] __initconst = {
|
||||
MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
|
||||
MUX(CLK_MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock exynos4210_mux_clks[] __initconst = {
|
||||
@ -603,7 +603,7 @@ static const struct samsung_div_clock exynos4_div_clks[] __initconst = {
|
||||
DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
|
||||
DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
|
||||
DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
|
||||
DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
|
||||
DIV(CLK_DIV_CORE2, "div_core2", "div_core", DIV_CPU0, 28, 3),
|
||||
DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
|
||||
DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
|
||||
DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
|
||||
@ -1228,6 +1228,16 @@ static const struct exynos_cpuclk_cfg_data e4412_armclk_d[] __initconst = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct samsung_cpu_clock exynos4210_cpu_clks[] __initconst = {
|
||||
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_SCLK_MPLL,
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4210_armclk_d),
|
||||
};
|
||||
|
||||
static const struct samsung_cpu_clock exynos4412_cpu_clks[] __initconst = {
|
||||
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL_USER_C,
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4412_armclk_d),
|
||||
};
|
||||
|
||||
/* register exynos4 clocks */
|
||||
static void __init exynos4_clk_init(struct device_node *np,
|
||||
enum exynos4_soc soc)
|
||||
@ -1254,21 +1264,21 @@ static void __init exynos4_clk_init(struct device_node *np,
|
||||
samsung_clk_register_mux(ctx, exynos4210_mux_early,
|
||||
ARRAY_SIZE(exynos4210_mux_early));
|
||||
|
||||
if (_get_rate("fin_pll") == 24000000) {
|
||||
if (clk_hw_get_rate(hws[CLK_FIN_PLL]) == 24000000) {
|
||||
exynos4210_plls[apll].rate_table =
|
||||
exynos4210_apll_rates;
|
||||
exynos4210_plls[epll].rate_table =
|
||||
exynos4210_epll_rates;
|
||||
}
|
||||
|
||||
if (_get_rate("mout_vpllsrc") == 24000000)
|
||||
if (clk_hw_get_rate(hws[CLK_MOUT_VPLLSRC]) == 24000000)
|
||||
exynos4210_plls[vpll].rate_table =
|
||||
exynos4210_vpll_rates;
|
||||
|
||||
samsung_clk_register_pll(ctx, exynos4210_plls,
|
||||
ARRAY_SIZE(exynos4210_plls), reg_base);
|
||||
} else {
|
||||
if (_get_rate("fin_pll") == 24000000) {
|
||||
if (clk_hw_get_rate(hws[CLK_FIN_PLL]) == 24000000) {
|
||||
exynos4x12_plls[apll].rate_table =
|
||||
exynos4x12_apll_rates;
|
||||
exynos4x12_plls[epll].rate_table =
|
||||
@ -1304,10 +1314,8 @@ static void __init exynos4_clk_init(struct device_node *np,
|
||||
samsung_clk_register_fixed_factor(ctx,
|
||||
exynos4210_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4210_fixed_factor_clks));
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
hws[CLK_MOUT_APLL], hws[CLK_SCLK_MPLL], 0x14200,
|
||||
e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d),
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
|
||||
samsung_clk_register_cpu(ctx, exynos4210_cpu_clks,
|
||||
ARRAY_SIZE(exynos4210_cpu_clks));
|
||||
} else {
|
||||
samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
|
||||
ARRAY_SIZE(exynos4x12_mux_clks));
|
||||
@ -1318,11 +1326,8 @@ static void __init exynos4_clk_init(struct device_node *np,
|
||||
samsung_clk_register_fixed_factor(ctx,
|
||||
exynos4x12_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4x12_fixed_factor_clks));
|
||||
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL_USER_C], 0x14200,
|
||||
e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d),
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
|
||||
samsung_clk_register_cpu(ctx, exynos4412_cpu_clks,
|
||||
ARRAY_SIZE(exynos4412_cpu_clks));
|
||||
}
|
||||
|
||||
if (soc == EXYNOS4X12)
|
||||
@ -1344,9 +1349,11 @@ static void __init exynos4_clk_init(struct device_node *np,
|
||||
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
|
||||
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
|
||||
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
|
||||
_get_rate("sclk_apll"), _get_rate("sclk_mpll"),
|
||||
_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
|
||||
_get_rate("div_core2"));
|
||||
clk_hw_get_rate(hws[CLK_SCLK_APLL]),
|
||||
clk_hw_get_rate(hws[CLK_SCLK_MPLL]),
|
||||
clk_hw_get_rate(hws[CLK_SCLK_EPLL]),
|
||||
clk_hw_get_rate(hws[CLK_SCLK_VPLL]),
|
||||
clk_hw_get_rate(hws[CLK_DIV_CORE2]));
|
||||
}
|
||||
|
||||
|
||||
|
@ -239,7 +239,7 @@ static const struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initconst = {
|
||||
MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
|
||||
MUX(CLK_MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = {
|
||||
@ -351,7 +351,7 @@ static const struct samsung_div_clock exynos5250_div_clks[] __initconst = {
|
||||
*/
|
||||
DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
|
||||
DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
|
||||
DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
|
||||
DIV(CLK_DIV_ARM2, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
|
||||
|
||||
/*
|
||||
* CMU_TOP
|
||||
@ -772,6 +772,11 @@ static const struct exynos_cpuclk_cfg_data exynos5250_armclk_d[] __initconst = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct samsung_cpu_clock exynos5250_cpu_clks[] __initconst = {
|
||||
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL, CLK_CPU_HAS_DIV1, 0x200,
|
||||
exynos5250_armclk_d),
|
||||
};
|
||||
|
||||
static const struct of_device_id ext_clk_match[] __initconst = {
|
||||
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
|
||||
{ },
|
||||
@ -801,12 +806,12 @@ static void __init exynos5250_clk_init(struct device_node *np)
|
||||
samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks,
|
||||
ARRAY_SIZE(exynos5250_pll_pmux_clks));
|
||||
|
||||
if (_get_rate("fin_pll") == 24 * MHZ) {
|
||||
if (clk_hw_get_rate(hws[CLK_FIN_PLL]) == 24 * MHZ) {
|
||||
exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
|
||||
exynos5250_plls[apll].rate_table = apll_24mhz_tbl;
|
||||
}
|
||||
|
||||
if (_get_rate("mout_vpllsrc") == 24 * MHZ)
|
||||
if (clk_hw_get_rate(hws[CLK_MOUT_VPLLSRC]) == 24 * MHZ)
|
||||
exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
|
||||
|
||||
samsung_clk_register_pll(ctx, exynos5250_plls,
|
||||
@ -822,10 +827,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
|
||||
ARRAY_SIZE(exynos5250_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos5250_gate_clks,
|
||||
ARRAY_SIZE(exynos5250_gate_clks));
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL], 0x200,
|
||||
exynos5250_armclk_d, ARRAY_SIZE(exynos5250_armclk_d),
|
||||
CLK_CPU_HAS_DIV1);
|
||||
samsung_clk_register_cpu(ctx, exynos5250_cpu_clks,
|
||||
ARRAY_SIZE(exynos5250_cpu_clks));
|
||||
|
||||
/*
|
||||
* Enable arm clock down (in idle) and set arm divider
|
||||
@ -855,6 +858,6 @@ static void __init exynos5250_clk_init(struct device_node *np)
|
||||
samsung_clk_of_add_provider(np, ctx);
|
||||
|
||||
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
|
||||
_get_rate("div_arm2"));
|
||||
clk_hw_get_rate(hws[CLK_DIV_ARM2]));
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
|
||||
|
@ -1551,6 +1551,20 @@ static const struct exynos_cpuclk_cfg_data exynos5420_kfcclk_d[] __initconst = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct samsung_cpu_clock exynos5420_cpu_clks[] __initconst = {
|
||||
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MSPLL_CPU, 0, 0x200,
|
||||
exynos5420_eglclk_d),
|
||||
CPU_CLK(CLK_KFC_CLK, "kfcclk", CLK_MOUT_KPLL, CLK_MOUT_MSPLL_KFC, 0, 0x28200,
|
||||
exynos5420_kfcclk_d),
|
||||
};
|
||||
|
||||
static const struct samsung_cpu_clock exynos5800_cpu_clks[] __initconst = {
|
||||
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MSPLL_CPU, 0, 0x200,
|
||||
exynos5800_eglclk_d),
|
||||
CPU_CLK(CLK_KFC_CLK, "kfcclk", CLK_MOUT_KPLL, CLK_MOUT_MSPLL_KFC, 0, 0x28200,
|
||||
exynos5420_kfcclk_d),
|
||||
};
|
||||
|
||||
static const struct of_device_id ext_clk_match[] __initconst = {
|
||||
{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
|
||||
{ },
|
||||
@ -1580,7 +1594,7 @@ static void __init exynos5x_clk_init(struct device_node *np,
|
||||
ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
|
||||
ext_clk_match);
|
||||
|
||||
if (_get_rate("fin_pll") == 24 * MHZ) {
|
||||
if (clk_hw_get_rate(hws[CLK_FIN_PLL]) == 24 * MHZ) {
|
||||
exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
exynos5x_plls[epll].rate_table = exynos5420_epll_24mhz_tbl;
|
||||
exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
@ -1625,17 +1639,12 @@ static void __init exynos5x_clk_init(struct device_node *np,
|
||||
}
|
||||
|
||||
if (soc == EXYNOS5420) {
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
hws[CLK_MOUT_APLL], hws[CLK_MOUT_MSPLL_CPU], 0x200,
|
||||
exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
|
||||
samsung_clk_register_cpu(ctx, exynos5420_cpu_clks,
|
||||
ARRAY_SIZE(exynos5420_cpu_clks));
|
||||
} else {
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
hws[CLK_MOUT_APLL], hws[CLK_MOUT_MSPLL_CPU], 0x200,
|
||||
exynos5800_eglclk_d, ARRAY_SIZE(exynos5800_eglclk_d), 0);
|
||||
samsung_clk_register_cpu(ctx, exynos5800_cpu_clks,
|
||||
ARRAY_SIZE(exynos5800_cpu_clks));
|
||||
}
|
||||
exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
|
||||
hws[CLK_MOUT_KPLL], hws[CLK_MOUT_MSPLL_KFC], 0x28200,
|
||||
exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
|
||||
|
||||
samsung_clk_extended_sleep_init(reg_base,
|
||||
exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs),
|
||||
|
597
drivers/clk/samsung/clk-exynos7885.c
Normal file
597
drivers/clk/samsung/clk-exynos7885.c
Normal file
@ -0,0 +1,597 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2021 Dávid Virág <virag.david003@gmail.com>
|
||||
* Author: Dávid Virág <virag.david003@gmail.com>
|
||||
*
|
||||
* Common Clock Framework support for Exynos7885 SoC.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <dt-bindings/clock/exynos7885.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-exynos-arm64.h"
|
||||
|
||||
/* ---- CMU_TOP ------------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_TOP (0x12060000) */
|
||||
#define PLL_LOCKTIME_PLL_SHARED0 0x0000
|
||||
#define PLL_LOCKTIME_PLL_SHARED1 0x0004
|
||||
#define PLL_CON0_PLL_SHARED0 0x0100
|
||||
#define PLL_CON0_PLL_SHARED1 0x0120
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1014
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CORE_G3D 0x101c
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_BUS 0x1058
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_SPI0 0x105c
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_SPI1 0x1060
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART0 0x1064
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART1 0x1068
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART2 0x106c
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_USI0 0x1070
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_USI1 0x1074
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_USI2 0x1078
|
||||
#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x181c
|
||||
#define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1820
|
||||
#define CLK_CON_DIV_CLKCMU_CORE_G3D 0x1824
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_BUS 0x1874
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_SPI0 0x1878
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_SPI1 0x187c
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_UART0 0x1880
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_UART1 0x1884
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_UART2 0x1888
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_USI0 0x188c
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_USI1 0x1890
|
||||
#define CLK_CON_DIV_CLKCMU_PERI_USI2 0x1894
|
||||
#define CLK_CON_DIV_PLL_SHARED0_DIV2 0x189c
|
||||
#define CLK_CON_DIV_PLL_SHARED0_DIV3 0x18a0
|
||||
#define CLK_CON_DIV_PLL_SHARED0_DIV4 0x18a4
|
||||
#define CLK_CON_DIV_PLL_SHARED0_DIV5 0x18a8
|
||||
#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x18ac
|
||||
#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x18b0
|
||||
#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18b4
|
||||
#define CLK_CON_GAT_GATE_CLKCMUC_PERI_UART1 0x2004
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x201c
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CORE_G3D 0x2024
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_BUS 0x207c
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_SPI0 0x2080
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_SPI1 0x2084
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_UART0 0x2088
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_UART2 0x208c
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_USI0 0x2090
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_USI1 0x2094
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_PERI_USI2 0x2098
|
||||
|
||||
static const unsigned long top_clk_regs[] __initconst = {
|
||||
PLL_LOCKTIME_PLL_SHARED0,
|
||||
PLL_LOCKTIME_PLL_SHARED1,
|
||||
PLL_CON0_PLL_SHARED0,
|
||||
PLL_CON0_PLL_SHARED1,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_BUS,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_CCI,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_G3D,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_BUS,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_SPI0,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_SPI1,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART0,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART1,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART2,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_USI0,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_USI1,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_USI2,
|
||||
CLK_CON_DIV_CLKCMU_CORE_BUS,
|
||||
CLK_CON_DIV_CLKCMU_CORE_CCI,
|
||||
CLK_CON_DIV_CLKCMU_CORE_G3D,
|
||||
CLK_CON_DIV_CLKCMU_PERI_BUS,
|
||||
CLK_CON_DIV_CLKCMU_PERI_SPI0,
|
||||
CLK_CON_DIV_CLKCMU_PERI_SPI1,
|
||||
CLK_CON_DIV_CLKCMU_PERI_UART0,
|
||||
CLK_CON_DIV_CLKCMU_PERI_UART1,
|
||||
CLK_CON_DIV_CLKCMU_PERI_UART2,
|
||||
CLK_CON_DIV_CLKCMU_PERI_USI0,
|
||||
CLK_CON_DIV_CLKCMU_PERI_USI1,
|
||||
CLK_CON_DIV_CLKCMU_PERI_USI2,
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV2,
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV3,
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV4,
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV5,
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV2,
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV3,
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV4,
|
||||
CLK_CON_GAT_GATE_CLKCMUC_PERI_UART1,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_BUS,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_CCI,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_G3D,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_BUS,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_SPI0,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_SPI1,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_UART0,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_UART2,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_USI0,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_USI1,
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_USI2,
|
||||
};
|
||||
|
||||
static const struct samsung_pll_clock top_pll_clks[] __initconst = {
|
||||
PLL(pll_1417x, CLK_FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk",
|
||||
PLL_LOCKTIME_PLL_SHARED0, PLL_CON0_PLL_SHARED0,
|
||||
NULL),
|
||||
PLL(pll_1417x, CLK_FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk",
|
||||
PLL_LOCKTIME_PLL_SHARED1, PLL_CON0_PLL_SHARED1,
|
||||
NULL),
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_TOP: for CMU_CORE */
|
||||
PNAME(mout_core_bus_p) = { "dout_shared0_div2", "dout_shared1_div2",
|
||||
"dout_shared0_div3", "dout_shared0_div3" };
|
||||
PNAME(mout_core_cci_p) = { "dout_shared0_div2", "dout_shared1_div2",
|
||||
"dout_shared0_div3", "dout_shared0_div3" };
|
||||
PNAME(mout_core_g3d_p) = { "dout_shared0_div2", "dout_shared1_div2",
|
||||
"dout_shared0_div3", "dout_shared0_div3" };
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_TOP: for CMU_PERI */
|
||||
PNAME(mout_peri_bus_p) = { "dout_shared0_div4", "dout_shared1_div4" };
|
||||
PNAME(mout_peri_spi0_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_spi1_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_uart0_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_uart1_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_uart2_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_usi0_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_usi1_p) = { "oscclk", "dout_shared0_div4" };
|
||||
PNAME(mout_peri_usi2_p) = { "oscclk", "dout_shared0_div4" };
|
||||
|
||||
static const struct samsung_mux_clock top_mux_clks[] __initconst = {
|
||||
/* CORE */
|
||||
MUX(CLK_MOUT_CORE_BUS, "mout_core_bus", mout_core_bus_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 2),
|
||||
MUX(CLK_MOUT_CORE_CCI, "mout_core_cci", mout_core_cci_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, 0, 2),
|
||||
MUX(CLK_MOUT_CORE_G3D, "mout_core_g3d", mout_core_g3d_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_G3D, 0, 2),
|
||||
|
||||
/* PERI */
|
||||
MUX(CLK_MOUT_PERI_BUS, "mout_peri_bus", mout_peri_bus_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_BUS, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_SPI0, "mout_peri_spi0", mout_peri_spi0_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_SPI0, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_SPI1, "mout_peri_spi1", mout_peri_spi1_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_SPI1, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_UART0, "mout_peri_uart0", mout_peri_uart0_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART0, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_UART1, "mout_peri_uart1", mout_peri_uart1_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART1, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_UART2, "mout_peri_uart2", mout_peri_uart2_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART2, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_USI0, "mout_peri_usi0", mout_peri_usi0_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_USI0, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_USI1, "mout_peri_usi1", mout_peri_usi1_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_USI1, 0, 1),
|
||||
MUX(CLK_MOUT_PERI_USI2, "mout_peri_usi2", mout_peri_usi2_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_USI2, 0, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock top_div_clks[] __initconst = {
|
||||
/* TOP */
|
||||
DIV(CLK_DOUT_SHARED0_DIV2, "dout_shared0_div2", "fout_shared0_pll",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1),
|
||||
DIV(CLK_DOUT_SHARED0_DIV3, "dout_shared0_div3", "fout_shared0_pll",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2),
|
||||
DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "fout_shared0_pll",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV4, 0, 1),
|
||||
DIV(CLK_DOUT_SHARED0_DIV5, "dout_shared0_div5", "fout_shared0_pll",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV5, 0, 3),
|
||||
DIV(CLK_DOUT_SHARED1_DIV2, "dout_shared1_div2", "fout_shared1_pll",
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1),
|
||||
DIV(CLK_DOUT_SHARED1_DIV3, "dout_shared1_div3", "fout_shared1_pll",
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2),
|
||||
DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "fout_shared1_pll",
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1),
|
||||
|
||||
/* CORE */
|
||||
DIV(CLK_DOUT_CORE_BUS, "dout_core_bus", "gout_core_bus",
|
||||
CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 3),
|
||||
DIV(CLK_DOUT_CORE_CCI, "dout_core_cci", "gout_core_cci",
|
||||
CLK_CON_DIV_CLKCMU_CORE_CCI, 0, 3),
|
||||
DIV(CLK_DOUT_CORE_G3D, "dout_core_g3d", "gout_core_g3d",
|
||||
CLK_CON_DIV_CLKCMU_CORE_G3D, 0, 3),
|
||||
|
||||
/* PERI */
|
||||
DIV(CLK_DOUT_PERI_BUS, "dout_peri_bus", "gout_peri_bus",
|
||||
CLK_CON_DIV_CLKCMU_PERI_BUS, 0, 4),
|
||||
DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "gout_peri_spi0",
|
||||
CLK_CON_DIV_CLKCMU_PERI_SPI0, 0, 6),
|
||||
DIV(CLK_DOUT_PERI_SPI1, "dout_peri_spi1", "gout_peri_spi1",
|
||||
CLK_CON_DIV_CLKCMU_PERI_SPI1, 0, 6),
|
||||
DIV(CLK_DOUT_PERI_UART0, "dout_peri_uart0", "gout_peri_uart0",
|
||||
CLK_CON_DIV_CLKCMU_PERI_UART0, 0, 4),
|
||||
DIV(CLK_DOUT_PERI_UART1, "dout_peri_uart1", "gout_peri_uart1",
|
||||
CLK_CON_DIV_CLKCMU_PERI_UART1, 0, 4),
|
||||
DIV(CLK_DOUT_PERI_UART2, "dout_peri_uart2", "gout_peri_uart2",
|
||||
CLK_CON_DIV_CLKCMU_PERI_UART2, 0, 4),
|
||||
DIV(CLK_DOUT_PERI_USI0, "dout_peri_usi0", "gout_peri_usi0",
|
||||
CLK_CON_DIV_CLKCMU_PERI_USI0, 0, 4),
|
||||
DIV(CLK_DOUT_PERI_USI1, "dout_peri_usi1", "gout_peri_usi1",
|
||||
CLK_CON_DIV_CLKCMU_PERI_USI1, 0, 4),
|
||||
DIV(CLK_DOUT_PERI_USI2, "dout_peri_usi2", "gout_peri_usi2",
|
||||
CLK_CON_DIV_CLKCMU_PERI_USI2, 0, 4),
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock top_gate_clks[] __initconst = {
|
||||
/* CORE */
|
||||
GATE(CLK_GOUT_CORE_BUS, "gout_core_bus", "mout_core_bus",
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CORE_CCI, "gout_core_cci", "mout_core_cci",
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CORE_G3D, "gout_core_g3d", "mout_core_g3d",
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_G3D, 21, 0, 0),
|
||||
|
||||
/* PERI */
|
||||
GATE(CLK_GOUT_PERI_BUS, "gout_peri_bus", "mout_peri_bus",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_BUS, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_SPI0, "gout_peri_spi0", "mout_peri_spi0",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_SPI0, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_SPI1, "gout_peri_spi1", "mout_peri_spi1",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_SPI1, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_UART0, "gout_peri_uart0", "mout_peri_uart0",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_UART0, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_UART1, "gout_peri_uart1", "mout_peri_uart1",
|
||||
CLK_CON_GAT_GATE_CLKCMUC_PERI_UART1, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_UART2, "gout_peri_uart2", "mout_peri_uart2",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_UART2, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_USI0, "gout_peri_usi0", "mout_peri_usi0",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_USI0, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_USI1, "gout_peri_usi1", "mout_peri_usi1",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_USI1, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PERI_USI2, "gout_peri_usi2", "mout_peri_usi2",
|
||||
CLK_CON_GAT_GATE_CLKCMU_PERI_USI2, 21, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info top_cmu_info __initconst = {
|
||||
.pll_clks = top_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(top_pll_clks),
|
||||
.mux_clks = top_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(top_mux_clks),
|
||||
.div_clks = top_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(top_div_clks),
|
||||
.gate_clks = top_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(top_gate_clks),
|
||||
.nr_clk_ids = TOP_NR_CLK,
|
||||
.clk_regs = top_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(top_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos7885_cmu_top_init(struct device_node *np)
|
||||
{
|
||||
exynos_arm64_register_cmu(NULL, np, &top_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_TOP early, as it's a dependency for other early domains */
|
||||
CLK_OF_DECLARE(exynos7885_cmu_top, "samsung,exynos7885-cmu-top",
|
||||
exynos7885_cmu_top_init);
|
||||
|
||||
/* ---- CMU_PERI ------------------------------------------------------------ */
|
||||
|
||||
/* Register Offset definitions for CMU_PERI (0x10010000) */
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_BUS_USER 0x0100
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_SPI0_USER 0x0120
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_SPI1_USER 0x0140
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_UART0_USER 0x0160
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_UART1_USER 0x0180
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_UART2_USER 0x01a0
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_USI0_USER 0x01c0
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_USI1_USER 0x01e0
|
||||
#define PLL_CON0_MUX_CLKCMU_PERI_USI2_USER 0x0200
|
||||
#define CLK_CON_GAT_GOUT_PERI_GPIO_TOP_PCLK 0x2024
|
||||
#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK 0x2028
|
||||
#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK 0x202c
|
||||
#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK 0x2030
|
||||
#define CLK_CON_GAT_GOUT_PERI_HSI2C_3_PCLK 0x2034
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK 0x2038
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK 0x203c
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK 0x2040
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK 0x2044
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK 0x2048
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK 0x204c
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK 0x2050
|
||||
#define CLK_CON_GAT_GOUT_PERI_I2C_7_PCLK 0x2054
|
||||
#define CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK 0x2058
|
||||
#define CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK 0x205c
|
||||
#define CLK_CON_GAT_GOUT_PERI_SPI_0_EXT_CLK 0x2060
|
||||
#define CLK_CON_GAT_GOUT_PERI_SPI_1_PCLK 0x2064
|
||||
#define CLK_CON_GAT_GOUT_PERI_SPI_1_EXT_CLK 0x2068
|
||||
#define CLK_CON_GAT_GOUT_PERI_UART_0_EXT_UCLK 0x206c
|
||||
#define CLK_CON_GAT_GOUT_PERI_UART_0_PCLK 0x2070
|
||||
#define CLK_CON_GAT_GOUT_PERI_UART_1_EXT_UCLK 0x2074
|
||||
#define CLK_CON_GAT_GOUT_PERI_UART_1_PCLK 0x2078
|
||||
#define CLK_CON_GAT_GOUT_PERI_UART_2_EXT_UCLK 0x207c
|
||||
#define CLK_CON_GAT_GOUT_PERI_UART_2_PCLK 0x2080
|
||||
#define CLK_CON_GAT_GOUT_PERI_USI0_PCLK 0x2084
|
||||
#define CLK_CON_GAT_GOUT_PERI_USI0_SCLK 0x2088
|
||||
#define CLK_CON_GAT_GOUT_PERI_USI1_PCLK 0x208c
|
||||
#define CLK_CON_GAT_GOUT_PERI_USI1_SCLK 0x2090
|
||||
#define CLK_CON_GAT_GOUT_PERI_USI2_PCLK 0x2094
|
||||
#define CLK_CON_GAT_GOUT_PERI_USI2_SCLK 0x2098
|
||||
#define CLK_CON_GAT_GOUT_PERI_MCT_PCLK 0x20a0
|
||||
#define CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK 0x20b0
|
||||
#define CLK_CON_GAT_GOUT_PERI_WDT_CLUSTER0_PCLK 0x20b4
|
||||
#define CLK_CON_GAT_GOUT_PERI_WDT_CLUSTER1_PCLK 0x20b8
|
||||
|
||||
static const unsigned long peri_clk_regs[] __initconst = {
|
||||
PLL_CON0_MUX_CLKCMU_PERI_BUS_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_SPI0_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_SPI1_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_UART0_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_UART1_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_UART2_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_USI0_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_USI1_USER,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_USI2_USER,
|
||||
CLK_CON_GAT_GOUT_PERI_GPIO_TOP_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_3_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_7_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_0_EXT_CLK,
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_1_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_1_EXT_CLK,
|
||||
CLK_CON_GAT_GOUT_PERI_UART_0_EXT_UCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_UART_0_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_UART_1_EXT_UCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_UART_1_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_UART_2_EXT_UCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_UART_2_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_USI0_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_USI0_SCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_USI1_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_USI1_SCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_USI2_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_USI2_SCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_MCT_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_WDT_CLUSTER0_PCLK,
|
||||
CLK_CON_GAT_GOUT_PERI_WDT_CLUSTER1_PCLK,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_PERI */
|
||||
PNAME(mout_peri_bus_user_p) = { "oscclk", "dout_peri_bus" };
|
||||
PNAME(mout_peri_spi0_user_p) = { "oscclk", "dout_peri_spi0" };
|
||||
PNAME(mout_peri_spi1_user_p) = { "oscclk", "dout_peri_spi1" };
|
||||
PNAME(mout_peri_uart0_user_p) = { "oscclk", "dout_peri_uart0" };
|
||||
PNAME(mout_peri_uart1_user_p) = { "oscclk", "dout_peri_uart1" };
|
||||
PNAME(mout_peri_uart2_user_p) = { "oscclk", "dout_peri_uart2" };
|
||||
PNAME(mout_peri_usi0_user_p) = { "oscclk", "dout_peri_usi0" };
|
||||
PNAME(mout_peri_usi1_user_p) = { "oscclk", "dout_peri_usi1" };
|
||||
PNAME(mout_peri_usi2_user_p) = { "oscclk", "dout_peri_usi2" };
|
||||
|
||||
static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_PERI_BUS_USER, "mout_peri_bus_user", mout_peri_bus_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_BUS_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_SPI0_USER, "mout_peri_spi0_user", mout_peri_spi0_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_SPI0_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_SPI1_USER, "mout_peri_spi1_user", mout_peri_spi1_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_PERI_SPI1_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_UART0_USER, "mout_peri_uart0_user",
|
||||
mout_peri_uart0_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART0_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_UART1_USER, "mout_peri_uart1_user",
|
||||
mout_peri_uart1_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART1_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_UART2_USER, "mout_peri_uart2_user",
|
||||
mout_peri_uart2_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART2_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_USI0_USER, "mout_peri_usi0_user",
|
||||
mout_peri_usi0_user_p, PLL_CON0_MUX_CLKCMU_PERI_USI0_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_USI1_USER, "mout_peri_usi1_user",
|
||||
mout_peri_usi1_user_p, PLL_CON0_MUX_CLKCMU_PERI_USI1_USER, 4, 1),
|
||||
MUX(CLK_MOUT_PERI_USI2_USER, "mout_peri_usi2_user",
|
||||
mout_peri_usi2_user_p, PLL_CON0_MUX_CLKCMU_PERI_USI2_USER, 4, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
|
||||
/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */
|
||||
GATE(CLK_GOUT_GPIO_TOP_PCLK, "gout_gpio_top_pclk",
|
||||
"mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_GPIO_TOP_PCLK, 21, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_GOUT_HSI2C0_PCLK, "gout_hsi2c0_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_HSI2C1_PCLK, "gout_hsi2c1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_HSI2C2_PCLK, "gout_hsi2c2_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_HSI2C3_PCLK, "gout_hsi2c3_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_HSI2C_3_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C0_PCLK, "gout_i2c0_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C1_PCLK, "gout_i2c1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C2_PCLK, "gout_i2c2_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C3_PCLK, "gout_i2c3_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C4_PCLK, "gout_i2c4_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C5_PCLK, "gout_i2c5_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C6_PCLK, "gout_i2c6_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I2C7_PCLK, "gout_i2c7_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_I2C_7_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_PWM_MOTOR_PCLK, "gout_pwm_motor_pclk",
|
||||
"mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SPI0_EXT_CLK, "gout_spi0_ipclk", "mout_peri_spi0_user",
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_0_EXT_CLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SPI1_PCLK, "gout_spi1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_1_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SPI1_EXT_CLK, "gout_spi1_ipclk", "mout_peri_spi1_user",
|
||||
CLK_CON_GAT_GOUT_PERI_SPI_1_EXT_CLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_UART0_EXT_UCLK, "gout_uart0_ext_uclk", "mout_peri_uart0_user",
|
||||
CLK_CON_GAT_GOUT_PERI_UART_0_EXT_UCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_UART0_PCLK, "gout_uart0_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_UART_0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_UART1_EXT_UCLK, "gout_uart1_ext_uclk", "mout_peri_uart1_user",
|
||||
CLK_CON_GAT_GOUT_PERI_UART_1_EXT_UCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_UART1_PCLK, "gout_uart1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_UART_1_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_UART2_EXT_UCLK, "gout_uart2_ext_uclk", "mout_peri_uart2_user",
|
||||
CLK_CON_GAT_GOUT_PERI_UART_2_EXT_UCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_UART2_PCLK, "gout_uart2_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_UART_2_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USI0_PCLK, "gout_usi0_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_USI0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USI0_SCLK, "gout_usi0_sclk", "mout_peri_usi0_user",
|
||||
CLK_CON_GAT_GOUT_PERI_USI0_SCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USI1_PCLK, "gout_usi1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_USI1_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USI1_SCLK, "gout_usi1_sclk", "mout_peri_usi1_user",
|
||||
CLK_CON_GAT_GOUT_PERI_USI1_SCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USI2_PCLK, "gout_usi2_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_USI2_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USI2_SCLK, "gout_usi2_sclk", "mout_peri_usi2_user",
|
||||
CLK_CON_GAT_GOUT_PERI_USI2_SCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_MCT_PCLK, "gout_mct_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_MCT_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk",
|
||||
"mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_WDT0_PCLK, "gout_wdt0_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_WDT_CLUSTER0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_WDT1_PCLK, "gout_wdt1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_WDT_CLUSTER1_PCLK, 21, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info peri_cmu_info __initconst = {
|
||||
.mux_clks = peri_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(peri_mux_clks),
|
||||
.gate_clks = peri_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(peri_gate_clks),
|
||||
.nr_clk_ids = PERI_NR_CLK,
|
||||
.clk_regs = peri_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(peri_clk_regs),
|
||||
.clk_name = "dout_peri_bus",
|
||||
};
|
||||
|
||||
static void __init exynos7885_cmu_peri_init(struct device_node *np)
|
||||
{
|
||||
exynos_arm64_register_cmu(NULL, np, &peri_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_PERI early, as it's needed for MCT timer */
|
||||
CLK_OF_DECLARE(exynos7885_cmu_peri, "samsung,exynos7885-cmu-peri",
|
||||
exynos7885_cmu_peri_init);
|
||||
|
||||
/* ---- CMU_CORE ------------------------------------------------------------ */
|
||||
|
||||
/* Register Offset definitions for CMU_CORE (0x12000000) */
|
||||
#define PLL_CON0_MUX_CLKCMU_CORE_BUS_USER 0x0100
|
||||
#define PLL_CON0_MUX_CLKCMU_CORE_CCI_USER 0x0120
|
||||
#define PLL_CON0_MUX_CLKCMU_CORE_G3D_USER 0x0140
|
||||
#define CLK_CON_MUX_MUX_CLK_CORE_GIC 0x1000
|
||||
#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800
|
||||
#define CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK 0x2054
|
||||
#define CLK_CON_GAT_GOUT_CORE_GIC400_CLK 0x2058
|
||||
|
||||
static const unsigned long core_clk_regs[] __initconst = {
|
||||
PLL_CON0_MUX_CLKCMU_CORE_BUS_USER,
|
||||
PLL_CON0_MUX_CLKCMU_CORE_CCI_USER,
|
||||
PLL_CON0_MUX_CLKCMU_CORE_G3D_USER,
|
||||
CLK_CON_MUX_MUX_CLK_CORE_GIC,
|
||||
CLK_CON_DIV_DIV_CLK_CORE_BUSP,
|
||||
CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK,
|
||||
CLK_CON_GAT_GOUT_CORE_GIC400_CLK,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_CORE */
|
||||
PNAME(mout_core_bus_user_p) = { "oscclk", "dout_core_bus" };
|
||||
PNAME(mout_core_cci_user_p) = { "oscclk", "dout_core_cci" };
|
||||
PNAME(mout_core_g3d_user_p) = { "oscclk", "dout_core_g3d" };
|
||||
PNAME(mout_core_gic_p) = { "dout_core_busp", "oscclk" };
|
||||
|
||||
static const struct samsung_mux_clock core_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_CORE_BUS_USER, "mout_core_bus_user", mout_core_bus_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CORE_CCI_USER, "mout_core_cci_user", mout_core_cci_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CORE_CCI_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CORE_G3D_USER, "mout_core_g3d_user", mout_core_g3d_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_CORE_G3D_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CORE_GIC, "mout_core_gic", mout_core_gic_p,
|
||||
CLK_CON_MUX_MUX_CLK_CORE_GIC, 0, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock core_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_CORE_BUSP, "dout_core_busp", "mout_core_bus_user",
|
||||
CLK_CON_DIV_DIV_CLK_CORE_BUSP, 0, 2),
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock core_gate_clks[] __initconst = {
|
||||
/* CCI (interconnect) clock must be always running */
|
||||
GATE(CLK_GOUT_CCI_ACLK, "gout_cci_aclk", "mout_core_cci_user",
|
||||
CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, CLK_IS_CRITICAL, 0),
|
||||
/* GIC (interrupt controller) clock must be always running */
|
||||
GATE(CLK_GOUT_GIC400_CLK, "gout_gic400_clk", "mout_core_gic",
|
||||
CLK_CON_GAT_GOUT_CORE_GIC400_CLK, 21, CLK_IS_CRITICAL, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info core_cmu_info __initconst = {
|
||||
.mux_clks = core_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(core_mux_clks),
|
||||
.div_clks = core_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(core_div_clks),
|
||||
.gate_clks = core_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(core_gate_clks),
|
||||
.nr_clk_ids = CORE_NR_CLK,
|
||||
.clk_regs = core_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(core_clk_regs),
|
||||
.clk_name = "dout_core_bus",
|
||||
};
|
||||
|
||||
/* ---- platform_driver ----------------------------------------------------- */
|
||||
|
||||
static int __init exynos7885_cmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct samsung_cmu_info *info;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
exynos_arm64_register_cmu(dev, dev->of_node, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id exynos7885_cmu_of_match[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos7885-cmu-core",
|
||||
.data = &core_cmu_info,
|
||||
}, {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_driver exynos7885_cmu_driver __refdata = {
|
||||
.driver = {
|
||||
.name = "exynos7885-cmu",
|
||||
.of_match_table = exynos7885_cmu_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = exynos7885_cmu_probe,
|
||||
};
|
||||
|
||||
static int __init exynos7885_cmu_init(void)
|
||||
{
|
||||
return platform_driver_register(&exynos7885_cmu_driver);
|
||||
}
|
||||
core_initcall(exynos7885_cmu_init);
|
@ -9,56 +9,13 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <dt-bindings/clock/exynos850.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
/* Gate register bits */
|
||||
#define GATE_MANUAL BIT(20)
|
||||
#define GATE_ENABLE_HWACG BIT(28)
|
||||
|
||||
/* Gate register offsets range */
|
||||
#define GATE_OFF_START 0x2000
|
||||
#define GATE_OFF_END 0x2fff
|
||||
|
||||
/**
|
||||
* exynos850_init_clocks - Set clocks initial configuration
|
||||
* @np: CMU device tree node with "reg" property (CMU addr)
|
||||
* @reg_offs: Register offsets array for clocks to init
|
||||
* @reg_offs_len: Number of register offsets in reg_offs array
|
||||
*
|
||||
* Set manual control mode for all gate clocks.
|
||||
*/
|
||||
static void __init exynos850_init_clocks(struct device_node *np,
|
||||
const unsigned long *reg_offs, size_t reg_offs_len)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
size_t i;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
|
||||
for (i = 0; i < reg_offs_len; ++i) {
|
||||
void __iomem *reg = reg_base + reg_offs[i];
|
||||
u32 val;
|
||||
|
||||
/* Modify only gate clock registers */
|
||||
if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END)
|
||||
continue;
|
||||
|
||||
val = readl(reg);
|
||||
val |= GATE_MANUAL;
|
||||
val &= ~GATE_ENABLE_HWACG;
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
iounmap(reg_base);
|
||||
}
|
||||
#include "clk-exynos-arm64.h"
|
||||
|
||||
/* ---- CMU_TOP ------------------------------------------------------------- */
|
||||
|
||||
@ -72,6 +29,7 @@ static void __init exynos850_init_clocks(struct device_node *np,
|
||||
#define PLL_CON3_PLL_SHARED0 0x014c
|
||||
#define PLL_CON0_PLL_SHARED1 0x0180
|
||||
#define PLL_CON3_PLL_SHARED1 0x018c
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_APM_BUS 0x1000
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1014
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c
|
||||
@ -83,6 +41,7 @@ static void __init exynos850_init_clocks(struct device_node *np,
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_BUS 0x1070
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_IP 0x1074
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART 0x1078
|
||||
#define CLK_CON_DIV_CLKCMU_APM_BUS 0x180c
|
||||
#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x1820
|
||||
#define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1824
|
||||
#define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828
|
||||
@ -100,6 +59,7 @@ static void __init exynos850_init_clocks(struct device_node *np,
|
||||
#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x1898
|
||||
#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x189c
|
||||
#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18a0
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_APM_BUS 0x2008
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x201c
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024
|
||||
@ -122,6 +82,7 @@ static const unsigned long top_clk_regs[] __initconst = {
|
||||
PLL_CON3_PLL_SHARED0,
|
||||
PLL_CON0_PLL_SHARED1,
|
||||
PLL_CON3_PLL_SHARED1,
|
||||
CLK_CON_MUX_MUX_CLKCMU_APM_BUS,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_BUS,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_CCI,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD,
|
||||
@ -133,6 +94,7 @@ static const unsigned long top_clk_regs[] __initconst = {
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_BUS,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_IP,
|
||||
CLK_CON_MUX_MUX_CLKCMU_PERI_UART,
|
||||
CLK_CON_DIV_CLKCMU_APM_BUS,
|
||||
CLK_CON_DIV_CLKCMU_CORE_BUS,
|
||||
CLK_CON_DIV_CLKCMU_CORE_CCI,
|
||||
CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD,
|
||||
@ -150,6 +112,7 @@ static const unsigned long top_clk_regs[] __initconst = {
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV2,
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV3,
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV4,
|
||||
CLK_CON_GAT_GATE_CLKCMU_APM_BUS,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_BUS,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_CCI,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD,
|
||||
@ -183,6 +146,8 @@ static const struct samsung_pll_clock top_pll_clks[] __initconst = {
|
||||
PNAME(mout_shared0_pll_p) = { "oscclk", "fout_shared0_pll" };
|
||||
PNAME(mout_shared1_pll_p) = { "oscclk", "fout_shared1_pll" };
|
||||
PNAME(mout_mmc_pll_p) = { "oscclk", "fout_mmc_pll" };
|
||||
/* List of parent clocks for Muxes in CMU_TOP: for CMU_APM */
|
||||
PNAME(mout_clkcmu_apm_bus_p) = { "dout_shared0_div4", "pll_shared1_div4" };
|
||||
/* List of parent clocks for Muxes in CMU_TOP: for CMU_CORE */
|
||||
PNAME(mout_core_bus_p) = { "dout_shared1_div2", "dout_shared0_div3",
|
||||
"dout_shared1_div3", "dout_shared0_div4" };
|
||||
@ -222,6 +187,10 @@ static const struct samsung_mux_clock top_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_MMC_PLL, "mout_mmc_pll", mout_mmc_pll_p,
|
||||
PLL_CON0_PLL_MMC, 4, 1),
|
||||
|
||||
/* APM */
|
||||
MUX(CLK_MOUT_CLKCMU_APM_BUS, "mout_clkcmu_apm_bus",
|
||||
mout_clkcmu_apm_bus_p, CLK_CON_MUX_MUX_CLKCMU_APM_BUS, 0, 1),
|
||||
|
||||
/* CORE */
|
||||
MUX(CLK_MOUT_CORE_BUS, "mout_core_bus", mout_core_bus_p,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 2),
|
||||
@ -268,6 +237,10 @@ static const struct samsung_div_clock top_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2",
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1),
|
||||
|
||||
/* APM */
|
||||
DIV(CLK_DOUT_CLKCMU_APM_BUS, "dout_clkcmu_apm_bus",
|
||||
"gout_clkcmu_apm_bus", CLK_CON_DIV_CLKCMU_APM_BUS, 0, 3),
|
||||
|
||||
/* CORE */
|
||||
DIV(CLK_DOUT_CORE_BUS, "dout_core_bus", "gout_core_bus",
|
||||
CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4),
|
||||
@ -310,6 +283,10 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
|
||||
GATE(CLK_GOUT_CORE_SSS, "gout_core_sss", "mout_core_sss",
|
||||
CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, 21, 0, 0),
|
||||
|
||||
/* APM */
|
||||
GATE(CLK_GOUT_CLKCMU_APM_BUS, "gout_clkcmu_apm_bus",
|
||||
"mout_clkcmu_apm_bus", CLK_CON_GAT_GATE_CLKCMU_APM_BUS, 21, 0, 0),
|
||||
|
||||
/* DPU */
|
||||
GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu",
|
||||
CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0),
|
||||
@ -347,13 +324,248 @@ static const struct samsung_cmu_info top_cmu_info __initconst = {
|
||||
|
||||
static void __init exynos850_cmu_top_init(struct device_node *np)
|
||||
{
|
||||
exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs));
|
||||
samsung_cmu_register_one(np, &top_cmu_info);
|
||||
exynos_arm64_register_cmu(NULL, np, &top_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_TOP early, as it's a dependency for other early domains */
|
||||
CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top",
|
||||
exynos850_cmu_top_init);
|
||||
|
||||
/* ---- CMU_APM ------------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_APM (0x11800000) */
|
||||
#define PLL_CON0_MUX_CLKCMU_APM_BUS_USER 0x0600
|
||||
#define PLL_CON0_MUX_CLK_RCO_APM_I3C_USER 0x0610
|
||||
#define PLL_CON0_MUX_CLK_RCO_APM_USER 0x0620
|
||||
#define PLL_CON0_MUX_DLL_USER 0x0630
|
||||
#define CLK_CON_MUX_MUX_CLKCMU_CHUB_BUS 0x1000
|
||||
#define CLK_CON_MUX_MUX_CLK_APM_BUS 0x1004
|
||||
#define CLK_CON_MUX_MUX_CLK_APM_I3C 0x1008
|
||||
#define CLK_CON_DIV_CLKCMU_CHUB_BUS 0x1800
|
||||
#define CLK_CON_DIV_DIV_CLK_APM_BUS 0x1804
|
||||
#define CLK_CON_DIV_DIV_CLK_APM_I3C 0x1808
|
||||
#define CLK_CON_GAT_CLKCMU_CMGP_BUS 0x2000
|
||||
#define CLK_CON_GAT_GATE_CLKCMU_CHUB_BUS 0x2014
|
||||
#define CLK_CON_GAT_GOUT_APM_APBIF_GPIO_ALIVE_PCLK 0x2018
|
||||
#define CLK_CON_GAT_GOUT_APM_APBIF_PMU_ALIVE_PCLK 0x2020
|
||||
#define CLK_CON_GAT_GOUT_APM_APBIF_RTC_PCLK 0x2024
|
||||
#define CLK_CON_GAT_GOUT_APM_APBIF_TOP_RTC_PCLK 0x2028
|
||||
#define CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_PCLK 0x2034
|
||||
#define CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_SCLK 0x2038
|
||||
#define CLK_CON_GAT_GOUT_APM_SPEEDY_APM_PCLK 0x20bc
|
||||
#define CLK_CON_GAT_GOUT_APM_SYSREG_APM_PCLK 0x20c0
|
||||
|
||||
static const unsigned long apm_clk_regs[] __initconst = {
|
||||
PLL_CON0_MUX_CLKCMU_APM_BUS_USER,
|
||||
PLL_CON0_MUX_CLK_RCO_APM_I3C_USER,
|
||||
PLL_CON0_MUX_CLK_RCO_APM_USER,
|
||||
PLL_CON0_MUX_DLL_USER,
|
||||
CLK_CON_MUX_MUX_CLKCMU_CHUB_BUS,
|
||||
CLK_CON_MUX_MUX_CLK_APM_BUS,
|
||||
CLK_CON_MUX_MUX_CLK_APM_I3C,
|
||||
CLK_CON_DIV_CLKCMU_CHUB_BUS,
|
||||
CLK_CON_DIV_DIV_CLK_APM_BUS,
|
||||
CLK_CON_DIV_DIV_CLK_APM_I3C,
|
||||
CLK_CON_GAT_CLKCMU_CMGP_BUS,
|
||||
CLK_CON_GAT_GATE_CLKCMU_CHUB_BUS,
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_GPIO_ALIVE_PCLK,
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_PMU_ALIVE_PCLK,
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_RTC_PCLK,
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_TOP_RTC_PCLK,
|
||||
CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_PCLK,
|
||||
CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_SCLK,
|
||||
CLK_CON_GAT_GOUT_APM_SPEEDY_APM_PCLK,
|
||||
CLK_CON_GAT_GOUT_APM_SYSREG_APM_PCLK,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_APM */
|
||||
PNAME(mout_apm_bus_user_p) = { "oscclk_rco_apm", "dout_clkcmu_apm_bus" };
|
||||
PNAME(mout_rco_apm_i3c_user_p) = { "oscclk_rco_apm", "clk_rco_i3c_pmic" };
|
||||
PNAME(mout_rco_apm_user_p) = { "oscclk_rco_apm", "clk_rco_apm__alv" };
|
||||
PNAME(mout_dll_user_p) = { "oscclk_rco_apm", "clk_dll_dco" };
|
||||
PNAME(mout_clkcmu_chub_bus_p) = { "mout_apm_bus_user", "mout_dll_user" };
|
||||
PNAME(mout_apm_bus_p) = { "mout_rco_apm_user", "mout_apm_bus_user",
|
||||
"mout_dll_user", "oscclk_rco_apm" };
|
||||
PNAME(mout_apm_i3c_p) = { "dout_apm_i3c", "mout_rco_apm_i3c_user" };
|
||||
|
||||
static const struct samsung_fixed_rate_clock apm_fixed_clks[] __initconst = {
|
||||
FRATE(CLK_RCO_I3C_PMIC, "clk_rco_i3c_pmic", NULL, 0, 491520000),
|
||||
FRATE(OSCCLK_RCO_APM, "oscclk_rco_apm", NULL, 0, 24576000),
|
||||
FRATE(CLK_RCO_APM__ALV, "clk_rco_apm__alv", NULL, 0, 49152000),
|
||||
FRATE(CLK_DLL_DCO, "clk_dll_dco", NULL, 0, 360000000),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock apm_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_APM_BUS_USER, "mout_apm_bus_user", mout_apm_bus_user_p,
|
||||
PLL_CON0_MUX_CLKCMU_APM_BUS_USER, 4, 1),
|
||||
MUX(CLK_MOUT_RCO_APM_I3C_USER, "mout_rco_apm_i3c_user",
|
||||
mout_rco_apm_i3c_user_p, PLL_CON0_MUX_CLK_RCO_APM_I3C_USER, 4, 1),
|
||||
MUX(CLK_MOUT_RCO_APM_USER, "mout_rco_apm_user", mout_rco_apm_user_p,
|
||||
PLL_CON0_MUX_CLK_RCO_APM_USER, 4, 1),
|
||||
MUX(CLK_MOUT_DLL_USER, "mout_dll_user", mout_dll_user_p,
|
||||
PLL_CON0_MUX_DLL_USER, 4, 1),
|
||||
MUX(CLK_MOUT_CLKCMU_CHUB_BUS, "mout_clkcmu_chub_bus",
|
||||
mout_clkcmu_chub_bus_p, CLK_CON_MUX_MUX_CLKCMU_CHUB_BUS, 0, 1),
|
||||
MUX(CLK_MOUT_APM_BUS, "mout_apm_bus", mout_apm_bus_p,
|
||||
CLK_CON_MUX_MUX_CLK_APM_BUS, 0, 2),
|
||||
MUX(CLK_MOUT_APM_I3C, "mout_apm_i3c", mout_apm_i3c_p,
|
||||
CLK_CON_MUX_MUX_CLK_APM_I3C, 0, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock apm_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_CLKCMU_CHUB_BUS, "dout_clkcmu_chub_bus",
|
||||
"gout_clkcmu_chub_bus",
|
||||
CLK_CON_DIV_CLKCMU_CHUB_BUS, 0, 3),
|
||||
DIV(CLK_DOUT_APM_BUS, "dout_apm_bus", "mout_apm_bus",
|
||||
CLK_CON_DIV_DIV_CLK_APM_BUS, 0, 3),
|
||||
DIV(CLK_DOUT_APM_I3C, "dout_apm_i3c", "mout_apm_bus",
|
||||
CLK_CON_DIV_DIV_CLK_APM_I3C, 0, 3),
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock apm_gate_clks[] __initconst = {
|
||||
GATE(CLK_GOUT_CLKCMU_CMGP_BUS, "gout_clkcmu_cmgp_bus", "dout_apm_bus",
|
||||
CLK_CON_GAT_CLKCMU_CMGP_BUS, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CLKCMU_CHUB_BUS, "gout_clkcmu_chub_bus",
|
||||
"mout_clkcmu_chub_bus",
|
||||
CLK_CON_GAT_GATE_CLKCMU_CHUB_BUS, 21, 0, 0),
|
||||
GATE(CLK_GOUT_RTC_PCLK, "gout_rtc_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_RTC_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_TOP_RTC_PCLK, "gout_top_rtc_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_TOP_RTC_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I3C_PCLK, "gout_i3c_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_I3C_SCLK, "gout_i3c_sclk", "mout_apm_i3c",
|
||||
CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_SCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SPEEDY_PCLK, "gout_speedy_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_SPEEDY_APM_PCLK, 21, 0, 0),
|
||||
/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */
|
||||
GATE(CLK_GOUT_GPIO_ALIVE_PCLK, "gout_gpio_alive_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_GPIO_ALIVE_PCLK, 21, CLK_IGNORE_UNUSED,
|
||||
0),
|
||||
GATE(CLK_GOUT_PMU_ALIVE_PCLK, "gout_pmu_alive_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_APBIF_PMU_ALIVE_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SYSREG_APM_PCLK, "gout_sysreg_apm_pclk", "dout_apm_bus",
|
||||
CLK_CON_GAT_GOUT_APM_SYSREG_APM_PCLK, 21, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info apm_cmu_info __initconst = {
|
||||
.mux_clks = apm_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(apm_mux_clks),
|
||||
.div_clks = apm_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(apm_div_clks),
|
||||
.gate_clks = apm_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(apm_gate_clks),
|
||||
.fixed_clks = apm_fixed_clks,
|
||||
.nr_fixed_clks = ARRAY_SIZE(apm_fixed_clks),
|
||||
.nr_clk_ids = APM_NR_CLK,
|
||||
.clk_regs = apm_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(apm_clk_regs),
|
||||
.clk_name = "dout_clkcmu_apm_bus",
|
||||
};
|
||||
|
||||
/* ---- CMU_CMGP ------------------------------------------------------------ */
|
||||
|
||||
/* Register Offset definitions for CMU_CMGP (0x11c00000) */
|
||||
#define CLK_CON_MUX_CLK_CMGP_ADC 0x1000
|
||||
#define CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0 0x1004
|
||||
#define CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1 0x1008
|
||||
#define CLK_CON_DIV_DIV_CLK_CMGP_ADC 0x1800
|
||||
#define CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0 0x1804
|
||||
#define CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1 0x1808
|
||||
#define CLK_CON_GAT_GOUT_CMGP_ADC_PCLK_S0 0x200c
|
||||
#define CLK_CON_GAT_GOUT_CMGP_ADC_PCLK_S1 0x2010
|
||||
#define CLK_CON_GAT_GOUT_CMGP_GPIO_PCLK 0x2018
|
||||
#define CLK_CON_GAT_GOUT_CMGP_SYSREG_CMGP_PCLK 0x2040
|
||||
#define CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK 0x2044
|
||||
#define CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_PCLK 0x2048
|
||||
#define CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK 0x204c
|
||||
#define CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_PCLK 0x2050
|
||||
|
||||
static const unsigned long cmgp_clk_regs[] __initconst = {
|
||||
CLK_CON_MUX_CLK_CMGP_ADC,
|
||||
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0,
|
||||
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1,
|
||||
CLK_CON_DIV_DIV_CLK_CMGP_ADC,
|
||||
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0,
|
||||
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1,
|
||||
CLK_CON_GAT_GOUT_CMGP_ADC_PCLK_S0,
|
||||
CLK_CON_GAT_GOUT_CMGP_ADC_PCLK_S1,
|
||||
CLK_CON_GAT_GOUT_CMGP_GPIO_PCLK,
|
||||
CLK_CON_GAT_GOUT_CMGP_SYSREG_CMGP_PCLK,
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK,
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_PCLK,
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK,
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_PCLK,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_CMGP */
|
||||
PNAME(mout_cmgp_usi0_p) = { "clk_rco_cmgp", "gout_clkcmu_cmgp_bus" };
|
||||
PNAME(mout_cmgp_usi1_p) = { "clk_rco_cmgp", "gout_clkcmu_cmgp_bus" };
|
||||
PNAME(mout_cmgp_adc_p) = { "oscclk", "dout_cmgp_adc" };
|
||||
|
||||
static const struct samsung_fixed_rate_clock cmgp_fixed_clks[] __initconst = {
|
||||
FRATE(CLK_RCO_CMGP, "clk_rco_cmgp", NULL, 0, 49152000),
|
||||
};
|
||||
|
||||
static const struct samsung_mux_clock cmgp_mux_clks[] __initconst = {
|
||||
MUX(CLK_MOUT_CMGP_ADC, "mout_cmgp_adc", mout_cmgp_adc_p,
|
||||
CLK_CON_MUX_CLK_CMGP_ADC, 0, 1),
|
||||
MUX(CLK_MOUT_CMGP_USI0, "mout_cmgp_usi0", mout_cmgp_usi0_p,
|
||||
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0, 0, 1),
|
||||
MUX(CLK_MOUT_CMGP_USI1, "mout_cmgp_usi1", mout_cmgp_usi1_p,
|
||||
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1, 0, 1),
|
||||
};
|
||||
|
||||
static const struct samsung_div_clock cmgp_div_clks[] __initconst = {
|
||||
DIV(CLK_DOUT_CMGP_ADC, "dout_cmgp_adc", "gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_DIV_DIV_CLK_CMGP_ADC, 0, 4),
|
||||
DIV(CLK_DOUT_CMGP_USI0, "dout_cmgp_usi0", "mout_cmgp_usi0",
|
||||
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0, 0, 5),
|
||||
DIV(CLK_DOUT_CMGP_USI1, "dout_cmgp_usi1", "mout_cmgp_usi1",
|
||||
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1, 0, 5),
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock cmgp_gate_clks[] __initconst = {
|
||||
GATE(CLK_GOUT_CMGP_ADC_S0_PCLK, "gout_adc_s0_pclk",
|
||||
"gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_GAT_GOUT_CMGP_ADC_PCLK_S0, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CMGP_ADC_S1_PCLK, "gout_adc_s1_pclk",
|
||||
"gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_GAT_GOUT_CMGP_ADC_PCLK_S1, 21, 0, 0),
|
||||
/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */
|
||||
GATE(CLK_GOUT_CMGP_GPIO_PCLK, "gout_gpio_cmgp_pclk",
|
||||
"gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_GAT_GOUT_CMGP_GPIO_PCLK, 21, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_GOUT_CMGP_USI0_IPCLK, "gout_cmgp_usi0_ipclk", "dout_cmgp_usi0",
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CMGP_USI0_PCLK, "gout_cmgp_usi0_pclk",
|
||||
"gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CMGP_USI1_IPCLK, "gout_cmgp_usi1_ipclk", "dout_cmgp_usi1",
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_CMGP_USI1_PCLK, "gout_cmgp_usi1_pclk",
|
||||
"gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SYSREG_CMGP_PCLK, "gout_sysreg_cmgp_pclk",
|
||||
"gout_clkcmu_cmgp_bus",
|
||||
CLK_CON_GAT_GOUT_CMGP_SYSREG_CMGP_PCLK, 21, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cmgp_cmu_info __initconst = {
|
||||
.mux_clks = cmgp_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(cmgp_mux_clks),
|
||||
.div_clks = cmgp_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(cmgp_div_clks),
|
||||
.gate_clks = cmgp_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(cmgp_gate_clks),
|
||||
.fixed_clks = cmgp_fixed_clks,
|
||||
.nr_fixed_clks = ARRAY_SIZE(cmgp_fixed_clks),
|
||||
.nr_clk_ids = CMGP_NR_CLK,
|
||||
.clk_regs = cmgp_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(cmgp_clk_regs),
|
||||
.clk_name = "gout_clkcmu_cmgp_bus",
|
||||
};
|
||||
|
||||
/* ---- CMU_HSI ------------------------------------------------------------- */
|
||||
|
||||
/* Register Offset definitions for CMU_HSI (0x13400000) */
|
||||
@ -413,8 +625,9 @@ static const struct samsung_gate_clock hsi_gate_clks[] __initconst = {
|
||||
CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50, 21, 0, 0),
|
||||
GATE(CLK_GOUT_USB_PHY_REF_CLK, "gout_usb_phy_ref", "oscclk",
|
||||
CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26, 21, 0, 0),
|
||||
/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */
|
||||
GATE(CLK_GOUT_GPIO_HSI_PCLK, "gout_gpio_hsi_pclk", "mout_hsi_bus_user",
|
||||
CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, 21, 0, 0),
|
||||
CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, 21, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_GOUT_MMC_CARD_ACLK, "gout_mmc_card_aclk", "mout_hsi_bus_user",
|
||||
CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_MMC_CARD_SDCLKIN, "gout_mmc_card_sdclkin",
|
||||
@ -597,9 +810,10 @@ static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
|
||||
CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_WDT1_PCLK, "gout_wdt1_pclk", "mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK, 21, 0, 0),
|
||||
/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */
|
||||
GATE(CLK_GOUT_GPIO_PERI_PCLK, "gout_gpio_peri_pclk",
|
||||
"mout_peri_bus_user",
|
||||
CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, 21, 0, 0),
|
||||
CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, 21, CLK_IGNORE_UNUSED, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info peri_cmu_info __initconst = {
|
||||
@ -615,6 +829,15 @@ static const struct samsung_cmu_info peri_cmu_info __initconst = {
|
||||
.clk_name = "dout_peri_bus",
|
||||
};
|
||||
|
||||
static void __init exynos850_cmu_peri_init(struct device_node *np)
|
||||
{
|
||||
exynos_arm64_register_cmu(NULL, np, &peri_cmu_info);
|
||||
}
|
||||
|
||||
/* Register CMU_PERI early, as it's needed for MCT timer */
|
||||
CLK_OF_DECLARE(exynos850_cmu_peri, "samsung,exynos850-cmu-peri",
|
||||
exynos850_cmu_peri_init);
|
||||
|
||||
/* ---- CMU_CORE ------------------------------------------------------------ */
|
||||
|
||||
/* Register Offset definitions for CMU_CORE (0x12000000) */
|
||||
@ -626,10 +849,12 @@ static const struct samsung_cmu_info peri_cmu_info __initconst = {
|
||||
#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800
|
||||
#define CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK 0x2038
|
||||
#define CLK_CON_GAT_GOUT_CORE_GIC_CLK 0x2040
|
||||
#define CLK_CON_GAT_GOUT_CORE_GPIO_CORE_PCLK 0x2044
|
||||
#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK 0x20e8
|
||||
#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN 0x20ec
|
||||
#define CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK 0x2128
|
||||
#define CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK 0x212c
|
||||
#define CLK_CON_GAT_GOUT_CORE_SYSREG_CORE_PCLK 0x2130
|
||||
|
||||
static const unsigned long core_clk_regs[] __initconst = {
|
||||
PLL_CON0_MUX_CLKCMU_CORE_BUS_USER,
|
||||
@ -640,10 +865,12 @@ static const unsigned long core_clk_regs[] __initconst = {
|
||||
CLK_CON_DIV_DIV_CLK_CORE_BUSP,
|
||||
CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK,
|
||||
CLK_CON_GAT_GOUT_CORE_GIC_CLK,
|
||||
CLK_CON_GAT_GOUT_CORE_GPIO_CORE_PCLK,
|
||||
CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK,
|
||||
CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
|
||||
CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK,
|
||||
CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK,
|
||||
CLK_CON_GAT_GOUT_CORE_SYSREG_CORE_PCLK,
|
||||
};
|
||||
|
||||
/* List of parent clocks for Muxes in CMU_CORE */
|
||||
@ -673,10 +900,12 @@ static const struct samsung_div_clock core_div_clks[] __initconst = {
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock core_gate_clks[] __initconst = {
|
||||
/* CCI (interconnect) clock must be always running */
|
||||
GATE(CLK_GOUT_CCI_ACLK, "gout_cci_aclk", "mout_core_cci_user",
|
||||
CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, 0, 0),
|
||||
CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, CLK_IS_CRITICAL, 0),
|
||||
/* GIC (interrupt controller) clock must be always running */
|
||||
GATE(CLK_GOUT_GIC_CLK, "gout_gic_clk", "mout_core_gic",
|
||||
CLK_CON_GAT_GOUT_CORE_GIC_CLK, 21, 0, 0),
|
||||
CLK_CON_GAT_GOUT_CORE_GIC_CLK, 21, CLK_IS_CRITICAL, 0),
|
||||
GATE(CLK_GOUT_MMC_EMBD_ACLK, "gout_mmc_embd_aclk", "dout_core_busp",
|
||||
CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_MMC_EMBD_SDCLKIN, "gout_mmc_embd_sdclkin",
|
||||
@ -686,6 +915,12 @@ static const struct samsung_gate_clock core_gate_clks[] __initconst = {
|
||||
CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK, 21, 0, 0),
|
||||
GATE(CLK_GOUT_SSS_PCLK, "gout_sss_pclk", "dout_core_busp",
|
||||
CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK, 21, 0, 0),
|
||||
/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */
|
||||
GATE(CLK_GOUT_GPIO_CORE_PCLK, "gout_gpio_core_pclk", "dout_core_busp",
|
||||
CLK_CON_GAT_GOUT_CORE_GPIO_CORE_PCLK, 21, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_GOUT_SYSREG_CORE_PCLK, "gout_sysreg_core_pclk",
|
||||
"dout_core_busp",
|
||||
CLK_CON_GAT_GOUT_CORE_SYSREG_CORE_PCLK, 21, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info core_cmu_info __initconst = {
|
||||
@ -742,8 +977,10 @@ static const struct samsung_div_clock dpu_div_clks[] __initconst = {
|
||||
};
|
||||
|
||||
static const struct samsung_gate_clock dpu_gate_clks[] __initconst = {
|
||||
/* TODO: Should be enabled in DSIM driver */
|
||||
GATE(CLK_GOUT_DPU_CMU_DPU_PCLK, "gout_dpu_cmu_dpu_pclk",
|
||||
"dout_dpu_busp", CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, 21, 0, 0),
|
||||
"dout_dpu_busp",
|
||||
CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, 21, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_GOUT_DPU_DECON0_ACLK, "gout_dpu_decon0_aclk", "mout_dpu_user",
|
||||
CLK_CON_GAT_GOUT_DPU_ACLK_DECON0, 21, 0, 0),
|
||||
GATE(CLK_GOUT_DPU_DMA_ACLK, "gout_dpu_dma_aclk", "mout_dpu_user",
|
||||
@ -779,36 +1016,23 @@ static int __init exynos850_cmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct samsung_cmu_info *info;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs);
|
||||
samsung_cmu_register_one(np, info);
|
||||
|
||||
/* Keep bus clock running, so it's possible to access CMU registers */
|
||||
if (info->clk_name) {
|
||||
struct clk *bus_clk;
|
||||
|
||||
bus_clk = clk_get(dev, info->clk_name);
|
||||
if (IS_ERR(bus_clk)) {
|
||||
pr_err("%s: could not find bus clock %s; err = %ld\n",
|
||||
__func__, info->clk_name, PTR_ERR(bus_clk));
|
||||
} else {
|
||||
clk_prepare_enable(bus_clk);
|
||||
}
|
||||
}
|
||||
exynos_arm64_register_cmu(dev, dev->of_node, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CMUs which belong to Power Domains and need runtime PM to be implemented */
|
||||
static const struct of_device_id exynos850_cmu_of_match[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos850-cmu-apm",
|
||||
.data = &apm_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos850-cmu-cmgp",
|
||||
.data = &cmgp_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos850-cmu-hsi",
|
||||
.data = &hsi_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos850-cmu-peri",
|
||||
.data = &peri_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos850-cmu-core",
|
||||
.data = &core_cmu_info,
|
||||
|
@ -1476,6 +1476,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
||||
else
|
||||
init.ops = &samsung_pll35xx_clk_ops;
|
||||
break;
|
||||
case pll_1417x:
|
||||
case pll_0822x:
|
||||
pll->enable_offs = PLL0822X_ENABLE_SHIFT;
|
||||
pll->lock_offs = PLL0822X_LOCK_STAT_SHIFT;
|
||||
|
@ -32,6 +32,7 @@ enum samsung_pll_type {
|
||||
pll_2550xx,
|
||||
pll_2650x,
|
||||
pll_2650xx,
|
||||
pll_1417x,
|
||||
pll_1450x,
|
||||
pll_1451x,
|
||||
pll_1452x,
|
||||
|
@ -323,6 +323,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
void __iomem *base)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct clk_hw **hws;
|
||||
reg_base = base;
|
||||
|
||||
if (np) {
|
||||
@ -332,13 +333,14 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
}
|
||||
|
||||
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
|
||||
hws = ctx->clk_data.hws;
|
||||
|
||||
/* Register external clocks only in non-dt cases */
|
||||
if (!np)
|
||||
s3c2410_common_clk_register_fixed_ext(ctx, xti_f);
|
||||
|
||||
if (current_soc == S3C2410) {
|
||||
if (_get_rate("xti") == 12 * MHZ) {
|
||||
if (clk_hw_get_rate(hws[XTI]) == 12 * MHZ) {
|
||||
s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl;
|
||||
s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl;
|
||||
}
|
||||
@ -348,7 +350,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
ARRAY_SIZE(s3c2410_plls), reg_base);
|
||||
|
||||
} else { /* S3C2440, S3C2442 */
|
||||
if (_get_rate("xti") == 12 * MHZ) {
|
||||
if (clk_hw_get_rate(hws[XTI]) == 12 * MHZ) {
|
||||
/*
|
||||
* plls follow different calculation schemes, with the
|
||||
* upll following the same scheme as the s3c2410 plls
|
||||
|
@ -394,6 +394,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
|
||||
void __iomem *base)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct clk_hw **hws;
|
||||
|
||||
reg_base = base;
|
||||
is_s3c6400 = s3c6400;
|
||||
@ -405,6 +406,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
|
||||
}
|
||||
|
||||
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
|
||||
hws = ctx->clk_data.hws;
|
||||
|
||||
/* Register external clocks. */
|
||||
if (!np)
|
||||
@ -459,8 +461,10 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
|
||||
pr_info("%s clocks: apll = %lu, mpll = %lu\n"
|
||||
"\tepll = %lu, arm_clk = %lu\n",
|
||||
is_s3c6400 ? "S3C6400" : "S3C6410",
|
||||
_get_rate("fout_apll"), _get_rate("fout_mpll"),
|
||||
_get_rate("fout_epll"), _get_rate("armclk"));
|
||||
clk_hw_get_rate(hws[MOUT_APLL]),
|
||||
clk_hw_get_rate(hws[MOUT_MPLL]),
|
||||
clk_hw_get_rate(hws[MOUT_EPLL]),
|
||||
clk_hw_get_rate(hws[ARMCLK]));
|
||||
}
|
||||
|
||||
static void __init s3c6400_clk_init(struct device_node *np)
|
||||
|
@ -741,8 +741,10 @@ static void __init __s5pv210_clk_init(struct device_node *np,
|
||||
bool is_s5p6442)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct clk_hw **hws;
|
||||
|
||||
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
|
||||
hws = ctx->clk_data.hws;
|
||||
|
||||
samsung_clk_register_mux(ctx, early_mux_clks,
|
||||
ARRAY_SIZE(early_mux_clks));
|
||||
@ -789,8 +791,10 @@ static void __init __s5pv210_clk_init(struct device_node *np,
|
||||
pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
|
||||
"\tmout_epll = %ld, mout_vpll = %ld\n",
|
||||
is_s5p6442 ? "S5P6442" : "S5PV210",
|
||||
_get_rate("mout_apll"), _get_rate("mout_mpll"),
|
||||
_get_rate("mout_epll"), _get_rate("mout_vpll"));
|
||||
clk_hw_get_rate(hws[MOUT_APLL]),
|
||||
clk_hw_get_rate(hws[MOUT_MPLL]),
|
||||
clk_hw_get_rate(hws[MOUT_EPLL]),
|
||||
clk_hw_get_rate(hws[MOUT_VPLL]));
|
||||
}
|
||||
|
||||
static void __init s5pv210_clk_dt_init(struct device_node *np)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user