Nothing looks out of the ordinary in this batch of clk driver updates. There

are a couple patches to the core clk framework, but they're all basically
 cleanups or debugging aids. The driver updates and new additions are dominated
 in the diffstat by Qualcomm and MediaTek drivers. Qualcomm gained a handful of
 new drivers for various SoCs, and MediaTek gained a bunch of drivers for
 MT8188. The MediaTek drivers are being modernized as well, so there are
 updates all over that vendor's clk drivers. There's also a couple other new clk
 drivers in here, for example the Starfive JH7110 SoC support is added.
 
 Outside of the two major SoC vendors though, we have the usual collection of
 non-critical fixes and cleanups to various clk drivers. It's good to see that
 we're getting more cleanups and modernization patches. Maybe one day we'll be
 able to properly split clk providers from clk consumers.
 
 Core:
  - Print an informational message before disabling unused clks
 
 New Drivers:
  - BCM63268 timer clock and reset controller
  - Frequency Hopping (FHCTL) on MediaTek MT6795, MT8173, MT8192 and
    MT8195 SoCs
  - Mediatek MT8188 SoC clk drivers
  - Clock driver for Sunplus SP7021 SoC
  - Clk driver support for Loongson-2 SoCs
  - Clock driver for Skyworks Si521xx I2C PCIe clock generators
  - Initial Starfive JH7110 clk/reset support
  - Global clock controller drivers for Qualcomm SM7150, IPQ9574, MSM8917 and IPQ5332 SoCs
  - GPU clock controller drivers for SM6115, SM6125, SM6375 and SA8775P SoCs
 
 Updates:
  - Shrink size of clk_fractional_divider a little
  - Convert various clk drivers to devm_of_clk_add_hw_provider()
  - Convert platform clk drivers to remove_new()
  - Converted most Mediatek clock drivers to struct platform_driver
  - MediaTek clock drivers can be built as modules
  - Reimplement Loongson-1 clk driver with DT support
  - Migrate socfpga clk driver to of_clk_add_hw_provider()
  - Support for i3c clks on Aspeed ast2600 SoCs
  - Add clock generic devm_clk_hw_register_gate_parent_data
  - Add audiomix block control for i.MX8MP
  - Add support for determine_rate to i.MX composite-8m
  - Let the LCDIF Pixel clock of i.MX8MM and i.MX8MN set parent rate
  - Provide clock name in error message for clk-gpr-mux on get parent failure
  - Drop duplicate imx_clk_mux_flags macro
  - Register the i.MX8MP Media Disp2 Pix clock as bus clock
  - Add Media LDB root clock to i.MX8MP
  - Make i.MX8MP nand_usdhc_bus clock as non-critical
  - Fix the rate table for i.MX fracn-gppll
  - Disable HW control for the fracn-gppll in order to be controlled by
    register write
  - Add support for interger PLL in fracn-gppll
  - Add mcore_booted module parameter to i.MX93 provider
  - Add NIC, A55 and ARM PLL clocks to i.MX93
  - Fix i.MX8ULP XBAR_DIVBUS and AD_SLOW clock parents
  - Use "divider closest" clock type for PLL4_PFD dividers on i.MX8ULP to
    get more accurate clock rates
  - Mark the MU0_Bi and TPM5 clocks on i.MX8ULP as critical
  - Update some of the i.MX critical clocks flags to allow glitchless
    on-the-fly rate change.
  - Add I2C5 clock on Renesas R-Car V3H
  - Exynos850: Add CMU_G3D clock controller for the Mali GPU
  - Extract Exynos5433 (ARM64) clock controller power management code to
    common driver parts
  - Exynos850: make PMU_ALIVE_PCLK clock critical
  - Add Audio, thermal, camera (CSI-2), Image Signal Processor/Channel
    Selector (ISPCS), and video capture (VIN) clocks on Renesas R-Car V4H
  - Add video capture (VIN) clocks on Renesas R-Car V3H
  - Add Cortex-A53 System CPU (Z2) clocks on Renesas R-Car V3M and V3H
  - Support for Stromer Plus PLL on Qualcomm IPQ5332
  - Add a missing reset to Qualcomm QCM2290
  - Migrate Qualcomm IPQ4019 to clk_parent_data
  - Make USB GDSCs enter retention state when disabled on Qualcomm SM6375,
    MSM8996 and MSM8998 SoCs
  - Set floor rounding clk_ops for Qualcomm QCM2290 SDCC2 clk
  - Add two EMAC GDSCs on Qualcomm SC8280XP
  - Use shared rcg clk ops in Qualcomm SM6115 GCC
  - Park Qualcomm SM8350 PCIe PIPE clks when disabled
  - Add GDSCs to Qualcomm SC7280 LPASS audio clock controller
  - Add missing XO clocks to Qualcomm MSM8226 and MSM8974
  - Convert some Qualcomm clk DT bindings to YAML
  - Reparenting fix for the clock supplying camera modules on Rockchip rk3399
  - Mark more critical (bus-)clocks on Rockchip rk3588
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAmRMbQURHHNib3lkQGtl
 cm5lbC5vcmcACgkQrQKIl8bklSUvyw//Vcqg0h8s+9npz0JsW+nffAXRguy1jum6
 tj10++zA+NBhKxmfhyOs/v9UK1nb2DXAhcTIjUDcTDkVy0b2pBUQoGEGMyy9TLve
 q4MfWx7CwKwASUG2Lr3f1n4qi/vT4PEDlvYzUO94p7c6Y6f6P4JHTCJlJR7cNb4o
 MyXgiXMxQGaxT0XucSR9J32VxqSbF9KQvb8q+tPV3CDMIWi96aO5ZyewY6KF8a/7
 chdXKYQXaYYG4/q4lNjZuvNQ2jidWqp0NlNw7M96U7SK5ESBryk4B4d1/J+QtzxX
 cuBTF1eoTKYlS3kPhhsuOhbsDi2SFE6D75ps5i9Y57ezSdS9qFcUsaNzUiN6t9ng
 uW+MRBTz20JDKBTLk6vD75O63fVDg3KG+kkLaF0Ax1Xa99sbrgBdNkPQ0Iu2AbSh
 assUmbz3s9MaPWj8LpOKLmactm4GbrQ2wtCEjguuynjaFoPUuyunReNkZ1yxfUUl
 MjRIYpvqVvYp29xHlBjN2cgttHjqVCBg8y7Io6RQonbIvnuN7Zo2cu+vbF7w7mdR
 2HtGBe/OFsnZmmsr0pIGQOU25otheIHPudEYLlXEKx03FaMzAXnnDe9f6xXWaWxk
 Wz0YBofejlkP9ycLjRas2BZo3T66TtAlbQH2UhrSpJZV02Jwfi+JwBaLi9dOwZ7O
 VL5HI5FSlG8=
 =bTtL
 -----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:
 "Nothing looks out of the ordinary in this batch of clk driver updates.

  There are a couple patches to the core clk framework, but they're all
  basically cleanups or debugging aids. The driver updates and new
  additions are dominated in the diffstat by Qualcomm and MediaTek
  drivers. Qualcomm gained a handful of new drivers for various SoCs,
  and MediaTek gained a bunch of drivers for MT8188. The MediaTek
  drivers are being modernized as well, so there are updates all over
  that vendor's clk drivers. There's also a couple other new clk drivers
  in here, for example the Starfive JH7110 SoC support is added.

  Outside of the two major SoC vendors though, we have the usual
  collection of non-critical fixes and cleanups to various clk drivers.
  It's good to see that we're getting more cleanups and modernization
  patches. Maybe one day we'll be able to properly split clk providers
  from clk consumers.

  Core:
   - Print an informational message before disabling unused clks

  New Drivers:
   - BCM63268 timer clock and reset controller
   - Frequency Hopping (FHCTL) on MediaTek MT6795, MT8173, MT8192 and
     MT8195 SoCs
   - Mediatek MT8188 SoC clk drivers
   - Clock driver for Sunplus SP7021 SoC
   - Clk driver support for Loongson-2 SoCs
   - Clock driver for Skyworks Si521xx I2C PCIe clock generators
   - Initial Starfive JH7110 clk/reset support
   - Global clock controller drivers for Qualcomm SM7150, IPQ9574,
     MSM8917 and IPQ5332 SoCs
   - GPU clock controller drivers for SM6115, SM6125, SM6375 and SA8775P
     SoCs

  Updates:
   - Shrink size of clk_fractional_divider a little
   - Convert various clk drivers to devm_of_clk_add_hw_provider()
   - Convert platform clk drivers to remove_new()
   - Converted most Mediatek clock drivers to struct platform_driver
   - MediaTek clock drivers can be built as modules
   - Reimplement Loongson-1 clk driver with DT support
   - Migrate socfpga clk driver to of_clk_add_hw_provider()
   - Support for i3c clks on Aspeed ast2600 SoCs
   - Add clock generic devm_clk_hw_register_gate_parent_data
   - Add audiomix block control for i.MX8MP
   - Add support for determine_rate to i.MX composite-8m
   - Let the LCDIF Pixel clock of i.MX8MM and i.MX8MN set parent rate
   - Provide clock name in error message for clk-gpr-mux on get parent
     failure
   - Drop duplicate imx_clk_mux_flags macro
   - Register the i.MX8MP Media Disp2 Pix clock as bus clock
   - Add Media LDB root clock to i.MX8MP
   - Make i.MX8MP nand_usdhc_bus clock as non-critical
   - Fix the rate table for i.MX fracn-gppll
   - Disable HW control for the fracn-gppll in order to be controlled by
     register write
   - Add support for interger PLL in fracn-gppll
   - Add mcore_booted module parameter to i.MX93 provider
   - Add NIC, A55 and ARM PLL clocks to i.MX93
   - Fix i.MX8ULP XBAR_DIVBUS and AD_SLOW clock parents
   - Use "divider closest" clock type for PLL4_PFD dividers on i.MX8ULP
     to get more accurate clock rates
   - Mark the MU0_Bi and TPM5 clocks on i.MX8ULP as critical
   - Update some of the i.MX critical clocks flags to allow glitchless
     on-the-fly rate change.
   - Add I2C5 clock on Renesas R-Car V3H
   - Exynos850: Add CMU_G3D clock controller for the Mali GPU
   - Extract Exynos5433 (ARM64) clock controller power management code
     to common driver parts
   - Exynos850: make PMU_ALIVE_PCLK clock critical
   - Add Audio, thermal, camera (CSI-2), Image Signal Processor/Channel
     Selector (ISPCS), and video capture (VIN) clocks on Renesas R-Car
     V4H
   - Add video capture (VIN) clocks on Renesas R-Car V3H
   - Add Cortex-A53 System CPU (Z2) clocks on Renesas R-Car V3M and V3H
   - Support for Stromer Plus PLL on Qualcomm IPQ5332
   - Add a missing reset to Qualcomm QCM2290
   - Migrate Qualcomm IPQ4019 to clk_parent_data
   - Make USB GDSCs enter retention state when disabled on Qualcomm
     SM6375, MSM8996 and MSM8998 SoCs
   - Set floor rounding clk_ops for Qualcomm QCM2290 SDCC2 clk
   - Add two EMAC GDSCs on Qualcomm SC8280XP
   - Use shared rcg clk ops in Qualcomm SM6115 GCC
   - Park Qualcomm SM8350 PCIe PIPE clks when disabled
   - Add GDSCs to Qualcomm SC7280 LPASS audio clock controller
   - Add missing XO clocks to Qualcomm MSM8226 and MSM8974
   - Convert some Qualcomm clk DT bindings to YAML
   - Reparenting fix for the clock supplying camera modules on Rockchip
     rk3399
   - Mark more critical (bus-)clocks on Rockchip rk3588"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (290 commits)
  clk: qcom: gcc-sc8280xp: Add EMAC GDSCs
  clk: starfive: Delete the redundant dev_set_drvdata() in JH7110 clock drivers
  clk: rockchip: rk3588: make gate linked clocks critical
  clk: qcom: dispcc-qcm2290: Remove inexistent DSI1PHY clk
  clk: qcom: add the GPUCC driver for sa8775p
  dt-bindings: clock: qcom: describe the GPUCC clock for SA8775P
  clk: qcom: gcc-sm8350: fix PCIe PIPE clocks handling
  clk: qcom: lpassaudiocc-sc7280: Add required gdsc power domain clks in lpass_cc_sc7280_desc
  clk: qcom: lpasscc-sc7280: Skip qdsp6ss clock registration
  dt-bindings: clock: qcom,sc7280-lpasscc: Add qcom,adsp-pil-mode property
  clk: starfive: Avoid casting iomem pointers
  clk: microchip: fix potential UAF in auxdev release callback
  clk: qcom: rpm: Use managed `of_clk_add_hw_provider()`
  clk: mediatek: fhctl: Mark local variables static
  clk: sifive: make SiFive clk drivers depend on ARCH_ symbols
  clk: uniphier: Use managed `of_clk_add_hw_provider()`
  clk: si5351: Use managed `of_clk_add_hw_provider()`
  clk: si570: Use managed `of_clk_add_hw_provider()`
  clk: si514: Use managed `of_clk_add_hw_provider()`
  clk: lmk04832: Use managed `of_clk_add_hw_provider()`
  ...
This commit is contained in:
Linus Torvalds 2023-04-29 17:29:39 -07:00
commit e81507acdc
383 changed files with 32602 additions and 7896 deletions

View File

@ -1,49 +0,0 @@
Krait Processor Sub-system (KPSS) Application Clock Controller (ACC)
The KPSS ACC provides clock, power domain, and reset control to a Krait CPU.
There is one ACC register region per CPU within the KPSS remapped region as
well as an alias register region that remaps accesses to the ACC associated
with the CPU accessing the region.
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: should be one of:
"qcom,kpss-acc-v1"
"qcom,kpss-acc-v2"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: the first element specifies the base address and size of
the register region. An optional second element specifies
the base address and size of the alias register region.
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the pll parents.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "pll8_vote", "pxo".
- clock-output-names:
Usage: optional
Value type: <string>
Definition: Name of the output clock. Typically acpuX_aux where X is a
CPU number starting at 0.
Example:
clock-controller@2088000 {
compatible = "qcom,kpss-acc-v2";
reg = <0x02088000 0x1000>,
<0x02008000 0x1000>;
clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
clock-names = "pll8_vote", "pxo";
clock-output-names = "acpu0_aux";
};

View File

@ -1,44 +0,0 @@
Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: should be one of the following. The generic compatible
"qcom,kpss-gcc" should also be included.
"qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc"
"qcom,kpss-gcc-apq8064", "qcom,kpss-gcc"
"qcom,kpss-gcc-msm8974", "qcom,kpss-gcc"
"qcom,kpss-gcc-msm8960", "qcom,kpss-gcc"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: base address and size of the register region
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the pll parents.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "pll8_vote", "pxo".
- clock-output-names:
Usage: required
Value type: <string>
Definition: Name of the output clock. Typically acpu_l2_aux indicating
an L2 cache auxiliary clock.
Example:
l2cc: clock-controller@2011000 {
compatible = "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc";
reg = <0x2011000 0x1000>;
clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
clock-names = "pll8_vote", "pxo";
clock-output-names = "acpu_l2_aux";
};

View File

@ -0,0 +1,40 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/brcm,bcm63268-timer-clocks.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM63268 Timer Clock and Reset Device Tree Bindings
maintainers:
- Álvaro Fernández Rojas <noltari@gmail.com>
properties:
compatible:
const: brcm,bcm63268-timer-clocks
reg:
maxItems: 1
"#clock-cells":
const: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- "#clock-cells"
- "#reset-cells"
additionalProperties: false
examples:
- |
timer_clk: clock-controller@100000ac {
compatible = "brcm,bcm63268-timer-clocks";
reg = <0x100000ac 0x4>;
#clock-cells = <1>;
#reset-cells = <1>;
};

View File

@ -0,0 +1,79 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/imx8mp-audiomix.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP i.MX8MP AudioMIX Block Control Binding
maintainers:
- Marek Vasut <marex@denx.de>
description: |
NXP i.MX8M Plus AudioMIX is dedicated clock muxing and gating IP
used to control Audio related clock on the SoC.
properties:
compatible:
const: fsl,imx8mp-audio-blk-ctrl
reg:
maxItems: 1
power-domains:
maxItems: 1
clocks:
minItems: 7
maxItems: 7
clock-names:
items:
- const: ahb
- const: sai1
- const: sai2
- const: sai3
- const: sai5
- const: sai6
- const: sai7
'#clock-cells':
const: 1
description:
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mp-clock.h
for the full list of i.MX8MP IMX8MP_CLK_AUDIOMIX_ clock IDs.
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- '#clock-cells'
additionalProperties: false
examples:
# Clock Control Module node:
- |
#include <dt-bindings/clock/imx8mp-clock.h>
clock-controller@30e20000 {
compatible = "fsl,imx8mp-audio-blk-ctrl";
reg = <0x30e20000 0x10000>;
#clock-cells = <1>;
clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>,
<&clk IMX8MP_CLK_SAI1>,
<&clk IMX8MP_CLK_SAI2>,
<&clk IMX8MP_CLK_SAI3>,
<&clk IMX8MP_CLK_SAI5>,
<&clk IMX8MP_CLK_SAI6>,
<&clk IMX8MP_CLK_SAI7>;
clock-names = "ahb",
"sai1", "sai2", "sai3",
"sai5", "sai6", "sai7";
power-domains = <&pgc_audio>;
};
...

View File

@ -0,0 +1,45 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/loongson,ls1x-clk.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Loongson-1 Clock Controller
maintainers:
- Keguang Zhang <keguang.zhang@gmail.com>
properties:
compatible:
enum:
- loongson,ls1b-clk
- loongson,ls1c-clk
reg:
maxItems: 1
clocks:
maxItems: 1
"#clock-cells":
const: 1
required:
- compatible
- reg
- clocks
- "#clock-cells"
additionalProperties: false
examples:
- |
clkc: clock-controller@1fe78030 {
compatible = "loongson,ls1b-clk";
reg = <0x1fe78030 0x8>;
clocks = <&xtal>;
#clock-cells = <1>;
};
...

View File

@ -16,7 +16,12 @@ description: |
properties:
compatible:
const: mediatek,mt8186-fhctl
enum:
- mediatek,mt6795-fhctl
- mediatek,mt8173-fhctl
- mediatek,mt8186-fhctl
- mediatek,mt8192-fhctl
- mediatek,mt8195-fhctl
reg:
maxItems: 1

View File

@ -0,0 +1,71 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/mediatek,mt8188-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek Functional Clock Controller for MT8188
maintainers:
- Garmin Chang <garmin.chang@mediatek.com>
description: |
The clock architecture in MediaTek like below
PLLs -->
dividers -->
muxes
-->
clock gate
The devices provide clock gate control in different IP blocks.
properties:
compatible:
enum:
- mediatek,mt8188-adsp-audio26m
- mediatek,mt8188-camsys
- mediatek,mt8188-camsys-rawa
- mediatek,mt8188-camsys-rawb
- mediatek,mt8188-camsys-yuva
- mediatek,mt8188-camsys-yuvb
- mediatek,mt8188-ccusys
- mediatek,mt8188-imgsys
- mediatek,mt8188-imgsys-wpe1
- mediatek,mt8188-imgsys-wpe2
- mediatek,mt8188-imgsys-wpe3
- mediatek,mt8188-imgsys1-dip-nr
- mediatek,mt8188-imgsys1-dip-top
- mediatek,mt8188-imp-iic-wrap-c
- mediatek,mt8188-imp-iic-wrap-en
- mediatek,mt8188-imp-iic-wrap-w
- mediatek,mt8188-ipesys
- mediatek,mt8188-mfgcfg
- mediatek,mt8188-vdecsys
- mediatek,mt8188-vdecsys-soc
- mediatek,mt8188-vencsys
- mediatek,mt8188-vppsys0
- mediatek,mt8188-vppsys1
- mediatek,mt8188-wpesys
- mediatek,mt8188-wpesys-vpp0
reg:
maxItems: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- '#clock-cells'
additionalProperties: false
examples:
- |
clock-controller@11283000 {
compatible = "mediatek,mt8188-imp-iic-wrap-c";
reg = <0x11283000 0x1000>;
#clock-cells = <1>;
};

View File

@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/mediatek,mt8188-sys-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek System Clock Controller for MT8188
maintainers:
- Garmin Chang <garmin.chang@mediatek.com>
description: |
The clock architecture in MediaTek like below
PLLs -->
dividers -->
muxes
-->
clock gate
The apmixedsys provides most of PLLs which generated from SoC 26m.
The topckgen provides dividers and muxes which provide the clock source to other IP blocks.
The infracfg_ao provides clock gate in peripheral and infrastructure IP blocks.
The mcusys provides mux control to select the clock source in AP MCU.
The device nodes also provide the system control capacity for configuration.
properties:
compatible:
items:
- enum:
- mediatek,mt8188-apmixedsys
- mediatek,mt8188-infracfg-ao
- mediatek,mt8188-pericfg-ao
- mediatek,mt8188-topckgen
- const: syscon
reg:
maxItems: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- '#clock-cells'
additionalProperties: false
examples:
- |
clock-controller@10000000 {
compatible = "mediatek,mt8188-topckgen", "syscon";
reg = <0x10000000 0x1000>;
#clock-cells = <1>;
};

View File

@ -16,6 +16,7 @@ description:
properties:
compatible:
enum:
- qcom,ipq5332-a53pll
- qcom,ipq6018-a53pll
- qcom,ipq8074-a53pll
- qcom,msm8916-a53pll

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,gcc-ipq4019.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller on IPQ4019
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
- Robert Marko <robert.markoo@sartura.hr>
description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on IPQ4019.
See also:: include/dt-bindings/clock/qcom,gcc-ipq4019.h
allOf:
- $ref: qcom,gcc.yaml#
properties:
compatible:
const: qcom,gcc-ipq4019
clocks:
items:
- description: board XO clock
- description: sleep clock
clock-names:
items:
- const: xo
- const: sleep_clk
required:
- compatible
unevaluatedProperties: false
examples:
- |
clock-controller@1800000 {
compatible = "qcom,gcc-ipq4019";
reg = <0x1800000 0x60000>;
#clock-cells = <1>;
#power-domain-cells = <1>;
#reset-cells = <1>;
clocks = <&xo>, <&sleep_clk>;
clock-names = "xo", "sleep_clk";
};
...

View File

@ -4,20 +4,25 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8909.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller on MSM8909
title: Qualcomm Global Clock & Reset Controller on MSM8909, MSM8917 and QM215
maintainers:
- Stephan Gerhold <stephan@gerhold.net>
description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on MSM8909.
domains on MSM8909, MSM8917 or QM215.
See also:: include/dt-bindings/clock/qcom,gcc-msm8909.h
See also::
include/dt-bindings/clock/qcom,gcc-msm8909.h
include/dt-bindings/clock/qcom,gcc-msm8917.h
properties:
compatible:
const: qcom,gcc-msm8909
enum:
- qcom,gcc-msm8909
- qcom,gcc-msm8917
- qcom,gcc-qm215
clocks:
items:

View File

@ -15,7 +15,6 @@ description: |
domains.
See also::
include/dt-bindings/clock/qcom,gcc-ipq4019.h
include/dt-bindings/clock/qcom,gcc-ipq6018.h
include/dt-bindings/reset/qcom,gcc-ipq6018.h
include/dt-bindings/clock/qcom,gcc-msm8953.h
@ -29,7 +28,6 @@ allOf:
properties:
compatible:
enum:
- qcom,gcc-ipq4019
- qcom,gcc-ipq6018
- qcom,gcc-mdm9607
- qcom,gcc-msm8953

View File

@ -15,6 +15,7 @@ description: |
See also::
include/dt-bindings/clock/qcom,gpucc-sdm845.h
include/dt-bindings/clock/qcom,gpucc-sa8775p.h
include/dt-bindings/clock/qcom,gpucc-sc7180.h
include/dt-bindings/clock/qcom,gpucc-sc7280.h
include/dt-bindings/clock/qcom,gpucc-sc8280xp.h
@ -27,6 +28,7 @@ properties:
compatible:
enum:
- qcom,sdm845-gpucc
- qcom,sa8775p-gpucc
- qcom,sc7180-gpucc
- qcom,sc7280-gpucc
- qcom,sc8180x-gpucc

View File

@ -0,0 +1,72 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,kpss-acc-v1.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Krait Processor Sub-system (KPSS) Application Clock Controller (ACC) v1
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
description:
The KPSS ACC provides clock, power domain, and reset control to a Krait CPU.
There is one ACC register region per CPU within the KPSS remapped region as
well as an alias register region that remaps accesses to the ACC associated
with the CPU accessing the region. ACC v1 is currently used as a
clock-controller for enabling the cpu and hanling the aux clocks.
properties:
compatible:
const: qcom,kpss-acc-v1
reg:
items:
- description: Base address and size of the register region
- description: Optional base address and size of the alias register region
minItems: 1
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: pll8_vote
- const: pxo
clock-output-names:
description: Name of the aux clock. Krait can have at most 4 cpu.
enum:
- acpu0_aux
- acpu1_aux
- acpu2_aux
- acpu3_aux
'#clock-cells':
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- clock-output-names
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
clock-controller@2088000 {
compatible = "qcom,kpss-acc-v1";
reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
clocks = <&gcc PLL8_VOTE>, <&pxo_board>;
clock-names = "pll8_vote", "pxo";
clock-output-names = "acpu0_aux";
#clock-cells = <0>;
};
...

View File

@ -0,0 +1,88 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,kpss-gcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
description:
Krait Processor Sub-system (KPSS) Global Clock Controller (GCC). Used
to control L2 mux (in the current implementation) and provide access
to the kpss-gcc registers.
properties:
compatible:
items:
- enum:
- qcom,kpss-gcc-ipq8064
- qcom,kpss-gcc-apq8064
- qcom,kpss-gcc-msm8974
- qcom,kpss-gcc-msm8960
- qcom,kpss-gcc-msm8660
- qcom,kpss-gcc-mdm9615
- const: qcom,kpss-gcc
- const: syscon
reg:
maxItems: 1
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: pll8_vote
- const: pxo
'#clock-cells':
const: 0
required:
- compatible
- reg
if:
properties:
compatible:
contains:
enum:
- qcom,kpss-gcc-ipq8064
- qcom,kpss-gcc-apq8064
- qcom,kpss-gcc-msm8974
- qcom,kpss-gcc-msm8960
then:
required:
- clocks
- clock-names
- '#clock-cells'
else:
properties:
clock: false
clock-names: false
'#clock-cells': false
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
clock-controller@2011000 {
compatible = "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc", "syscon";
reg = <0x2011000 0x1000>;
clocks = <&gcc PLL8_VOTE>, <&pxo_board>;
clock-names = "pll8_vote", "pxo";
#clock-cells = <0>;
};
- |
clock-controller@2011000 {
compatible = "qcom,kpss-gcc-mdm9615", "qcom,kpss-gcc", "syscon";
reg = <0x02011000 0x1000>;
};
...

View File

@ -31,6 +31,7 @@ properties:
- qcom,rpmcc-msm8660
- qcom,rpmcc-msm8909
- qcom,rpmcc-msm8916
- qcom,rpmcc-msm8917
- qcom,rpmcc-msm8936
- qcom,rpmcc-msm8953
- qcom,rpmcc-msm8974
@ -107,6 +108,7 @@ allOf:
- qcom,rpmcc-mdm9607
- qcom,rpmcc-msm8226
- qcom,rpmcc-msm8916
- qcom,rpmcc-msm8917
- qcom,rpmcc-msm8936
- qcom,rpmcc-msm8953
- qcom,rpmcc-msm8974

View File

@ -41,6 +41,12 @@ properties:
- const: qdsp6ss
- const: top_cc
qcom,adsp-pil-mode:
description:
Indicates if the LPASS would be brought out of reset using
remoteproc peripheral loader.
type: boolean
required:
- compatible
- reg
@ -60,6 +66,7 @@ examples:
reg-names = "qdsp6ss", "top_cc";
clocks = <&gcc GCC_CFG_NOC_LPASS_CLK>;
clock-names = "iface";
qcom,adsp-pil-mode;
#clock-cells = <1>;
};
...

View File

@ -0,0 +1,52 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,sm7150-gcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller on SM7150
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Danila Tikhonov <danila@jiaxyga.com>
- David Wronek <davidwronek@gmail.com>
description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on SM7150
See also:: include/dt-bindings/clock/qcom,sm7150-gcc.h
properties:
compatible:
const: qcom,sm7150-gcc
clocks:
items:
- description: Board XO source
- description: Board XO Active-Only source
- description: Sleep clock source
required:
- compatible
- clocks
allOf:
- $ref: qcom,gcc.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@100000 {
compatible = "qcom,sm7150-gcc";
reg = <0x00100000 0x001f0000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&rpmhcc RPMH_CXO_CLK_A>,
<&sleep_clk>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...

View File

@ -16,6 +16,11 @@ description: |
- 9FGV0241:
0 -- DIF0
1 -- DIF1
- 9FGV0441:
0 -- DIF0
1 -- DIF1
2 -- DIF2
3 -- DIF3
maintainers:
- Marek Vasut <marex@denx.de>
@ -24,6 +29,7 @@ properties:
compatible:
enum:
- renesas,9fgv0241
- renesas,9fgv0441
reg:
description: I2C device address

View File

@ -0,0 +1,59 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/skyworks,si521xx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Skyworks Si521xx I2C PCIe clock generators
description: |
The Skyworks Si521xx are I2C PCIe clock generators providing
from 4 to 9 output clocks.
maintainers:
- Marek Vasut <marex@denx.de>
properties:
compatible:
enum:
- skyworks,si52144
- skyworks,si52146
- skyworks,si52147
reg:
const: 0x6b
'#clock-cells':
const: 1
clocks:
items:
- description: XTal input clock
skyworks,out-amplitude-microvolt:
enum: [ 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000 ]
description: Output clock signal amplitude
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
clock-generator@6b {
compatible = "skyworks,si52144";
reg = <0x6b>;
#clock-cells = <1>;
clocks = <&ref25m>;
};
};
...

View File

@ -91,20 +91,21 @@ allOf:
- if:
properties:
compatible:
enum:
- qcom,sdx55-apcs-gcc
contains:
enum:
- qcom,sdx55-apcs-gcc
then:
properties:
clocks:
items:
- description: reference clock
- description: primary pll parent of the clock driver
- description: auxiliary parent
- description: reference clock
clock-names:
items:
- const: ref
- const: pll
- const: aux
- const: ref
- if:
properties:
compatible:

View File

@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/qcom,kpss-acc-v2.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Krait Processor Sub-system (KPSS) Application Clock Controller (ACC) v2
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
description:
The KPSS ACC provides clock, power manager, and reset control to a Krait CPU.
There is one ACC register region per CPU within the KPSS remapped region as
well as an alias register region that remaps accesses to the ACC associated
with the CPU accessing the region. ACC v2 is currently used as a
power-manager for enabling the cpu.
properties:
compatible:
const: qcom,kpss-acc-v2
reg:
items:
- description: Base address and size of the register region
- description: Optional base address and size of the alias register region
minItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
power-manager@f9088000 {
compatible = "qcom,kpss-acc-v2";
reg = <0xf9088000 0x1000>,
<0xf9008000 0x1000>;
};
...

View File

@ -2862,6 +2862,7 @@ F: Documentation/devicetree/bindings/reset/sunplus,reset.yaml
F: arch/arm/boot/dts/sunplus-sp7021*.dts*
F: arch/arm/configs/sp7021_*defconfig
F: arch/arm/mach-sunplus/
F: drivers/clk/clk-sp7021.c
F: drivers/irqchip/irq-sp7021-intc.c
F: drivers/reset/reset-sunplus.c
F: include/dt-bindings/clock/sunplus,sp7021-clkc.h
@ -12198,6 +12199,7 @@ M: Yinbo Zhu <zhuyinbo@loongson.cn>
L: linux-clk@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
F: drivers/clk/clk-loongson2.c
F: include/dt-bindings/clock/loongson,ls2k-clk.h
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
@ -14096,7 +14098,6 @@ L: linux-mips@vger.kernel.org
S: Maintained
F: arch/mips/include/asm/mach-loongson32/
F: arch/mips/loongson32/
F: drivers/*/*/*loongson1*
F: drivers/*/*loongson1*
MIPS/LOONGSON2EF ARCHITECTURE
@ -20046,19 +20047,20 @@ S: Maintained
F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
STARFIVE JH7100 CLOCK DRIVERS
M: Emil Renner Berthing <kernel@esmil.dk>
S: Maintained
F: Documentation/devicetree/bindings/clock/starfive,jh7100-*.yaml
F: drivers/clk/starfive/clk-starfive-jh7100*
F: include/dt-bindings/clock/starfive-jh7100*.h
STARFIVE JH7110 MMC/SD/SDIO DRIVER
M: William Qiu <william.qiu@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/mmc/starfive*
F: drivers/mmc/host/dw_mmc-starfive.c
STARFIVE JH71X0 CLOCK DRIVERS
M: Emil Renner Berthing <kernel@esmil.dk>
M: Hal Feng <hal.feng@starfivetech.com>
S: Maintained
F: Documentation/devicetree/bindings/clock/starfive,jh71*.yaml
F: drivers/clk/starfive/clk-starfive-jh71*
F: include/dt-bindings/clock/starfive?jh71*.h
STARFIVE JH71X0 PINCTRL DRIVERS
M: Emil Renner Berthing <kernel@esmil.dk>
M: Jianlong Huang <jianlong.huang@starfivetech.com>
@ -20069,12 +20071,13 @@ F: drivers/pinctrl/starfive/pinctrl-starfive-jh71*
F: include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h
F: include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
STARFIVE JH7100 RESET CONTROLLER DRIVER
STARFIVE JH71X0 RESET CONTROLLER DRIVERS
M: Emil Renner Berthing <kernel@esmil.dk>
M: Hal Feng <hal.feng@starfivetech.com>
S: Maintained
F: Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
F: drivers/reset/reset-starfive-jh7100.c
F: include/dt-bindings/reset/starfive-jh7100.h
F: drivers/reset/starfive/reset-starfive-jh71*
F: include/dt-bindings/reset/starfive?jh71*.h
STARFIVE JH71XX PMU CONTROLLER DRIVER
M: Walker Chen <walker.chen@starfivetech.com>

View File

@ -20,7 +20,6 @@ extern struct platform_device ls1x_gpio1_pdev;
extern struct platform_device ls1x_rtc_pdev;
extern struct platform_device ls1x_wdt_pdev;
void __init ls1x_clk_init(void);
void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
void __init ls1x_serial_set_uartclk(struct platform_device *pdev);

View File

@ -4,6 +4,7 @@
*/
#include <linux/clk.h>
#include <linux/of_clk.h>
#include <linux/interrupt.h>
#include <linux/sizes.h>
#include <asm/time.h>
@ -211,7 +212,7 @@ void __init plat_time_init(void)
struct clk *clk = NULL;
/* initialize LS1X clocks */
ls1x_clk_init();
of_clk_init(NULL);
#ifdef CONFIG_CEVT_CSRC_LS1X
/* setup LS1X PWM timer */

View File

@ -325,6 +325,15 @@ config COMMON_CLK_LOCHNAGAR
This driver supports the clocking features of the Cirrus Logic
Lochnagar audio development board.
config COMMON_CLK_LOONGSON2
bool "Clock driver for Loongson-2 SoC"
depends on LOONGARCH || COMPILE_TEST
help
This driver provides support for clock controller on Loongson-2 SoC.
The clock controller can generates and supplies clock to various
peripherals within the SoC.
Say Y here to support Loongson-2 SoC clock driver.
config COMMON_CLK_NXP
def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
select REGMAP_MMIO if ARCH_LPC32XX
@ -367,6 +376,15 @@ config COMMON_CLK_RS9_PCIE
This driver supports the Renesas 9-series PCIe clock generator
models 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ.
config COMMON_CLK_SI521XX
tristate "Clock driver for SkyWorks Si521xx PCIe clock generators"
depends on I2C
depends on OF
select REGMAP_I2C
help
This driver supports the SkyWorks Si521xx PCIe clock generator
models Si52144/Si52146/Si52147.
config COMMON_CLK_VC5
tristate "Clock driver for IDT VersaClock 5,6 devices"
depends on I2C
@ -436,6 +454,16 @@ config COMMON_CLK_K210
help
Support for the Canaan Kendryte K210 RISC-V SoC clocks.
config COMMON_CLK_SP7021
tristate "Clock driver for Sunplus SP7021 SoC"
depends on SOC_SP7021 || COMPILE_TEST
default SOC_SP7021
help
This driver supports the Sunplus SP7021 SoC clocks.
It implements SP7021 PLLs/gate.
Not all features of the PLL are currently supported
by the driver.
source "drivers/clk/actions/Kconfig"
source "drivers/clk/analogbits/Kconfig"
source "drivers/clk/baikal-t1/Kconfig"

View File

@ -43,6 +43,8 @@ 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_MACH_LOONGSON32) += clk-loongson1.o
obj-$(CONFIG_COMMON_CLK_LOONGSON2) += clk-loongson2.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o
obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o
@ -65,6 +67,7 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
obj-$(CONFIG_COMMON_CLK_SI544) += clk-si544.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_COMMON_CLK_SP7021) += clk-sp7021.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
@ -72,6 +75,7 @@ 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_RS9_PCIE) += clk-renesas-pcie.o
obj-$(CONFIG_COMMON_CLK_SI521XX) += clk-si521xx.o
obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o
obj-$(CONFIG_COMMON_CLK_VC7) += clk-versaclock7.o
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
@ -93,7 +97,6 @@ obj-y += imx/
obj-y += ingenic/
obj-$(CONFIG_ARCH_K3) += keystone/
obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
obj-$(CONFIG_MACH_LOONGSON32) += loongson1/
obj-y += mediatek/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-y += microchip/
@ -117,7 +120,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-y += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_STM32) += stm32/
obj-$(CONFIG_SOC_STARFIVE) += starfive/
obj-y += starfive/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-y += sunxi-ng/
obj-$(CONFIG_ARCH_TEGRA) += tegra/

View File

@ -668,7 +668,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
ret = sam9x60_frac_pll_compute_mul_frac(&frac->core, FCORE_MIN,
parent_rate, true);
if (ret <= 0) {
if (ret < 0) {
hw = ERR_PTR(ret);
goto free;
}

View File

@ -198,10 +198,9 @@ static int i2s_pll_clk_probe(struct platform_device *pdev)
return of_clk_add_provider(node, of_clk_src_simple_get, clk);
}
static int i2s_pll_clk_remove(struct platform_device *pdev)
static void i2s_pll_clk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
}
static const struct of_device_id i2s_pll_clk_id[] = {
@ -216,7 +215,7 @@ static struct platform_driver i2s_pll_clk_driver = {
.of_match_table = i2s_pll_clk_id,
},
.probe = i2s_pll_clk_probe,
.remove = i2s_pll_clk_remove,
.remove_new = i2s_pll_clk_remove,
};
module_platform_driver(i2s_pll_clk_driver);

View File

@ -253,14 +253,8 @@ static int axs10x_pll_clk_probe(struct platform_device *pdev)
return ret;
}
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get,
&pll_clk->hw);
}
static int axs10x_pll_clk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&pll_clk->hw);
}
static void __init of_axs10x_pll_clk_setup(struct device_node *node)
@ -332,7 +326,6 @@ static struct platform_driver axs10x_pll_clk_driver = {
.of_match_table = axs10x_pll_clk_id,
},
.probe = axs10x_pll_clk_probe,
.remove = axs10x_pll_clk_remove,
};
builtin_platform_driver(axs10x_pll_clk_driver);

View File

@ -37,6 +37,15 @@ config CLK_BCM_63XX_GATE
Enable common clock framework support for Broadcom BCM63xx DSL SoCs
based on the MIPS architecture
config CLK_BCM63268_TIMER
bool "Broadcom BCM63268 timer clock and reset support"
depends on BMIPS_GENERIC || COMPILE_TEST
default BMIPS_GENERIC
select RESET_CONTROLLER
help
Enable timer clock and reset support for Broadcom BCM63268 DSL SoCs
based on the MIPS architecture.
config CLK_BCM_KONA
bool "Broadcom Kona CCU clock support"
depends on ARCH_BCM_MOBILE || COMPILE_TEST

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o
obj-$(CONFIG_CLK_BCM_63XX_GATE) += clk-bcm63xx-gate.o
obj-$(CONFIG_CLK_BCM63268_TIMER) += clk-bcm63268-timer.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o

View File

@ -92,15 +92,13 @@ unregister_clk0:
return ret;
};
static int clk_dvp_remove(struct platform_device *pdev)
static void clk_dvp_remove(struct platform_device *pdev)
{
struct clk_dvp *dvp = platform_get_drvdata(pdev);
struct clk_hw_onecell_data *data = dvp->data;
clk_hw_unregister_gate(data->hws[1]);
clk_hw_unregister_gate(data->hws[0]);
return 0;
}
static const struct of_device_id clk_dvp_dt_ids[] = {
@ -111,7 +109,7 @@ MODULE_DEVICE_TABLE(of, clk_dvp_dt_ids);
static struct platform_driver clk_dvp_driver = {
.probe = clk_dvp_probe,
.remove = clk_dvp_remove,
.remove_new = clk_dvp_remove,
.driver = {
.name = "brcm2711-dvp",
.of_match_table = clk_dvp_dt_ids,

View File

@ -0,0 +1,216 @@
// SPDX-License-Identifier: GPL-2.0
/*
* BCM63268 Timer Clock and Reset Controller Driver
*
* Copyright (C) 2023 Álvaro Fernández Rojas <noltari@gmail.com>
*/
#include <linux/clk-provider.h>
#include <linux/container_of.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include <dt-bindings/clock/bcm63268-clock.h>
#define BCM63268_TIMER_RESET_SLEEP_MIN_US 10000
#define BCM63268_TIMER_RESET_SLEEP_MAX_US 20000
struct bcm63268_tclkrst_hw {
void __iomem *regs;
spinlock_t lock;
struct reset_controller_dev rcdev;
struct clk_hw_onecell_data data;
};
struct bcm63268_tclk_table_entry {
const char * const name;
u8 bit;
};
static const struct bcm63268_tclk_table_entry bcm63268_timer_clocks[] = {
{
.name = "ephy1",
.bit = BCM63268_TCLK_EPHY1,
}, {
.name = "ephy2",
.bit = BCM63268_TCLK_EPHY2,
}, {
.name = "ephy3",
.bit = BCM63268_TCLK_EPHY3,
}, {
.name = "gphy1",
.bit = BCM63268_TCLK_GPHY1,
}, {
.name = "dsl",
.bit = BCM63268_TCLK_DSL,
}, {
.name = "wakeon_ephy",
.bit = BCM63268_TCLK_WAKEON_EPHY,
}, {
.name = "wakeon_dsl",
.bit = BCM63268_TCLK_WAKEON_DSL,
}, {
.name = "fap1_pll",
.bit = BCM63268_TCLK_FAP1,
}, {
.name = "fap2_pll",
.bit = BCM63268_TCLK_FAP2,
}, {
.name = "uto_50",
.bit = BCM63268_TCLK_UTO_50,
}, {
.name = "uto_extin",
.bit = BCM63268_TCLK_UTO_EXTIN,
}, {
.name = "usb_ref",
.bit = BCM63268_TCLK_USB_REF,
}, {
/* sentinel */
}
};
static inline struct bcm63268_tclkrst_hw *
to_bcm63268_timer_reset(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct bcm63268_tclkrst_hw, rcdev);
}
static int bcm63268_timer_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev);
unsigned long flags;
uint32_t val;
spin_lock_irqsave(&reset->lock, flags);
val = __raw_readl(reset->regs);
if (assert)
val &= ~BIT(id);
else
val |= BIT(id);
__raw_writel(val, reset->regs);
spin_unlock_irqrestore(&reset->lock, flags);
return 0;
}
static int bcm63268_timer_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return bcm63268_timer_reset_update(rcdev, id, true);
}
static int bcm63268_timer_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return bcm63268_timer_reset_update(rcdev, id, false);
}
static int bcm63268_timer_reset_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
bcm63268_timer_reset_update(rcdev, id, true);
usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US,
BCM63268_TIMER_RESET_SLEEP_MAX_US);
bcm63268_timer_reset_update(rcdev, id, false);
/*
* Ensure component is taken out reset state by sleeping also after
* deasserting the reset. Otherwise, the component may not be ready
* for operation.
*/
usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US,
BCM63268_TIMER_RESET_SLEEP_MAX_US);
return 0;
}
static int bcm63268_timer_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev);
return !(__raw_readl(reset->regs) & BIT(id));
}
static const struct reset_control_ops bcm63268_timer_reset_ops = {
.assert = bcm63268_timer_reset_assert,
.deassert = bcm63268_timer_reset_deassert,
.reset = bcm63268_timer_reset_reset,
.status = bcm63268_timer_reset_status,
};
static int bcm63268_tclk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct bcm63268_tclk_table_entry *entry;
struct bcm63268_tclkrst_hw *hw;
struct clk_hw *clk;
u8 maxbit = 0;
int i, ret;
for (entry = bcm63268_timer_clocks; entry->name; entry++)
maxbit = max(maxbit, entry->bit);
maxbit++;
hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
GFP_KERNEL);
if (!hw)
return -ENOMEM;
platform_set_drvdata(pdev, hw);
spin_lock_init(&hw->lock);
hw->data.num = maxbit;
for (i = 0; i < maxbit; i++)
hw->data.hws[i] = ERR_PTR(-ENODEV);
hw->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->regs))
return PTR_ERR(hw->regs);
for (entry = bcm63268_timer_clocks; entry->name; entry++) {
clk = devm_clk_hw_register_gate(dev, entry->name, NULL, 0,
hw->regs, entry->bit,
CLK_GATE_BIG_ENDIAN,
&hw->lock);
if (IS_ERR(clk))
return PTR_ERR(clk);
hw->data.hws[entry->bit] = clk;
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
&hw->data);
if (ret)
return ret;
hw->rcdev.of_node = dev->of_node;
hw->rcdev.ops = &bcm63268_timer_reset_ops;
ret = devm_reset_controller_register(dev, &hw->rcdev);
if (ret)
dev_err(dev, "Failed to register reset controller\n");
return 0;
}
static const struct of_device_id bcm63268_tclk_dt_ids[] = {
{ .compatible = "brcm,bcm63268-timer-clocks" },
{ /* sentinel */ }
};
static struct platform_driver bcm63268_tclk = {
.probe = bcm63268_tclk_probe,
.driver = {
.name = "bcm63268-timer-clock",
.of_match_table = bcm63268_tclk_dt_ids,
},
};
builtin_platform_driver(bcm63268_tclk);

View File

@ -541,7 +541,7 @@ out_err:
return ret;
}
static int clk_bcm63xx_remove(struct platform_device *pdev)
static void clk_bcm63xx_remove(struct platform_device *pdev)
{
struct clk_bcm63xx_hw *hw = platform_get_drvdata(pdev);
int i;
@ -552,8 +552,6 @@ static int clk_bcm63xx_remove(struct platform_device *pdev)
if (!IS_ERR(hw->data.hws[i]))
clk_hw_unregister_gate(hw->data.hws[i]);
}
return 0;
}
static const struct of_device_id clk_bcm63xx_dt_ids[] = {
@ -570,7 +568,7 @@ static const struct of_device_id clk_bcm63xx_dt_ids[] = {
static struct platform_driver clk_bcm63xx = {
.probe = clk_bcm63xx_probe,
.remove = clk_bcm63xx_remove,
.remove_new = clk_bcm63xx_remove,
.driver = {
.name = "bcm63xx-clock",
.of_match_table = clk_bcm63xx_dt_ids,

View File

@ -439,13 +439,11 @@ static int raspberrypi_clk_probe(struct platform_device *pdev)
return 0;
}
static int raspberrypi_clk_remove(struct platform_device *pdev)
static void raspberrypi_clk_remove(struct platform_device *pdev)
{
struct raspberrypi_clk *rpi = platform_get_drvdata(pdev);
platform_device_unregister(rpi->cpufreq);
return 0;
}
static const struct of_device_id raspberrypi_clk_match[] = {
@ -460,7 +458,7 @@ static struct platform_driver raspberrypi_clk_driver = {
.of_match_table = raspberrypi_clk_match,
},
.probe = raspberrypi_clk_probe,
.remove = raspberrypi_clk_remove,
.remove_new = raspberrypi_clk_remove,
};
module_platform_driver(raspberrypi_clk_driver);

View File

@ -15,7 +15,11 @@
#include "clk-aspeed.h"
#define ASPEED_G6_NUM_CLKS 71
/*
* This includes the gates (configured from aspeed_g6_gates), plus the
* explicitly-configured clocks (ASPEED_CLK_HPLL and up).
*/
#define ASPEED_G6_NUM_CLKS 72
#define ASPEED_G6_SILICON_REV 0x014
#define CHIP_REVISION_ID GENMASK(23, 16)
@ -32,6 +36,20 @@
#define ASPEED_G6_CLK_SELECTION1 0x300
#define ASPEED_G6_CLK_SELECTION2 0x304
#define ASPEED_G6_CLK_SELECTION4 0x310
#define ASPEED_G6_CLK_SELECTION5 0x314
#define I3C_CLK_SELECTION_SHIFT 31
#define I3C_CLK_SELECTION BIT(31)
#define I3C_CLK_SELECT_HCLK (0 << I3C_CLK_SELECTION_SHIFT)
#define I3C_CLK_SELECT_APLL_DIV (1 << I3C_CLK_SELECTION_SHIFT)
#define APLL_DIV_SELECTION_SHIFT 28
#define APLL_DIV_SELECTION GENMASK(30, 28)
#define APLL_DIV_2 (0b001 << APLL_DIV_SELECTION_SHIFT)
#define APLL_DIV_3 (0b010 << APLL_DIV_SELECTION_SHIFT)
#define APLL_DIV_4 (0b011 << APLL_DIV_SELECTION_SHIFT)
#define APLL_DIV_5 (0b100 << APLL_DIV_SELECTION_SHIFT)
#define APLL_DIV_6 (0b101 << APLL_DIV_SELECTION_SHIFT)
#define APLL_DIV_7 (0b110 << APLL_DIV_SELECTION_SHIFT)
#define APLL_DIV_8 (0b111 << APLL_DIV_SELECTION_SHIFT)
#define ASPEED_HPLL_PARAM 0x200
#define ASPEED_APLL_PARAM 0x210
@ -55,6 +73,27 @@ static void __iomem *scu_g6_base;
static u8 soc_rev;
/*
* The majority of the clocks in the system are gates paired with a reset
* controller that holds the IP in reset; this is represented by the @reset_idx
* member of entries here.
*
* This borrows from clk_hw_register_gate, but registers two 'gates', one
* to control the clock enable register and the other to control the reset
* IP. This allows us to enforce the ordering:
*
* 1. Place IP in reset
* 2. Enable clock
* 3. Delay
* 4. Release reset
*
* Consequently, if reset_idx is set, reset control is implicit: the clock
* consumer does not need its own reset handling, as enabling the clock will
* also deassert reset.
*
* There are some gates that do not have an associated reset; these are
* handled by using -1 as the index for the reset, and the consumer must
* explictly assert/deassert reset lines as required.
*
* Clocks marked with CLK_IS_CRITICAL:
*
* ref0 and ref1 are essential for the SoC to operate
@ -97,14 +136,13 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = {
[ASPEED_CLK_GATE_LHCCLK] = { 37, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */
/* Reserved 38 RSA: no longer used */
/* Reserved 39 */
[ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", NULL, 0 }, /* I3C0 */
[ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", NULL, 0 }, /* I3C1 */
[ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", NULL, 0 }, /* I3C2 */
[ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", NULL, 0 }, /* I3C3 */
[ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", NULL, 0 }, /* I3C4 */
[ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", NULL, 0 }, /* I3C5 */
[ASPEED_CLK_GATE_I3C6CLK] = { 46, 46, "i3c6clk-gate", NULL, 0 }, /* I3C6 */
[ASPEED_CLK_GATE_I3C7CLK] = { 47, 47, "i3c7clk-gate", NULL, 0 }, /* I3C7 */
[ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", "i3cclk", 0 }, /* I3C0 */
[ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", "i3cclk", 0 }, /* I3C1 */
[ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", "i3cclk", 0 }, /* I3C2 */
[ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", "i3cclk", 0 }, /* I3C3 */
[ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", "i3cclk", 0 }, /* I3C4 */
[ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", "i3cclk", 0 }, /* I3C5 */
/* Reserved: 46 & 47 */
[ASPEED_CLK_GATE_UART1CLK] = { 48, -1, "uart1clk-gate", "uart", 0 }, /* UART1 */
[ASPEED_CLK_GATE_UART2CLK] = { 49, -1, "uart2clk-gate", "uart", 0 }, /* UART2 */
[ASPEED_CLK_GATE_UART3CLK] = { 50, -1, "uart3clk-gate", "uart", 0 }, /* UART3 */
@ -652,6 +690,9 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
const struct aspeed_gate_data *gd = &aspeed_g6_gates[i];
u32 gate_flags;
if (!gd->name)
continue;
/*
* Special case: the USB port 1 clock (bit 14) is always
* working the opposite way from the other ones.
@ -772,6 +813,14 @@ static void __init aspeed_g6_cc(struct regmap *map)
/* USB 2.0 port1 phy 40MHz clock */
hw = clk_hw_register_fixed_rate(NULL, "usb-phy-40m", NULL, 0, 40000000);
aspeed_g6_clk_data->hws[ASPEED_CLK_USBPHY_40M] = hw;
/* i3c clock: source from apll, divide by 8 */
regmap_update_bits(map, ASPEED_G6_CLK_SELECTION5,
I3C_CLK_SELECTION | APLL_DIV_SELECTION,
I3C_CLK_SELECT_APLL_DIV | APLL_DIV_8);
hw = clk_hw_register_fixed_factor(NULL, "i3cclk", "apll", 0, 1, 8);
aspeed_g6_clk_data->hws[ASPEED_CLK_I3C] = hw;
};
static void __init aspeed_g6_cc_init(struct device_node *np)

View File

@ -553,15 +553,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
if (ret)
return ret;
return of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_simple_get,
&axi_clkgen->clk_hw);
}
static int axi_clkgen_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
&axi_clkgen->clk_hw);
}
static const struct of_device_id axi_clkgen_ids[] = {
@ -583,7 +576,6 @@ static struct platform_driver axi_clkgen_driver = {
.of_match_table = axi_clkgen_ids,
},
.probe = axi_clkgen_probe,
.remove = axi_clkgen_remove,
};
module_platform_driver(axi_clkgen_driver);

View File

@ -569,18 +569,11 @@ static int axmclk_probe(struct platform_device *pdev)
return ret;
}
return of_clk_add_hw_provider(dev->of_node, of_clk_axmclk_get, NULL);
}
static int axmclk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
return devm_of_clk_add_hw_provider(dev, of_clk_axmclk_get, NULL);
}
static struct platform_driver axmclk_driver = {
.probe = axmclk_probe,
.remove = axmclk_remove,
.driver = {
.name = "clk-axm5516",
.of_match_table = axmclk_match_table,

View File

@ -661,16 +661,10 @@ static int cdce706_probe(struct i2c_client *client)
ret = cdce706_register_clkouts(cdce);
if (ret < 0)
return ret;
return of_clk_add_hw_provider(client->dev.of_node, of_clk_cdce_get,
cdce);
return devm_of_clk_add_hw_provider(&client->dev, of_clk_cdce_get,
cdce);
}
static void cdce706_remove(struct i2c_client *client)
{
of_clk_del_provider(client->dev.of_node);
}
#ifdef CONFIG_OF
static const struct of_device_id cdce706_dt_match[] = {
{ .compatible = "ti,cdce706" },
@ -691,7 +685,6 @@ static struct i2c_driver cdce706_i2c_driver = {
.of_match_table = of_match_ptr(cdce706_dt_match),
},
.probe_new = cdce706_probe,
.remove = cdce706_remove,
.id_table = cdce706_id,
};
module_i2c_driver(cdce706_i2c_driver);

View File

@ -33,9 +33,12 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
else
return rc;
}
if (clkspec.np == node && !clk_supplier)
if (clkspec.np == node && !clk_supplier) {
of_node_put(clkspec.np);
return 0;
}
pclk = of_clk_get_from_provider(&clkspec);
of_node_put(clkspec.np);
if (IS_ERR(pclk)) {
if (PTR_ERR(pclk) != -EPROBE_DEFER)
pr_warn("clk: couldn't get parent clock %d for %pOF\n",
@ -48,10 +51,12 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
if (rc < 0)
goto err;
if (clkspec.np == node && !clk_supplier) {
of_node_put(clkspec.np);
rc = 0;
goto err;
}
clk = of_clk_get_from_provider(&clkspec);
of_node_put(clkspec.np);
if (IS_ERR(clk)) {
if (PTR_ERR(clk) != -EPROBE_DEFER)
pr_warn("clk: couldn't get assigned clock %d for %pOF\n",
@ -93,10 +98,13 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
else
return rc;
}
if (clkspec.np == node && !clk_supplier)
if (clkspec.np == node && !clk_supplier) {
of_node_put(clkspec.np);
return 0;
}
clk = of_clk_get_from_provider(&clkspec);
of_node_put(clkspec.np);
if (IS_ERR(clk)) {
if (PTR_ERR(clk) != -EPROBE_DEFER)
pr_warn("clk: couldn't get clock %d for %pOF\n",

View File

@ -297,14 +297,12 @@ void __init of_fixed_factor_clk_setup(struct device_node *node)
CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock",
of_fixed_factor_clk_setup);
static int of_fixed_factor_clk_remove(struct platform_device *pdev)
static void of_fixed_factor_clk_remove(struct platform_device *pdev)
{
struct clk_hw *clk = platform_get_drvdata(pdev);
of_clk_del_provider(pdev->dev.of_node);
clk_hw_unregister_fixed_factor(clk);
return 0;
}
static int of_fixed_factor_clk_probe(struct platform_device *pdev)
@ -336,7 +334,7 @@ static struct platform_driver of_fixed_factor_clk_driver = {
.of_match_table = of_fixed_factor_clk_ids,
},
.probe = of_fixed_factor_clk_probe,
.remove = of_fixed_factor_clk_remove,
.remove_new = of_fixed_factor_clk_remove,
};
builtin_platform_driver(of_fixed_factor_clk_driver);
#endif

View File

@ -71,14 +71,12 @@ static int of_fixed_mmio_clk_probe(struct platform_device *pdev)
return 0;
}
static int of_fixed_mmio_clk_remove(struct platform_device *pdev)
static void of_fixed_mmio_clk_remove(struct platform_device *pdev)
{
struct clk_hw *clk = platform_get_drvdata(pdev);
of_clk_del_provider(pdev->dev.of_node);
clk_hw_unregister_fixed_rate(clk);
return 0;
}
static const struct of_device_id of_fixed_mmio_clk_ids[] = {
@ -93,7 +91,7 @@ static struct platform_driver of_fixed_mmio_clk_driver = {
.of_match_table = of_fixed_mmio_clk_ids,
},
.probe = of_fixed_mmio_clk_probe,
.remove = of_fixed_mmio_clk_remove,
.remove_new = of_fixed_mmio_clk_remove,
};
module_platform_driver(of_fixed_mmio_clk_driver);

View File

@ -196,14 +196,12 @@ void __init of_fixed_clk_setup(struct device_node *node)
}
CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup);
static int of_fixed_clk_remove(struct platform_device *pdev)
static void of_fixed_clk_remove(struct platform_device *pdev)
{
struct clk_hw *hw = platform_get_drvdata(pdev);
of_clk_del_provider(pdev->dev.of_node);
clk_hw_unregister_fixed_rate(hw);
return 0;
}
static int of_fixed_clk_probe(struct platform_device *pdev)
@ -234,7 +232,7 @@ static struct platform_driver of_fixed_clk_driver = {
.of_match_table = of_fixed_clk_ids,
},
.probe = of_fixed_clk_probe,
.remove = of_fixed_clk_remove,
.remove_new = of_fixed_clk_remove,
};
builtin_platform_driver(of_fixed_clk_driver);
#endif

View File

@ -71,6 +71,7 @@ static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
unsigned long m, n;
u32 mmask, nmask;
u32 val;
if (fd->lock)
@ -85,8 +86,11 @@ static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
else
__release(fd->lock);
m = (val & fd->mmask) >> fd->mshift;
n = (val & fd->nmask) >> fd->nshift;
mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
m = (val & mmask) >> fd->mshift;
n = (val & nmask) >> fd->nshift;
if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
m++;
@ -166,6 +170,7 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
unsigned long m, n;
u32 mmask, nmask;
u32 val;
rational_best_approximation(rate, parent_rate,
@ -182,8 +187,11 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
else
__acquire(fd->lock);
mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
val = clk_fd_readl(fd);
val &= ~(fd->mmask | fd->nmask);
val &= ~(mmask | nmask);
val |= (m << fd->mshift) | (n << fd->nshift);
clk_fd_writel(fd, val);
@ -260,10 +268,8 @@ struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
fd->reg = reg;
fd->mshift = mshift;
fd->mwidth = mwidth;
fd->mmask = GENMASK(mwidth - 1, 0) << mshift;
fd->nshift = nshift;
fd->nwidth = nwidth;
fd->nmask = GENMASK(nwidth - 1, 0) << nshift;
fd->flags = clk_divider_flags;
fd->lock = lock;
fd->hw.init = &init;

View File

@ -346,14 +346,8 @@ static int hsdk_pll_clk_probe(struct platform_device *pdev)
return ret;
}
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get,
&pll_clk->hw);
}
static int hsdk_pll_clk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&pll_clk->hw);
}
static void __init of_hsdk_pll_clk_setup(struct device_node *node)
@ -432,6 +426,5 @@ static struct platform_driver hsdk_pll_clk_driver = {
.of_match_table = hsdk_pll_clk_id,
},
.probe = hsdk_pll_clk_probe,
.remove = hsdk_pll_clk_remove,
};
builtin_platform_driver(hsdk_pll_clk_driver);

View File

@ -1522,8 +1522,8 @@ static int lmk04832_probe(struct spi_device *spi)
}
lmk->clk_data->num = info->num_channels;
ret = of_clk_add_hw_provider(lmk->dev->of_node, of_clk_hw_onecell_get,
lmk->clk_data);
ret = devm_of_clk_add_hw_provider(lmk->dev, of_clk_hw_onecell_get,
lmk->clk_data);
if (ret) {
dev_err(lmk->dev, "failed to add provider (%d)\n", ret);
goto err_disable_vco;
@ -1547,7 +1547,6 @@ static void lmk04832_remove(struct spi_device *spi)
struct lmk04832 *lmk = spi_get_drvdata(spi);
clk_disable_unprepare(lmk->oscin);
of_clk_del_provider(spi->dev.of_node);
}
static const struct spi_device_id lmk04832_id[] = {

303
drivers/clk/clk-loongson1.c Normal file
View File

@ -0,0 +1,303 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Clock driver for Loongson-1 SoC
*
* Copyright (C) 2012-2023 Keguang Zhang <keguang.zhang@gmail.com>
*/
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/container_of.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/printk.h>
#include <dt-bindings/clock/loongson,ls1x-clk.h>
/* Loongson 1 Clock Register Definitions */
#define CLK_PLL_FREQ 0x0
#define CLK_PLL_DIV 0x4
static DEFINE_SPINLOCK(ls1x_clk_div_lock);
struct ls1x_clk_pll_data {
u32 fixed;
u8 shift;
u8 int_shift;
u8 int_width;
u8 frac_shift;
u8 frac_width;
};
struct ls1x_clk_div_data {
u8 shift;
u8 width;
unsigned long flags;
const struct clk_div_table *table;
u8 bypass_shift;
u8 bypass_inv;
spinlock_t *lock; /* protect access to DIV registers */
};
struct ls1x_clk {
void __iomem *reg;
unsigned int offset;
struct clk_hw hw;
const void *data;
};
#define to_ls1x_clk(_hw) container_of(_hw, struct ls1x_clk, hw)
static inline unsigned long ls1x_pll_rate_part(unsigned int val,
unsigned int shift,
unsigned int width)
{
return (val & GENMASK(shift + width, shift)) >> shift;
}
static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw);
const struct ls1x_clk_pll_data *d = ls1x_clk->data;
u32 val, rate;
val = readl(ls1x_clk->reg);
rate = d->fixed;
rate += ls1x_pll_rate_part(val, d->int_shift, d->int_width);
if (d->frac_width)
rate += ls1x_pll_rate_part(val, d->frac_shift, d->frac_width);
rate *= parent_rate;
rate >>= d->shift;
return rate;
}
static const struct clk_ops ls1x_pll_clk_ops = {
.recalc_rate = ls1x_pll_recalc_rate,
};
static unsigned long ls1x_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw);
const struct ls1x_clk_div_data *d = ls1x_clk->data;
unsigned int val;
val = readl(ls1x_clk->reg) >> d->shift;
val &= clk_div_mask(d->width);
return divider_recalc_rate(hw, parent_rate, val, d->table,
d->flags, d->width);
}
static long ls1x_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw);
const struct ls1x_clk_div_data *d = ls1x_clk->data;
return divider_round_rate(hw, rate, prate, d->table,
d->width, d->flags);
}
static int ls1x_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw);
const struct ls1x_clk_div_data *d = ls1x_clk->data;
int val, div_val;
unsigned long flags = 0;
div_val = divider_get_val(rate, parent_rate, d->table,
d->width, d->flags);
if (div_val < 0)
return div_val;
spin_lock_irqsave(d->lock, flags);
/* Bypass the clock */
val = readl(ls1x_clk->reg);
if (d->bypass_inv)
val &= ~BIT(d->bypass_shift);
else
val |= BIT(d->bypass_shift);
writel(val, ls1x_clk->reg);
val = readl(ls1x_clk->reg);
val &= ~(clk_div_mask(d->width) << d->shift);
val |= (u32)div_val << d->shift;
writel(val, ls1x_clk->reg);
/* Restore the clock */
val = readl(ls1x_clk->reg);
if (d->bypass_inv)
val |= BIT(d->bypass_shift);
else
val &= ~BIT(d->bypass_shift);
writel(val, ls1x_clk->reg);
spin_unlock_irqrestore(d->lock, flags);
return 0;
}
static const struct clk_ops ls1x_clk_divider_ops = {
.recalc_rate = ls1x_divider_recalc_rate,
.round_rate = ls1x_divider_round_rate,
.set_rate = ls1x_divider_set_rate,
};
#define LS1X_CLK_PLL(_name, _offset, _fixed, _shift, \
f_shift, f_width, i_shift, i_width) \
struct ls1x_clk _name = { \
.offset = (_offset), \
.data = &(const struct ls1x_clk_pll_data) { \
.fixed = (_fixed), \
.shift = (_shift), \
.int_shift = (i_shift), \
.int_width = (i_width), \
.frac_shift = (f_shift), \
.frac_width = (f_width), \
}, \
.hw.init = &(const struct clk_init_data) { \
.name = #_name, \
.ops = &ls1x_pll_clk_ops, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "xtal", \
.name = "xtal", \
.index = -1, \
}, \
.num_parents = 1, \
}, \
}
#define LS1X_CLK_DIV(_name, _pname, _offset, _shift, _width, \
_table, _bypass_shift, _bypass_inv, _flags) \
struct ls1x_clk _name = { \
.offset = (_offset), \
.data = &(const struct ls1x_clk_div_data){ \
.shift = (_shift), \
.width = (_width), \
.table = (_table), \
.flags = (_flags), \
.bypass_shift = (_bypass_shift), \
.bypass_inv = (_bypass_inv), \
.lock = &ls1x_clk_div_lock, \
}, \
.hw.init = &(const struct clk_init_data) { \
.name = #_name, \
.ops = &ls1x_clk_divider_ops, \
.parent_hws = (const struct clk_hw *[]) { _pname }, \
.num_parents = 1, \
.flags = CLK_GET_RATE_NOCACHE, \
}, \
}
static LS1X_CLK_PLL(ls1b_clk_pll, CLK_PLL_FREQ, 12, 1, 0, 5, 0, 0);
static LS1X_CLK_DIV(ls1b_clk_cpu, &ls1b_clk_pll.hw, CLK_PLL_DIV,
20, 4, NULL, 8, 0,
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST);
static LS1X_CLK_DIV(ls1b_clk_dc, &ls1b_clk_pll.hw, CLK_PLL_DIV,
26, 4, NULL, 12, 0, CLK_DIVIDER_ONE_BASED);
static LS1X_CLK_DIV(ls1b_clk_ahb, &ls1b_clk_pll.hw, CLK_PLL_DIV,
14, 4, NULL, 10, 0, CLK_DIVIDER_ONE_BASED);
static CLK_FIXED_FACTOR(ls1b_clk_apb, "ls1b_clk_apb", "ls1b_clk_ahb", 2, 1,
CLK_SET_RATE_PARENT);
static struct clk_hw_onecell_data ls1b_clk_hw_data = {
.hws = {
[LS1X_CLKID_PLL] = &ls1b_clk_pll.hw,
[LS1X_CLKID_CPU] = &ls1b_clk_cpu.hw,
[LS1X_CLKID_DC] = &ls1b_clk_dc.hw,
[LS1X_CLKID_AHB] = &ls1b_clk_ahb.hw,
[LS1X_CLKID_APB] = &ls1b_clk_apb.hw,
},
.num = CLK_NR_CLKS,
};
static const struct clk_div_table ls1c_ahb_div_table[] = {
[0] = { .val = 0, .div = 2 },
[1] = { .val = 1, .div = 4 },
[2] = { .val = 2, .div = 3 },
[3] = { .val = 3, .div = 3 },
[4] = { /* sentinel */ }
};
static LS1X_CLK_PLL(ls1c_clk_pll, CLK_PLL_FREQ, 0, 2, 8, 8, 16, 8);
static LS1X_CLK_DIV(ls1c_clk_cpu, &ls1c_clk_pll.hw, CLK_PLL_DIV,
8, 7, NULL, 0, 1,
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST);
static LS1X_CLK_DIV(ls1c_clk_dc, &ls1c_clk_pll.hw, CLK_PLL_DIV,
24, 7, NULL, 4, 1, CLK_DIVIDER_ONE_BASED);
static LS1X_CLK_DIV(ls1c_clk_ahb, &ls1c_clk_cpu.hw, CLK_PLL_FREQ,
0, 2, ls1c_ahb_div_table, 0, 0, CLK_DIVIDER_ALLOW_ZERO);
static CLK_FIXED_FACTOR(ls1c_clk_apb, "ls1c_clk_apb", "ls1c_clk_ahb", 1, 1,
CLK_SET_RATE_PARENT);
static struct clk_hw_onecell_data ls1c_clk_hw_data = {
.hws = {
[LS1X_CLKID_PLL] = &ls1c_clk_pll.hw,
[LS1X_CLKID_CPU] = &ls1c_clk_cpu.hw,
[LS1X_CLKID_DC] = &ls1c_clk_dc.hw,
[LS1X_CLKID_AHB] = &ls1c_clk_ahb.hw,
[LS1X_CLKID_APB] = &ls1c_clk_apb.hw,
},
.num = CLK_NR_CLKS,
};
static void __init ls1x_clk_init(struct device_node *np,
struct clk_hw_onecell_data *hw_data)
{
struct ls1x_clk *ls1x_clk;
void __iomem *reg;
int i, ret;
reg = of_iomap(np, 0);
if (!reg) {
pr_err("Unable to map base for %pOF\n", np);
return;
}
for (i = 0; i < hw_data->num; i++) {
/* array might be sparse */
if (!hw_data->hws[i])
continue;
if (i != LS1X_CLKID_APB) {
ls1x_clk = to_ls1x_clk(hw_data->hws[i]);
ls1x_clk->reg = reg + ls1x_clk->offset;
}
ret = of_clk_hw_register(np, hw_data->hws[i]);
if (ret)
goto err;
}
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, hw_data);
if (!ret)
return;
err:
pr_err("Failed to register %pOF\n", np);
while (--i >= 0)
clk_hw_unregister(hw_data->hws[i]);
iounmap(reg);
}
static void __init ls1b_clk_init(struct device_node *np)
{
return ls1x_clk_init(np, &ls1b_clk_hw_data);
}
static void __init ls1c_clk_init(struct device_node *np)
{
return ls1x_clk_init(np, &ls1c_clk_hw_data);
}
CLK_OF_DECLARE(ls1b_clk, "loongson,ls1b-clk", ls1b_clk_init);
CLK_OF_DECLARE(ls1c_clk, "loongson,ls1c-clk", ls1c_clk_init);

341
drivers/clk/clk-loongson2.c Normal file
View File

@ -0,0 +1,341 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Author: Yinbo Zhu <zhuyinbo@loongson.cn>
* Copyright (C) 2022-2023 Loongson Technology Corporation Limited
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <dt-bindings/clock/loongson,ls2k-clk.h>
#define LOONGSON2_PLL_MULT_SHIFT 32
#define LOONGSON2_PLL_MULT_WIDTH 10
#define LOONGSON2_PLL_DIV_SHIFT 26
#define LOONGSON2_PLL_DIV_WIDTH 6
#define LOONGSON2_APB_FREQSCALE_SHIFT 20
#define LOONGSON2_APB_FREQSCALE_WIDTH 3
#define LOONGSON2_USB_FREQSCALE_SHIFT 16
#define LOONGSON2_USB_FREQSCALE_WIDTH 3
#define LOONGSON2_SATA_FREQSCALE_SHIFT 12
#define LOONGSON2_SATA_FREQSCALE_WIDTH 3
#define LOONGSON2_BOOT_FREQSCALE_SHIFT 8
#define LOONGSON2_BOOT_FREQSCALE_WIDTH 3
static void __iomem *loongson2_pll_base;
static const struct clk_parent_data pdata[] = {
{ .fw_name = "ref_100m",},
};
static struct clk_hw *loongson2_clk_register(struct device *dev,
const char *name,
const char *parent_name,
const struct clk_ops *ops,
unsigned long flags)
{
int ret;
struct clk_hw *hw;
struct clk_init_data init;
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = ops;
init.flags = flags;
init.num_parents = 1;
if (!parent_name)
init.parent_data = pdata;
else
init.parent_names = &parent_name;
hw->init = &init;
ret = devm_clk_hw_register(dev, hw);
if (ret)
hw = ERR_PTR(ret);
return hw;
}
static unsigned long loongson2_calc_pll_rate(int offset, unsigned long rate)
{
u64 val;
u32 mult, div;
val = readq(loongson2_pll_base + offset);
mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
return div_u64((u64)rate * mult, div);
}
static unsigned long loongson2_node_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_pll_rate(0x0, parent_rate);
}
static const struct clk_ops loongson2_node_clk_ops = {
.recalc_rate = loongson2_node_recalc_rate,
};
static unsigned long loongson2_ddr_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_pll_rate(0x10, parent_rate);
}
static const struct clk_ops loongson2_ddr_clk_ops = {
.recalc_rate = loongson2_ddr_recalc_rate,
};
static unsigned long loongson2_dc_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_pll_rate(0x20, parent_rate);
}
static const struct clk_ops loongson2_dc_clk_ops = {
.recalc_rate = loongson2_dc_recalc_rate,
};
static unsigned long loongson2_pix0_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_pll_rate(0x30, parent_rate);
}
static const struct clk_ops loongson2_pix0_clk_ops = {
.recalc_rate = loongson2_pix0_recalc_rate,
};
static unsigned long loongson2_pix1_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_pll_rate(0x40, parent_rate);
}
static const struct clk_ops loongson2_pix1_clk_ops = {
.recalc_rate = loongson2_pix1_recalc_rate,
};
static unsigned long loongson2_calc_rate(unsigned long rate,
int shift, int width)
{
u64 val;
u32 mult;
val = readq(loongson2_pll_base + 0x50);
mult = (val >> shift) & clk_div_mask(width);
return div_u64((u64)rate * (mult + 1), 8);
}
static unsigned long loongson2_boot_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_rate(parent_rate,
LOONGSON2_BOOT_FREQSCALE_SHIFT,
LOONGSON2_BOOT_FREQSCALE_WIDTH);
}
static const struct clk_ops loongson2_boot_clk_ops = {
.recalc_rate = loongson2_boot_recalc_rate,
};
static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_rate(parent_rate,
LOONGSON2_APB_FREQSCALE_SHIFT,
LOONGSON2_APB_FREQSCALE_WIDTH);
}
static const struct clk_ops loongson2_apb_clk_ops = {
.recalc_rate = loongson2_apb_recalc_rate,
};
static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_rate(parent_rate,
LOONGSON2_USB_FREQSCALE_SHIFT,
LOONGSON2_USB_FREQSCALE_WIDTH);
}
static const struct clk_ops loongson2_usb_clk_ops = {
.recalc_rate = loongson2_usb_recalc_rate,
};
static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return loongson2_calc_rate(parent_rate,
LOONGSON2_SATA_FREQSCALE_SHIFT,
LOONGSON2_SATA_FREQSCALE_WIDTH);
}
static const struct clk_ops loongson2_sata_clk_ops = {
.recalc_rate = loongson2_sata_recalc_rate,
};
static inline int loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
{
unsigned int i;
for (i = 0; i < count; i++)
if (IS_ERR(clks[i])) {
pr_err("Loongson2 clk %u: register failed with %ld\n",
i, PTR_ERR(clks[i]));
return PTR_ERR(clks[i]);
}
return 0;
}
static int loongson2_clk_probe(struct platform_device *pdev)
{
int ret;
struct clk_hw **hws;
struct clk_hw_onecell_data *clk_hw_data;
spinlock_t loongson2_clk_lock;
struct device *dev = &pdev->dev;
loongson2_pll_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(loongson2_pll_base))
return PTR_ERR(loongson2_pll_base);
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
clk_hw_data->num = LOONGSON2_CLK_END;
hws = clk_hw_data->hws;
hws[LOONGSON2_NODE_PLL] = loongson2_clk_register(dev, "node_pll",
NULL,
&loongson2_node_clk_ops, 0);
hws[LOONGSON2_DDR_PLL] = loongson2_clk_register(dev, "ddr_pll",
NULL,
&loongson2_ddr_clk_ops, 0);
hws[LOONGSON2_DC_PLL] = loongson2_clk_register(dev, "dc_pll",
NULL,
&loongson2_dc_clk_ops, 0);
hws[LOONGSON2_PIX0_PLL] = loongson2_clk_register(dev, "pix0_pll",
NULL,
&loongson2_pix0_clk_ops, 0);
hws[LOONGSON2_PIX1_PLL] = loongson2_clk_register(dev, "pix1_pll",
NULL,
&loongson2_pix1_clk_ops, 0);
hws[LOONGSON2_BOOT_CLK] = loongson2_clk_register(dev, "boot",
NULL,
&loongson2_boot_clk_ops, 0);
hws[LOONGSON2_NODE_CLK] = devm_clk_hw_register_divider(dev, "node",
"node_pll", 0,
loongson2_pll_base + 0x8, 0,
6, CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
/*
* The hda clk divisor in the upper 32bits and the clk-prodiver
* layer code doesn't support 64bit io operation thus a conversion
* is required that subtract shift by 32 and add 4byte to the hda
* address
*/
hws[LOONGSON2_HDA_CLK] = devm_clk_hw_register_divider(dev, "hda",
"ddr_pll", 0,
loongson2_pll_base + 0x22, 12,
7, CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
hws[LOONGSON2_GPU_CLK] = devm_clk_hw_register_divider(dev, "gpu",
"ddr_pll", 0,
loongson2_pll_base + 0x18, 22,
6, CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
hws[LOONGSON2_DDR_CLK] = devm_clk_hw_register_divider(dev, "ddr",
"ddr_pll", 0,
loongson2_pll_base + 0x18, 0,
6, CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
hws[LOONGSON2_GMAC_CLK] = devm_clk_hw_register_divider(dev, "gmac",
"dc_pll", 0,
loongson2_pll_base + 0x28, 22,
6, CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
hws[LOONGSON2_DC_CLK] = devm_clk_hw_register_divider(dev, "dc",
"dc_pll", 0,
loongson2_pll_base + 0x28, 0,
6, CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
hws[LOONGSON2_APB_CLK] = loongson2_clk_register(dev, "apb",
"gmac",
&loongson2_apb_clk_ops, 0);
hws[LOONGSON2_USB_CLK] = loongson2_clk_register(dev, "usb",
"gmac",
&loongson2_usb_clk_ops, 0);
hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(dev, "sata",
"gmac",
&loongson2_sata_clk_ops, 0);
hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
"pix0_pll", 0,
loongson2_pll_base + 0x38, 0, 6,
CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
"pix1_pll", 0,
loongson2_pll_base + 0x48, 0, 6,
CLK_DIVIDER_ONE_BASED,
&loongson2_clk_lock);
ret = loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
if (ret)
return ret;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
}
static const struct of_device_id loongson2_clk_match_table[] = {
{ .compatible = "loongson,ls2k-clk" },
{ }
};
MODULE_DEVICE_TABLE(of, loongson2_clk_match_table);
static struct platform_driver loongson2_clk_driver = {
.probe = loongson2_clk_probe,
.driver = {
.name = "loongson2-clk",
.of_match_table = loongson2_clk_match_table,
},
};
module_platform_driver(loongson2_clk_driver);
MODULE_DESCRIPTION("Loongson2 clock driver");
MODULE_LICENSE("GPL");

View File

@ -560,14 +560,12 @@ static void m10v_reg_mux_pre(const struct m10v_clk_mux_factors *factors,
static int m10v_clk_probe(struct platform_device *pdev)
{
int id;
struct resource *res;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
void __iomem *base;
const char *parent_name;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);

View File

@ -271,10 +271,9 @@ static int palmas_clks_probe(struct platform_device *pdev)
return ret;
}
static int palmas_clks_remove(struct platform_device *pdev)
static void palmas_clks_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
}
static struct platform_driver palmas_clks_driver = {
@ -283,7 +282,7 @@ static struct platform_driver palmas_clks_driver = {
.of_match_table = palmas_clks_of_match,
},
.probe = palmas_clks_probe,
.remove = palmas_clks_remove,
.remove_new = palmas_clks_remove,
};
module_platform_driver(palmas_clks_driver);

View File

@ -129,11 +129,9 @@ static int clk_pwm_probe(struct platform_device *pdev)
return of_clk_add_hw_provider(node, of_clk_hw_simple_get, &clk_pwm->hw);
}
static int clk_pwm_remove(struct platform_device *pdev)
static void clk_pwm_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
}
static const struct of_device_id clk_pwm_dt_ids[] = {
@ -144,7 +142,7 @@ MODULE_DEVICE_TABLE(of, clk_pwm_dt_ids);
static struct platform_driver clk_pwm_driver = {
.probe = clk_pwm_probe,
.remove = clk_pwm_remove,
.remove_new = clk_pwm_remove,
.driver = {
.name = "pwm-clock",
.of_match_table = clk_pwm_dt_ids,

View File

@ -6,6 +6,7 @@
* - 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ
* Currently supported:
* - 9FGV0241
* - 9FGV0441
*
* Copyright (C) 2022 Marek Vasut <marex@denx.de>
*/
@ -18,7 +19,6 @@
#include <linux/regmap.h>
#define RS9_REG_OE 0x0
#define RS9_REG_OE_DIF_OE(n) BIT((n) + 1)
#define RS9_REG_SS 0x1
#define RS9_REG_SS_AMP_0V6 0x0
#define RS9_REG_SS_AMP_0V7 0x1
@ -31,9 +31,6 @@
#define RS9_REG_SS_SSC_MASK (3 << 3)
#define RS9_REG_SS_SSC_LOCK BIT(5)
#define RS9_REG_SR 0x2
#define RS9_REG_SR_2V0_DIF(n) 0
#define RS9_REG_SR_3V0_DIF(n) BIT((n) + 1)
#define RS9_REG_SR_DIF_MASK(n) BIT((n) + 1)
#define RS9_REG_REF 0x3
#define RS9_REG_REF_OE BIT(4)
#define RS9_REG_REF_OD BIT(5)
@ -45,22 +42,31 @@
#define RS9_REG_DID 0x6
#define RS9_REG_BCP 0x7
#define RS9_REG_VID_IDT 0x01
#define RS9_REG_DID_TYPE_FGV (0x0 << RS9_REG_DID_TYPE_SHIFT)
#define RS9_REG_DID_TYPE_DBV (0x1 << RS9_REG_DID_TYPE_SHIFT)
#define RS9_REG_DID_TYPE_DMV (0x2 << RS9_REG_DID_TYPE_SHIFT)
#define RS9_REG_DID_TYPE_SHIFT 0x6
/* Supported Renesas 9-series models. */
enum rs9_model {
RENESAS_9FGV0241,
RENESAS_9FGV0441,
};
/* Structure to describe features of a particular 9-series model */
struct rs9_chip_info {
const enum rs9_model model;
unsigned int num_clks;
u8 did;
};
struct rs9_driver_data {
struct i2c_client *client;
struct regmap *regmap;
const struct rs9_chip_info *chip_info;
struct clk_hw *clk_dif[2];
struct clk_hw *clk_dif[4];
u8 pll_amplitude;
u8 pll_ssc;
u8 clk_dif_sr;
@ -152,17 +158,29 @@ static const struct regmap_config rs9_regmap_config = {
.reg_read = rs9_regmap_i2c_read,
};
static u8 rs9_calc_dif(const struct rs9_driver_data *rs9, int idx)
{
enum rs9_model model = rs9->chip_info->model;
if (model == RENESAS_9FGV0241)
return BIT(idx) + 1;
else if (model == RENESAS_9FGV0441)
return BIT(idx);
return 0;
}
static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
{
struct i2c_client *client = rs9->client;
u8 dif = rs9_calc_dif(rs9, idx);
unsigned char name[5] = "DIF0";
struct device_node *np;
int ret;
u32 sr;
/* Set defaults */
rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx);
rs9->clk_dif_sr |= dif;
snprintf(name, 5, "DIF%d", idx);
np = of_get_child_by_name(client->dev.of_node, name);
@ -174,11 +192,9 @@ static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
of_node_put(np);
if (!ret) {
if (sr == 2000000) { /* 2V/ns */
rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
rs9->clk_dif_sr |= RS9_REG_SR_2V0_DIF(idx);
rs9->clk_dif_sr &= ~dif;
} else if (sr == 3000000) { /* 3V/ns (default) */
rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx);
rs9->clk_dif_sr |= dif;
} else
ret = dev_err_probe(&client->dev, -EINVAL,
"Invalid renesas,slew-rate value\n");
@ -249,11 +265,13 @@ static void rs9_update_config(struct rs9_driver_data *rs9)
}
for (i = 0; i < rs9->chip_info->num_clks; i++) {
if (rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i))
u8 dif = rs9_calc_dif(rs9, i);
if (rs9->clk_dif_sr & dif)
continue;
regmap_update_bits(rs9->regmap, RS9_REG_SR, RS9_REG_SR_3V0_DIF(i),
rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i));
regmap_update_bits(rs9->regmap, RS9_REG_SR, dif,
rs9->clk_dif_sr & dif);
}
}
@ -270,6 +288,7 @@ static int rs9_probe(struct i2c_client *client)
{
unsigned char name[5] = "DIF0";
struct rs9_driver_data *rs9;
unsigned int vid, did;
struct clk_hw *hw;
int i, ret;
@ -306,6 +325,20 @@ static int rs9_probe(struct i2c_client *client)
if (ret < 0)
return ret;
ret = regmap_read(rs9->regmap, RS9_REG_VID, &vid);
if (ret < 0)
return ret;
ret = regmap_read(rs9->regmap, RS9_REG_DID, &did);
if (ret < 0)
return ret;
if (vid != RS9_REG_VID_IDT || did != rs9->chip_info->did)
return dev_err_probe(&client->dev, -ENODEV,
"Incorrect VID/DID: %#02x, %#02x. Expected %#02x, %#02x\n",
vid, did, RS9_REG_VID_IDT,
rs9->chip_info->did);
/* Register clock */
for (i = 0; i < rs9->chip_info->num_clks; i++) {
snprintf(name, 5, "DIF%d", i);
@ -349,16 +382,25 @@ static int __maybe_unused rs9_resume(struct device *dev)
static const struct rs9_chip_info renesas_9fgv0241_info = {
.model = RENESAS_9FGV0241,
.num_clks = 2,
.did = RS9_REG_DID_TYPE_FGV | 0x02,
};
static const struct rs9_chip_info renesas_9fgv0441_info = {
.model = RENESAS_9FGV0441,
.num_clks = 4,
.did = RS9_REG_DID_TYPE_FGV | 0x04,
};
static const struct i2c_device_id rs9_id[] = {
{ "9fgv0241", .driver_data = RENESAS_9FGV0241 },
{ "9fgv0441", .driver_data = RENESAS_9FGV0441 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rs9_id);
static const struct of_device_id clk_rs9_of_match[] = {
{ .compatible = "renesas,9fgv0241", .data = &renesas_9fgv0241_info },
{ .compatible = "renesas,9fgv0441", .data = &renesas_9fgv0441_info },
{ }
};
MODULE_DEVICE_TABLE(of, clk_rs9_of_match);

View File

@ -202,7 +202,7 @@ err_reg:
return ret;
}
static int s2mps11_clk_remove(struct platform_device *pdev)
static void s2mps11_clk_remove(struct platform_device *pdev)
{
struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
int i;
@ -217,8 +217,6 @@ static int s2mps11_clk_remove(struct platform_device *pdev)
continue;
clkdev_drop(s2mps11_clks[i].lookup);
}
return 0;
}
static const struct platform_device_id s2mps11_clk_id[] = {
@ -265,7 +263,7 @@ static struct platform_driver s2mps11_clk_driver = {
.name = "s2mps11-clk",
},
.probe = s2mps11_clk_probe,
.remove = s2mps11_clk_remove,
.remove_new = s2mps11_clk_remove,
.id_table = s2mps11_clk_id,
};
module_platform_driver(s2mps11_clk_driver);

View File

@ -246,7 +246,7 @@ static int scpi_clk_add(struct device *dev, struct device_node *np,
return of_clk_add_hw_provider(np, scpi_of_clk_src_get, clk_data);
}
static int scpi_clocks_remove(struct platform_device *pdev)
static void scpi_clocks_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *child, *np = dev->of_node;
@ -258,7 +258,6 @@ static int scpi_clocks_remove(struct platform_device *pdev)
for_each_available_child_of_node(np, child)
of_clk_del_provider(np);
return 0;
}
static int scpi_clocks_probe(struct platform_device *pdev)
@ -305,7 +304,7 @@ static struct platform_driver scpi_clocks_driver = {
.of_match_table = scpi_clocks_ids,
},
.probe = scpi_clocks_probe,
.remove = scpi_clocks_remove,
.remove_new = scpi_clocks_remove,
};
module_platform_driver(scpi_clocks_driver);

View File

@ -360,8 +360,8 @@ static int si514_probe(struct i2c_client *client)
dev_err(&client->dev, "clock registration failed\n");
return err;
}
err = of_clk_add_hw_provider(client->dev.of_node, of_clk_hw_simple_get,
&data->hw);
err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get,
&data->hw);
if (err) {
dev_err(&client->dev, "unable to add clk provider\n");
return err;
@ -370,11 +370,6 @@ static int si514_probe(struct i2c_client *client)
return 0;
}
static void si514_remove(struct i2c_client *client)
{
of_clk_del_provider(client->dev.of_node);
}
static const struct i2c_device_id si514_id[] = {
{ "si514", 0 },
{ }
@ -393,7 +388,6 @@ static struct i2c_driver si514_driver = {
.of_match_table = clk_si514_of_match,
},
.probe_new = si514_probe,
.remove = si514_remove,
.id_table = si514_id,
};
module_i2c_driver(si514_driver);

395
drivers/clk/clk-si521xx.c Normal file
View File

@ -0,0 +1,395 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for Skyworks Si521xx PCIe clock generator driver
*
* The following series can be supported:
* - Si52144 - 4x DIFF
* - Si52146 - 6x DIFF
* - Si52147 - 9x DIFF
* Currently tested:
* - Si52144
*
* Copyright (C) 2022 Marek Vasut <marex@denx.de>
*/
#include <linux/bitfield.h>
#include <linux/bitrev.h>
#include <linux/clk-provider.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
/* OE1 and OE2 register */
#define SI521XX_REG_OE(n) (((n) & 0x1) + 1)
#define SI521XX_REG_ID 0x3
#define SI521XX_REG_ID_PROG GENMASK(7, 4)
#define SI521XX_REG_ID_VENDOR GENMASK(3, 0)
#define SI521XX_REG_BC 0x4
#define SI521XX_REG_DA 0x5
#define SI521XX_REG_DA_AMP_SEL BIT(7)
#define SI521XX_REG_DA_AMP_MASK GENMASK(6, 4)
#define SI521XX_REG_DA_AMP_MIN 300000
#define SI521XX_REG_DA_AMP_DEFAULT 800000
#define SI521XX_REG_DA_AMP_MAX 1000000
#define SI521XX_REG_DA_AMP_STEP 100000
#define SI521XX_REG_DA_AMP(UV) \
FIELD_PREP(SI521XX_REG_DA_AMP_MASK, \
((UV) - SI521XX_REG_DA_AMP_MIN) / SI521XX_REG_DA_AMP_STEP)
#define SI521XX_REG_DA_UNKNOWN BIT(3) /* Always set */
/* Count of populated OE bits in control register ref, 1 and 2 */
#define SI521XX_OE_MAP(cr1, cr2) (((cr2) << 8) | (cr1))
#define SI521XX_OE_MAP_GET_OE(oe, map) (((map) >> (((oe) - 1) * 8)) & 0xff)
#define SI521XX_DIFF_MULT 4
#define SI521XX_DIFF_DIV 1
/* Supported Skyworks Si521xx models. */
enum si521xx_model {
SI52144 = 0x44,
SI52146 = 0x46,
SI52147 = 0x47,
};
struct si521xx;
struct si_clk {
struct clk_hw hw;
struct si521xx *si;
u8 reg;
u8 bit;
};
struct si521xx {
struct i2c_client *client;
struct regmap *regmap;
struct si_clk clk_dif[9];
u16 chip_info;
u8 pll_amplitude;
};
/*
* Si521xx i2c regmap
*/
static const struct regmap_range si521xx_readable_ranges[] = {
regmap_reg_range(SI521XX_REG_OE(0), SI521XX_REG_DA),
};
static const struct regmap_access_table si521xx_readable_table = {
.yes_ranges = si521xx_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(si521xx_readable_ranges),
};
static const struct regmap_range si521xx_writeable_ranges[] = {
regmap_reg_range(SI521XX_REG_OE(0), SI521XX_REG_OE(1)),
regmap_reg_range(SI521XX_REG_BC, SI521XX_REG_DA),
};
static const struct regmap_access_table si521xx_writeable_table = {
.yes_ranges = si521xx_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(si521xx_writeable_ranges),
};
static int si521xx_regmap_i2c_write(void *context, unsigned int reg,
unsigned int val)
{
struct i2c_client *i2c = context;
const u8 data[3] = { reg, 1, val };
const int count = ARRAY_SIZE(data);
int ret;
ret = i2c_master_send(i2c, data, count);
if (ret == count)
return 0;
else if (ret < 0)
return ret;
else
return -EIO;
}
static int si521xx_regmap_i2c_read(void *context, unsigned int reg,
unsigned int *val)
{
struct i2c_client *i2c = context;
struct i2c_msg xfer[2];
u8 txdata = reg;
u8 rxdata[2];
int ret;
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = 1;
xfer[0].buf = (void *)&txdata;
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = 2;
xfer[1].buf = (void *)rxdata;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (ret < 0)
return ret;
if (ret != 2)
return -EIO;
/*
* Byte 0 is transfer length, which is always 1 due
* to BCP register programming to 1 in si521xx_probe(),
* ignore it and use data from Byte 1.
*/
*val = rxdata[1];
return 0;
}
static const struct regmap_config si521xx_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_NONE,
.max_register = SI521XX_REG_DA,
.rd_table = &si521xx_readable_table,
.wr_table = &si521xx_writeable_table,
.reg_write = si521xx_regmap_i2c_write,
.reg_read = si521xx_regmap_i2c_read,
};
static unsigned long si521xx_diff_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long long rate;
rate = (unsigned long long)parent_rate * SI521XX_DIFF_MULT;
do_div(rate, SI521XX_DIFF_DIV);
return (unsigned long)rate;
}
static long si521xx_diff_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long best_parent;
best_parent = (rate / SI521XX_DIFF_MULT) * SI521XX_DIFF_DIV;
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
return (*prate / SI521XX_DIFF_DIV) * SI521XX_DIFF_MULT;
}
static int si521xx_diff_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
/*
* We must report success but we can do so unconditionally because
* si521xx_diff_round_rate returns values that ensure this call is a
* nop.
*/
return 0;
}
#define to_si521xx_clk(_hw) container_of(_hw, struct si_clk, hw)
static int si521xx_diff_prepare(struct clk_hw *hw)
{
struct si_clk *si_clk = to_si521xx_clk(hw);
struct si521xx *si = si_clk->si;
regmap_set_bits(si->regmap, SI521XX_REG_OE(si_clk->reg), si_clk->bit);
return 0;
}
static void si521xx_diff_unprepare(struct clk_hw *hw)
{
struct si_clk *si_clk = to_si521xx_clk(hw);
struct si521xx *si = si_clk->si;
regmap_clear_bits(si->regmap, SI521XX_REG_OE(si_clk->reg), si_clk->bit);
}
static const struct clk_ops si521xx_diff_clk_ops = {
.round_rate = si521xx_diff_round_rate,
.set_rate = si521xx_diff_set_rate,
.recalc_rate = si521xx_diff_recalc_rate,
.prepare = si521xx_diff_prepare,
.unprepare = si521xx_diff_unprepare,
};
static int si521xx_get_common_config(struct si521xx *si)
{
struct i2c_client *client = si->client;
struct device_node *np = client->dev.of_node;
unsigned int amp;
int ret;
/* Set defaults */
si->pll_amplitude = SI521XX_REG_DA_AMP(SI521XX_REG_DA_AMP_DEFAULT);
/* Output clock amplitude */
ret = of_property_read_u32(np, "skyworks,out-amplitude-microvolt",
&amp);
if (!ret) {
if (amp < SI521XX_REG_DA_AMP_MIN || amp > SI521XX_REG_DA_AMP_MAX ||
amp % SI521XX_REG_DA_AMP_STEP) {
return dev_err_probe(&client->dev, -EINVAL,
"Invalid skyworks,out-amplitude-microvolt value\n");
}
si->pll_amplitude = SI521XX_REG_DA_AMP(amp);
}
return 0;
}
static void si521xx_update_config(struct si521xx *si)
{
/* If amplitude is non-default, update it. */
if (si->pll_amplitude == SI521XX_REG_DA_AMP(SI521XX_REG_DA_AMP_DEFAULT))
return;
regmap_update_bits(si->regmap, SI521XX_REG_DA,
SI521XX_REG_DA_AMP_MASK, si->pll_amplitude);
}
static void si521xx_diff_idx_to_reg_bit(const u16 chip_info, const int idx,
struct si_clk *clk)
{
unsigned long mask;
int oe, b, ctr = 0;
for (oe = 1; oe <= 2; oe++) {
mask = bitrev8(SI521XX_OE_MAP_GET_OE(oe, chip_info));
for_each_set_bit(b, &mask, 8) {
if (ctr++ != idx)
continue;
clk->reg = SI521XX_REG_OE(oe);
clk->bit = 7 - b;
return;
}
}
}
static struct clk_hw *
si521xx_of_clk_get(struct of_phandle_args *clkspec, void *data)
{
struct si521xx *si = data;
unsigned int idx = clkspec->args[0];
return &si->clk_dif[idx].hw;
}
static int si521xx_probe(struct i2c_client *client)
{
const u16 chip_info = (u16)(uintptr_t)device_get_match_data(&client->dev);
const struct clk_parent_data clk_parent_data = { .index = 0 };
struct si521xx *si;
unsigned char name[6] = "DIFF0";
struct clk_init_data init = {};
int i, ret;
if (!chip_info)
return -EINVAL;
si = devm_kzalloc(&client->dev, sizeof(*si), GFP_KERNEL);
if (!si)
return -ENOMEM;
i2c_set_clientdata(client, si);
si->client = client;
/* Fetch common configuration from DT (if specified) */
ret = si521xx_get_common_config(si);
if (ret)
return ret;
si->regmap = devm_regmap_init(&client->dev, NULL, client,
&si521xx_regmap_config);
if (IS_ERR(si->regmap))
return dev_err_probe(&client->dev, PTR_ERR(si->regmap),
"Failed to allocate register map\n");
/* Always read back 1 Byte via I2C */
ret = regmap_write(si->regmap, SI521XX_REG_BC, 1);
if (ret < 0)
return ret;
/* Register clock */
for (i = 0; i < hweight16(chip_info); i++) {
memset(&init, 0, sizeof(init));
snprintf(name, 6, "DIFF%d", i);
init.name = name;
init.ops = &si521xx_diff_clk_ops;
init.parent_data = &clk_parent_data;
init.num_parents = 1;
init.flags = CLK_SET_RATE_PARENT;
si->clk_dif[i].hw.init = &init;
si->clk_dif[i].si = si;
si521xx_diff_idx_to_reg_bit(chip_info, i, &si->clk_dif[i]);
ret = devm_clk_hw_register(&client->dev, &si->clk_dif[i].hw);
if (ret)
return ret;
}
ret = devm_of_clk_add_hw_provider(&client->dev, si521xx_of_clk_get, si);
if (!ret)
si521xx_update_config(si);
return ret;
}
static int __maybe_unused si521xx_suspend(struct device *dev)
{
struct si521xx *si = dev_get_drvdata(dev);
regcache_cache_only(si->regmap, true);
regcache_mark_dirty(si->regmap);
return 0;
}
static int __maybe_unused si521xx_resume(struct device *dev)
{
struct si521xx *si = dev_get_drvdata(dev);
int ret;
regcache_cache_only(si->regmap, false);
ret = regcache_sync(si->regmap);
if (ret)
dev_err(dev, "Failed to restore register map: %d\n", ret);
return ret;
}
static const struct i2c_device_id si521xx_id[] = {
{ "si52144", .driver_data = SI521XX_OE_MAP(0x5, 0xc0) },
{ "si52146", .driver_data = SI521XX_OE_MAP(0x15, 0xe0) },
{ "si52147", .driver_data = SI521XX_OE_MAP(0x17, 0xf8) },
{ }
};
MODULE_DEVICE_TABLE(i2c, si521xx_id);
static const struct of_device_id clk_si521xx_of_match[] = {
{ .compatible = "skyworks,si52144", .data = (void *)SI521XX_OE_MAP(0x5, 0xc0) },
{ .compatible = "skyworks,si52146", .data = (void *)SI521XX_OE_MAP(0x15, 0xe0) },
{ .compatible = "skyworks,si52147", .data = (void *)SI521XX_OE_MAP(0x15, 0xf8) },
{ }
};
MODULE_DEVICE_TABLE(of, clk_si521xx_of_match);
static SIMPLE_DEV_PM_OPS(si521xx_pm_ops, si521xx_suspend, si521xx_resume);
static struct i2c_driver si521xx_driver = {
.driver = {
.name = "clk-si521xx",
.pm = &si521xx_pm_ops,
.of_match_table = clk_si521xx_of_match,
},
.probe_new = si521xx_probe,
.id_table = si521xx_id,
};
module_i2c_driver(si521xx_driver);
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_DESCRIPTION("Skyworks Si521xx PCIe clock generator driver");
MODULE_LICENSE("GPL");

View File

@ -1641,8 +1641,8 @@ static int si5351_i2c_probe(struct i2c_client *client)
}
}
ret = of_clk_add_hw_provider(client->dev.of_node, si53351_of_clk_get,
drvdata);
ret = devm_of_clk_add_hw_provider(&client->dev, si53351_of_clk_get,
drvdata);
if (ret) {
dev_err(&client->dev, "unable to add clk provider\n");
return ret;
@ -1651,18 +1651,12 @@ static int si5351_i2c_probe(struct i2c_client *client)
return 0;
}
static void si5351_i2c_remove(struct i2c_client *client)
{
of_clk_del_provider(client->dev.of_node);
}
static struct i2c_driver si5351_driver = {
.driver = {
.name = "si5351",
.of_match_table = of_match_ptr(si5351_dt_ids),
},
.probe_new = si5351_i2c_probe,
.remove = si5351_i2c_remove,
.id_table = si5351_i2c_ids,
};
module_i2c_driver(si5351_driver);

View File

@ -474,8 +474,8 @@ static int si570_probe(struct i2c_client *client)
dev_err(&client->dev, "clock registration failed\n");
return err;
}
err = of_clk_add_hw_provider(client->dev.of_node, of_clk_hw_simple_get,
&data->hw);
err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get,
&data->hw);
if (err) {
dev_err(&client->dev, "unable to add clk provider\n");
return err;
@ -485,10 +485,8 @@ static int si570_probe(struct i2c_client *client)
if (!of_property_read_u32(client->dev.of_node, "clock-frequency",
&initial_fout)) {
err = clk_set_rate(data->hw.clk, initial_fout);
if (err) {
of_clk_del_provider(client->dev.of_node);
if (err)
return err;
}
}
/* Display a message indicating that we've successfully registered */
@ -498,11 +496,6 @@ static int si570_probe(struct i2c_client *client)
return 0;
}
static void si570_remove(struct i2c_client *client)
{
of_clk_del_provider(client->dev.of_node);
}
static const struct of_device_id clk_si570_of_match[] = {
{ .compatible = "silabs,si570" },
{ .compatible = "silabs,si571" },
@ -518,7 +511,6 @@ static struct i2c_driver si570_driver = {
.of_match_table = clk_si570_of_match,
},
.probe_new = si570_probe,
.remove = si570_remove,
.id_table = si570_id,
};
module_i2c_driver(si570_driver);

713
drivers/clk/clk-sp7021.c Normal file
View File

@ -0,0 +1,713 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/*
* Copyright (C) Sunplus Technology Co., Ltd.
* All rights reserved.
*/
#include <linux/module.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/bitfield.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/sunplus,sp7021-clkc.h>
/* speical div_width values for PLLTV/PLLA */
#define DIV_TV 33
#define DIV_A 34
/* PLLTV parameters */
enum {
SEL_FRA,
SDM_MOD,
PH_SEL,
NFRA,
DIVR,
DIVN,
DIVM,
P_MAX
};
#define MASK_SEL_FRA GENMASK(1, 1)
#define MASK_SDM_MOD GENMASK(2, 2)
#define MASK_PH_SEL GENMASK(4, 4)
#define MASK_NFRA GENMASK(12, 6)
#define MASK_DIVR GENMASK(8, 7)
#define MASK_DIVN GENMASK(7, 0)
#define MASK_DIVM GENMASK(14, 8)
/* HIWORD_MASK FIELD_PREP */
#define HWM_FIELD_PREP(mask, value) \
({ \
u32 _m = mask; \
(_m << 16) | FIELD_PREP(_m, value); \
})
struct sp_pll {
struct clk_hw hw;
void __iomem *reg;
spinlock_t lock; /* lock for reg */
int div_shift;
int div_width;
int pd_bit; /* power down bit idx */
int bp_bit; /* bypass bit idx */
unsigned long brate; /* base rate, TODO: replace brate with muldiv */
u32 p[P_MAX]; /* for hold PLLTV/PLLA parameters */
};
#define to_sp_pll(_hw) container_of(_hw, struct sp_pll, hw)
struct sp_clk_gate_info {
u16 reg; /* reg_index_shift */
u16 ext_parent; /* parent is extclk */
};
static const struct sp_clk_gate_info sp_clk_gates[] = {
{ 0x02 },
{ 0x05 },
{ 0x06 },
{ 0x07 },
{ 0x09 },
{ 0x0b, 1 },
{ 0x0f, 1 },
{ 0x14 },
{ 0x15 },
{ 0x16 },
{ 0x17 },
{ 0x18, 1 },
{ 0x19, 1 },
{ 0x1a, 1 },
{ 0x1b, 1 },
{ 0x1c, 1 },
{ 0x1d, 1 },
{ 0x1e },
{ 0x1f, 1 },
{ 0x20 },
{ 0x21 },
{ 0x22 },
{ 0x23 },
{ 0x24 },
{ 0x25 },
{ 0x26 },
{ 0x2a },
{ 0x2b },
{ 0x2d },
{ 0x2e },
{ 0x30 },
{ 0x31 },
{ 0x32 },
{ 0x33 },
{ 0x3d },
{ 0x3e },
{ 0x3f },
{ 0x42 },
{ 0x44 },
{ 0x4b },
{ 0x4c },
{ 0x4d },
{ 0x4e },
{ 0x4f },
{ 0x50 },
{ 0x55 },
{ 0x60 },
{ 0x61 },
{ 0x6a },
{ 0x73 },
{ 0x86 },
{ 0x8a },
{ 0x8b },
{ 0x8d },
{ 0x8e },
{ 0x8f },
{ 0x90 },
{ 0x92 },
{ 0x93 },
{ 0x95 },
{ 0x96 },
{ 0x97 },
{ 0x98 },
{ 0x99 },
};
#define _M 1000000UL
#define F_27M (27 * _M)
/*********************************** PLL_TV **********************************/
/* TODO: set proper FVCO range */
#define FVCO_MIN (100 * _M)
#define FVCO_MAX (200 * _M)
#define F_MIN (FVCO_MIN / 8)
#define F_MAX (FVCO_MAX)
static long plltv_integer_div(struct sp_pll *clk, unsigned long freq)
{
/* valid m values: 27M must be divisible by m */
static const u32 m_table[] = {
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32
};
u32 m, n, r;
unsigned long fvco, nf;
long ret;
freq = clamp(freq, F_MIN, F_MAX);
/* DIVR 0~3 */
for (r = 0; r <= 3; r++) {
fvco = freq << r;
if (fvco <= FVCO_MAX)
break;
}
/* DIVM */
for (m = 0; m < ARRAY_SIZE(m_table); m++) {
nf = fvco * m_table[m];
n = nf / F_27M;
if ((n * F_27M) == nf)
break;
}
if (m >= ARRAY_SIZE(m_table)) {
ret = -EINVAL;
goto err_not_found;
}
/* save parameters */
clk->p[SEL_FRA] = 0;
clk->p[DIVR] = r;
clk->p[DIVN] = n;
clk->p[DIVM] = m_table[m];
return freq;
err_not_found:
pr_err("%s: %s freq:%lu not found a valid setting\n",
__func__, clk_hw_get_name(&clk->hw), freq);
return ret;
}
/* parameters for PLLTV fractional divider */
static const u32 pt[][5] = {
/* conventional fractional */
{
1, /* factor */
5, /* 5 * p0 (nint) */
1, /* 1 * p0 */
F_27M, /* F_27M / p0 */
1, /* p0 / p2 */
},
/* phase rotation */
{
10, /* factor */
54, /* 5.4 * p0 (nint) */
2, /* 0.2 * p0 */
F_27M / 10, /* F_27M / p0 */
5, /* p0 / p2 */
},
};
static const u32 sdm_mod_vals[] = { 91, 55 };
static long plltv_fractional_div(struct sp_pll *clk, unsigned long freq)
{
u32 m, r;
u32 nint, nfra;
u32 df_quotient_min = 210000000;
u32 df_remainder_min = 0;
unsigned long fvco, nf, f, fout = 0;
int sdm, ph;
freq = clamp(freq, F_MIN, F_MAX);
/* DIVR 0~3 */
for (r = 0; r <= 3; r++) {
fvco = freq << r;
if (fvco <= FVCO_MAX)
break;
}
f = F_27M >> r;
/* PH_SEL */
for (ph = ARRAY_SIZE(pt) - 1; ph >= 0; ph--) {
const u32 *pp = pt[ph];
/* SDM_MOD */
for (sdm = 0; sdm < ARRAY_SIZE(sdm_mod_vals); sdm++) {
u32 mod = sdm_mod_vals[sdm];
/* DIVM 1~32 */
for (m = 1; m <= 32; m++) {
u32 df; /* diff freq */
u32 df_quotient, df_remainder;
nf = fvco * m;
nint = nf / pp[3];
if (nint < pp[1])
continue;
if (nint > pp[1])
break;
nfra = (((nf % pp[3]) * mod * pp[4]) + (F_27M / 2)) / F_27M;
if (nfra) {
u32 df0 = f * (nint + pp[2]) / pp[0];
u32 df1 = f * (mod - nfra) / mod / pp[4];
df = df0 - df1;
} else {
df = f * (nint) / pp[0];
}
df_quotient = df / m;
df_remainder = ((df % m) * 1000) / m;
if (freq > df_quotient) {
df_quotient = freq - df_quotient - 1;
df_remainder = 1000 - df_remainder;
} else {
df_quotient = df_quotient - freq;
}
if (df_quotient_min > df_quotient ||
(df_quotient_min == df_quotient &&
df_remainder_min > df_remainder)) {
/* found a closer freq, save parameters */
clk->p[SEL_FRA] = 1;
clk->p[SDM_MOD] = sdm;
clk->p[PH_SEL] = ph;
clk->p[NFRA] = nfra;
clk->p[DIVR] = r;
clk->p[DIVM] = m;
fout = df / m;
df_quotient_min = df_quotient;
df_remainder_min = df_remainder;
}
}
}
}
if (!fout) {
pr_err("%s: %s freq:%lu not found a valid setting\n",
__func__, clk_hw_get_name(&clk->hw), freq);
return -EINVAL;
}
return fout;
}
static long plltv_div(struct sp_pll *clk, unsigned long freq)
{
if (freq % 100)
return plltv_fractional_div(clk, freq);
return plltv_integer_div(clk, freq);
}
static int plltv_set_rate(struct sp_pll *clk)
{
unsigned long flags;
u32 r0, r1, r2;
r0 = BIT(clk->bp_bit + 16);
r0 |= HWM_FIELD_PREP(MASK_SEL_FRA, clk->p[SEL_FRA]);
r0 |= HWM_FIELD_PREP(MASK_SDM_MOD, clk->p[SDM_MOD]);
r0 |= HWM_FIELD_PREP(MASK_PH_SEL, clk->p[PH_SEL]);
r0 |= HWM_FIELD_PREP(MASK_NFRA, clk->p[NFRA]);
r1 = HWM_FIELD_PREP(MASK_DIVR, clk->p[DIVR]);
r2 = HWM_FIELD_PREP(MASK_DIVN, clk->p[DIVN] - 1);
r2 |= HWM_FIELD_PREP(MASK_DIVM, clk->p[DIVM] - 1);
spin_lock_irqsave(&clk->lock, flags);
writel(r0, clk->reg);
writel(r1, clk->reg + 4);
writel(r2, clk->reg + 8);
spin_unlock_irqrestore(&clk->lock, flags);
return 0;
}
/*********************************** PLL_A ***********************************/
/* from Q628_PLLs_REG_setting.xlsx */
static const struct {
u32 rate;
u32 regs[5];
} pa[] = {
{
.rate = 135475200,
.regs = {
0x4801,
0x02df,
0x248f,
0x0211,
0x33e9
}
},
{
.rate = 147456000,
.regs = {
0x4801,
0x1adf,
0x2490,
0x0349,
0x33e9
}
},
{
.rate = 196608000,
.regs = {
0x4801,
0x42ef,
0x2495,
0x01c6,
0x33e9
}
},
};
static int plla_set_rate(struct sp_pll *clk)
{
const u32 *pp = pa[clk->p[0]].regs;
unsigned long flags;
int i;
spin_lock_irqsave(&clk->lock, flags);
for (i = 0; i < ARRAY_SIZE(pa->regs); i++)
writel(0xffff0000 | pp[i], clk->reg + (i * 4));
spin_unlock_irqrestore(&clk->lock, flags);
return 0;
}
static long plla_round_rate(struct sp_pll *clk, unsigned long rate)
{
int i = ARRAY_SIZE(pa);
while (--i) {
if (rate >= pa[i].rate)
break;
}
clk->p[0] = i;
return pa[i].rate;
}
/********************************** SP_PLL ***********************************/
static long sp_pll_calc_div(struct sp_pll *clk, unsigned long rate)
{
u32 fbdiv;
u32 max = 1 << clk->div_width;
fbdiv = DIV_ROUND_CLOSEST(rate, clk->brate);
if (fbdiv > max)
fbdiv = max;
return fbdiv;
}
static long sp_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct sp_pll *clk = to_sp_pll(hw);
long ret;
if (rate == *prate) {
ret = *prate; /* bypass */
} else if (clk->div_width == DIV_A) {
ret = plla_round_rate(clk, rate);
} else if (clk->div_width == DIV_TV) {
ret = plltv_div(clk, rate);
if (ret < 0)
ret = *prate;
} else {
ret = sp_pll_calc_div(clk, rate) * clk->brate;
}
return ret;
}
static unsigned long sp_pll_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct sp_pll *clk = to_sp_pll(hw);
u32 reg = readl(clk->reg);
unsigned long ret;
if (reg & BIT(clk->bp_bit)) {
ret = prate; /* bypass */
} else if (clk->div_width == DIV_A) {
ret = pa[clk->p[0]].rate;
} else if (clk->div_width == DIV_TV) {
u32 m, r, reg2;
r = FIELD_GET(MASK_DIVR, readl(clk->reg + 4));
reg2 = readl(clk->reg + 8);
m = FIELD_GET(MASK_DIVM, reg2) + 1;
if (reg & MASK_SEL_FRA) {
/* fractional divider */
u32 sdm = FIELD_GET(MASK_SDM_MOD, reg);
u32 ph = FIELD_GET(MASK_PH_SEL, reg);
u32 nfra = FIELD_GET(MASK_NFRA, reg);
const u32 *pp = pt[ph];
unsigned long r0, r1;
ret = prate >> r;
r0 = ret * (pp[1] + pp[2]) / pp[0];
r1 = ret * (sdm_mod_vals[sdm] - nfra) / sdm_mod_vals[sdm] / pp[4];
ret = (r0 - r1) / m;
} else {
/* integer divider */
u32 n = FIELD_GET(MASK_DIVN, reg2) + 1;
ret = (prate / m * n) >> r;
}
} else {
u32 fbdiv = ((reg >> clk->div_shift) & ((1 << clk->div_width) - 1)) + 1;
ret = clk->brate * fbdiv;
}
return ret;
}
static int sp_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
struct sp_pll *clk = to_sp_pll(hw);
unsigned long flags;
u32 reg;
reg = BIT(clk->bp_bit + 16); /* HIWORD_MASK */
if (rate == prate) {
reg |= BIT(clk->bp_bit); /* bypass */
} else if (clk->div_width == DIV_A) {
return plla_set_rate(clk);
} else if (clk->div_width == DIV_TV) {
return plltv_set_rate(clk);
} else if (clk->div_width) {
u32 fbdiv = sp_pll_calc_div(clk, rate);
u32 mask = GENMASK(clk->div_shift + clk->div_width - 1, clk->div_shift);
reg |= mask << 16;
reg |= ((fbdiv - 1) << clk->div_shift) & mask;
}
spin_lock_irqsave(&clk->lock, flags);
writel(reg, clk->reg);
spin_unlock_irqrestore(&clk->lock, flags);
return 0;
}
static int sp_pll_enable(struct clk_hw *hw)
{
struct sp_pll *clk = to_sp_pll(hw);
writel(BIT(clk->pd_bit + 16) | BIT(clk->pd_bit), clk->reg);
return 0;
}
static void sp_pll_disable(struct clk_hw *hw)
{
struct sp_pll *clk = to_sp_pll(hw);
writel(BIT(clk->pd_bit + 16), clk->reg);
}
static int sp_pll_is_enabled(struct clk_hw *hw)
{
struct sp_pll *clk = to_sp_pll(hw);
return readl(clk->reg) & BIT(clk->pd_bit);
}
static const struct clk_ops sp_pll_ops = {
.enable = sp_pll_enable,
.disable = sp_pll_disable,
.is_enabled = sp_pll_is_enabled,
.round_rate = sp_pll_round_rate,
.recalc_rate = sp_pll_recalc_rate,
.set_rate = sp_pll_set_rate
};
static const struct clk_ops sp_pll_sub_ops = {
.enable = sp_pll_enable,
.disable = sp_pll_disable,
.is_enabled = sp_pll_is_enabled,
.recalc_rate = sp_pll_recalc_rate,
};
static struct clk_hw *sp_pll_register(struct device *dev, const char *name,
const struct clk_parent_data *parent_data,
void __iomem *reg, int pd_bit, int bp_bit,
unsigned long brate, int shift, int width,
unsigned long flags)
{
struct sp_pll *pll;
struct clk_hw *hw;
struct clk_init_data initd = {
.name = name,
.parent_data = parent_data,
.ops = (bp_bit >= 0) ? &sp_pll_ops : &sp_pll_sub_ops,
.num_parents = 1,
.flags = flags,
};
int ret;
pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
pll->hw.init = &initd;
pll->reg = reg;
pll->pd_bit = pd_bit;
pll->bp_bit = bp_bit;
pll->brate = brate;
pll->div_shift = shift;
pll->div_width = width;
spin_lock_init(&pll->lock);
hw = &pll->hw;
ret = devm_clk_hw_register(dev, hw);
if (ret)
return ERR_PTR(ret);
return hw;
}
#define PLLA_CTL (pll_base + 0x1c)
#define PLLE_CTL (pll_base + 0x30)
#define PLLF_CTL (pll_base + 0x34)
#define PLLTV_CTL (pll_base + 0x38)
static int sp7021_clk_probe(struct platform_device *pdev)
{
static const u32 sp_clken[] = {
0x67ef, 0x03ff, 0xff03, 0xfff0, 0x0004, /* G0.1~5 */
0x0000, 0x8000, 0xffff, 0x0040, 0x0000, /* G0.6~10 */
};
static struct clk_parent_data pd_ext, pd_sys, pd_e;
struct device *dev = &pdev->dev;
void __iomem *clk_base, *pll_base, *sys_base;
struct clk_hw_onecell_data *clk_data;
struct clk_hw **hws;
int i;
clk_base = devm_platform_ioremap_resource(pdev, 0);
if (!clk_base)
return -ENXIO;
pll_base = devm_platform_ioremap_resource(pdev, 1);
if (!pll_base)
return -ENXIO;
sys_base = devm_platform_ioremap_resource(pdev, 2);
if (!sys_base)
return -ENXIO;
/* enable default clks */
for (i = 0; i < ARRAY_SIZE(sp_clken); i++)
writel((sp_clken[i] << 16) | sp_clken[i], clk_base + i * 4);
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, CLK_MAX),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
hws = clk_data->hws;
pd_ext.index = 0;
/* PLLs */
hws[PLL_A] = sp_pll_register(dev, "plla", &pd_ext, PLLA_CTL,
11, 12, 27000000, 0, DIV_A, 0);
if (IS_ERR(hws[PLL_A]))
return PTR_ERR(hws[PLL_A]);
hws[PLL_E] = sp_pll_register(dev, "plle", &pd_ext, PLLE_CTL,
6, 2, 50000000, 0, 0, 0);
if (IS_ERR(hws[PLL_E]))
return PTR_ERR(hws[PLL_E]);
pd_e.hw = hws[PLL_E];
hws[PLL_E_2P5] = sp_pll_register(dev, "plle_2p5", &pd_e, PLLE_CTL,
13, -1, 2500000, 0, 0, 0);
if (IS_ERR(hws[PLL_E_2P5]))
return PTR_ERR(hws[PLL_E_2P5]);
hws[PLL_E_25] = sp_pll_register(dev, "plle_25", &pd_e, PLLE_CTL,
12, -1, 25000000, 0, 0, 0);
if (IS_ERR(hws[PLL_E_25]))
return PTR_ERR(hws[PLL_E_25]);
hws[PLL_E_112P5] = sp_pll_register(dev, "plle_112p5", &pd_e, PLLE_CTL,
11, -1, 112500000, 0, 0, 0);
if (IS_ERR(hws[PLL_E_112P5]))
return PTR_ERR(hws[PLL_E_112P5]);
hws[PLL_F] = sp_pll_register(dev, "pllf", &pd_ext, PLLF_CTL,
0, 10, 13500000, 1, 4, 0);
if (IS_ERR(hws[PLL_F]))
return PTR_ERR(hws[PLL_F]);
hws[PLL_TV] = sp_pll_register(dev, "plltv", &pd_ext, PLLTV_CTL,
0, 15, 27000000, 0, DIV_TV, 0);
if (IS_ERR(hws[PLL_TV]))
return PTR_ERR(hws[PLL_TV]);
hws[PLL_TV_A] = devm_clk_hw_register_divider(dev, "plltv_a", "plltv", 0,
PLLTV_CTL + 4, 5, 1,
CLK_DIVIDER_POWER_OF_TWO,
&to_sp_pll(hws[PLL_TV])->lock);
if (IS_ERR(hws[PLL_TV_A]))
return PTR_ERR(hws[PLL_TV_A]);
/* system clock, should not be disabled */
hws[PLL_SYS] = sp_pll_register(dev, "pllsys", &pd_ext, sys_base,
10, 9, 13500000, 0, 4, CLK_IS_CRITICAL);
if (IS_ERR(hws[PLL_SYS]))
return PTR_ERR(hws[PLL_SYS]);
pd_sys.hw = hws[PLL_SYS];
/* gates */
for (i = 0; i < ARRAY_SIZE(sp_clk_gates); i++) {
char name[10];
u32 j = sp_clk_gates[i].reg;
struct clk_parent_data *pd = sp_clk_gates[i].ext_parent ? &pd_ext : &pd_sys;
sprintf(name, "%02d_0x%02x", i, j);
hws[i] = devm_clk_hw_register_gate_parent_data(dev, name, pd, 0,
clk_base + (j >> 4) * 4,
j & 0x0f,
CLK_GATE_HIWORD_MASK,
NULL);
if (IS_ERR(hws[i]))
return PTR_ERR(hws[i]);
}
clk_data->num = CLK_MAX;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
}
static const struct of_device_id sp7021_clk_dt_ids[] = {
{ .compatible = "sunplus,sp7021-clkc" },
{ }
};
MODULE_DEVICE_TABLE(of, sp7021_clk_dt_ids);
static struct platform_driver sp7021_clk_driver = {
.probe = sp7021_clk_probe,
.driver = {
.name = "sp7021-clk",
.of_match_table = sp7021_clk_dt_ids,
},
};
module_platform_driver(sp7021_clk_driver);
MODULE_AUTHOR("Sunplus Technology");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Clock driver for Sunplus SP7021 SoC");

View File

@ -667,7 +667,6 @@ struct stm32_fractional_divider {
void __iomem *mreg;
u8 mshift;
u8 mwidth;
u32 mmask;
void __iomem *nreg;
u8 nshift;

View File

@ -2434,15 +2434,13 @@ static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev)
return ret;
}
static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev)
static void stm32mp1_rcc_clocks_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *child, *np = dev_of_node(dev);
for_each_available_child_of_node(np, child)
of_clk_del_provider(child);
return 0;
}
static struct platform_driver stm32mp1_rcc_clocks_driver = {
@ -2451,7 +2449,7 @@ static struct platform_driver stm32mp1_rcc_clocks_driver = {
.of_match_table = stm32mp1_match_data,
},
.probe = stm32mp1_rcc_clocks_probe,
.remove = stm32mp1_rcc_clocks_remove,
.remove_new = stm32mp1_rcc_clocks_remove,
};
static int __init stm32mp1_clocks_init(void)

View File

@ -1406,6 +1406,8 @@ static int __init clk_disable_unused(void)
return 0;
}
pr_info("clk: Disabling unused clocks\n");
clk_prepare_lock();
hlist_for_each_entry(core, &clk_root_list, child_node)
@ -3194,7 +3196,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
static int clk_summary_show(struct seq_file *s, void *data)
{
struct clk_core *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
struct hlist_head **lists = s->private;
seq_puts(s, " enable prepare protect duty hardware\n");
seq_puts(s, " clock count count count rate accuracy phase cycle enable\n");
@ -3253,7 +3255,7 @@ static int clk_dump_show(struct seq_file *s, void *data)
{
struct clk_core *c;
bool first_node = true;
struct hlist_head **lists = (struct hlist_head **)s->private;
struct hlist_head **lists = s->private;
seq_putc(s, '{');
clk_prepare_lock();
@ -4880,8 +4882,8 @@ static struct device_node *get_clk_provider_node(struct device *dev)
np = dev->of_node;
parent_np = dev->parent ? dev->parent->of_node : NULL;
if (!of_find_property(np, "#clock-cells", NULL))
if (of_find_property(parent_np, "#clock-cells", NULL))
if (!of_property_present(np, "#clock-cells"))
if (of_property_present(parent_np, "#clock-cells"))
np = parent_np;
return np;

View File

@ -162,13 +162,12 @@ static int hi3519_clk_probe(struct platform_device *pdev)
return 0;
}
static int hi3519_clk_remove(struct platform_device *pdev)
static void hi3519_clk_remove(struct platform_device *pdev)
{
struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
hisi_reset_exit(crg->rstc);
hi3519_clk_unregister(pdev);
return 0;
}
@ -180,7 +179,7 @@ MODULE_DEVICE_TABLE(of, hi3519_clk_match_table);
static struct platform_driver hi3519_clk_driver = {
.probe = hi3519_clk_probe,
.remove = hi3519_clk_remove,
.remove_new = hi3519_clk_remove,
.driver = {
.name = "hi3519-clk",
.of_match_table = hi3519_clk_match_table,

View File

@ -810,18 +810,17 @@ static int hi3559av100_crg_probe(struct platform_device *pdev)
return 0;
}
static int hi3559av100_crg_remove(struct platform_device *pdev)
static void hi3559av100_crg_remove(struct platform_device *pdev)
{
struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
hisi_reset_exit(crg->rstc);
crg->funcs->unregister_clks(pdev);
return 0;
}
static struct platform_driver hi3559av100_crg_driver = {
.probe = hi3559av100_crg_probe,
.remove = hi3559av100_crg_remove,
.remove_new = hi3559av100_crg_remove,
.driver = {
.name = "hi3559av100-clock",
.of_match_table = hi3559av100_crg_match_table,

View File

@ -284,18 +284,17 @@ static int hi3516cv300_crg_probe(struct platform_device *pdev)
return 0;
}
static int hi3516cv300_crg_remove(struct platform_device *pdev)
static void hi3516cv300_crg_remove(struct platform_device *pdev)
{
struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
hisi_reset_exit(crg->rstc);
crg->funcs->unregister_clks(pdev);
return 0;
}
static struct platform_driver hi3516cv300_crg_driver = {
.probe = hi3516cv300_crg_probe,
.remove = hi3516cv300_crg_remove,
.remove_new = hi3516cv300_crg_remove,
.driver = {
.name = "hi3516cv300-crg",
.of_match_table = hi3516cv300_crg_match_table,

View File

@ -367,18 +367,17 @@ static int hi3798cv200_crg_probe(struct platform_device *pdev)
return 0;
}
static int hi3798cv200_crg_remove(struct platform_device *pdev)
static void hi3798cv200_crg_remove(struct platform_device *pdev)
{
struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
hisi_reset_exit(crg->rstc);
crg->funcs->unregister_clks(pdev);
return 0;
}
static struct platform_driver hi3798cv200_crg_driver = {
.probe = hi3798cv200_crg_probe,
.remove = hi3798cv200_crg_remove,
.remove_new = hi3798cv200_crg_remove,
.driver = {
.name = "hi3798cv200-crg",
.of_match_table = hi3798cv200_crg_match_table,

View File

@ -27,7 +27,7 @@ obj-$(CONFIG_MXC_CLK) += mxc-clk.o
obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-imx8mp-audiomix.o
obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
obj-$(CONFIG_CLK_IMX93) += clk-imx93.o

View File

@ -19,10 +19,8 @@
#define PCG_CGC_SHIFT 30
#define PCG_FRAC_SHIFT 3
#define PCG_FRAC_WIDTH 1
#define PCG_FRAC_MASK BIT(3)
#define PCG_PCD_SHIFT 0
#define PCG_PCD_WIDTH 3
#define PCG_PCD_MASK 0x7
#define SW_RST BIT(28)
@ -102,10 +100,8 @@ static struct clk_hw *imx_ulp_clk_hw_composite(const char *name,
fd->reg = reg;
fd->mshift = PCG_FRAC_SHIFT;
fd->mwidth = PCG_FRAC_WIDTH;
fd->mmask = PCG_FRAC_MASK;
fd->nshift = PCG_PCD_SHIFT;
fd->nwidth = PCG_PCD_WIDTH;
fd->nmask = PCG_PCD_MASK;
fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
if (has_swrst)
fd->lock = &imx_ccm_lock;

View File

@ -119,10 +119,17 @@ static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
return ret;
}
static int imx8m_clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return clk_divider_ops.determine_rate(hw, req);
}
static const struct clk_ops imx8m_clk_composite_divider_ops = {
.recalc_rate = imx8m_clk_composite_divider_recalc_rate,
.round_rate = imx8m_clk_composite_divider_round_rate,
.set_rate = imx8m_clk_composite_divider_set_rate,
.determine_rate = imx8m_clk_divider_determine_rate,
};
static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)

View File

@ -222,7 +222,7 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
mux_hw, &clk_mux_ro_ops, div_hw,
&clk_divider_ro_ops, NULL, NULL, flags);
} else {
} else if (!mcore_booted) {
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
goto fail;
@ -238,6 +238,12 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
&imx93_clk_composite_divider_ops, gate_hw,
&imx93_clk_composite_gate_ops,
flags | CLK_SET_RATE_NO_REPARENT);
} else {
hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
mux_hw, &imx93_clk_composite_mux_ops, div_hw,
&imx93_clk_composite_divider_ops, NULL,
&imx93_clk_composite_gate_ops,
flags | CLK_SET_RATE_NO_REPARENT);
}
if (IS_ERR(hw))

View File

@ -15,6 +15,7 @@
#include "clk.h"
#define PLL_CTRL 0x0
#define HW_CTRL_SEL BIT(16)
#define CLKMUX_BYPASS BIT(2)
#define CLKMUX_EN BIT(1)
#define POWERUP_MASK BIT(0)
@ -52,26 +53,40 @@
.odiv = (_odiv), \
}
#define PLL_FRACN_GP_INTEGER(_rate, _mfi, _rdiv, _odiv) \
{ \
.rate = (_rate), \
.mfi = (_mfi), \
.mfn = 0, \
.mfd = 0, \
.rdiv = (_rdiv), \
.odiv = (_odiv), \
}
struct clk_fracn_gppll {
struct clk_hw hw;
void __iomem *base;
const struct imx_fracn_gppll_rate_table *rate_table;
int rate_count;
u32 flags;
};
/*
* Fvco = Fref * (MFI + MFN / MFD)
* Fout = Fvco / (rdiv * odiv)
* Fvco = (Fref / rdiv) * (MFI + MFN / MFD)
* Fout = Fvco / odiv
* The (Fref / rdiv) should be in range 20MHz to 40MHz
* The Fvco should be in range 2.5Ghz to 5Ghz
*/
static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
PLL_FRACN_GP(650000000U, 81, 0, 1, 0, 3),
PLL_FRACN_GP(650000000U, 162, 50, 100, 0, 6),
PLL_FRACN_GP(594000000U, 198, 0, 1, 0, 8),
PLL_FRACN_GP(560000000U, 70, 0, 1, 0, 3),
PLL_FRACN_GP(498000000U, 83, 0, 1, 0, 4),
PLL_FRACN_GP(560000000U, 140, 0, 1, 0, 6),
PLL_FRACN_GP(498000000U, 166, 0, 1, 0, 8),
PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6),
PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
PLL_FRACN_GP(400000000U, 50, 0, 1, 0, 3),
PLL_FRACN_GP(393216000U, 81, 92, 100, 0, 5)
PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12),
PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10),
PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12)
};
struct imx_fracn_gppll_clk imx_fracn_gppll = {
@ -80,6 +95,24 @@ struct imx_fracn_gppll_clk imx_fracn_gppll = {
};
EXPORT_SYMBOL_GPL(imx_fracn_gppll);
/*
* Fvco = (Fref / rdiv) * MFI
* Fout = Fvco / odiv
* The (Fref / rdiv) should be in range 20MHz to 40MHz
* The Fvco should be in range 2.5Ghz to 5Ghz
*/
static const struct imx_fracn_gppll_rate_table int_tbl[] = {
PLL_FRACN_GP_INTEGER(1700000000U, 141, 1, 2),
PLL_FRACN_GP_INTEGER(1400000000U, 175, 1, 3),
PLL_FRACN_GP_INTEGER(900000000U, 150, 1, 4),
};
struct imx_fracn_gppll_clk imx_fracn_gppll_integer = {
.rate_table = int_tbl,
.rate_count = ARRAY_SIZE(int_tbl),
};
EXPORT_SYMBOL_GPL(imx_fracn_gppll_integer);
static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
{
return container_of(hw, struct clk_fracn_gppll, hw);
@ -166,9 +199,15 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned lon
break;
}
/* Fvco = Fref * (MFI + MFN / MFD) */
fvco = fvco * mfi * mfd + fvco * mfn;
do_div(fvco, mfd * rdiv * odiv);
if (pll->flags & CLK_FRACN_GPPLL_INTEGER) {
/* Fvco = (Fref / rdiv) * MFI */
fvco = fvco * mfi;
do_div(fvco, rdiv * odiv);
} else {
/* Fvco = (Fref / rdiv) * (MFI + MFN / MFD) */
fvco = fvco * mfi * mfd + fvco * mfn;
do_div(fvco, mfd * rdiv * odiv);
}
return (unsigned long)fvco;
}
@ -191,6 +230,11 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
rate = imx_get_pll_settings(pll, drate);
/* Hardware control select disable. PLL is control by register */
tmp = readl_relaxed(pll->base + PLL_CTRL);
tmp &= ~HW_CTRL_SEL;
writel_relaxed(tmp, pll->base + PLL_CTRL);
/* Disable output */
tmp = readl_relaxed(pll->base + PLL_CTRL);
tmp &= ~CLKMUX_EN;
@ -207,8 +251,10 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
FIELD_PREP(PLL_MFI_MASK, rate->mfi);
writel_relaxed(pll_div, pll->base + PLL_DIV);
writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
if (pll->flags & CLK_FRACN_GPPLL_FRACN) {
writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
}
/* Wait for 5us according to fracn mode pll doc */
udelay(5);
@ -292,8 +338,10 @@ static const struct clk_ops clk_fracn_gppll_ops = {
.set_rate = clk_fracn_gppll_set_rate,
};
struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
const struct imx_fracn_gppll_clk *pll_clk)
static struct clk_hw *_imx_clk_fracn_gppll(const char *name, const char *parent_name,
void __iomem *base,
const struct imx_fracn_gppll_clk *pll_clk,
u32 pll_flags)
{
struct clk_fracn_gppll *pll;
struct clk_hw *hw;
@ -314,6 +362,7 @@ struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, vo
pll->hw.init = &init;
pll->rate_table = pll_clk->rate_table;
pll->rate_count = pll_clk->rate_count;
pll->flags = pll_flags;
hw = &pll->hw;
@ -326,4 +375,18 @@ struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, vo
return hw;
}
struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
const struct imx_fracn_gppll_clk *pll_clk)
{
return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_FRACN);
}
EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);
struct clk_hw *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
void __iomem *base,
const struct imx_fracn_gppll_clk *pll_clk)
{
return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_INTEGER);
}
EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll_integer);

View File

@ -48,7 +48,8 @@ static u8 imx_clk_gpr_mux_get_parent(struct clk_hw *hw)
return ret;
get_parent_err:
pr_err("failed to get parent (%pe)\n", ERR_PTR(ret));
pr_err("%s: failed to get parent (%pe)\n",
clk_hw_get_name(hw), ERR_PTR(ret));
/* return some realistic non negative value. Potentially we could
* give index to some dummy error parent.

View File

@ -468,7 +468,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
hws[IMX8MM_CLK_PCIE1_PHY] = imx8m_clk_hw_composite("pcie1_phy", imx8mm_pcie1_phy_sels, base + 0xa380);
hws[IMX8MM_CLK_PCIE1_AUX] = imx8m_clk_hw_composite("pcie1_aux", imx8mm_pcie1_aux_sels, base + 0xa400);
hws[IMX8MM_CLK_DC_PIXEL] = imx8m_clk_hw_composite("dc_pixel", imx8mm_dc_pixel_sels, base + 0xa480);
hws[IMX8MM_CLK_LCDIF_PIXEL] = imx8m_clk_hw_composite("lcdif_pixel", imx8mm_lcdif_pixel_sels, base + 0xa500);
hws[IMX8MM_CLK_LCDIF_PIXEL] = imx8m_clk_hw_composite_flags("lcdif_pixel", imx8mm_lcdif_pixel_sels, base + 0xa500, CLK_SET_RATE_PARENT);
hws[IMX8MM_CLK_SAI1] = imx8m_clk_hw_composite("sai1", imx8mm_sai1_sels, base + 0xa580);
hws[IMX8MM_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mm_sai2_sels, base + 0xa600);
hws[IMX8MM_CLK_SAI3] = imx8m_clk_hw_composite("sai3", imx8mm_sai3_sels, base + 0xa680);

View File

@ -470,7 +470,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000);
hws[IMX8MN_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mn_dram_apb_sels, base + 0xa080);
hws[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_hw_composite("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500);
hws[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_hw_composite_flags("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500, CLK_SET_RATE_PARENT);
hws[IMX8MN_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mn_sai2_sels, base + 0xa600);
hws[IMX8MN_CLK_SAI3] = imx8m_clk_hw_composite("sai3", imx8mn_sai3_sels, base + 0xa680);
hws[IMX8MN_CLK_SAI5] = imx8m_clk_hw_composite("sai5", imx8mn_sai5_sels, base + 0xa780);

View File

@ -0,0 +1,277 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for i.MX8M Plus Audio BLK_CTRL
*
* Copyright (C) 2022 Marek Vasut <marex@denx.de>
*/
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/imx8mp-clock.h>
#include "clk.h"
#define CLKEN0 0x000
#define CLKEN1 0x004
#define SAI_MCLK_SEL(n) (0x300 + 4 * (n)) /* n in 0..5 */
#define PDM_SEL 0x318
#define SAI_PLL_GNRL_CTL 0x400
#define SAIn_MCLK1_PARENT(n) \
static const struct clk_parent_data \
clk_imx8mp_audiomix_sai##n##_mclk1_parents[] = { \
{ \
.fw_name = "sai"__stringify(n), \
.name = "sai"__stringify(n) \
}, { \
.fw_name = "sai"__stringify(n)"_mclk", \
.name = "sai"__stringify(n)"_mclk" \
}, \
}
SAIn_MCLK1_PARENT(1);
SAIn_MCLK1_PARENT(2);
SAIn_MCLK1_PARENT(3);
SAIn_MCLK1_PARENT(5);
SAIn_MCLK1_PARENT(6);
SAIn_MCLK1_PARENT(7);
static const struct clk_parent_data clk_imx8mp_audiomix_sai_mclk2_parents[] = {
{ .fw_name = "sai1", .name = "sai1" },
{ .fw_name = "sai2", .name = "sai2" },
{ .fw_name = "sai3", .name = "sai3" },
{ .name = "dummy" },
{ .fw_name = "sai5", .name = "sai5" },
{ .fw_name = "sai6", .name = "sai6" },
{ .fw_name = "sai7", .name = "sai7" },
{ .fw_name = "sai1_mclk", .name = "sai1_mclk" },
{ .fw_name = "sai2_mclk", .name = "sai2_mclk" },
{ .fw_name = "sai3_mclk", .name = "sai3_mclk" },
{ .name = "dummy" },
{ .fw_name = "sai5_mclk", .name = "sai5_mclk" },
{ .fw_name = "sai6_mclk", .name = "sai6_mclk" },
{ .fw_name = "sai7_mclk", .name = "sai7_mclk" },
{ .fw_name = "spdif_extclk", .name = "spdif_extclk" },
{ .name = "dummy" },
};
static const struct clk_parent_data clk_imx8mp_audiomix_pdm_parents[] = {
{ .fw_name = "pdm", .name = "pdm" },
{ .name = "sai_pll_out_div2" },
{ .fw_name = "sai1_mclk", .name = "sai1_mclk" },
{ .name = "dummy" },
};
static const struct clk_parent_data clk_imx8mp_audiomix_pll_parents[] = {
{ .fw_name = "osc_24m", .name = "osc_24m" },
{ .name = "dummy" },
{ .name = "dummy" },
{ .name = "dummy" },
};
static const struct clk_parent_data clk_imx8mp_audiomix_pll_bypass_sels[] = {
{ .fw_name = "sai_pll", .name = "sai_pll" },
{ .fw_name = "sai_pll_ref_sel", .name = "sai_pll_ref_sel" },
};
#define CLK_GATE(gname, cname) \
{ \
gname"_cg", \
IMX8MP_CLK_AUDIOMIX_##cname, \
{ .fw_name = "ahb", .name = "ahb" }, NULL, 1, \
CLKEN0 + 4 * !!(IMX8MP_CLK_AUDIOMIX_##cname / 32), \
1, IMX8MP_CLK_AUDIOMIX_##cname % 32 \
}
#define CLK_SAIn(n) \
{ \
"sai"__stringify(n)"_mclk1_sel", \
IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK1_SEL, {}, \
clk_imx8mp_audiomix_sai##n##_mclk1_parents, \
ARRAY_SIZE(clk_imx8mp_audiomix_sai##n##_mclk1_parents), \
SAI_MCLK_SEL(n), 1, 0 \
}, { \
"sai"__stringify(n)"_mclk2_sel", \
IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK2_SEL, {}, \
clk_imx8mp_audiomix_sai_mclk2_parents, \
ARRAY_SIZE(clk_imx8mp_audiomix_sai_mclk2_parents), \
SAI_MCLK_SEL(n), 4, 1 \
}, { \
"sai"__stringify(n)"_ipg_cg", \
IMX8MP_CLK_AUDIOMIX_SAI##n##_IPG, \
{ .fw_name = "ahb", .name = "ahb" }, NULL, 1, \
CLKEN0, 1, IMX8MP_CLK_AUDIOMIX_SAI##n##_IPG \
}, { \
"sai"__stringify(n)"_mclk1_cg", \
IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK1, \
{ \
.fw_name = "sai"__stringify(n)"_mclk1_sel", \
.name = "sai"__stringify(n)"_mclk1_sel" \
}, NULL, 1, \
CLKEN0, 1, IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK1 \
}, { \
"sai"__stringify(n)"_mclk2_cg", \
IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK2, \
{ \
.fw_name = "sai"__stringify(n)"_mclk2_sel", \
.name = "sai"__stringify(n)"_mclk2_sel" \
}, NULL, 1, \
CLKEN0, 1, IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK2 \
}, { \
"sai"__stringify(n)"_mclk3_cg", \
IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK3, \
{ \
.fw_name = "sai_pll_out_div2", \
.name = "sai_pll_out_div2" \
}, NULL, 1, \
CLKEN0, 1, IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK3 \
}
#define CLK_PDM \
{ \
"pdm_sel", IMX8MP_CLK_AUDIOMIX_PDM_SEL, {}, \
clk_imx8mp_audiomix_pdm_parents, \
ARRAY_SIZE(clk_imx8mp_audiomix_pdm_parents), \
PDM_SEL, 2, 0 \
}
struct clk_imx8mp_audiomix_sel {
const char *name;
int clkid;
const struct clk_parent_data parent; /* For gate */
const struct clk_parent_data *parents; /* For mux */
int num_parents;
u16 reg;
u8 width;
u8 shift;
};
static struct clk_imx8mp_audiomix_sel sels[] = {
CLK_GATE("asrc", ASRC_IPG),
CLK_GATE("pdm", PDM_IPG),
CLK_GATE("earc", EARC_IPG),
CLK_GATE("ocrama", OCRAMA_IPG),
CLK_GATE("aud2htx", AUD2HTX_IPG),
CLK_GATE("earc_phy", EARC_PHY),
CLK_GATE("sdma2", SDMA2_ROOT),
CLK_GATE("sdma3", SDMA3_ROOT),
CLK_GATE("spba2", SPBA2_ROOT),
CLK_GATE("dsp", DSP_ROOT),
CLK_GATE("dspdbg", DSPDBG_ROOT),
CLK_GATE("edma", EDMA_ROOT),
CLK_GATE("audpll", AUDPLL_ROOT),
CLK_GATE("mu2", MU2_ROOT),
CLK_GATE("mu3", MU3_ROOT),
CLK_PDM,
CLK_SAIn(1),
CLK_SAIn(2),
CLK_SAIn(3),
CLK_SAIn(5),
CLK_SAIn(6),
CLK_SAIn(7)
};
static int clk_imx8mp_audiomix_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *priv;
struct device *dev = &pdev->dev;
void __iomem *base;
struct clk_hw *hw;
int i;
priv = devm_kzalloc(dev,
struct_size(priv, hws, IMX8MP_CLK_AUDIOMIX_END),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->num = IMX8MP_CLK_AUDIOMIX_END;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
for (i = 0; i < ARRAY_SIZE(sels); i++) {
if (sels[i].num_parents == 1) {
hw = devm_clk_hw_register_gate_parent_data(dev,
sels[i].name, &sels[i].parent, 0,
base + sels[i].reg, sels[i].shift, 0, NULL);
} else {
hw = devm_clk_hw_register_mux_parent_data_table(dev,
sels[i].name, sels[i].parents,
sels[i].num_parents, 0,
base + sels[i].reg,
sels[i].shift, sels[i].width,
0, NULL, NULL);
}
if (IS_ERR(hw))
return PTR_ERR(hw);
priv->hws[sels[i].clkid] = hw;
}
/* SAI PLL */
hw = devm_clk_hw_register_mux_parent_data_table(dev,
"sai_pll_ref_sel", clk_imx8mp_audiomix_pll_parents,
ARRAY_SIZE(clk_imx8mp_audiomix_pll_parents),
CLK_SET_RATE_NO_REPARENT, base + SAI_PLL_GNRL_CTL,
0, 2, 0, NULL, NULL);
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_REF_SEL] = hw;
hw = imx_dev_clk_hw_pll14xx(dev, "sai_pll", "sai_pll_ref_sel",
base + 0x400, &imx_1443x_pll);
if (IS_ERR(hw))
return PTR_ERR(hw);
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL] = hw;
hw = devm_clk_hw_register_mux_parent_data_table(dev,
"sai_pll_bypass", clk_imx8mp_audiomix_pll_bypass_sels,
ARRAY_SIZE(clk_imx8mp_audiomix_pll_bypass_sels),
CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
base + SAI_PLL_GNRL_CTL, 16, 1, 0, NULL, NULL);
if (IS_ERR(hw))
return PTR_ERR(hw);
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_BYPASS] = hw;
hw = devm_clk_hw_register_gate(dev, "sai_pll_out", "sai_pll_bypass",
0, base + SAI_PLL_GNRL_CTL, 13,
0, NULL);
if (IS_ERR(hw))
return PTR_ERR(hw);
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_OUT] = hw;
hw = devm_clk_hw_register_fixed_factor(dev, "sai_pll_out_div2",
"sai_pll_out", 0, 1, 2);
if (IS_ERR(hw))
return PTR_ERR(hw);
return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
priv);
}
static const struct of_device_id clk_imx8mp_audiomix_of_match[] = {
{ .compatible = "fsl,imx8mp-audio-blk-ctrl" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, clk_imx8mp_audiomix_of_match);
static struct platform_driver clk_imx8mp_audiomix_driver = {
.probe = clk_imx8mp_audiomix_probe,
.driver = {
.name = "imx8mp-audio-blk-ctrl",
.of_match_table = clk_imx8mp_audiomix_of_match,
},
};
module_platform_driver(clk_imx8mp_audiomix_driver);
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_DESCRIPTION("Freescale i.MX8MP Audio Block Controller driver");
MODULE_LICENSE("GPL");

View File

@ -538,7 +538,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
@ -554,7 +554,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
hws[IMX8MP_CLK_MEDIA_DISP2_PIX] = imx8m_clk_hw_composite("media_disp2_pix", imx8mp_media_disp_pix_sels, ccm_base + 0x9300);
hws[IMX8MP_CLK_MEDIA_DISP2_PIX] = imx8m_clk_hw_composite_bus("media_disp2_pix", imx8mp_media_disp_pix_sels, ccm_base + 0x9300);
hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1);
@ -696,6 +696,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp1_pix_root_clk", "media_disp1_pix", ccm_base + 0x45d0, 0, &share_count_media);
hws[IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp2_pix_root_clk", "media_disp2_pix", ccm_base + 0x45d0, 0, &share_count_media);
hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT] = imx_clk_hw_gate2_shared2("media_mipi_phy1_ref_root", "media_mipi_phy1_ref", ccm_base + 0x45d0, 0, &share_count_media);
hws[IMX8MP_CLK_MEDIA_LDB_ROOT] = imx_clk_hw_gate2_shared2("media_ldb_root_clk", "media_ldb", ccm_base + 0x45d0, 0, &share_count_media);
hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp", ccm_base + 0x45d0, 0, &share_count_media);
hws[IMX8MP_CLK_USDHC3_ROOT] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3", ccm_base + 0x45e0, 0);

View File

@ -198,10 +198,10 @@ static int imx8ulp_clk_cgc1_init(struct platform_device *pdev)
clks[IMX8ULP_CLK_NIC_SEL] = imx_clk_hw_mux2("nic_sel", base + 0x34, 28, 2, nic_sels, ARRAY_SIZE(nic_sels));
clks[IMX8ULP_CLK_NIC_AD_DIVPLAT] = imx_clk_hw_divider_flags("nic_ad_divplat", "nic_sel", base + 0x34, 21, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_NIC_PER_DIVPLAT] = imx_clk_hw_divider_flags("nic_per_divplat", "nic_ad_divplat", base + 0x34, 14, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_XBAR_AD_DIVPLAT] = imx_clk_hw_divider_flags("xbar_ad_divplat", "nic_ad_divplat", base + 0x38, 14, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_XBAR_DIVBUS] = imx_clk_hw_divider_flags("xbar_divbus", "nic_ad_divplat", base + 0x38, 7, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_XBAR_AD_SLOW] = imx_clk_hw_divider_flags("xbar_ad_slow", "nic_ad_divplat", base + 0x38, 0, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_NIC_PER_DIVPLAT] = imx_clk_hw_divider_flags("nic_per_divplat", "nic_ad_divplat", base + 0x34, 14, 6, CLK_SET_RATE_PARENT);
clks[IMX8ULP_CLK_XBAR_AD_DIVPLAT] = imx_clk_hw_divider_flags("xbar_ad_divplat", "nic_ad_divplat", base + 0x38, 14, 6, CLK_SET_RATE_PARENT);
clks[IMX8ULP_CLK_XBAR_DIVBUS] = imx_clk_hw_divider_flags("xbar_divbus", "xbar_ad_divplat", base + 0x38, 7, 6, CLK_SET_RATE_PARENT);
clks[IMX8ULP_CLK_XBAR_AD_SLOW] = imx_clk_hw_divider_flags("xbar_ad_slow", "xbar_divbus", base + 0x38, 0, 6, CLK_SET_RATE_PARENT);
clks[IMX8ULP_CLK_SOSC_DIV1_GATE] = imx_clk_hw_gate_dis("sosc_div1_gate", "sosc", base + 0x108, 7);
clks[IMX8ULP_CLK_SOSC_DIV2_GATE] = imx_clk_hw_gate_dis("sosc_div2_gate", "sosc", base + 0x108, 15);
@ -255,9 +255,9 @@ static int imx8ulp_clk_cgc2_init(struct platform_device *pdev)
clks[IMX8ULP_CLK_HIFI_DIVCORE] = imx_clk_hw_divider("hifi_core_div", "hifi_sel", base + 0x14, 21, 6);
clks[IMX8ULP_CLK_HIFI_DIVPLAT] = imx_clk_hw_divider("hifi_plat_div", "hifi_core_div", base + 0x14, 14, 6);
clks[IMX8ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x40, 28, 3, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_PARENT_GATE);
clks[IMX8ULP_CLK_DDR_DIV] = imx_clk_hw_divider_flags("ddr_div", "ddr_sel", base + 0x40, 21, 6, CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_LPAV_AXI_SEL] = imx_clk_hw_mux("lpav_sel", base + 0x3c, 28, 2, lpav_sels, ARRAY_SIZE(lpav_sels));
clks[IMX8ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x40, 28, 3, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_GET_RATE_NOCACHE);
clks[IMX8ULP_CLK_DDR_DIV] = imx_clk_hw_divider_flags("ddr_div", "ddr_sel", base + 0x40, 21, 6, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
clks[IMX8ULP_CLK_LPAV_AXI_SEL] = imx_clk_hw_mux2("lpav_sel", base + 0x3c, 28, 2, lpav_sels, ARRAY_SIZE(lpav_sels));
clks[IMX8ULP_CLK_LPAV_AXI_DIV] = imx_clk_hw_divider_flags("lpav_axi_div", "lpav_sel", base + 0x3c, 21, 6, CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_LPAV_AHB_DIV] = imx_clk_hw_divider_flags("lpav_ahb_div", "lpav_axi_div", base + 0x3c, 14, 6, CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_LPAV_BUS_DIV] = imx_clk_hw_divider_flags("lpav_bus_div", "lpav_axi_div", base + 0x3c, 7, 6, CLK_IS_CRITICAL);
@ -275,14 +275,14 @@ static int imx8ulp_clk_cgc2_init(struct platform_device *pdev)
clks[IMX8ULP_CLK_PLL4_PFD2_DIV2_GATE] = imx_clk_hw_gate_dis("pll4_pfd2_div2_gate", "pll4_pfd2", base + 0x60c, 15);
clks[IMX8ULP_CLK_PLL4_PFD3_DIV1_GATE] = imx_clk_hw_gate_dis("pll4_pfd3_div1_gate", "pll4_pfd3", base + 0x60c, 23);
clks[IMX8ULP_CLK_PLL4_PFD3_DIV2_GATE] = imx_clk_hw_gate_dis("pll4_pfd3_div2_gate", "pll4_pfd3", base + 0x60c, 31);
clks[IMX8ULP_CLK_PLL4_PFD0_DIV1] = imx_clk_hw_divider("pll4_pfd0_div1", "pll4_pfd0_div1_gate", base + 0x608, 0, 6);
clks[IMX8ULP_CLK_PLL4_PFD0_DIV2] = imx_clk_hw_divider("pll4_pfd0_div2", "pll4_pfd0_div2_gate", base + 0x608, 8, 6);
clks[IMX8ULP_CLK_PLL4_PFD1_DIV1] = imx_clk_hw_divider("pll4_pfd1_div1", "pll4_pfd1_div1_gate", base + 0x608, 16, 6);
clks[IMX8ULP_CLK_PLL4_PFD1_DIV2] = imx_clk_hw_divider("pll4_pfd1_div2", "pll4_pfd1_div2_gate", base + 0x608, 24, 6);
clks[IMX8ULP_CLK_PLL4_PFD2_DIV1] = imx_clk_hw_divider("pll4_pfd2_div1", "pll4_pfd2_div1_gate", base + 0x60c, 0, 6);
clks[IMX8ULP_CLK_PLL4_PFD2_DIV2] = imx_clk_hw_divider("pll4_pfd2_div2", "pll4_pfd2_div2_gate", base + 0x60c, 8, 6);
clks[IMX8ULP_CLK_PLL4_PFD3_DIV1] = imx_clk_hw_divider("pll4_pfd3_div1", "pll4_pfd3_div1_gate", base + 0x60c, 16, 6);
clks[IMX8ULP_CLK_PLL4_PFD3_DIV2] = imx_clk_hw_divider("pll4_pfd3_div2", "pll4_pfd3_div2_gate", base + 0x60c, 24, 6);
clks[IMX8ULP_CLK_PLL4_PFD0_DIV1] = imx_clk_hw_divider_closest("pll4_pfd0_div1", "pll4_pfd0_div1_gate", base + 0x608, 0, 6);
clks[IMX8ULP_CLK_PLL4_PFD0_DIV2] = imx_clk_hw_divider_closest("pll4_pfd0_div2", "pll4_pfd0_div2_gate", base + 0x608, 8, 6);
clks[IMX8ULP_CLK_PLL4_PFD1_DIV1] = imx_clk_hw_divider_closest("pll4_pfd1_div1", "pll4_pfd1_div1_gate", base + 0x608, 16, 6);
clks[IMX8ULP_CLK_PLL4_PFD1_DIV2] = imx_clk_hw_divider_closest("pll4_pfd1_div2", "pll4_pfd1_div2_gate", base + 0x608, 24, 6);
clks[IMX8ULP_CLK_PLL4_PFD2_DIV1] = imx_clk_hw_divider_closest("pll4_pfd2_div1", "pll4_pfd2_div1_gate", base + 0x60c, 0, 6);
clks[IMX8ULP_CLK_PLL4_PFD2_DIV2] = imx_clk_hw_divider_closest("pll4_pfd2_div2", "pll4_pfd2_div2_gate", base + 0x60c, 8, 6);
clks[IMX8ULP_CLK_PLL4_PFD3_DIV1] = imx_clk_hw_divider_closest("pll4_pfd3_div1", "pll4_pfd3_div1_gate", base + 0x60c, 16, 6);
clks[IMX8ULP_CLK_PLL4_PFD3_DIV2] = imx_clk_hw_divider_closest("pll4_pfd3_div2", "pll4_pfd3_div2_gate", base + 0x60c, 24, 6);
clks[IMX8ULP_CLK_CGC2_SOSC_DIV1_GATE] = imx_clk_hw_gate_dis("cgc2_sosc_div1_gate", "sosc", base + 0x108, 7);
clks[IMX8ULP_CLK_CGC2_SOSC_DIV2_GATE] = imx_clk_hw_gate_dis("cgc2_sosc_div2_gate", "sosc", base + 0x108, 15);
@ -333,7 +333,6 @@ static int imx8ulp_clk_pcc3_init(struct platform_device *pdev)
clks[IMX8ULP_CLK_WDOG4] = imx8ulp_clk_hw_composite("wdog4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xac, 1);
clks[IMX8ULP_CLK_LPIT1] = imx8ulp_clk_hw_composite("lpit1", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xc8, 1);
clks[IMX8ULP_CLK_TPM4] = imx8ulp_clk_hw_composite("tpm4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xcc, 1);
clks[IMX8ULP_CLK_TPM5] = imx8ulp_clk_hw_composite("tpm5", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xd0, 1);
clks[IMX8ULP_CLK_FLEXIO1] = imx8ulp_clk_hw_composite("flexio1", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xd4, 1);
clks[IMX8ULP_CLK_I3C2] = imx8ulp_clk_hw_composite("i3c2", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xd8, 1);
clks[IMX8ULP_CLK_LPI2C4] = imx8ulp_clk_hw_composite("lpi2c4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), true, true, true, base + 0xdc, 1);
@ -376,8 +375,9 @@ static int imx8ulp_clk_pcc3_init(struct platform_device *pdev)
clks[IMX8ULP_CLK_DMA1_CH29] = imx_clk_hw_gate("pcc_dma1_ch29", "xbar_ad_divplat", base + 0x7c, 30);
clks[IMX8ULP_CLK_DMA1_CH30] = imx_clk_hw_gate("pcc_dma1_ch30", "xbar_ad_divplat", base + 0x80, 30);
clks[IMX8ULP_CLK_DMA1_CH31] = imx_clk_hw_gate("pcc_dma1_ch31", "xbar_ad_divplat", base + 0x84, 30);
clks[IMX8ULP_CLK_MU0_B] = imx_clk_hw_gate("mu0_b", "xbar_ad_divplat", base + 0x88, 30);
clks[IMX8ULP_CLK_MU0_B] = imx_clk_hw_gate_flags("mu0_b", "xbar_ad_divplat", base + 0x88, 30, CLK_IS_CRITICAL);
clks[IMX8ULP_CLK_MU3_A] = imx_clk_hw_gate("mu3_a", "xbar_ad_divplat", base + 0x8c, 30);
clks[IMX8ULP_CLK_TPM5] = imx_clk_hw_gate_flags("tpm5", "sosc_div2", base + 0xd0, 30, CLK_IS_CRITICAL);
imx_check_clk_hws(clks, clk_data->num);

View File

@ -33,6 +33,7 @@ static u32 share_count_sai2;
static u32 share_count_sai3;
static u32 share_count_mub;
static const char * const a55_core_sels[] = {"a55_alt", "arm_pll"};
static const char *parent_names[MAX_SEL][4] = {
{"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "video_pll"},
{"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "sys_pll_pfd2_div2"},
@ -55,7 +56,7 @@ static const struct imx93_clk_root {
/* a55/m33/bus critical clk for system run */
{ IMX93_CLK_A55_PERIPH, "a55_periph_root", 0x0000, FAST_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_A55_MTR_BUS, "a55_mtr_bus_root", 0x0080, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_A55, "a55_root", 0x0100, FAST_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_A55, "a55_alt_root", 0x0100, FAST_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_M33, "m33_root", 0x0180, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_BUS_WAKEUP, "bus_wakeup_root", 0x0280, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_BUS_AON, "bus_aon_root", 0x0300, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
@ -117,6 +118,7 @@ static const struct imx93_clk_root {
{ IMX93_CLK_HSIO_USB_TEST_60M, "hsio_usb_test_60m_root", 0x1f00, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, },
{ IMX93_CLK_NIC_AXI, "nic_axi_root", 0x2080, FAST_SEL, CLK_IS_CRITICAL, },
{ IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, },
{ IMX93_CLK_MEDIA_AXI, "media_axi_root", 0x2280, FAST_SEL, },
@ -153,7 +155,7 @@ static const struct imx93_clk_ccgr {
unsigned long flags;
u32 *shared_count;
} ccgr_array[] = {
{ IMX93_CLK_A55_GATE, "a55", "a55_root", 0x8000, },
{ IMX93_CLK_A55_GATE, "a55_alt", "a55_alt_root", 0x8000, },
/* M33 critical clk for system run */
{ IMX93_CLK_CM33_GATE, "cm33", "m33_root", 0x8040, CLK_IS_CRITICAL },
{ IMX93_CLK_ADC1_GATE, "adc1", "adc_root", 0x82c0, },
@ -291,6 +293,9 @@ static int imx93_clocks_probe(struct platform_device *pdev)
if (WARN_ON(!anatop_base))
return -ENOMEM;
clks[IMX93_CLK_ARM_PLL] = imx_clk_fracn_gppll_integer("arm_pll", "osc_24m",
anatop_base + 0x1000,
&imx_fracn_gppll_integer);
clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", anatop_base + 0x1200,
&imx_fracn_gppll);
clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", anatop_base + 0x1400,
@ -318,6 +323,14 @@ static int imx93_clocks_probe(struct platform_device *pdev)
ccgr->shared_count);
}
clks[IMX93_CLK_A55_SEL] = imx_clk_hw_mux2("a55_sel", base + 0x4820, 0, 1, a55_core_sels,
ARRAY_SIZE(a55_core_sels));
clks[IMX93_CLK_A55_CORE] = imx_clk_hw_cpu("a55_core", "a55_sel",
clks[IMX93_CLK_A55_SEL]->clk,
clks[IMX93_CLK_A55_SEL]->clk,
clks[IMX93_CLK_ARM_PLL]->clk,
clks[IMX93_CLK_A55_GATE]->clk);
imx_check_clk_hws(clks, IMX93_CLK_END);
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
@ -352,6 +365,8 @@ static struct platform_driver imx93_clk_driver = {
},
};
module_platform_driver(imx93_clk_driver);
module_param(mcore_booted, bool, 0444);
MODULE_PARM_DESC(mcore_booted, "See Cortex-M core is booted or not");
MODULE_DESCRIPTION("NXP i.MX93 clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -73,6 +73,9 @@ extern struct imx_pll14xx_clk imx_1416x_pll;
extern struct imx_pll14xx_clk imx_1443x_pll;
extern struct imx_pll14xx_clk imx_1443x_dram_pll;
#define CLK_FRACN_GPPLL_INTEGER BIT(0)
#define CLK_FRACN_GPPLL_FRACN BIT(1)
/* NOTE: Rate table should be kept sorted in descending order. */
struct imx_fracn_gppll_rate_table {
unsigned int rate;
@ -91,8 +94,12 @@ struct imx_fracn_gppll_clk {
struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
const struct imx_fracn_gppll_clk *pll_clk);
struct clk_hw *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
void __iomem *base,
const struct imx_fracn_gppll_clk *pll_clk);
extern struct imx_fracn_gppll_clk imx_fracn_gppll;
extern struct imx_fracn_gppll_clk imx_fracn_gppll_integer;
#define imx_clk_cpu(name, parent_name, div, mux, pll, step) \
to_clk(imx_clk_hw_cpu(name, parent_name, div, mux, pll, step))
@ -153,9 +160,6 @@ extern struct imx_fracn_gppll_clk imx_fracn_gppll;
#define imx_clk_pllv2(name, parent, base) \
to_clk(imx_clk_hw_pllv2(name, parent, base))
#define imx_clk_mux_flags(name, reg, shift, width, parents, num_parents, flags) \
to_clk(imx_clk_hw_mux_flags(name, reg, shift, width, parents, num_parents, flags))
#define imx_clk_hw_gate(name, parent, reg, shift) \
imx_clk_hw_gate_flags(name, parent, reg, shift, 0)
@ -349,6 +353,15 @@ static inline struct clk_hw *imx_clk_hw_fixed_factor(const char *name,
CLK_SET_RATE_PARENT, mult, div);
}
static inline struct clk_hw *imx_clk_hw_divider_closest(const char *name,
const char *parent,
void __iomem *reg, u8 shift,
u8 width)
{
return clk_hw_register_divider(NULL, name, parent, 0,
reg, shift, width, CLK_DIVIDER_ROUND_CLOSEST, &imx_ccm_lock);
}
static inline struct clk_hw *__imx_clk_hw_divider(const char *name,
const char *parent,
void __iomem *reg, u8 shift,
@ -417,6 +430,10 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name,
_imx8m_clk_hw_composite(name, parent_names, reg, \
0, IMX_COMPOSITE_CLK_FLAGS_DEFAULT)
#define imx8m_clk_hw_composite_flags(name, parent_names, reg, flags) \
_imx8m_clk_hw_composite(name, parent_names, reg, \
0, IMX_COMPOSITE_CLK_FLAGS_DEFAULT | flags)
#define imx8m_clk_hw_composite_critical(name, parent_names, reg) \
_imx8m_clk_hw_composite(name, parent_names, reg, \
0, IMX_COMPOSITE_CLK_FLAGS_CRITICAL)

View File

@ -689,16 +689,14 @@ static int ti_sci_clk_probe(struct platform_device *pdev)
* via common clock framework. Any memory allocated for the device will
* be free'd silently via the devm framework. Returns 0 always.
*/
static int ti_sci_clk_remove(struct platform_device *pdev)
static void ti_sci_clk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
}
static struct platform_driver ti_sci_clk_driver = {
.probe = ti_sci_clk_probe,
.remove = ti_sci_clk_remove,
.remove_new = ti_sci_clk_remove,
.driver = {
.name = "ti-sci-clk",
.of_match_table = of_match_ptr(ti_sci_clk_of_match),

View File

@ -1,4 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += clk.o
obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o
obj-$(CONFIG_LOONGSON1_LS1C) += clk-loongson1c.o

View File

@ -1,118 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
*/
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/err.h>
#include <loongson1.h>
#include "clk.h"
#define OSC (33 * 1000000)
#define DIV_APB 2
static DEFINE_SPINLOCK(_lock);
static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
u32 pll, rate;
pll = __raw_readl(LS1X_CLK_PLL_FREQ);
rate = 12 + (pll & GENMASK(5, 0));
rate *= OSC;
rate >>= 1;
return rate;
}
static const struct clk_ops ls1x_pll_clk_ops = {
.recalc_rate = ls1x_pll_recalc_rate,
};
static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
void __init ls1x_clk_init(void)
{
struct clk_hw *hw;
hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
clk_hw_register_clkdev(hw, "osc_clk", NULL);
/* clock derived from 33 MHz OSC clk */
hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
&ls1x_pll_clk_ops, 0);
clk_hw_register_clkdev(hw, "pll_clk", NULL);
/* clock derived from PLL clk */
/* _____
* _______________________| |
* OSC ___/ | MUX |___ CPU CLK
* \___ PLL ___ CPU DIV ___| |
* |_____|
*/
hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
DIV_CPU_SHIFT, DIV_CPU_WIDTH,
CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ROUND_CLOSEST, &_lock);
clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
ARRAY_SIZE(cpu_parents),
CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
clk_hw_register_clkdev(hw, "cpu_clk", NULL);
/* _____
* _______________________| |
* OSC ___/ | MUX |___ DC CLK
* \___ PLL ___ DC DIV ___| |
* |_____|
*/
hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
ARRAY_SIZE(dc_parents),
CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
clk_hw_register_clkdev(hw, "dc_clk", NULL);
/* _____
* _______________________| |
* OSC ___/ | MUX |___ DDR CLK
* \___ PLL ___ DDR DIV ___| |
* |_____|
*/
hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
&_lock);
clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
ARRAY_SIZE(ahb_parents),
CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
clk_hw_register_clkdev(hw, "ahb_clk", NULL);
clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
clk_hw_register_clkdev(hw, "stmmaceth", NULL);
/* clock derived from AHB clk */
/* APB clk is always half of the AHB clk */
hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
DIV_APB);
clk_hw_register_clkdev(hw, "apb_clk", NULL);
clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
clk_hw_register_clkdev(hw, "ls1x-nand", NULL);
clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL);
clk_hw_register_clkdev(hw, "ls1x-spi", NULL);
clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
clk_hw_register_clkdev(hw, "serial8250", NULL);
}

View File

@ -1,95 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
*/
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <loongson1.h>
#include "clk.h"
#define OSC (24 * 1000000)
#define DIV_APB 1
static DEFINE_SPINLOCK(_lock);
static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
u32 pll, rate;
pll = __raw_readl(LS1X_CLK_PLL_FREQ);
rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
rate *= OSC;
rate >>= 2;
return rate;
}
static const struct clk_ops ls1x_pll_clk_ops = {
.recalc_rate = ls1x_pll_recalc_rate,
};
static const struct clk_div_table ahb_div_table[] = {
[0] = { .val = 0, .div = 2 },
[1] = { .val = 1, .div = 4 },
[2] = { .val = 2, .div = 3 },
[3] = { .val = 3, .div = 3 },
[4] = { /* sentinel */ }
};
void __init ls1x_clk_init(void)
{
struct clk_hw *hw;
hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
clk_hw_register_clkdev(hw, "osc_clk", NULL);
/* clock derived from 24 MHz OSC clk */
hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
&ls1x_pll_clk_ops, 0);
clk_hw_register_clkdev(hw, "pll_clk", NULL);
hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
DIV_CPU_SHIFT, DIV_CPU_WIDTH,
CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ROUND_CLOSEST, &_lock);
clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
0, 1, 1);
clk_hw_register_clkdev(hw, "cpu_clk", NULL);
hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div",
0, 1, 1);
clk_hw_register_clkdev(hw, "dc_clk", NULL);
hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
ahb_div_table, &_lock);
clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
0, 1, 1);
clk_hw_register_clkdev(hw, "ahb_clk", NULL);
clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
clk_hw_register_clkdev(hw, "stmmaceth", NULL);
/* clock derived from AHB clk */
hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
DIV_APB);
clk_hw_register_clkdev(hw, "apb_clk", NULL);
clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
clk_hw_register_clkdev(hw, "ls1x-nand", NULL);
clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL);
clk_hw_register_clkdev(hw, "ls1x-spi", NULL);
clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
clk_hw_register_clkdev(hw, "serial8250", NULL);
}

View File

@ -1,41 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
*/
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include "clk.h"
struct clk_hw *__init clk_hw_register_pll(struct device *dev,
const char *name,
const char *parent_name,
const struct clk_ops *ops,
unsigned long flags)
{
int ret;
struct clk_hw *hw;
struct clk_init_data init;
/* allocate the divider */
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = ops;
init.flags = flags;
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
hw->init = &init;
/* register the clock */
ret = clk_hw_register(dev, hw);
if (ret) {
kfree(hw);
hw = ERR_PTR(ret);
}
return hw;
}

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
*/
#ifndef __LOONGSON1_CLK_H
#define __LOONGSON1_CLK_H
struct clk_hw *clk_hw_register_pll(struct device *dev,
const char *name,
const char *parent_name,
const struct clk_ops *ops,
unsigned long flags);
#endif /* __LOONGSON1_CLK_H */

View File

@ -75,7 +75,7 @@ config COMMON_CLK_MT2701_G3DSYS
This driver supports MediaTek MT2701 g3dsys clocks.
config COMMON_CLK_MT2712
bool "Clock driver for MediaTek MT2712"
tristate "Clock driver for MediaTek MT2712"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
@ -83,43 +83,43 @@ config COMMON_CLK_MT2712
This driver supports MediaTek MT2712 basic clocks.
config COMMON_CLK_MT2712_BDPSYS
bool "Clock driver for MediaTek MT2712 bdpsys"
tristate "Clock driver for MediaTek MT2712 bdpsys"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 bdpsys clocks.
config COMMON_CLK_MT2712_IMGSYS
bool "Clock driver for MediaTek MT2712 imgsys"
tristate "Clock driver for MediaTek MT2712 imgsys"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 imgsys clocks.
config COMMON_CLK_MT2712_JPGDECSYS
bool "Clock driver for MediaTek MT2712 jpgdecsys"
tristate "Clock driver for MediaTek MT2712 jpgdecsys"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 jpgdecsys clocks.
config COMMON_CLK_MT2712_MFGCFG
bool "Clock driver for MediaTek MT2712 mfgcfg"
tristate "Clock driver for MediaTek MT2712 mfgcfg"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 mfgcfg clocks.
config COMMON_CLK_MT2712_MMSYS
bool "Clock driver for MediaTek MT2712 mmsys"
tristate "Clock driver for MediaTek MT2712 mmsys"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 mmsys clocks.
config COMMON_CLK_MT2712_VDECSYS
bool "Clock driver for MediaTek MT2712 vdecsys"
tristate "Clock driver for MediaTek MT2712 vdecsys"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 vdecsys clocks.
config COMMON_CLK_MT2712_VENCSYS
bool "Clock driver for MediaTek MT2712 vencsys"
tristate "Clock driver for MediaTek MT2712 vencsys"
depends on COMMON_CLK_MT2712
help
This driver supports MediaTek MT2712 vencsys clocks.
@ -133,79 +133,79 @@ config COMMON_CLK_MT6765
This driver supports MediaTek MT6765 basic clocks.
config COMMON_CLK_MT6765_AUDIOSYS
bool "Clock driver for MediaTek MT6765 audiosys"
tristate "Clock driver for MediaTek MT6765 audiosys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 audiosys clocks.
config COMMON_CLK_MT6765_CAMSYS
bool "Clock driver for MediaTek MT6765 camsys"
tristate "Clock driver for MediaTek MT6765 camsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 camsys clocks.
config COMMON_CLK_MT6765_GCESYS
bool "Clock driver for MediaTek MT6765 gcesys"
tristate "Clock driver for MediaTek MT6765 gcesys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 gcesys clocks.
config COMMON_CLK_MT6765_MMSYS
bool "Clock driver for MediaTek MT6765 mmsys"
tristate "Clock driver for MediaTek MT6765 mmsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mmsys clocks.
config COMMON_CLK_MT6765_IMGSYS
bool "Clock driver for MediaTek MT6765 imgsys"
tristate "Clock driver for MediaTek MT6765 imgsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 imgsys clocks.
config COMMON_CLK_MT6765_VCODECSYS
bool "Clock driver for MediaTek MT6765 vcodecsys"
tristate "Clock driver for MediaTek MT6765 vcodecsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 vcodecsys clocks.
config COMMON_CLK_MT6765_MFGSYS
bool "Clock driver for MediaTek MT6765 mfgsys"
tristate "Clock driver for MediaTek MT6765 mfgsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mfgsys clocks.
config COMMON_CLK_MT6765_MIPI0ASYS
bool "Clock driver for MediaTek MT6765 mipi0asys"
tristate "Clock driver for MediaTek MT6765 mipi0asys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi0asys clocks.
config COMMON_CLK_MT6765_MIPI0BSYS
bool "Clock driver for MediaTek MT6765 mipi0bsys"
tristate "Clock driver for MediaTek MT6765 mipi0bsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi0bsys clocks.
config COMMON_CLK_MT6765_MIPI1ASYS
bool "Clock driver for MediaTek MT6765 mipi1asys"
tristate "Clock driver for MediaTek MT6765 mipi1asys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi1asys clocks.
config COMMON_CLK_MT6765_MIPI1BSYS
bool "Clock driver for MediaTek MT6765 mipi1bsys"
tristate "Clock driver for MediaTek MT6765 mipi1bsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi1bsys clocks.
config COMMON_CLK_MT6765_MIPI2ASYS
bool "Clock driver for MediaTek MT6765 mipi2asys"
tristate "Clock driver for MediaTek MT6765 mipi2asys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi2asys clocks.
config COMMON_CLK_MT6765_MIPI2BSYS
bool "Clock driver for MediaTek MT6765 mipi2bsys"
tristate "Clock driver for MediaTek MT6765 mipi2bsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi2bsys clocks.
@ -270,6 +270,7 @@ config COMMON_CLK_MT6795
tristate "Clock driver for MediaTek MT6795"
depends on ARCH_MEDIATEK || COMPILE_TEST
select COMMON_CLK_MEDIATEK
select COMMON_CLK_MEDIATEK_FHCTL
default ARCH_MEDIATEK
help
This driver supports MediaTek MT6795 basic clocks and clocks
@ -312,31 +313,31 @@ config COMMON_CLK_MT6797
This driver supports MediaTek MT6797 basic clocks.
config COMMON_CLK_MT6797_MMSYS
bool "Clock driver for MediaTek MT6797 mmsys"
tristate "Clock driver for MediaTek MT6797 mmsys"
depends on COMMON_CLK_MT6797
help
This driver supports MediaTek MT6797 mmsys clocks.
config COMMON_CLK_MT6797_IMGSYS
bool "Clock driver for MediaTek MT6797 imgsys"
tristate "Clock driver for MediaTek MT6797 imgsys"
depends on COMMON_CLK_MT6797
help
This driver supports MediaTek MT6797 imgsys clocks.
config COMMON_CLK_MT6797_VDECSYS
bool "Clock driver for MediaTek MT6797 vdecsys"
tristate "Clock driver for MediaTek MT6797 vdecsys"
depends on COMMON_CLK_MT6797
help
This driver supports MediaTek MT6797 vdecsys clocks.
config COMMON_CLK_MT6797_VENCSYS
bool "Clock driver for MediaTek MT6797 vencsys"
tristate "Clock driver for MediaTek MT6797 vencsys"
depends on COMMON_CLK_MT6797
help
This driver supports MediaTek MT6797 vencsys clocks.
config COMMON_CLK_MT7622
bool "Clock driver for MediaTek MT7622"
tristate "Clock driver for MediaTek MT7622"
depends on ARCH_MEDIATEK || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
@ -345,21 +346,21 @@ config COMMON_CLK_MT7622
required for various periperals found on MediaTek.
config COMMON_CLK_MT7622_ETHSYS
bool "Clock driver for MediaTek MT7622 ETHSYS"
tristate "Clock driver for MediaTek MT7622 ETHSYS"
depends on COMMON_CLK_MT7622
help
This driver add support for clocks for Ethernet and SGMII
required on MediaTek MT7622 SoC.
config COMMON_CLK_MT7622_HIFSYS
bool "Clock driver for MediaTek MT7622 HIFSYS"
tristate "Clock driver for MediaTek MT7622 HIFSYS"
depends on COMMON_CLK_MT7622
help
This driver supports MediaTek MT7622 HIFSYS clocks providing
to PCI-E and USB.
config COMMON_CLK_MT7622_AUDSYS
bool "Clock driver for MediaTek MT7622 AUDSYS"
tristate "Clock driver for MediaTek MT7622 AUDSYS"
depends on COMMON_CLK_MT7622
help
This driver supports MediaTek MT7622 AUDSYS clocks providing
@ -406,7 +407,7 @@ config COMMON_CLK_MT7981_ETHSYS
required on MediaTek MT7981 SoC.
config COMMON_CLK_MT7986
bool "Clock driver for MediaTek MT7986"
tristate "Clock driver for MediaTek MT7986"
depends on ARCH_MEDIATEK || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
@ -415,7 +416,7 @@ config COMMON_CLK_MT7986
required for various peripherals found on MediaTek.
config COMMON_CLK_MT7986_ETHSYS
bool "Clock driver for MediaTek MT7986 ETHSYS"
tristate "Clock driver for MediaTek MT7986 ETHSYS"
depends on COMMON_CLK_MT7986
default COMMON_CLK_MT7986
help
@ -423,7 +424,7 @@ config COMMON_CLK_MT7986_ETHSYS
required on MediaTek MT7986 SoC.
config COMMON_CLK_MT8135
bool "Clock driver for MediaTek MT8135"
tristate "Clock driver for MediaTek MT8135"
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM
@ -431,7 +432,7 @@ config COMMON_CLK_MT8135
This driver supports MediaTek MT8135 clocks.
config COMMON_CLK_MT8167
bool "Clock driver for MediaTek MT8167"
tristate "Clock driver for MediaTek MT8167"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
@ -439,35 +440,35 @@ config COMMON_CLK_MT8167
This driver supports MediaTek MT8167 basic clocks.
config COMMON_CLK_MT8167_AUDSYS
bool "Clock driver for MediaTek MT8167 audsys"
tristate "Clock driver for MediaTek MT8167 audsys"
depends on COMMON_CLK_MT8167
default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 audsys clocks.
config COMMON_CLK_MT8167_IMGSYS
bool "Clock driver for MediaTek MT8167 imgsys"
tristate "Clock driver for MediaTek MT8167 imgsys"
depends on COMMON_CLK_MT8167
default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 imgsys clocks.
config COMMON_CLK_MT8167_MFGCFG
bool "Clock driver for MediaTek MT8167 mfgcfg"
tristate "Clock driver for MediaTek MT8167 mfgcfg"
depends on COMMON_CLK_MT8167
default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 mfgcfg clocks.
config COMMON_CLK_MT8167_MMSYS
bool "Clock driver for MediaTek MT8167 mmsys"
tristate "Clock driver for MediaTek MT8167 mmsys"
depends on COMMON_CLK_MT8167
default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 mmsys clocks.
config COMMON_CLK_MT8167_VDECSYS
bool "Clock driver for MediaTek MT8167 vdecsys"
tristate "Clock driver for MediaTek MT8167 vdecsys"
depends on COMMON_CLK_MT8167
default COMMON_CLK_MT8167
help
@ -477,6 +478,7 @@ config COMMON_CLK_MT8173
tristate "Clock driver for MediaTek MT8173"
depends on ARM64 || COMPILE_TEST
select COMMON_CLK_MEDIATEK
select COMMON_CLK_MEDIATEK_FHCTL
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8173 basic clocks and clocks
@ -511,7 +513,7 @@ config COMMON_CLK_MT8173_VENCSYS
This driver supports MediaTek MT8173 vencsys clocks.
config COMMON_CLK_MT8183
bool "Clock driver for MediaTek MT8183"
tristate "Clock driver for MediaTek MT8183"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
@ -519,84 +521,84 @@ config COMMON_CLK_MT8183
This driver supports MediaTek MT8183 basic clocks.
config COMMON_CLK_MT8183_AUDIOSYS
bool "Clock driver for MediaTek MT8183 audiosys"
tristate "Clock driver for MediaTek MT8183 audiosys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 audiosys clocks.
config COMMON_CLK_MT8183_CAMSYS
bool "Clock driver for MediaTek MT8183 camsys"
tristate "Clock driver for MediaTek MT8183 camsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 camsys clocks.
config COMMON_CLK_MT8183_IMGSYS
bool "Clock driver for MediaTek MT8183 imgsys"
tristate "Clock driver for MediaTek MT8183 imgsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 imgsys clocks.
config COMMON_CLK_MT8183_IPU_CORE0
bool "Clock driver for MediaTek MT8183 ipu_core0"
tristate "Clock driver for MediaTek MT8183 ipu_core0"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_core0 clocks.
config COMMON_CLK_MT8183_IPU_CORE1
bool "Clock driver for MediaTek MT8183 ipu_core1"
tristate "Clock driver for MediaTek MT8183 ipu_core1"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_core1 clocks.
config COMMON_CLK_MT8183_IPU_ADL
bool "Clock driver for MediaTek MT8183 ipu_adl"
tristate "Clock driver for MediaTek MT8183 ipu_adl"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_adl clocks.
config COMMON_CLK_MT8183_IPU_CONN
bool "Clock driver for MediaTek MT8183 ipu_conn"
tristate "Clock driver for MediaTek MT8183 ipu_conn"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_conn clocks.
config COMMON_CLK_MT8183_MFGCFG
bool "Clock driver for MediaTek MT8183 mfgcfg"
tristate "Clock driver for MediaTek MT8183 mfgcfg"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 mfgcfg clocks.
config COMMON_CLK_MT8183_MMSYS
bool "Clock driver for MediaTek MT8183 mmsys"
tristate "Clock driver for MediaTek MT8183 mmsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 mmsys clocks.
config COMMON_CLK_MT8183_VDECSYS
bool "Clock driver for MediaTek MT8183 vdecsys"
tristate "Clock driver for MediaTek MT8183 vdecsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 vdecsys clocks.
config COMMON_CLK_MT8183_VENCSYS
bool "Clock driver for MediaTek MT8183 vencsys"
tristate "Clock driver for MediaTek MT8183 vencsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 vencsys clocks.
config COMMON_CLK_MT8186
bool "Clock driver for MediaTek MT8186"
tristate "Clock driver for MediaTek MT8186"
depends on ARM64 || COMPILE_TEST
select COMMON_CLK_MEDIATEK
select COMMON_CLK_MEDIATEK_FHCTL
@ -604,82 +606,246 @@ config COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 clocks.
config COMMON_CLK_MT8192
bool "Clock driver for MediaTek MT8192"
config COMMON_CLK_MT8186_CAMSYS
tristate "Clock driver for MediaTek MT8186 camsys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 camsys and camsys_raw clocks.
config COMMON_CLK_MT8186_IMGSYS
tristate "Clock driver for MediaTek MT8186 imgsys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 imgsys and imgsys2 clocks.
config COMMON_CLK_MT8186_IPESYS
tristate "Clock driver for MediaTek MT8186 ipesys"
depends on COMMON_CLK_MT8186_IMGSYS
default COMMON_CLK_MT8186_IMGSYS
help
This driver supports MediaTek MT8186 ipesys clocks.
config COMMON_CLK_MT8186_WPESYS
tristate "Clock driver for MediaTek MT8186 wpesys"
depends on COMMON_CLK_MT8186_IMGSYS
default COMMON_CLK_MT8186_IMGSYS
help
This driver supports MediaTek MT8186 Warp Engine clocks.
config COMMON_CLK_MT8186_IMP_IIC_WRAP
tristate "Clock driver for MediaTek MT8186 imp_iic_wrap"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 imp_iic_wrap clocks.
config COMMON_CLK_MT8186_MCUSYS
tristate "Clock driver for MediaTek MT8186 mcusys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 mcusys clocks.
config COMMON_CLK_MT8186_MDPSYS
tristate "Clock driver for MediaTek MT8186 mdpsys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 mdpsys clocks.
config COMMON_CLK_MT8186_MFGCFG
tristate "Clock driver for MediaTek MT8186 mfgcfg"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 mfgcfg clocks.
config COMMON_CLK_MT8186_MMSYS
tristate "Clock driver for MediaTek MT8186 mmsys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 mmsys clocks.
config COMMON_CLK_MT8186_VDECSYS
tristate "Clock driver for MediaTek MT8186 vdecsys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 vdecsys and vdecsys_soc clocks.
config COMMON_CLK_MT8186_VENCSYS
tristate "Clock driver for MediaTek MT8186 vencsys"
depends on COMMON_CLK_MT8186
default COMMON_CLK_MT8186
help
This driver supports MediaTek MT8186 vencsys clocks.
config COMMON_CLK_MT8188
tristate "Clock driver for MediaTek MT8188"
depends on ARM64 || COMPILE_TEST
select COMMON_CLK_MEDIATEK
select COMMON_CLK_MEDIATEK_FHCTL
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8188 clocks.
config COMMON_CLK_MT8188_ADSP_AUDIO26M
tristate "Clock driver for MediaTek MT8188 adsp audio26m"
depends on COMMON_CLK_MT8188
default COMMON_CLK_MT8188
help
This driver supports MediaTek MT8188 adsp audio26m clocks.
config COMMON_CLK_MT8188_CAMSYS
tristate "Clock driver for MediaTek MT8188 camsys"
depends on COMMON_CLK_MT8188_VPPSYS
default COMMON_CLK_MT8188_VPPSYS
help
This driver supports MediaTek MT8188 camsys and camsys_raw clocks.
config COMMON_CLK_MT8188_IMGSYS
tristate "Clock driver for MediaTek MT8188 imgsys"
depends on COMMON_CLK_MT8188_VPPSYS
default COMMON_CLK_MT8188_VPPSYS
help
This driver supports MediaTek MT8188 imgsys and imgsys2 clocks.
config COMMON_CLK_MT8188_IMP_IIC_WRAP
tristate "Clock driver for MediaTek MT8188 imp_iic_wrap"
depends on COMMON_CLK_MT8188
default COMMON_CLK_MT8188
help
This driver supports MediaTek MT8188 I2C/I3C clocks.
config COMMON_CLK_MT8188_IPESYS
tristate "Clock driver for MediaTek MT8188 ipesys"
depends on COMMON_CLK_MT8188_IMGSYS
default COMMON_CLK_MT8188_IMGSYS
help
This driver supports MediaTek MT8188 ipesys clocks.
config COMMON_CLK_MT8188_MFGCFG
tristate "Clock driver for MediaTek MT8188 mfgcfg"
depends on COMMON_CLK_MT8188
default COMMON_CLK_MT8188
help
This driver supports MediaTek MT8188 mfgcfg clocks.
config COMMON_CLK_MT8188_VDECSYS
tristate "Clock driver for MediaTek MT8188 vdecsys"
depends on COMMON_CLK_MT8188_VPPSYS
default COMMON_CLK_MT8188_VPPSYS
help
This driver supports MediaTek MT8188 vdecsys and vdecsys_soc clocks.
config COMMON_CLK_MT8188_VDOSYS
tristate "Clock driver for MediaTek MT8188 vdosys"
depends on COMMON_CLK_MT8188
default COMMON_CLK_MT8188
help
This driver supports MediaTek MT8188 vdosys0/1 (multimedia) clocks.
config COMMON_CLK_MT8188_VENCSYS
tristate "Clock driver for MediaTek MT8188 vencsys"
depends on COMMON_CLK_MT8188_VPPSYS
default COMMON_CLK_MT8188_VPPSYS
help
This driver supports MediaTek MT8188 vencsys clocks.
config COMMON_CLK_MT8188_VPPSYS
tristate "Clock driver for MediaTek MT8188 vppsys"
depends on COMMON_CLK_MT8188
default COMMON_CLK_MT8188
help
This driver supports MediaTek MT8188 vppsys0/1 clocks.
config COMMON_CLK_MT8188_WPESYS
tristate "Clock driver for MediaTek MT8188 wpesys"
depends on COMMON_CLK_MT8188_IMGSYS
default COMMON_CLK_MT8188_IMGSYS
help
This driver supports MediaTek MT8188 Warp Engine clocks.
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
select COMMON_CLK_MEDIATEK
select COMMON_CLK_MEDIATEK_FHCTL
default ARM64
help
This driver supports MediaTek MT8192 basic clocks.
config COMMON_CLK_MT8192_AUDSYS
bool "Clock driver for MediaTek MT8192 audsys"
tristate "Clock driver for MediaTek MT8192 audsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 audsys clocks.
config COMMON_CLK_MT8192_CAMSYS
bool "Clock driver for MediaTek MT8192 camsys"
tristate "Clock driver for MediaTek MT8192 camsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 camsys and camsys_raw clocks.
config COMMON_CLK_MT8192_IMGSYS
bool "Clock driver for MediaTek MT8192 imgsys"
tristate "Clock driver for MediaTek MT8192 imgsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 imgsys and imgsys2 clocks.
config COMMON_CLK_MT8192_IMP_IIC_WRAP
bool "Clock driver for MediaTek MT8192 imp_iic_wrap"
tristate "Clock driver for MediaTek MT8192 imp_iic_wrap"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 imp_iic_wrap clocks.
config COMMON_CLK_MT8192_IPESYS
bool "Clock driver for MediaTek MT8192 ipesys"
tristate "Clock driver for MediaTek MT8192 ipesys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 ipesys clocks.
config COMMON_CLK_MT8192_MDPSYS
bool "Clock driver for MediaTek MT8192 mdpsys"
tristate "Clock driver for MediaTek MT8192 mdpsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 mdpsys clocks.
config COMMON_CLK_MT8192_MFGCFG
bool "Clock driver for MediaTek MT8192 mfgcfg"
tristate "Clock driver for MediaTek MT8192 mfgcfg"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 mfgcfg clocks.
config COMMON_CLK_MT8192_MMSYS
bool "Clock driver for MediaTek MT8192 mmsys"
tristate "Clock driver for MediaTek MT8192 mmsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 mmsys clocks.
config COMMON_CLK_MT8192_MSDC
bool "Clock driver for MediaTek MT8192 msdc"
tristate "Clock driver for MediaTek MT8192 msdc"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 msdc and msdc_top clocks.
config COMMON_CLK_MT8192_SCP_ADSP
bool "Clock driver for MediaTek MT8192 scp_adsp"
tristate "Clock driver for MediaTek MT8192 scp_adsp"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 scp_adsp clocks.
config COMMON_CLK_MT8192_VDECSYS
bool "Clock driver for MediaTek MT8192 vdecsys"
tristate "Clock driver for MediaTek MT8192 vdecsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 vdecsys and vdecsys_soc clocks.
config COMMON_CLK_MT8192_VENCSYS
bool "Clock driver for MediaTek MT8192 vencsys"
tristate "Clock driver for MediaTek MT8192 vencsys"
depends on COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 vencsys clocks.
@ -688,10 +854,111 @@ config COMMON_CLK_MT8195
bool "Clock driver for MediaTek MT8195"
depends on ARM64 || COMPILE_TEST
select COMMON_CLK_MEDIATEK
select COMMON_CLK_MEDIATEK_FHCTL
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8195 clocks.
config COMMON_CLK_MT8195_APUSYS
tristate "Clock driver for MediaTek MT8195 apusys"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 AI Processor Unit System clocks.
config COMMON_CLK_MT8195_AUDSYS
tristate "Clock driver for MediaTek MT8195 audsys"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 audsys clocks.
config COMMON_CLK_MT8195_IMP_IIC_WRAP
tristate "Clock driver for MediaTek MT8195 imp_iic_wrap"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 I2C/I3C clocks.
config COMMON_CLK_MT8195_MFGCFG
tristate "Clock driver for MediaTek MT8195 mfgcfg"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 mfgcfg clocks.
config COMMON_CLK_MT8195_MSDC
tristate "Clock driver for MediaTek MT8195 msdc"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 MMC and SD Controller's
msdc and msdc_top clocks.
config COMMON_CLK_MT8195_SCP_ADSP
tristate "Clock driver for MediaTek MT8195 scp_adsp"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 System Companion Processor
Audio DSP clocks.
config COMMON_CLK_MT8195_VDOSYS
tristate "Clock driver for MediaTek MT8195 vdosys"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 vdosys0/1 (multimedia) clocks.
config COMMON_CLK_MT8195_VPPSYS
tristate "Clock driver for MediaTek MT8195 vppsys"
depends on COMMON_CLK_MT8195
default COMMON_CLK_MT8195
help
This driver supports MediaTek MT8195 vppsys0/1 clocks.
config COMMON_CLK_MT8195_CAMSYS
tristate "Clock driver for MediaTek MT8195 camsys"
depends on COMMON_CLK_MT8195_VPPSYS
default COMMON_CLK_MT8195_VPPSYS
help
This driver supports MediaTek MT8195 camsys and camsys_raw clocks.
config COMMON_CLK_MT8195_IMGSYS
tristate "Clock driver for MediaTek MT8195 imgsys"
depends on COMMON_CLK_MT8195_VPPSYS
default COMMON_CLK_MT8195_VPPSYS
help
This driver supports MediaTek MT8195 imgsys and imgsys2 clocks.
config COMMON_CLK_MT8195_IPESYS
tristate "Clock driver for MediaTek MT8195 ipesys"
depends on COMMON_CLK_MT8195_IMGSYS
default COMMON_CLK_MT8195_IMGSYS
help
This driver supports MediaTek MT8195 ipesys clocks.
config COMMON_CLK_MT8195_WPESYS
tristate "Clock driver for MediaTek MT8195 wpesys"
depends on COMMON_CLK_MT8195_IMGSYS
default COMMON_CLK_MT8195_IMGSYS
help
This driver supports MediaTek MT8195 Warp Engine clocks.
config COMMON_CLK_MT8195_VDECSYS
tristate "Clock driver for MediaTek MT8195 vdecsys"
depends on COMMON_CLK_MT8195_VPPSYS
default COMMON_CLK_MT8195_VPPSYS
help
This driver supports MediaTek MT8195 vdecsys and vdecsys_soc clocks.
config COMMON_CLK_MT8195_VENCSYS
tristate "Clock driver for MediaTek MT8195 vencsys"
depends on COMMON_CLK_MT8195_VPPSYS
default COMMON_CLK_MT8195_VPPSYS
help
This driver supports MediaTek MT8195 vencsys clocks.
config COMMON_CLK_MT8365
tristate "Clock driver for MediaTek MT8365"
depends on ARCH_MEDIATEK || COMPILE_TEST
@ -743,7 +1010,7 @@ config COMMON_CLK_MT8365_VENC
This driver supports MediaTek MT8365 venc clocks.
config COMMON_CLK_MT8516
bool "Clock driver for MediaTek MT8516"
tristate "Clock driver for MediaTek MT8516"
depends on ARCH_MEDIATEK || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
@ -751,7 +1018,7 @@ config COMMON_CLK_MT8516
This driver supports MediaTek MT8516 clocks.
config COMMON_CLK_MT8516_AUDSYS
bool "Clock driver for MediaTek MT8516 audsys"
tristate "Clock driver for MediaTek MT8516 audsys"
depends on COMMON_CLK_MT8516
help
This driver supports MediaTek MT8516 audsys clocks.

View File

@ -38,7 +38,7 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o
obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712-apmixedsys.o clk-mt2712.o
obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o
obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o
obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o
@ -46,7 +46,8 @@ obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o
obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o
obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o
obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o
obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o
obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622-apmixedsys.o clk-mt7622.o \
clk-mt7622-infracfg.o
obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o
obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o
obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o
@ -61,8 +62,8 @@ 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_MT8135) += clk-mt8135-apmixedsys.o clk-mt8135.o
obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167-apmixedsys.o clk-mt8167.o
obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o
obj-$(CONFIG_COMMON_CLK_MT8167_IMGSYS) += clk-mt8167-img.o
obj-$(CONFIG_COMMON_CLK_MT8167_MFGCFG) += clk-mt8167-mfgcfg.o
@ -74,7 +75,7 @@ obj-$(CONFIG_COMMON_CLK_MT8173_IMGSYS) += clk-mt8173-img.o
obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o
obj-$(CONFIG_COMMON_CLK_MT8173_VDECSYS) += clk-mt8173-vdecsys.o
obj-$(CONFIG_COMMON_CLK_MT8173_VENCSYS) += clk-mt8173-vencsys.o
obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o
obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183-apmixedsys.o clk-mt8183.o
obj-$(CONFIG_COMMON_CLK_MT8183_AUDIOSYS) += clk-mt8183-audio.o
obj-$(CONFIG_COMMON_CLK_MT8183_CAMSYS) += clk-mt8183-cam.o
obj-$(CONFIG_COMMON_CLK_MT8183_IMGSYS) += clk-mt8183-img.o
@ -86,12 +87,33 @@ obj-$(CONFIG_COMMON_CLK_MT8183_MFGCFG) += clk-mt8183-mfgcfg.o
obj-$(CONFIG_COMMON_CLK_MT8183_MMSYS) += clk-mt8183-mm.o
obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o
obj-$(CONFIG_COMMON_CLK_MT8186) += clk-mt8186-mcu.o clk-mt8186-topckgen.o clk-mt8186-infra_ao.o \
clk-mt8186-apmixedsys.o clk-mt8186-imp_iic_wrap.o \
clk-mt8186-mfg.o clk-mt8186-mm.o clk-mt8186-wpe.o \
clk-mt8186-img.o clk-mt8186-vdec.o clk-mt8186-venc.o \
clk-mt8186-cam.o clk-mt8186-mdp.o clk-mt8186-ipe.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8186) += clk-mt8186-apmixedsys.o clk-mt8186-topckgen.o \
clk-mt8186-infra_ao.o
obj-$(CONFIG_COMMON_CLK_MT8186_CAMSYS) += clk-mt8186-cam.o
obj-$(CONFIG_COMMON_CLK_MT8186_IMGSYS) += clk-mt8186-img.o
obj-$(CONFIG_COMMON_CLK_MT8186_IMP_IIC_WRAP) += clk-mt8186-imp_iic_wrap.o
obj-$(CONFIG_COMMON_CLK_MT8186_IPESYS) += clk-mt8186-ipe.o
obj-$(CONFIG_COMMON_CLK_MT8186_MCUSYS) += clk-mt8186-mcu.o
obj-$(CONFIG_COMMON_CLK_MT8186_MDPSYS) += clk-mt8186-mdp.o
obj-$(CONFIG_COMMON_CLK_MT8186_MFGCFG) += clk-mt8186-mfg.o
obj-$(CONFIG_COMMON_CLK_MT8186_MMSYS) += clk-mt8186-mm.o
obj-$(CONFIG_COMMON_CLK_MT8186_VDECSYS) += clk-mt8186-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8186_VENCSYS) += clk-mt8186-venc.o
obj-$(CONFIG_COMMON_CLK_MT8186_WPESYS) += clk-mt8186-wpe.o
obj-$(CONFIG_COMMON_CLK_MT8188) += clk-mt8188-apmixedsys.o clk-mt8188-topckgen.o \
clk-mt8188-peri_ao.o clk-mt8188-infra_ao.o
obj-$(CONFIG_COMMON_CLK_MT8188_ADSP_AUDIO26M) += clk-mt8188-adsp_audio26m.o
obj-$(CONFIG_COMMON_CLK_MT8188_CAMSYS) += clk-mt8188-cam.o clk-mt8188-ccu.o
obj-$(CONFIG_COMMON_CLK_MT8188_IMGSYS) += clk-mt8188-img.o
obj-$(CONFIG_COMMON_CLK_MT8188_IMP_IIC_WRAP) += clk-mt8188-imp_iic_wrap.o
obj-$(CONFIG_COMMON_CLK_MT8188_IPESYS) += clk-mt8188-ipe.o
obj-$(CONFIG_COMMON_CLK_MT8188_MFGCFG) += clk-mt8188-mfg.o
obj-$(CONFIG_COMMON_CLK_MT8188_VDECSYS) += clk-mt8188-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8188_VDOSYS) += clk-mt8188-vdo0.o clk-mt8188-vdo1.o
obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
obj-$(CONFIG_COMMON_CLK_MT8192_IMGSYS) += clk-mt8192-img.o
@ -105,19 +127,25 @@ obj-$(CONFIG_COMMON_CLK_MT8192_SCP_ADSP) += clk-mt8192-scp_adsp.o
obj-$(CONFIG_COMMON_CLK_MT8192_VDECSYS) += clk-mt8192-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8192_VENCSYS) += clk-mt8192-venc.o
obj-$(CONFIG_COMMON_CLK_MT8195) += clk-mt8195-apmixedsys.o clk-mt8195-topckgen.o \
clk-mt8195-peri_ao.o clk-mt8195-infra_ao.o \
clk-mt8195-cam.o clk-mt8195-ccu.o clk-mt8195-img.o \
clk-mt8195-ipe.o clk-mt8195-mfg.o clk-mt8195-scp_adsp.o \
clk-mt8195-vdec.o clk-mt8195-vdo0.o clk-mt8195-vdo1.o \
clk-mt8195-venc.o clk-mt8195-vpp0.o clk-mt8195-vpp1.o \
clk-mt8195-wpe.o clk-mt8195-imp_iic_wrap.o \
clk-mt8195-apusys_pll.o
obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365.o
clk-mt8195-peri_ao.o clk-mt8195-infra_ao.o
obj-$(CONFIG_COMMON_CLK_MT8195_APUSYS) += clk-mt8195-apusys_pll.o
obj-$(CONFIG_COMMON_CLK_MT8195_CAMSYS) += clk-mt8195-cam.o clk-mt8195-ccu.o
obj-$(CONFIG_COMMON_CLK_MT8195_IMGSYS) += clk-mt8195-img.o
obj-$(CONFIG_COMMON_CLK_MT8195_IMP_IIC_WRAP) += clk-mt8195-imp_iic_wrap.o
obj-$(CONFIG_COMMON_CLK_MT8195_IPESYS) += clk-mt8195-ipe.o
obj-$(CONFIG_COMMON_CLK_MT8195_MFGCFG) += clk-mt8195-mfg.o
obj-$(CONFIG_COMMON_CLK_MT8195_SCP_ADSP) += clk-mt8195-scp_adsp.o
obj-$(CONFIG_COMMON_CLK_MT8195_VDECSYS) += clk-mt8195-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8195_VDOSYS) += clk-mt8195-vdo0.o clk-mt8195-vdo1.o
obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
obj-$(CONFIG_COMMON_CLK_MT8365_MFG) += clk-mt8365-mfg.o
obj-$(CONFIG_COMMON_CLK_MT8365_MMSYS) += clk-mt8365-mm.o
obj-$(CONFIG_COMMON_CLK_MT8365_VDEC) += clk-mt8365-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8365_VENC) += clk-mt8365-venc.o
obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516.o
obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516-apmixedsys.o clk-mt8516.o
obj-$(CONFIG_COMMON_CLK_MT8516_AUDSYS) += clk-mt8516-aud.o

View File

@ -14,7 +14,20 @@
#define PERCENT_TO_DDSLMT(dds, percent_m10) \
((((dds) * (percent_m10)) >> 5) / 100)
static const struct fhctl_offset fhctl_offset = {
static const struct fhctl_offset fhctl_offset_v1 = {
.offset_hp_en = 0x0,
.offset_clk_con = 0x4,
.offset_rst_con = 0x8,
.offset_slope0 = 0xc,
.offset_slope1 = 0x10,
.offset_cfg = 0x0,
.offset_updnlmt = 0x4,
.offset_dds = 0x8,
.offset_dvfs = 0xc,
.offset_mon = 0x10,
};
static const struct fhctl_offset fhctl_offset_v2 = {
.offset_hp_en = 0x0,
.offset_clk_con = 0x8,
.offset_rst_con = 0xc,
@ -27,9 +40,16 @@ static const struct fhctl_offset fhctl_offset = {
.offset_mon = 0x10,
};
const struct fhctl_offset *fhctl_get_offset_table(void)
const struct fhctl_offset *fhctl_get_offset_table(enum fhctl_variant v)
{
return &fhctl_offset;
switch (v) {
case FHCTL_PLLFH_V1:
return &fhctl_offset_v1;
case FHCTL_PLLFH_V2:
return &fhctl_offset_v2;
default:
return ERR_PTR(-EINVAL);
};
}
static void dump_hw(struct mtk_clk_pll *pll, struct fh_pll_regs *regs,

View File

@ -7,6 +7,13 @@
#ifndef __CLK_FHCTL_H
#define __CLK_FHCTL_H
#include "clk-pllfh.h"
enum fhctl_variant {
FHCTL_PLLFH_V1,
FHCTL_PLLFH_V2,
};
struct fhctl_offset {
u32 offset_hp_en;
u32 offset_clk_con;
@ -19,7 +26,7 @@ struct fhctl_offset {
u32 offset_dvfs;
u32 offset_mon;
};
const struct fhctl_offset *fhctl_get_offset_table(void);
const struct fhctl_offset *fhctl_get_offset_table(enum fhctl_variant v);
const struct fh_operation *fhctl_get_ops(void);
void fhctl_hw_init(struct mtk_fh *fh);

View File

@ -15,41 +15,17 @@
#include <dt-bindings/clock/mt2701-clk.h>
#define GATE_AUDIO0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
#define GATE_AUDIO1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
#define GATE_AUDIO2(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio2_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO2(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
#define GATE_AUDIO3(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio3_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO3(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio3_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
static const struct mtk_gate_regs audio0_cg_regs = {
.set_ofs = 0x0,
@ -148,6 +124,7 @@ static const struct of_device_id of_match_clk_mt2701_aud[] = {
{ .compatible = "mediatek,mt2701-audsys", .data = &audio_desc },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_aud);
static int clk_mt2701_aud_probe(struct platform_device *pdev)
{
@ -187,5 +164,5 @@ static struct platform_driver clk_mt2701_aud_drv = {
.of_match_table = of_match_clk_mt2701_aud,
},
};
builtin_platform_driver(clk_mt2701_aud_drv);
module_platform_driver(clk_mt2701_aud_drv);
MODULE_LICENSE("GPL");

View File

@ -24,23 +24,11 @@ static const struct mtk_gate_regs bdp1_cg_regs = {
.sta_ofs = 0x0110,
};
#define GATE_BDP0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &bdp0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
#define GATE_BDP0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &bdp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
#define GATE_BDP1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &bdp1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
#define GATE_BDP1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &bdp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
static const struct mtk_gate bdp_clks[] = {
GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
@ -107,6 +95,7 @@ static const struct of_device_id of_match_clk_mt2701_bdp[] = {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_bdp);
static struct platform_driver clk_mt2701_bdp_drv = {
.probe = mtk_clk_simple_probe,
@ -116,5 +105,5 @@ static struct platform_driver clk_mt2701_bdp_drv = {
.of_match_table = of_match_clk_mt2701_bdp,
},
};
builtin_platform_driver(clk_mt2701_bdp_drv);
module_platform_driver(clk_mt2701_bdp_drv);
MODULE_LICENSE("GPL");

View File

@ -16,14 +16,8 @@ static const struct mtk_gate_regs eth_cg_regs = {
.sta_ofs = 0x0030,
};
#define GATE_ETH(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &eth_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
#define GATE_ETH(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &eth_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
static const struct mtk_gate eth_clks[] = {
GATE_DUMMY(CLK_DUMMY, "eth_dummy"),
@ -55,6 +49,7 @@ static const struct of_device_id of_match_clk_mt2701_eth[] = {
{ .compatible = "mediatek,mt2701-ethsys", .data = &eth_desc },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_eth);
static struct platform_driver clk_mt2701_eth_drv = {
.probe = mtk_clk_simple_probe,
@ -64,5 +59,5 @@ static struct platform_driver clk_mt2701_eth_drv = {
.of_match_table = of_match_clk_mt2701_eth,
},
};
builtin_platform_driver(clk_mt2701_eth_drv);
module_platform_driver(clk_mt2701_eth_drv);
MODULE_LICENSE("GPL");

View File

@ -16,14 +16,8 @@
#include <dt-bindings/clock/mt2701-clk.h>
#define GATE_G3D(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &g3d_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_G3D(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &g3d_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
static const struct mtk_gate_regs g3d_cg_regs = {
.sta_ofs = 0x0,
@ -54,6 +48,7 @@ static const struct of_device_id of_match_clk_mt2701_g3d[] = {
{ .compatible = "mediatek,mt2701-g3dsys", .data = &g3d_desc },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_g3d);
static struct platform_driver clk_mt2701_g3d_drv = {
.probe = mtk_clk_simple_probe,
@ -63,5 +58,5 @@ static struct platform_driver clk_mt2701_g3d_drv = {
.of_match_table = of_match_clk_mt2701_g3d,
},
};
builtin_platform_driver(clk_mt2701_g3d_drv);
module_platform_driver(clk_mt2701_g3d_drv);
MODULE_LICENSE("GPL");

View File

@ -16,14 +16,8 @@ static const struct mtk_gate_regs hif_cg_regs = {
.sta_ofs = 0x0030,
};
#define GATE_HIF(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &hif_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
#define GATE_HIF(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &hif_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
static const struct mtk_gate hif_clks[] = {
GATE_DUMMY(CLK_DUMMY, "hif_dummy"),
@ -52,6 +46,7 @@ static const struct of_device_id of_match_clk_mt2701_hif[] = {
{ .compatible = "mediatek,mt2701-hifsys", .data = &hif_desc },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_hif);
static struct platform_driver clk_mt2701_hif_drv = {
.probe = mtk_clk_simple_probe,
@ -61,5 +56,5 @@ static struct platform_driver clk_mt2701_hif_drv = {
.of_match_table = of_match_clk_mt2701_hif,
},
};
builtin_platform_driver(clk_mt2701_hif_drv);
module_platform_driver(clk_mt2701_hif_drv);
MODULE_LICENSE("GPL");

View File

@ -18,14 +18,8 @@ static const struct mtk_gate_regs img_cg_regs = {
.sta_ofs = 0x0000,
};
#define GATE_IMG(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &img_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_IMG(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
static const struct mtk_gate img_clks[] = {
GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
@ -49,6 +43,7 @@ static const struct of_device_id of_match_clk_mt2701_img[] = {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_img);
static struct platform_driver clk_mt2701_img_drv = {
.probe = mtk_clk_simple_probe,
@ -58,5 +53,5 @@ static struct platform_driver clk_mt2701_img_drv = {
.of_match_table = of_match_clk_mt2701_img,
},
};
builtin_platform_driver(clk_mt2701_img_drv);
module_platform_driver(clk_mt2701_img_drv);
MODULE_LICENSE("GPL");

View File

@ -24,23 +24,11 @@ static const struct mtk_gate_regs disp1_cg_regs = {
.sta_ofs = 0x0110,
};
#define GATE_DISP0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &disp0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_DISP0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &disp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
#define GATE_DISP1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &disp1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_DISP1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &disp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
static const struct mtk_gate mm_clks[] = {
GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
@ -79,32 +67,24 @@ static const struct mtk_gate mm_clks[] = {
GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
};
static int clk_mt2701_mm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->parent->of_node;
struct clk_hw_onecell_data *clk_data;
int r;
static const struct mtk_clk_desc mm_desc = {
.clks = mm_clks,
.num_clks = ARRAY_SIZE(mm_clks),
};
clk_data = mtk_alloc_clk_data(CLK_MM_NR);
mtk_clk_register_gates(&pdev->dev, node, mm_clks,
ARRAY_SIZE(mm_clks), clk_data);
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static const struct platform_device_id clk_mt2701_mm_id_table[] = {
{ .name = "clk-mt2701-mm", .driver_data = (kernel_ulong_t)&mm_desc },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, clk_mt2701_mm_id_table);
static struct platform_driver clk_mt2701_mm_drv = {
.probe = clk_mt2701_mm_probe,
.probe = mtk_clk_pdev_probe,
.remove = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt2701-mm",
},
.id_table = clk_mt2701_mm_id_table,
};
builtin_platform_driver(clk_mt2701_mm_drv);
module_platform_driver(clk_mt2701_mm_drv);
MODULE_LICENSE("GPL");

View File

@ -24,23 +24,11 @@ static const struct mtk_gate_regs vdec1_cg_regs = {
.sta_ofs = 0x0008,
};
#define GATE_VDEC0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &vdec0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
#define GATE_VDEC0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
#define GATE_VDEC1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &vdec1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
#define GATE_VDEC1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
static const struct mtk_gate vdec_clks[] = {
GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
@ -60,6 +48,7 @@ static const struct of_device_id of_match_clk_mt2701_vdec[] = {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_vdec);
static struct platform_driver clk_mt2701_vdec_drv = {
.probe = mtk_clk_simple_probe,
@ -69,5 +58,5 @@ static struct platform_driver clk_mt2701_vdec_drv = {
.of_match_table = of_match_clk_mt2701_vdec,
},
};
builtin_platform_driver(clk_mt2701_vdec_drv);
module_platform_driver(clk_mt2701_vdec_drv);
MODULE_LICENSE("GPL");

View File

@ -636,14 +636,8 @@ static const struct mtk_gate_regs top_aud_cg_regs = {
.sta_ofs = 0x012C,
};
#define GATE_TOP_AUD(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &top_aud_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_TOP_AUD(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &top_aud_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
static const struct mtk_gate top_clks[] = {
GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
@ -687,7 +681,7 @@ static int mtk_topckgen_init(struct platform_device *pdev)
ARRAY_SIZE(top_muxes), base,
&mt2701_clk_lock, clk_data);
mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
mtk_clk_register_dividers(&pdev->dev, top_adj_divs, ARRAY_SIZE(top_adj_divs),
base, &mt2701_clk_lock, clk_data);
mtk_clk_register_gates(&pdev->dev, node, top_clks,
@ -702,14 +696,8 @@ static const struct mtk_gate_regs infra_cg_regs = {
.sta_ofs = 0x0048,
};
#define GATE_ICG(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &infra_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_ICG(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
static const struct mtk_gate infra_clks[] = {
GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
@ -823,23 +811,11 @@ static const struct mtk_gate_regs peri1_cg_regs = {
.sta_ofs = 0x001c,
};
#define GATE_PERI0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &peri0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_PERI0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
#define GATE_PERI1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &peri1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_PERI1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
static const struct mtk_gate peri_clks[] = {
GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
@ -1023,6 +999,7 @@ static const struct of_device_id of_match_clk_mt2701[] = {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2701);
static int clk_mt2701_probe(struct platform_device *pdev)
{
@ -1056,3 +1033,4 @@ static int __init clk_mt2701_init(void)
}
arch_initcall(clk_mt2701_init);
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,168 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017 MediaTek Inc.
* Weiyi Lu <weiyi.lu@mediatek.com>
* Copyright (c) 2023 Collabora Ltd.
* AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include "clk-pll.h"
#include "clk-mtk.h"
#include <dt-bindings/clock/mt2712-clk.h>
#define MT2712_PLL_FMAX (3000UL * MHZ)
#define CON0_MT2712_RST_BAR BIT(24)
#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
_tuner_en_bit, _pcw_reg, _pcw_shift, \
_div_table) { \
.id = _id, \
.name = _name, \
.reg = _reg, \
.pwr_reg = _pwr_reg, \
.en_mask = _en_mask, \
.flags = _flags, \
.rst_bar_mask = CON0_MT2712_RST_BAR, \
.fmax = MT2712_PLL_FMAX, \
.pcwbits = _pcwbits, \
.pd_reg = _pd_reg, \
.pd_shift = _pd_shift, \
.tuner_reg = _tuner_reg, \
.tuner_en_reg = _tuner_en_reg, \
.tuner_en_bit = _tuner_en_bit, \
.pcw_reg = _pcw_reg, \
.pcw_shift = _pcw_shift, \
.div_table = _div_table, \
}
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
_tuner_en_bit, _pcw_reg, _pcw_shift) \
PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, \
_tuner_en_reg, _tuner_en_bit, _pcw_reg, \
_pcw_shift, NULL)
static const struct mtk_pll_div_table armca35pll_div_table[] = {
{ .div = 0, .freq = MT2712_PLL_FMAX },
{ .div = 1, .freq = 1202500000 },
{ .div = 2, .freq = 500500000 },
{ .div = 3, .freq = 315250000 },
{ .div = 4, .freq = 157625000 },
{ /* sentinel */ }
};
static const struct mtk_pll_div_table armca72pll_div_table[] = {
{ .div = 0, .freq = MT2712_PLL_FMAX },
{ .div = 1, .freq = 994500000 },
{ .div = 2, .freq = 520000000 },
{ .div = 3, .freq = 315250000 },
{ .div = 4, .freq = 157625000 },
{ /* sentinel */ }
};
static const struct mtk_pll_div_table mmpll_div_table[] = {
{ .div = 0, .freq = MT2712_PLL_FMAX },
{ .div = 1, .freq = 1001000000 },
{ .div = 2, .freq = 601250000 },
{ .div = 3, .freq = 250250000 },
{ .div = 4, .freq = 125125000 },
{ /* sentinel */ }
};
static const struct mtk_pll_data plls[] = {
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000100,
HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0),
PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000100,
HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0),
PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000100,
0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0),
PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000100,
0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0),
PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000100,
0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0),
PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000100,
0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0),
PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000100,
0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0),
PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000100,
0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0),
PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000100,
0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0),
PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000100,
0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0),
PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000100,
0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0),
PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000100,
0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0, mmpll_div_table),
PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000100,
HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0, armca35pll_div_table),
PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000100,
0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0, armca72pll_div_table),
PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000100,
0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0),
};
static int clk_mt2712_apmixed_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return -ENOMEM;
r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
if (r)
goto free_clk_data;
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
if (r) {
dev_err(&pdev->dev, "Cannot register clock provider: %d\n", r);
goto unregister_plls;
}
return 0;
unregister_plls:
mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
free_clk_data:
mtk_free_clk_data(clk_data);
return r;
}
static int clk_mt2712_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
of_clk_del_provider(node);
mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
mtk_free_clk_data(clk_data);
return 0;
}
static const struct of_device_id of_match_clk_mt2712_apmixed[] = {
{ .compatible = "mediatek,mt2712-apmixedsys" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_apmixed);
static struct platform_driver clk_mt2712_apmixed_drv = {
.probe = clk_mt2712_apmixed_probe,
.remove = clk_mt2712_apmixed_remove,
.driver = {
.name = "clk-mt2712-apmixed",
.of_match_table = of_match_clk_mt2712_apmixed,
},
};
module_platform_driver(clk_mt2712_apmixed_drv)
MODULE_LICENSE("GPL");

Some files were not shown because too many files have changed in this diff Show More