Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk updates from Stephen Boyd:
 "Mostly the usual clk driver updates and new SoC additions plus
  non-critical data fixes for things that weren't used yet.

  One thing that's new here in the core is SSC spread spectrum support
  (SSC) in the clk provider API. The idea is that DT authors will
  configure SSC for certain clks and they'll be configured at clk
  provider registration time or when a consumer device is probed,
  similar to how we handle assigned clk rates or parents.

  On the clk driver side we have Qualcomm adding almost half the diff
  because they add support for 4 different SoCs and then a long tail of
  other SoCs like Mediatek, Renesas, Rockchip, SpaceMiT, etc. add more
  SoC support this time around. Luckily it's mostly clk data for these
  new SoCs because the actual clk_ops are already there. Beyond the new
  drivers we get all the little fixups for more compilation coverage or
  usage of more modern APIs. That all looks normal.

  Finally, I kinda buried the lede, I'm bringing on Brian and Jerome to
  help out with maintaining the clk subsystem. The current working model
  is already semi-distributed in that silicon vendors typically take
  care of their drivers and send me pull requests but I'm becoming a
  bottleneck for new drivers and core framework review because this has
  become a 100% volunteer effort on my part.

  Mike is stepping down after all these years (thanks Mike!) and that
  jump started the conversation around finding co-maintainers. Brian and
  Jerome have graciously offered to help me with the work load, meaning
  in the future they'll be sending pull requests and committing directly
  to the clk.git tree. They've both been around on the list for a while,
  I've met them both in person, and they've been making changes to the
  core clk framework along with helping review patches so I'm pretty
  confident this will work well.

  Core:
   - devm_clk_bulk_get_enable() consumer API
   - devm_clk_hw_register_composite_pdata() provider API
   - Spread Spectrum Clock (SSC) support via DT bindings and provider APIs
   - Divider clk rounding improved (and tested)

  New Drivers:
   - Cix Sky1 audio subsystem (AUDSS)
   - UltraRISC DP1000
   - MediaTek MT8173 MFG_TOP
   - Si549
   - Aspeed AST2700 PECI
   - Airoha EN7523 PCIe
   - Rockchip RV1106
   - Mobileye EyeQ7H
   - Qualcomm Maili GCC, TCSR, RPMh, and video clks
   - Qualcomm Shikra GCC, RPM, GPU, display, and audio clks
   - Qualcomm Nord display and graphics clks
   - Qualcomm Glymur camera and EVA clks
   - Qualcomm Hawi video clks
   - Amlogic A9 AO and peripheral clks
   - Renesas R-Car X5H (R8A78000) CPG"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (269 commits)
  clk: microchip: mpfs: fix regmap_update_bits() mask/val order
  clk: visconti: Make sure clk_init_data is fully initialized
  clk: ti: Make sure clk_init_data is fully initialized
  MAINTAINERS: Add Brian Masney and Jerome Brunet as co-maintainers for clk subsystem
  Drop Michael Turquette's clk maintainer entry
  clk: ti: composite: resolve parent clocks by DT index, not by name
  clk: ti: mux: resolve parent clocks by DT index, not by name
  clk: devres: fix cleanup in devm_clk_get_optional_enabled_with_rate()
  dt-bindings: clock: ti,keystone-gate: Convert to DT schema
  dt-bindings: clock: ti: Convert APLL clock to DT schema
  clk: zynq: pll: Fix kernel-doc after determine_rate() conversion
  dt-bindings: clock: ti,clockdomain: Convert to DT schema
  dt-bindings: clock: Correct white-space style
  clk: samsung: Don't include <linux/mod_devicetable.h>
  clk: at91: Read "reg" with helper
  clk: renesas: Add R-Car X5H CPG driver
  clk: rockchip: rk3576: fix source muxes for SPI0..SPI4
  clk: rockchip: Add clock controller for the RV1106
  dt-bindings: clock: rockchip: Add RV1106 CRU support
  dt-bindings: clock: Document Renesas R-Car X5H Clock Pulse Generator
  ...
This commit is contained in:
Linus Torvalds
2026-08-26 11:14:30 -07:00
277 changed files with 29815 additions and 2588 deletions
+4
View File
@@ -4112,6 +4112,10 @@ S: 4226 Landgreen Street
S: Rockville, Maryland 20853
S: USA
N: Michael Turquette
E: mturquette@baylibre.com
D: common clk maintenance
N: Stephen Tweedie
E: sct@redhat.com
P: 1024/E7A417AD E2 FE A4 20 34 EC ED FC 7D 7E 67 8D E0 31 D1 69
@@ -0,0 +1,76 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2026 Amlogic, Inc. All rights reserved
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/amlogic,a9-aoclkc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic A9 Series Always-On Clock Controller
maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
- Jerome Brunet <jbrunet@baylibre.com>
- Jian Hu <jian.hu@amlogic.com>
- Xianwei Zhao <xianwei.zhao@amlogic.com>
properties:
compatible:
const: amlogic,a9-aoclkc
reg:
maxItems: 1
'#clock-cells':
const: 1
clocks:
minItems: 5
items:
- description: input oscillator
- description: input fclk div 3
- description: input fclk div 4
- description: input fclk div 5
- description: input sys clk
- description: external fixed 32k (optional)
clock-names:
minItems: 5
items:
- const: xtal
- const: fdiv3
- const: fdiv4
- const: fdiv5
- const: sys
- const: ext_32k
required:
- compatible
- reg
- '#clock-cells'
- clocks
- clock-names
additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
clock-controller@0 {
compatible = "amlogic,a9-aoclkc";
reg = <0x0 0x0 0x0 0x58>;
#clock-cells = <1>;
clocks = <&xtal>,
<&scmi_clk 14>,
<&scmi_clk 16>,
<&scmi_clk 18>,
<&scmi_clk 21>;
clock-names = "xtal",
"fdiv3",
"fdiv4",
"fdiv5",
"sys";
};
};
@@ -0,0 +1,164 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2026 Amlogic, Inc. All rights reserved
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/amlogic,a9-peripherals-clkc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic A9 Series Peripherals Clock Controller
maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
- Jerome Brunet <jbrunet@baylibre.com>
- Jian Hu <jian.hu@amlogic.com>
- Xianwei Zhao <xianwei.zhao@amlogic.com>
properties:
compatible:
const: amlogic,a9-peripherals-clkc
reg:
maxItems: 1
'#clock-cells':
const: 1
clocks:
minItems: 27
items:
- description: input oscillator
- description: input fclk div 2
- description: input fclk div 3
- description: input fclk div 4
- description: input fclk div 5
- description: input fclk div 7
- description: input fclk div 2p5
- description: input sys clk
- description: input gp1 pll
- description: input gp2 pll
- description: input sys pll div 16
- description: input cpu clk div 16
- description: input a78 clk div 16
- description: input dsu clk div 16
- description: input rtc clk
- description: input gp0 pll
- description: input hifi0 pll
- description: input hifi1 pll
- description: input mclk0 pll
- description: input mclk1 pll
- description: input video1 pll
- description: input video2 pll
- description: input hdmi out2 clk
- description: input hdmi pixel clk
- description: input pixel0 pll
- description: input pixel1 pll
- description: input ddr pll test clk
- description: external input rmii oscillator (optional)
clock-names:
minItems: 27
items:
- const: xtal
- const: fdiv2
- const: fdiv3
- const: fdiv4
- const: fdiv5
- const: fdiv7
- const: fdiv2p5
- const: sys
- const: gp1
- const: gp2
- const: sysplldiv16
- const: cpudiv16
- const: a78div16
- const: dsudiv16
- const: rtc
- const: gp0
- const: hifi0
- const: hifi1
- const: mclk0
- const: mclk1
- const: vid1
- const: vid2
- const: hdmiout2
- const: hdmipix
- const: pix0
- const: pix1
- const: ddr_test
- const: ext_rmii
required:
- compatible
- reg
- '#clock-cells'
- clocks
- clock-names
additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
clock-controller@200 {
compatible = "amlogic,a9-peripherals-clkc";
reg = <0x0 0x200 0x0 0x2f8>;
#clock-cells = <1>;
clocks = <&xtal>,
<&scmi_clk 10>,
<&scmi_clk 12>,
<&scmi_clk 14>,
<&scmi_clk 16>,
<&scmi_clk 18>,
<&scmi_clk 20>,
<&scmi_clk 21>,
<&scmi_clk 33>,
<&scmi_clk 34>,
<&scmi_clk 35>,
<&scmi_clk 36>,
<&scmi_clk 37>,
<&scmi_clk 38>,
<&scmi_clk 40>,
<&gp0 3>,
<&hifi0 3>,
<&hifi1 3>,
<&mclk0 3>,
<&mclk1 3>,
<&vid1>,
<&vid2>,
<&hdmitx 10>,
<&hdmitx 11>,
<&pix0>,
<&pix1>,
<&ddr 3>;
clock-names = "xtal",
"fdiv2",
"fdiv3",
"fdiv4",
"fdiv5",
"fdiv7",
"fdiv2p5",
"sys",
"gp1",
"gp2",
"sysplldiv16",
"cpudiv16",
"a78div16",
"dsudiv16",
"rtc",
"gp0",
"hifi0",
"hifi1",
"mclk0",
"mclk1",
"vid1",
"vid2",
"hdmiout2",
"hdmipix",
"pix0",
"pix1",
"ddr_test";
};
};
@@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/eswin,eic7700-hspcrg.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ESWIN EIC7700 HSP Clock and Reset Generator
maintainers:
- Xuyang Dong <dongxuyang@eswincomputing.com>
description:
Clock and reset generator for the ESWIN EIC7700 HSP (high-speed peripherals).
properties:
compatible:
const: eswin,eic7700-hspcrg
reg:
maxItems: 1
clocks:
items:
- description: HSP configuration top clock
- description: MMC top clock
- description: SATA top clock
clock-names:
items:
- const: cfg
- const: mmc
- const: sata
'#clock-cells':
const: 1
description:
See <dt-bindings/clock/eswin,eic7700-hspcrg.h> for valid indices.
'#reset-cells':
const: 1
description:
See <dt-bindings/reset/eswin,eic7700-hspcrg.h> for valid indices.
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
- '#reset-cells'
additionalProperties: false
examples:
- |
clock-controller@50440000 {
compatible = "eswin,eic7700-hspcrg";
reg = <0x50440000 0x2000>;
clocks = <&clock 171>, <&clock 254>, <&clock 187>;
clock-names = "cfg", "mmc", "sata";
#clock-cells = <1>;
#reset-cells = <1>;
};
@@ -1,27 +0,0 @@
Binding for Keystone gate control driver which uses PSC controller IP.
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be "ti,keystone,psc-clock".
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : parent clock phandle
- reg : psc control and domain address address space
- reg-names : psc control and domain registers
- domain-id : psc domain id needed to check the transition state register
Optional properties:
- clock-output-names : From common clock binding to override the
default output clock name
Example:
clkusb: clkusb {
#clock-cells = <0>;
compatible = "ti,keystone,psc-clock";
clocks = <&chipclk16>;
clock-output-names = "usb";
reg = <0x02350008 0xb00>, <0x02350000 0x400>;
reg-names = "control", "domain";
domain-id = <0>;
};
@@ -0,0 +1,70 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/mediatek,mt8173-mfgtop.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8173 MFG TOP controller
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
description:
The MFG TOP glue layer controls various signals going to the MFG (GPU)
block on the MT8173.
properties:
compatible:
const: mediatek,mt8173-mfgtop
reg:
maxItems: 1
clocks:
maxItems: 4
clock-names:
items:
- const: sys
- const: mem
- const: core
- const: clk26m
power-domains:
maxItems: 1
'#clock-cells':
const: 1
'#power-domain-cells':
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- '#clock-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/power/mt8173-power.h>
clock-controller@13fff000 {
compatible = "mediatek,mt8173-mfgtop";
reg = <0x13fff000 0x1000>;
clocks = <&topckgen CLK_TOP_AXI_MFG_IN_SEL>,
<&topckgen CLK_TOP_MEM_MFG_IN_SEL>,
<&topckgen CLK_TOP_MFG_SEL>,
<&clk26m>;
clock-names = "sys", "mem", "core", "clk26m";
power-domains = <&spm MT8173_POWER_DOMAIN_MFG>;
#clock-cells = <1>;
#power-domain-cells = <0>;
};
@@ -65,7 +65,7 @@ examples:
- |
pericfg@10003000 {
compatible = "mediatek,mt7623-pericfg", "mediatek,mt2701-pericfg", "syscon";
compatible = "mediatek,mt7623-pericfg", "mediatek,mt2701-pericfg", "syscon";
reg = <0x10003000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -17,6 +17,7 @@ properties:
compatible:
enum:
- qcom,ipq5018-a53pll
- qcom,ipq5210-a53pll
- qcom,ipq5332-a53pll
- qcom,ipq6018-a53pll
- qcom,ipq8074-a53pll
@@ -25,19 +25,33 @@ properties:
enum:
- qcom,gcc-mdm9607
clocks:
items:
- description: XO source
- description: Sleep clock source
clock-names:
items:
- const: xo
- const: sleep_clk
required:
- compatible
- clocks
- clock-names
- '#power-domain-cells'
unevaluatedProperties: false
examples:
- |
clock-controller@900000 {
clock-controller@1800000 {
compatible = "qcom,gcc-mdm9607";
reg = <0x900000 0x4000>;
reg = <0x01800000 0x80000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
clocks = <&xo_board>, <&sleep_clk>;
clock-names = "xo", "sleep_clk";
};
...
@@ -65,9 +65,15 @@ properties:
- description: USB4 PHY 2 pcie pipe clock source
- description: USB4 PHY 2 Max pipe clock source
power-domains:
description:
A phandle and PM domain specifier for the CX power domain.
maxItems: 1
required:
- compatible
- clocks
- power-domains
- '#power-domain-cells'
allOf:
@@ -78,6 +84,7 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/power/qcom-rpmpd.h>
clock-controller@100000 {
compatible = "qcom,glymur-gcc";
reg = <0x100000 0x1f9000>;
@@ -113,6 +120,7 @@ examples:
<&usb4_phy_0_pcie_pipe>, <&usb4_phy_0_max_pipe>,
<&usb4_phy_1_pcie_pipe>, <&usb4_phy_1_max_pipe>,
<&usb4_phy_2_pcie_pipe>, <&usb4_phy_2_max_pipe>;
power-domains = <&rpmhpd RPMHPD_CX>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
@@ -0,0 +1,146 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,glymur-tcsr.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm TCSR Clock Controller on Glymur
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Taniya Das <taniya.das@oss.qualcomm.com>
description: |
Qualcomm TCSR clock control module provides the clocks, resets and
power domains on Glymur
See also:
- include/dt-bindings/clock/qcom,glymur-tcsr.h
properties:
compatible:
items:
- enum:
- qcom,glymur-tcsr
- qcom,mahua-tcsr
- const: syscon
clocks:
items:
- description: TCXO pad clock
reg:
maxItems: 1
'#clock-cells':
const: 1
'#reset-cells':
const: 1
vdda-qrefrpt0-0p9-supply: true
vdda-qrefrpt1-0p9-supply: true
vdda-qrefrpt2-0p9-supply: true
vdda-qrefrpt3-0p9-supply: true
vdda-qrefrpt4-0p9-supply: true
vdda-qrefrpt5-0p9-supply: true
vdda-qrefrx0-0p9-supply: true
vdda-qrefrx1-0p9-supply: true
vdda-qrefrx2-0p9-supply: true
vdda-qrefrx3-0p9-supply: true
vdda-qrefrx4-0p9-supply: true
vdda-qrefrx5-0p9-supply: true
vdda-qreftx0-0p9-supply: true
vdda-qreftx0-1p2-supply: true
vdda-qreftx1-0p9-supply: true
vdda-refgen3-0p9-supply: true
vdda-refgen3-1p2-supply: true
vdda-refgen4-0p9-supply: true
vdda-refgen4-1p2-supply: true
allOf:
- if:
properties:
compatible:
contains:
const: qcom,glymur-tcsr
then:
required:
- vdda-qrefrpt0-0p9-supply
- vdda-qrefrpt1-0p9-supply
- vdda-qrefrpt2-0p9-supply
- vdda-qrefrpt3-0p9-supply
- vdda-qrefrpt4-0p9-supply
- vdda-qrefrx0-0p9-supply
- vdda-qrefrx1-0p9-supply
- vdda-qrefrx2-0p9-supply
- vdda-qrefrx4-0p9-supply
- vdda-qrefrx5-0p9-supply
- vdda-qreftx0-0p9-supply
- vdda-qreftx0-1p2-supply
- vdda-qreftx1-0p9-supply
- vdda-refgen3-0p9-supply
- vdda-refgen3-1p2-supply
- vdda-refgen4-0p9-supply
- vdda-refgen4-1p2-supply
- if:
properties:
compatible:
contains:
const: qcom,mahua-tcsr
then:
required:
- vdda-qrefrpt0-0p9-supply
- vdda-qrefrpt1-0p9-supply
- vdda-qrefrpt2-0p9-supply
- vdda-qrefrpt3-0p9-supply
- vdda-qrefrpt4-0p9-supply
- vdda-qrefrpt5-0p9-supply
- vdda-qrefrx1-0p9-supply
- vdda-qrefrx2-0p9-supply
- vdda-qrefrx3-0p9-supply
- vdda-qreftx1-0p9-supply
- vdda-refgen3-0p9-supply
- vdda-refgen3-1p2-supply
required:
- compatible
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
clock-controller@1fd5000 {
compatible = "qcom,glymur-tcsr", "syscon";
reg = <0x0 0x1fd5000 0x0 0x21000>;
clocks = <&rpmhcc RPMH_CXO_CLK>;
#clock-cells = <1>;
#reset-cells = <1>;
vdda-qrefrpt0-0p9-supply = <&vreg_l1a>;
vdda-qrefrpt1-0p9-supply = <&vreg_l1a>;
vdda-qrefrpt2-0p9-supply = <&vreg_l1a>;
vdda-qrefrpt3-0p9-supply = <&vreg_l1a>;
vdda-qrefrpt4-0p9-supply = <&vreg_l1a>;
vdda-qrefrx0-0p9-supply = <&vreg_l1a>;
vdda-qrefrx1-0p9-supply = <&vreg_l1a>;
vdda-qrefrx2-0p9-supply = <&vreg_l1a>;
vdda-qrefrx4-0p9-supply = <&vreg_l1a>;
vdda-qrefrx5-0p9-supply = <&vreg_l1a>;
vdda-qreftx0-0p9-supply = <&vreg_l1a>;
vdda-qreftx0-1p2-supply = <&vreg_l2a>;
vdda-qreftx1-0p9-supply = <&vreg_l1a>;
vdda-refgen3-0p9-supply = <&vreg_l1a>;
vdda-refgen3-1p2-supply = <&vreg_l2a>;
vdda-refgen4-0p9-supply = <&vreg_l1a>;
vdda-refgen4-1p2-supply = <&vreg_l2a>;
};
};
...
@@ -8,16 +8,21 @@ title: Qualcomm Global Clock & Reset Controller on Hawi
maintainers:
- Vivek Aknurwar <vivek.aknurwar@oss.qualcomm.com>
- Taniya Das <taniya.das@oss.qualcomm.com>
description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on Hawi.
domains on Hawi and Maili.
See also: include/dt-bindings/clock/qcom,hawi-gcc.h
See also:
include/dt-bindings/clock/qcom,hawi-gcc.h
include/dt-bindings/clock/qcom,maili-gcc.h
properties:
compatible:
const: qcom,hawi-gcc
enum:
- qcom,hawi-gcc
- qcom,maili-gcc
clocks:
items:
@@ -17,7 +17,13 @@ description: |
properties:
compatible:
const: qcom,qcm2290-dispcc
oneOf:
- items:
- enum:
- qcom,shikra-dispcc
- const: qcom,qcm2290-dispcc
- enum:
- qcom,qcm2290-dispcc
clocks:
items:
@@ -37,10 +43,15 @@ properties:
- const: dsi0_phy_pll_out_byteclk
- const: dsi0_phy_pll_out_dsiclk
power-domains:
items:
- description: CX domain
required:
- compatible
- clocks
- clock-names
- power-domains
- '#power-domain-cells'
allOf:
@@ -53,6 +64,7 @@ examples:
#include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
#include <dt-bindings/clock/qcom,gcc-qcm2290.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/power/qcom-rpmpd.h>
clock-controller@5f00000 {
compatible = "qcom,qcm2290-dispcc";
reg = <0x5f00000 0x20000>;
@@ -68,6 +80,7 @@ examples:
"gcc_disp_gpll0_div_clk_src",
"dsi0_phy_pll_out_byteclk",
"dsi0_phy_pll_out_dsiclk";
power-domains = <&rpmpd RPMPD_VDDCX>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
@@ -18,7 +18,9 @@ description: |
properties:
compatible:
const: qcom,qcm2290-gpucc
enum:
- qcom,qcm2290-gpucc
- qcom,shikra-gpucc
reg:
maxItems: 1
@@ -16,36 +16,41 @@ description: |
properties:
compatible:
enum:
- qcom,eliza-rpmh-clk
- qcom,glymur-rpmh-clk
- qcom,hawi-rpmh-clk
- qcom,kaanapali-rpmh-clk
- qcom,milos-rpmh-clk
- qcom,nord-rpmh-clk
- qcom,qcs615-rpmh-clk
- qcom,qdu1000-rpmh-clk
- qcom,sa8775p-rpmh-clk
- qcom,sar2130p-rpmh-clk
- qcom,sc7180-rpmh-clk
- qcom,sc7280-rpmh-clk
- qcom,sc8180x-rpmh-clk
- qcom,sc8280xp-rpmh-clk
- qcom,sdm670-rpmh-clk
- qcom,sdm845-rpmh-clk
- qcom,sdx55-rpmh-clk
- qcom,sdx65-rpmh-clk
- qcom,sdx75-rpmh-clk
- qcom,sm4450-rpmh-clk
- qcom,sm6350-rpmh-clk
- qcom,sm8150-rpmh-clk
- qcom,sm8250-rpmh-clk
- qcom,sm8350-rpmh-clk
- qcom,sm8450-rpmh-clk
- qcom,sm8550-rpmh-clk
- qcom,sm8650-rpmh-clk
- qcom,sm8750-rpmh-clk
- qcom,x1e80100-rpmh-clk
oneOf:
- enum:
- qcom,eliza-rpmh-clk
- qcom,glymur-rpmh-clk
- qcom,hawi-rpmh-clk
- qcom,kaanapali-rpmh-clk
- qcom,milos-rpmh-clk
- qcom,nord-rpmh-clk
- qcom,qcs615-rpmh-clk
- qcom,qdu1000-rpmh-clk
- qcom,sa8775p-rpmh-clk
- qcom,sar2130p-rpmh-clk
- qcom,sc7180-rpmh-clk
- qcom,sc7280-rpmh-clk
- qcom,sc8180x-rpmh-clk
- qcom,sc8280xp-rpmh-clk
- qcom,sdm670-rpmh-clk
- qcom,sdm845-rpmh-clk
- qcom,sdx55-rpmh-clk
- qcom,sdx65-rpmh-clk
- qcom,sdx75-rpmh-clk
- qcom,sm4450-rpmh-clk
- qcom,sm6350-rpmh-clk
- qcom,sm8150-rpmh-clk
- qcom,sm8250-rpmh-clk
- qcom,sm8350-rpmh-clk
- qcom,sm8450-rpmh-clk
- qcom,sm8550-rpmh-clk
- qcom,sm8650-rpmh-clk
- qcom,sm8750-rpmh-clk
- qcom,x1e80100-rpmh-clk
- items:
- enum:
- qcom,maili-rpmh-clk
- const: qcom,hawi-rpmh-clk
clocks:
maxItems: 1
@@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,shikra-audiocorecc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Audio Core Clock Controller for Qualcomm Shikra SoC
maintainers:
- Imran Shaik <imran.shaik@oss.qualcomm.com>
description: |
Audio core clock control module provides the clocks on Qualcomm Shikra
SoC platform.
See also:
- include/dt-bindings/clock/qcom,shikra-audiocorecc.h
properties:
compatible:
const: qcom,shikra-audiocorecc
clocks:
items:
- description: Board XO source
- description: Board sleep clock
- description: Audio ref clock source
reg:
maxItems: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/clock/qcom,shikra-gcc.h>
clock-controller@a0a0000 {
compatible = "qcom,shikra-audiocorecc";
reg = <0x0a0a0000 0x10000>;
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
<&sleep_clk>,
<&aud_ref_clk_src>;
#clock-cells = <1>;
};
...
@@ -70,13 +70,11 @@ allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,kaanapali-cambistmclkcc
- qcom,kaanapali-camcc
- qcom,sc8280xp-camcc
- qcom,sm8450-camcc
- qcom,sm8550-camcc
not:
contains:
enum:
- qcom,sm8475-camcc
- qcom,sm8650-camcc
then:
required:
- required-opps
@@ -18,6 +18,8 @@ description: |
include/dt-bindings/clock/qcom,glymur-gpucc.h
include/dt-bindings/clock/qcom,kaanapali-gpucc.h
include/dt-bindings/clock/qcom,milos-gpucc.h
include/dt-bindings/clock/qcom,nord-gpu2cc.h
include/dt-bindings/clock/qcom,nord-gpucc.h
include/dt-bindings/clock/qcom,sar2130p-gpucc.h
include/dt-bindings/clock/qcom,sm4450-gpucc.h
include/dt-bindings/clock/qcom,sm8450-gpucc.h
@@ -33,6 +35,8 @@ properties:
- qcom,glymur-gpucc
- qcom,kaanapali-gpucc
- qcom,milos-gpucc
- qcom,nord-gpu2cc
- qcom,nord-gpucc
- qcom,sar2130p-gpucc
- qcom,sm4450-gpucc
- qcom,sm8450-gpucc
@@ -16,7 +16,9 @@ description: |
See also:
include/dt-bindings/clock/qcom,glymur-videocc.h
include/dt-bindings/clock/qcom,hawi-videocc.h
include/dt-bindings/clock/qcom,kaanapali-videocc.h
include/dt-bindings/clock/qcom,maili-videocc.h
include/dt-bindings/clock/qcom,sm8450-videocc.h
include/dt-bindings/clock/qcom,sm8650-videocc.h
include/dt-bindings/clock/qcom,sm8750-videocc.h
@@ -26,7 +28,9 @@ properties:
compatible:
enum:
- qcom,glymur-videocc
- qcom,hawi-videocc
- qcom,kaanapali-videocc
- qcom,maili-videocc
- qcom,sm8450-videocc
- qcom,sm8475-videocc
- qcom,sm8550-videocc
@@ -65,14 +69,11 @@ allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,glymur-videocc
- qcom,kaanapali-videocc
- qcom,sm8450-videocc
- qcom,sm8550-videocc
- qcom,sm8750-videocc
- qcom,x1p42100-videocc
not:
contains:
enum:
- qcom,sm8475-videocc
- qcom,sm8650-videocc
then:
required:
- required-opps
@@ -16,6 +16,7 @@ description: |
See also:
- include/dt-bindings/clock/qcom,kaanapali-dispcc.h
- include/dt-bindings/clock/qcom,nord-dispcc.h
- include/dt-bindings/clock/qcom,sm8550-dispcc.h
- include/dt-bindings/clock/qcom,sm8650-dispcc.h
- include/dt-bindings/clock/qcom,sm8750-dispcc.h
@@ -25,6 +26,8 @@ properties:
compatible:
enum:
- qcom,kaanapali-dispcc
- qcom,nord-dispcc0
- qcom,nord-dispcc1
- qcom,sar2130p-dispcc
- qcom,sm8550-dispcc
- qcom,sm8650-dispcc
@@ -16,7 +16,6 @@ description: |
See also:
- include/dt-bindings/clock/qcom,eliza-tcsr.h
- include/dt-bindings/clock/qcom,glymur-tcsr.h
- include/dt-bindings/clock/qcom,hawi-tcsrcc.h
- include/dt-bindings/clock/qcom,nord-tcsrcc.h
- include/dt-bindings/clock/qcom,sm8550-tcsr.h
@@ -25,20 +24,25 @@ description: |
properties:
compatible:
items:
- enum:
- qcom,eliza-tcsr
- qcom,glymur-tcsr
- qcom,hawi-tcsrcc
- qcom,kaanapali-tcsr
- qcom,milos-tcsr
- qcom,nord-tcsrcc
- qcom,sar2130p-tcsr
- qcom,sm8550-tcsr
- qcom,sm8650-tcsr
- qcom,sm8750-tcsr
- qcom,x1e80100-tcsr
- const: syscon
oneOf:
- items:
- enum:
- qcom,eliza-tcsr
- qcom,hawi-tcsrcc
- qcom,kaanapali-tcsr
- qcom,milos-tcsr
- qcom,nord-tcsrcc
- qcom,sar2130p-tcsr
- qcom,sm8550-tcsr
- qcom,sm8650-tcsr
- qcom,sm8750-tcsr
- qcom,x1e80100-tcsr
- const: syscon
- items:
- enum:
- qcom,maili-tcsrcc
- const: qcom,hawi-tcsrcc
- const: syscon
clocks:
items:
@@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/renesas,r8a78000-cpg.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas R-Car X5H Clock Pulse Generator
maintainers:
- Geert Uytterhoeven <geert+renesas@glider.be>
description:
The R-Car X5H Clock Pulse Generator (CLK CONTROL) consists of oscillators,
PLL circuits, clock dividers and clock control circuits. It provides various
clocks for other modules.
properties:
compatible:
const: renesas,r8a78000-cpg
reg:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: extal
- const: extalr
'#clock-cells':
description:
The single clock specifier cell must be the clock number, as defined in
<dt-bindings/clock/renesas,r8a78000-cpg.h>.
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
additionalProperties: false
examples:
- |
clock-controller@c1320000 {
compatible = "renesas,r8a78000-cpg";
reg = <0xc1320000 0x10000>;
clocks = <&extal_clk>, <&extalr_clk>;
clock-names = "extal", "extalr";
#clock-cells = <1>;
};
@@ -26,16 +26,22 @@ properties:
maxItems: 1
clocks:
minItems: 3
items:
- description: AUDIO_EXTAL clock input
- description: RTXIN clock input
- description: QEXTAL clock input
- description: AUDIO_CLKB clock input
- description: AUDIO_CLKC clock input
clock-names:
minItems: 3
items:
- const: audio_extal
- const: rtxin
- const: qextal
- const: audio_clkb
- const: audio_clkc
'#clock-cells':
description: |
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas Versaclock7 Programmable Clock
maintainers:
- Alex Helms <alexander.helms.jy@renesas.com>
- Biju Das <biju.das.jz@bp.renesas.com>
description: |
Renesas Versaclock7 is a family of configurable clock generator and
@@ -0,0 +1,60 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/rockchip,rv1106-cru.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip RV1106 Clock and Reset Unit
maintainers:
- Simon Glass <sjg@chromium.org>
- Heiko Stuebner <heiko@sntech.de>
description:
The RV1106 clock controller generates the clock and also implements a
reset controller for SoC peripherals.
properties:
compatible:
const: rockchip,rv1106-cru
reg:
maxItems: 1
"#clock-cells":
const: 1
"#reset-cells":
const: 1
clocks:
maxItems: 1
clock-names:
const: xin24m
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to the syscon managing the "general register files" (GRF).
If missing, pll rates are not changeable due to the missing pll
lock status, and the MMC drive and sample phase clocks, whose
control registers live in the GRF region, are not registered.
required:
- compatible
- reg
- "#clock-cells"
- "#reset-cells"
additionalProperties: false
examples:
- |
clock-controller@ff3b0000 {
compatible = "rockchip,rv1106-cru";
reg = <0xff3b0000 0x20000>;
rockchip,grf = <&grf>;
#clock-cells = <1>;
#reset-cells = <1>;
};
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/clock/silabs,si544.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Silicon Labs SI514/SI544 clock generator
title: Silicon Labs SI514/SI544/SI549 clock generator
maintainers:
- Mike Looijmans <mike.looijmans@topic.nl>
@@ -13,8 +13,9 @@ description: >
Silicon Labs 514/544 programmable I2C clock generator. Details about the device
can be found in the datasheet:
https://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf
https://www.silabs.com/documents/public/data-sheets/si544-datasheet.pdf
https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/Si514.pdf
https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/si544-datasheet.pdf
https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/si549-datasheet.pdf
properties:
compatible:
@@ -23,6 +24,9 @@ properties:
- silabs,si544a
- silabs,si544b
- silabs,si544c
- silabs,si549a
- silabs,si549b
- silabs,si549c
reg:
maxItems: 1
@@ -125,75 +125,75 @@ examples:
reg = <0x44200000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
clocks = <&scmi_clk CK_SCMI_HSE>,
<&scmi_clk CK_SCMI_HSI>,
<&scmi_clk CK_SCMI_MSI>,
<&scmi_clk CK_SCMI_LSE>,
<&scmi_clk CK_SCMI_LSI>,
<&scmi_clk CK_SCMI_HSE_DIV2>,
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
<&scmi_clk CK_SCMI_ICN_SDMMC>,
<&scmi_clk CK_SCMI_ICN_DDR>,
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
<&scmi_clk CK_SCMI_ICN_HSL>,
<&scmi_clk CK_SCMI_ICN_NIC>,
<&scmi_clk CK_SCMI_FLEXGEN_07>,
<&scmi_clk CK_SCMI_FLEXGEN_08>,
<&scmi_clk CK_SCMI_FLEXGEN_09>,
<&scmi_clk CK_SCMI_FLEXGEN_10>,
<&scmi_clk CK_SCMI_FLEXGEN_11>,
<&scmi_clk CK_SCMI_FLEXGEN_12>,
<&scmi_clk CK_SCMI_FLEXGEN_13>,
<&scmi_clk CK_SCMI_FLEXGEN_14>,
<&scmi_clk CK_SCMI_FLEXGEN_16>,
<&scmi_clk CK_SCMI_FLEXGEN_17>,
<&scmi_clk CK_SCMI_FLEXGEN_18>,
<&scmi_clk CK_SCMI_FLEXGEN_19>,
<&scmi_clk CK_SCMI_FLEXGEN_20>,
<&scmi_clk CK_SCMI_FLEXGEN_21>,
<&scmi_clk CK_SCMI_FLEXGEN_22>,
<&scmi_clk CK_SCMI_FLEXGEN_23>,
<&scmi_clk CK_SCMI_FLEXGEN_24>,
<&scmi_clk CK_SCMI_FLEXGEN_25>,
<&scmi_clk CK_SCMI_FLEXGEN_26>,
<&scmi_clk CK_SCMI_FLEXGEN_27>,
<&scmi_clk CK_SCMI_FLEXGEN_29>,
<&scmi_clk CK_SCMI_FLEXGEN_30>,
<&scmi_clk CK_SCMI_FLEXGEN_31>,
<&scmi_clk CK_SCMI_FLEXGEN_33>,
<&scmi_clk CK_SCMI_FLEXGEN_36>,
<&scmi_clk CK_SCMI_FLEXGEN_37>,
<&scmi_clk CK_SCMI_FLEXGEN_38>,
<&scmi_clk CK_SCMI_FLEXGEN_39>,
<&scmi_clk CK_SCMI_FLEXGEN_40>,
<&scmi_clk CK_SCMI_FLEXGEN_41>,
<&scmi_clk CK_SCMI_FLEXGEN_42>,
<&scmi_clk CK_SCMI_FLEXGEN_43>,
<&scmi_clk CK_SCMI_FLEXGEN_44>,
<&scmi_clk CK_SCMI_FLEXGEN_45>,
<&scmi_clk CK_SCMI_FLEXGEN_46>,
<&scmi_clk CK_SCMI_FLEXGEN_47>,
<&scmi_clk CK_SCMI_FLEXGEN_48>,
<&scmi_clk CK_SCMI_FLEXGEN_50>,
<&scmi_clk CK_SCMI_FLEXGEN_51>,
<&scmi_clk CK_SCMI_FLEXGEN_52>,
<&scmi_clk CK_SCMI_FLEXGEN_53>,
<&scmi_clk CK_SCMI_FLEXGEN_54>,
<&scmi_clk CK_SCMI_FLEXGEN_55>,
<&scmi_clk CK_SCMI_FLEXGEN_56>,
<&scmi_clk CK_SCMI_FLEXGEN_57>,
<&scmi_clk CK_SCMI_FLEXGEN_58>,
<&scmi_clk CK_SCMI_FLEXGEN_61>,
<&scmi_clk CK_SCMI_FLEXGEN_62>,
<&scmi_clk CK_SCMI_FLEXGEN_63>,
<&scmi_clk CK_SCMI_ICN_APB1>,
<&scmi_clk CK_SCMI_ICN_APB2>,
<&scmi_clk CK_SCMI_ICN_APB3>,
<&scmi_clk CK_SCMI_ICN_APB4>,
<&scmi_clk CK_SCMI_ICN_APB5>,
<&scmi_clk CK_SCMI_ICN_APBDBG>,
<&scmi_clk CK_SCMI_TIMG1>,
<&scmi_clk CK_SCMI_TIMG2>;
clocks = <&scmi_clk CK_SCMI_HSE>,
<&scmi_clk CK_SCMI_HSI>,
<&scmi_clk CK_SCMI_MSI>,
<&scmi_clk CK_SCMI_LSE>,
<&scmi_clk CK_SCMI_LSI>,
<&scmi_clk CK_SCMI_HSE_DIV2>,
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
<&scmi_clk CK_SCMI_ICN_SDMMC>,
<&scmi_clk CK_SCMI_ICN_DDR>,
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
<&scmi_clk CK_SCMI_ICN_HSL>,
<&scmi_clk CK_SCMI_ICN_NIC>,
<&scmi_clk CK_SCMI_FLEXGEN_07>,
<&scmi_clk CK_SCMI_FLEXGEN_08>,
<&scmi_clk CK_SCMI_FLEXGEN_09>,
<&scmi_clk CK_SCMI_FLEXGEN_10>,
<&scmi_clk CK_SCMI_FLEXGEN_11>,
<&scmi_clk CK_SCMI_FLEXGEN_12>,
<&scmi_clk CK_SCMI_FLEXGEN_13>,
<&scmi_clk CK_SCMI_FLEXGEN_14>,
<&scmi_clk CK_SCMI_FLEXGEN_16>,
<&scmi_clk CK_SCMI_FLEXGEN_17>,
<&scmi_clk CK_SCMI_FLEXGEN_18>,
<&scmi_clk CK_SCMI_FLEXGEN_19>,
<&scmi_clk CK_SCMI_FLEXGEN_20>,
<&scmi_clk CK_SCMI_FLEXGEN_21>,
<&scmi_clk CK_SCMI_FLEXGEN_22>,
<&scmi_clk CK_SCMI_FLEXGEN_23>,
<&scmi_clk CK_SCMI_FLEXGEN_24>,
<&scmi_clk CK_SCMI_FLEXGEN_25>,
<&scmi_clk CK_SCMI_FLEXGEN_26>,
<&scmi_clk CK_SCMI_FLEXGEN_27>,
<&scmi_clk CK_SCMI_FLEXGEN_29>,
<&scmi_clk CK_SCMI_FLEXGEN_30>,
<&scmi_clk CK_SCMI_FLEXGEN_31>,
<&scmi_clk CK_SCMI_FLEXGEN_33>,
<&scmi_clk CK_SCMI_FLEXGEN_36>,
<&scmi_clk CK_SCMI_FLEXGEN_37>,
<&scmi_clk CK_SCMI_FLEXGEN_38>,
<&scmi_clk CK_SCMI_FLEXGEN_39>,
<&scmi_clk CK_SCMI_FLEXGEN_40>,
<&scmi_clk CK_SCMI_FLEXGEN_41>,
<&scmi_clk CK_SCMI_FLEXGEN_42>,
<&scmi_clk CK_SCMI_FLEXGEN_43>,
<&scmi_clk CK_SCMI_FLEXGEN_44>,
<&scmi_clk CK_SCMI_FLEXGEN_45>,
<&scmi_clk CK_SCMI_FLEXGEN_46>,
<&scmi_clk CK_SCMI_FLEXGEN_47>,
<&scmi_clk CK_SCMI_FLEXGEN_48>,
<&scmi_clk CK_SCMI_FLEXGEN_50>,
<&scmi_clk CK_SCMI_FLEXGEN_51>,
<&scmi_clk CK_SCMI_FLEXGEN_52>,
<&scmi_clk CK_SCMI_FLEXGEN_53>,
<&scmi_clk CK_SCMI_FLEXGEN_54>,
<&scmi_clk CK_SCMI_FLEXGEN_55>,
<&scmi_clk CK_SCMI_FLEXGEN_56>,
<&scmi_clk CK_SCMI_FLEXGEN_57>,
<&scmi_clk CK_SCMI_FLEXGEN_58>,
<&scmi_clk CK_SCMI_FLEXGEN_61>,
<&scmi_clk CK_SCMI_FLEXGEN_62>,
<&scmi_clk CK_SCMI_FLEXGEN_63>,
<&scmi_clk CK_SCMI_ICN_APB1>,
<&scmi_clk CK_SCMI_ICN_APB2>,
<&scmi_clk CK_SCMI_ICN_APB3>,
<&scmi_clk CK_SCMI_ICN_APB4>,
<&scmi_clk CK_SCMI_ICN_APB5>,
<&scmi_clk CK_SCMI_ICN_APBDBG>,
<&scmi_clk CK_SCMI_TIMG1>,
<&scmi_clk CK_SCMI_TIMG2>;
};
...
@@ -135,85 +135,85 @@ examples:
reg = <0x44200000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
clocks = <&scmi_clk CK_SCMI_HSE>,
<&scmi_clk CK_SCMI_HSI>,
<&scmi_clk CK_SCMI_MSI>,
<&scmi_clk CK_SCMI_LSE>,
<&scmi_clk CK_SCMI_LSI>,
<&scmi_clk CK_SCMI_HSE_DIV2>,
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
<&scmi_clk CK_SCMI_ICN_SDMMC>,
<&scmi_clk CK_SCMI_ICN_DDR>,
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
<&scmi_clk CK_SCMI_ICN_HSL>,
<&scmi_clk CK_SCMI_ICN_NIC>,
<&scmi_clk CK_SCMI_ICN_VID>,
<&scmi_clk CK_SCMI_FLEXGEN_07>,
<&scmi_clk CK_SCMI_FLEXGEN_08>,
<&scmi_clk CK_SCMI_FLEXGEN_09>,
<&scmi_clk CK_SCMI_FLEXGEN_10>,
<&scmi_clk CK_SCMI_FLEXGEN_11>,
<&scmi_clk CK_SCMI_FLEXGEN_12>,
<&scmi_clk CK_SCMI_FLEXGEN_13>,
<&scmi_clk CK_SCMI_FLEXGEN_14>,
<&scmi_clk CK_SCMI_FLEXGEN_15>,
<&scmi_clk CK_SCMI_FLEXGEN_16>,
<&scmi_clk CK_SCMI_FLEXGEN_17>,
<&scmi_clk CK_SCMI_FLEXGEN_18>,
<&scmi_clk CK_SCMI_FLEXGEN_19>,
<&scmi_clk CK_SCMI_FLEXGEN_20>,
<&scmi_clk CK_SCMI_FLEXGEN_21>,
<&scmi_clk CK_SCMI_FLEXGEN_22>,
<&scmi_clk CK_SCMI_FLEXGEN_23>,
<&scmi_clk CK_SCMI_FLEXGEN_24>,
<&scmi_clk CK_SCMI_FLEXGEN_25>,
<&scmi_clk CK_SCMI_FLEXGEN_26>,
<&scmi_clk CK_SCMI_FLEXGEN_27>,
<&scmi_clk CK_SCMI_FLEXGEN_28>,
<&scmi_clk CK_SCMI_FLEXGEN_29>,
<&scmi_clk CK_SCMI_FLEXGEN_30>,
<&scmi_clk CK_SCMI_FLEXGEN_31>,
<&scmi_clk CK_SCMI_FLEXGEN_32>,
<&scmi_clk CK_SCMI_FLEXGEN_33>,
<&scmi_clk CK_SCMI_FLEXGEN_34>,
<&scmi_clk CK_SCMI_FLEXGEN_35>,
<&scmi_clk CK_SCMI_FLEXGEN_36>,
<&scmi_clk CK_SCMI_FLEXGEN_37>,
<&scmi_clk CK_SCMI_FLEXGEN_38>,
<&scmi_clk CK_SCMI_FLEXGEN_39>,
<&scmi_clk CK_SCMI_FLEXGEN_40>,
<&scmi_clk CK_SCMI_FLEXGEN_41>,
<&scmi_clk CK_SCMI_FLEXGEN_42>,
<&scmi_clk CK_SCMI_FLEXGEN_43>,
<&scmi_clk CK_SCMI_FLEXGEN_44>,
<&scmi_clk CK_SCMI_FLEXGEN_45>,
<&scmi_clk CK_SCMI_FLEXGEN_46>,
<&scmi_clk CK_SCMI_FLEXGEN_47>,
<&scmi_clk CK_SCMI_FLEXGEN_48>,
<&scmi_clk CK_SCMI_FLEXGEN_49>,
<&scmi_clk CK_SCMI_FLEXGEN_50>,
<&scmi_clk CK_SCMI_FLEXGEN_51>,
<&scmi_clk CK_SCMI_FLEXGEN_52>,
<&scmi_clk CK_SCMI_FLEXGEN_53>,
<&scmi_clk CK_SCMI_FLEXGEN_54>,
<&scmi_clk CK_SCMI_FLEXGEN_55>,
<&scmi_clk CK_SCMI_FLEXGEN_56>,
<&scmi_clk CK_SCMI_FLEXGEN_57>,
<&scmi_clk CK_SCMI_FLEXGEN_58>,
<&scmi_clk CK_SCMI_FLEXGEN_59>,
<&scmi_clk CK_SCMI_FLEXGEN_60>,
<&scmi_clk CK_SCMI_FLEXGEN_61>,
<&scmi_clk CK_SCMI_FLEXGEN_62>,
<&scmi_clk CK_SCMI_FLEXGEN_63>,
<&scmi_clk CK_SCMI_ICN_APB1>,
<&scmi_clk CK_SCMI_ICN_APB2>,
<&scmi_clk CK_SCMI_ICN_APB3>,
<&scmi_clk CK_SCMI_ICN_APB4>,
<&scmi_clk CK_SCMI_ICN_APBDBG>,
<&scmi_clk CK_SCMI_TIMG1>,
<&scmi_clk CK_SCMI_TIMG2>,
<&scmi_clk CK_SCMI_PLL3>,
<&clk_dsi_txbyte>;
clocks = <&scmi_clk CK_SCMI_HSE>,
<&scmi_clk CK_SCMI_HSI>,
<&scmi_clk CK_SCMI_MSI>,
<&scmi_clk CK_SCMI_LSE>,
<&scmi_clk CK_SCMI_LSI>,
<&scmi_clk CK_SCMI_HSE_DIV2>,
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
<&scmi_clk CK_SCMI_ICN_SDMMC>,
<&scmi_clk CK_SCMI_ICN_DDR>,
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
<&scmi_clk CK_SCMI_ICN_HSL>,
<&scmi_clk CK_SCMI_ICN_NIC>,
<&scmi_clk CK_SCMI_ICN_VID>,
<&scmi_clk CK_SCMI_FLEXGEN_07>,
<&scmi_clk CK_SCMI_FLEXGEN_08>,
<&scmi_clk CK_SCMI_FLEXGEN_09>,
<&scmi_clk CK_SCMI_FLEXGEN_10>,
<&scmi_clk CK_SCMI_FLEXGEN_11>,
<&scmi_clk CK_SCMI_FLEXGEN_12>,
<&scmi_clk CK_SCMI_FLEXGEN_13>,
<&scmi_clk CK_SCMI_FLEXGEN_14>,
<&scmi_clk CK_SCMI_FLEXGEN_15>,
<&scmi_clk CK_SCMI_FLEXGEN_16>,
<&scmi_clk CK_SCMI_FLEXGEN_17>,
<&scmi_clk CK_SCMI_FLEXGEN_18>,
<&scmi_clk CK_SCMI_FLEXGEN_19>,
<&scmi_clk CK_SCMI_FLEXGEN_20>,
<&scmi_clk CK_SCMI_FLEXGEN_21>,
<&scmi_clk CK_SCMI_FLEXGEN_22>,
<&scmi_clk CK_SCMI_FLEXGEN_23>,
<&scmi_clk CK_SCMI_FLEXGEN_24>,
<&scmi_clk CK_SCMI_FLEXGEN_25>,
<&scmi_clk CK_SCMI_FLEXGEN_26>,
<&scmi_clk CK_SCMI_FLEXGEN_27>,
<&scmi_clk CK_SCMI_FLEXGEN_28>,
<&scmi_clk CK_SCMI_FLEXGEN_29>,
<&scmi_clk CK_SCMI_FLEXGEN_30>,
<&scmi_clk CK_SCMI_FLEXGEN_31>,
<&scmi_clk CK_SCMI_FLEXGEN_32>,
<&scmi_clk CK_SCMI_FLEXGEN_33>,
<&scmi_clk CK_SCMI_FLEXGEN_34>,
<&scmi_clk CK_SCMI_FLEXGEN_35>,
<&scmi_clk CK_SCMI_FLEXGEN_36>,
<&scmi_clk CK_SCMI_FLEXGEN_37>,
<&scmi_clk CK_SCMI_FLEXGEN_38>,
<&scmi_clk CK_SCMI_FLEXGEN_39>,
<&scmi_clk CK_SCMI_FLEXGEN_40>,
<&scmi_clk CK_SCMI_FLEXGEN_41>,
<&scmi_clk CK_SCMI_FLEXGEN_42>,
<&scmi_clk CK_SCMI_FLEXGEN_43>,
<&scmi_clk CK_SCMI_FLEXGEN_44>,
<&scmi_clk CK_SCMI_FLEXGEN_45>,
<&scmi_clk CK_SCMI_FLEXGEN_46>,
<&scmi_clk CK_SCMI_FLEXGEN_47>,
<&scmi_clk CK_SCMI_FLEXGEN_48>,
<&scmi_clk CK_SCMI_FLEXGEN_49>,
<&scmi_clk CK_SCMI_FLEXGEN_50>,
<&scmi_clk CK_SCMI_FLEXGEN_51>,
<&scmi_clk CK_SCMI_FLEXGEN_52>,
<&scmi_clk CK_SCMI_FLEXGEN_53>,
<&scmi_clk CK_SCMI_FLEXGEN_54>,
<&scmi_clk CK_SCMI_FLEXGEN_55>,
<&scmi_clk CK_SCMI_FLEXGEN_56>,
<&scmi_clk CK_SCMI_FLEXGEN_57>,
<&scmi_clk CK_SCMI_FLEXGEN_58>,
<&scmi_clk CK_SCMI_FLEXGEN_59>,
<&scmi_clk CK_SCMI_FLEXGEN_60>,
<&scmi_clk CK_SCMI_FLEXGEN_61>,
<&scmi_clk CK_SCMI_FLEXGEN_62>,
<&scmi_clk CK_SCMI_FLEXGEN_63>,
<&scmi_clk CK_SCMI_ICN_APB1>,
<&scmi_clk CK_SCMI_ICN_APB2>,
<&scmi_clk CK_SCMI_ICN_APB3>,
<&scmi_clk CK_SCMI_ICN_APB4>,
<&scmi_clk CK_SCMI_ICN_APBDBG>,
<&scmi_clk CK_SCMI_TIMG1>,
<&scmi_clk CK_SCMI_TIMG2>,
<&scmi_clk CK_SCMI_PLL3>,
<&clk_dsi_txbyte>;
};
...
@@ -0,0 +1,60 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/ti,keystone,psc-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI Keystone PSC clock
maintainers:
- Santosh Shilimkar <santosh.shilimkar@ti.com>
- Murali Karicheri <m-karicheri2@ti.com>
properties:
compatible:
const: ti,keystone,psc-clock
reg:
items:
- description: PSC control
- description: Domain
reg-names:
items:
- const: control
- const: domain
domain-id:
$ref: /schemas/types.yaml#/definitions/uint32
description: PSC domain id needed to check the transition state register
clocks:
maxItems: 1
clock-output-names:
maxItems: 1
"#clock-cells":
const: 0
required:
- compatible
- reg
- reg-names
- domain-id
- clocks
- "#clock-cells"
additionalProperties: false
examples:
- |
clkusb@2350008 {
compatible = "ti,keystone,psc-clock";
reg = <0x02350008 0xb00>, <0x02350000 0x400>;
reg-names = "control", "domain";
domain-id = <0>;
clocks = <&chipclk16>;
clock-output-names = "usb";
#clock-cells = <0>;
};
@@ -1,43 +0,0 @@
Binding for Texas Instruments APLL clock.
This binding uses the common clock binding[1]. It assumes a
register-mapped APLL with usually two selectable input clocks
(reference clock and bypass clock), with analog phase locked
loop logic for multiplying the input clock to a desired output
clock. This clock also typically supports different operation
modes (locked, low power stop etc.) APLL mostly behaves like
a subtype of a DPLL [2], although a simplified one at that.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
Required properties:
- compatible : shall be "ti,dra7-apll-clock" or "ti,omap2-apll-clock"
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
- reg : address and length of the register set for controlling the APLL.
It contains the information of registers in the following order:
"control" - contains the control register offset
"idlest" - contains the idlest register offset
"autoidle" - contains the autoidle register offset (OMAP2 only)
- ti,clock-frequency : static clock frequency for the clock (OMAP2 only)
- ti,idlest-shift : bit-shift for the idlest field (OMAP2 only)
- ti,bit-shift : bit-shift for enable and autoidle fields (OMAP2 only)
Examples:
apll_pcie_ck: apll_pcie_ck {
#clock-cells = <0>;
clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
reg = <0x021c>, <0x0220>;
compatible = "ti,dra7-apll-clock";
};
apll96_ck: apll96_ck {
#clock-cells = <0>;
compatible = "ti,omap2-apll-clock";
clocks = <&sys_ck>;
ti,bit-shift = <2>;
ti,idlest-shift = <8>;
ti,clock-frequency = <96000000>;
reg = <0x0500>, <0x0530>, <0x0520>;
};
@@ -1,25 +0,0 @@
Binding for Texas Instruments clockdomain.
This binding uses the common clock binding[1] in consumer role.
Every clock on TI SoC belongs to one clockdomain, but software
only needs this information for specific clocks which require
their parent clockdomain to be controlled when the clock is
enabled/disabled. This binding doesn't define a new clock
binding type, it is used to group existing clock nodes under
hardware hierarchy.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be "ti,clockdomain"
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : link phandles of clocks within this domain
Optional properties:
- clock-output-names : from common clock binding.
Examples:
dss_clkdm: dss_clkdm {
compatible = "ti,clockdomain";
clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
};
@@ -0,0 +1,89 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/ti/ti,apll-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments APLL clock
maintainers:
- Eduard Bostina <egbostina@gmail.com>
allOf:
- $ref: /schemas/clock/clock.yaml#
description:
This binding assumes a register-mapped APLL with usually two selectable
input clocks (reference clock and bypass clock), with analog phase locked
loop logic for multiplying the input clock to a desired output clock.
This clock also typically supports different operation modes (locked, low
power stop etc.) APLL mostly behaves like a subtype of a DPLL, although
a simplified one at that.
properties:
compatible:
enum:
- ti,dra7-apll-clock
- ti,omap2-apll-clock
"#clock-cells":
const: 0
clocks:
minItems: 1
maxItems: 2
description: Link phandles of parent clocks (clk-ref and clk-bypass)
reg:
minItems: 2
maxItems: 3
description: |
Address and length of the register set for controlling the APLL.
It contains the information of registers in the following order:
"control" - contains the control register offset
"idlest" - contains the idlest register offset
"autoidle" - contains the autoidle register offset (OMAP2 only)
ti,clock-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
description: static clock frequency for the clock (OMAP2 only)
ti,idlest-shift:
$ref: /schemas/types.yaml#/definitions/uint32
description: bit-shift for the idlest field (OMAP2 only)
ti,bit-shift:
$ref: /schemas/types.yaml#/definitions/uint32
description: bit-shift for enable and autoidle fields (OMAP2 only)
required:
- compatible
- "#clock-cells"
- clocks
- reg
unevaluatedProperties: false
examples:
- |
bus {
#address-cells = <1>;
#size-cells = <0>;
clock@21c {
#clock-cells = <0>;
compatible = "ti,dra7-apll-clock";
clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
reg = <0x021c>, <0x0220>;
};
clock@500 {
#clock-cells = <0>;
compatible = "ti,omap2-apll-clock";
clocks = <&sys_ck>;
ti,bit-shift = <2>;
ti,idlest-shift = <8>;
ti,clock-frequency = <96000000>;
reg = <0x0500>, <0x0530>, <0x0520>;
};
};
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/ti/ti,clockdomain.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments clockdomain
maintainers:
- Tero Kristo <kristo@kernel.org>
description:
This binding uses the common clock binding in consumer role. Every clock on TI
SoC belongs to one clockdomain, but software only needs this information for
specific clocks which require their parent clockdomain to be controlled when
the clock is enabled/disabled. This binding doesn't define a new clock binding
type, it is used to group existing clock nodes under hardware hierarchy.
properties:
compatible:
const: ti,clockdomain
"#clock-cells":
const: 0
clocks:
minItems: 1
maxItems: 64
clock-output-names:
maxItems: 1
required:
- compatible
- clocks
additionalProperties: false
examples:
- |
dss_clkdm {
compatible = "ti,clockdomain";
clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
};
@@ -19,7 +19,7 @@ description: |
that is used.
[1] Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
[2] Documentation/devicetree/bindings/clock/ti/clockdomain.txt
[2] Documentation/devicetree/bindings/clock/ti/ti,clockdomain.yaml
properties:
compatible:
@@ -0,0 +1,60 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/ultrarisc,dp1000-clk.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: UltraRISC DP1000 Clock Controller
maintainers:
- Jia Wang <wangjia@ultrarisc.com>
description: |
The UltraRISC DP1000 clock controller is driven from a single external
oscillator input. It provides a system PLL with fractional multiplier
and post-divider stages, several fixed-ratio derived clocks for
the on-chip subsystem, Clock Configuration Register (CCR) divider
outputs for GMAC and the UART, I2C, and SPI root clocks, and
per-instance gate clocks for UART0-3, I2C0-3, and SPI0-1.
All available clocks are defined as preprocessor macros in
include/dt-bindings/clock/ultrarisc,dp1000-clk.h
properties:
compatible:
const: ultrarisc,dp1000-clk
reg:
maxItems: 1
clocks:
maxItems: 1
description:
External oscillator input clock used as the parent of the PLLs.
"#clock-cells":
const: 1
required:
- compatible
- reg
- clocks
- "#clock-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/ultrarisc,dp1000-clk.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
clock-controller@11080000 {
compatible = "ultrarisc,dp1000-clk";
reg = <0x0 0x11080000 0x0 0x1000>;
clocks = <&osc>;
#clock-cells = <1>;
};
};
@@ -70,7 +70,7 @@ additionalProperties: false
examples:
- |
clock-controller@b0000000 {
clock-controller@b0000000 {
compatible = "xlnx,clocking-wizard";
reg = <0xb0000000 0x10000>;
#clock-cells = <1>;
@@ -75,7 +75,7 @@ SoCs only:
- clocks: Should contain the device's input clock, and should be
defined as per the bindings in,
Documentation/devicetree/bindings/clock/keystone-gate.txt
Documentation/devicetree/bindings/clock/ti,keystone,psc-clock.yaml
The following are mandatory properties for Keystone 2 66AK2G SoCs only:
@@ -0,0 +1,42 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/qcom,shikra-audiocore-csr.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Audio Core CSR for Qualcomm Shikra SoC
maintainers:
- Imran Shaik <imran.shaik@oss.qualcomm.com>
description: |
Audio Core CSR module provides the resets on Qualcomm Shikra SoC platform.
See also:
- include/dt-bindings/clock/qcom,shikra-audiocorecc.h
properties:
compatible:
const: qcom,shikra-audiocore-csr
reg:
maxItems: 1
'#reset-cells':
const: 1
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
reset-controller@a0b4000 {
compatible = "qcom,shikra-audiocore-csr";
reg = <0x0a0b4000 0x1000>;
#reset-cells = <1>;
};
...
@@ -33,6 +33,7 @@ properties:
- enum:
- allwinner,sun20i-d1-rtc
- allwinner,sun55i-a523-rtc
- allwinner,sun60i-a733-rtc
- const: allwinner,sun50i-r329-rtc
reg:
@@ -175,6 +176,18 @@ allOf:
interrupts:
minItems: 2
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun50i-h616-rtc
- allwinner,sun50i-r329-rtc
then:
properties:
clock-output-names: false
required:
- "#clock-cells"
- compatible
@@ -0,0 +1,92 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/cix/cix,sky1-audss-cru.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cix Sky1 audio subsystem clock and reset unit
maintainers:
- Joakim Zhang <joakim.zhang@cixtech.com>
description: |
The Cix Sky1 Audio Subsystem (AUDSS) Clock and Reset Unit (CRU) groups
audio-related clock muxing, gating and block-level software reset control
in a single register block.
A single device node exposes both the clock controller and software reset
lines. The clock driver registers as a platform driver; the reset controller
is registered by an auxiliary driver bound from the clock driver.
Four SoC-level reference clocks listed in clocks/clock-names feed the AUDSS
clock tree. Internal AUDSS clocks are exposed via #clock-cells; indices are
defined in include/dt-bindings/clock/cix,sky1-audss-cru.h.
Block-level software reset indices are exposed via #reset-cells; indices
are defined in include/dt-bindings/reset/cix,sky1-audss-cru.h.
The SoC syscon NoC (or bus) reset is described via resets. The audio
subsystem power domain is described via power-domains.
properties:
compatible:
const: cix,sky1-audss-cru
reg:
maxItems: 1
'#clock-cells':
const: 1
description:
Clock indices are defined in include/dt-bindings/clock/cix,sky1-audss-cru.h.
'#reset-cells':
const: 1
description:
Reset indices are defined in include/dt-bindings/reset/cix,sky1-audss-cru.h.
clocks:
items:
- description: I2S parent clock for sampling rates multiple of 8kHz.
- description: I2S parent clock for sampling rates multiple of 11.025kHz.
- description: Clock feeding most devices in AUDSS (NOC, DSP, SRAM, HDA, DMAC, I2S, and mailbox).
- description: Clock feeding HDA, timer and watchdog, which is a dedicated 48 MHz clock.
clock-names:
items:
- const: x8k
- const: x11k
- const: sys
- const: 48m
power-domains:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- '#clock-cells'
- '#reset-cells'
- clocks
- clock-names
- power-domains
- resets
additionalProperties: false
examples:
- |
audss_cru: clock-controller@7110000 {
compatible = "cix,sky1-audss-cru";
reg = <0x7110000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
clocks = <&scmi_clk 76>, <&scmi_clk 78>,
<&scmi_clk 70>, <&scmi_clk 71>;
clock-names = "x8k", "x11k", "sys", "48m";
power-domains = <&smc_devpd 0>;
resets = <&s5_syscon 31>;
};
@@ -0,0 +1,192 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/mobileye/mobileye,eyeq7h-olb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mobileye EyeQ7H SoC system controller
maintainers:
- Benoît Monin <benoit.monin@bootlin.com>
- Grégory Clement <gregory.clement@bootlin.com>
- Théo Lebrun <theo.lebrun@bootlin.com>
- Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
description:
OLB ("Other Logic Block") is a hardware system controller grouping
smaller blocks. Clocks and resets are generated by those blocks and
used by internal controllers of the SoC. The EyeQ7H SoC hosts 14
different OLB.
properties:
compatible:
items:
- enum:
- mobileye,eyeq7h-acc0-olb
- mobileye,eyeq7h-acc1-olb
- mobileye,eyeq7h-ddr0-olb
- mobileye,eyeq7h-ddr1-olb
- mobileye,eyeq7h-east-olb
- mobileye,eyeq7h-mips0-olb
- mobileye,eyeq7h-mips1-olb
- mobileye,eyeq7h-mips2-olb
- mobileye,eyeq7h-periph-east-olb
- mobileye,eyeq7h-periph-west-olb
- mobileye,eyeq7h-south-olb
- mobileye,eyeq7h-west-olb
- mobileye,eyeq7h-xnn0-olb
- mobileye,eyeq7h-xnn1-olb
- const: syscon
reg:
maxItems: 1
'#reset-cells':
description:
First cell is domain and optional if compatible has a single reset domain.
Second cell is reset index inside that domain.
enum: [ 1, 2 ]
'#clock-cells':
const: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
maxItems: 2
required:
- compatible
- reg
- '#clock-cells'
- clocks
- clock-names
allOf:
- if:
properties:
compatible:
contains:
enum:
- mobileye,eyeq7h-ddr0-olb
- mobileye,eyeq7h-ddr1-olb
- mobileye,eyeq7h-mips0-olb
- mobileye,eyeq7h-mips1-olb
- mobileye,eyeq7h-mips2-olb
- mobileye,eyeq7h-periph-east-olb
- mobileye,eyeq7h-south-olb
then:
properties:
clocks:
items:
- description: Reference input clock.
clock-names:
items:
- const: ref
- if:
properties:
compatible:
contains:
enum:
- mobileye,eyeq7h-east-olb
- mobileye,eyeq7h-west-olb
then:
properties:
clocks:
items:
- description: Reference input clock from the main oscillator.
- description: 100MHz reference input clock.
clock-names:
items:
- const: ref
- const: ref_100p0
- if:
properties:
compatible:
contains:
enum:
- mobileye,eyeq7h-acc0-olb
- mobileye,eyeq7h-acc1-olb
- mobileye,eyeq7h-periph-west-olb
- mobileye,eyeq7h-xnn0-olb
- mobileye,eyeq7h-xnn1-olb
then:
properties:
clocks:
items:
- description: 100MHz reference input clock.
- description: 106.6MHz reference input clock.
clock-names:
items:
- const: ref_100p0
- const: ref_106p6
- if:
properties:
compatible:
contains:
enum:
- mobileye,eyeq7h-ddr0-olb
- mobileye,eyeq7h-ddr1-olb
- mobileye,eyeq7h-east-olb
- mobileye,eyeq7h-periph-east-olb
- mobileye,eyeq7h-periph-west-olb
- mobileye,eyeq7h-west-olb
then:
properties:
'#reset-cells':
const: 1
required:
- '#reset-cells'
- if:
properties:
compatible:
contains:
enum:
- mobileye,eyeq7h-acc0-olb
- mobileye,eyeq7h-acc1-olb
- mobileye,eyeq7h-south-olb
- mobileye,eyeq7h-xnn0-olb
- mobileye,eyeq7h-xnn1-olb
then:
properties:
'#reset-cells':
const: 2
required:
- '#reset-cells'
- if:
properties:
compatible:
contains:
enum:
- mobileye,eyeq7h-mips0-olb
- mobileye,eyeq7h-mips1-olb
- mobileye,eyeq7h-mips2-olb
then:
properties:
'#reset-cells': false
additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
system-controller0@45000000 {
compatible = "mobileye,eyeq7h-acc0-olb", "syscon";
reg = <0x0 0x45000000 0x0 0x1000>;
#reset-cells = <2>;
#clock-cells = <1>;
clocks = <&olb_south 7>, <&olb_east 5>;
clock-names = "ref_100p0", "ref_106p6";
};
};
+12 -46
View File
@@ -42,21 +42,8 @@ clock interface.
Common data structures and api
==============================
Below is the common struct clk_core definition from
drivers/clk/clk.c, modified for brevity::
struct clk_core {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
struct clk_core *parent;
const char **parent_names;
struct clk_core **parents;
u8 num_parents;
u8 new_parent_index;
...
};
.. kernel-doc:: drivers/clk/clk.c
:identifiers: struct clk_core
The members above make up the core of the clk tree topology. The clk
api itself defines several driver-facing functions which operate on
@@ -64,38 +51,17 @@ struct clk. That api is documented in include/linux/clk.h.
Platforms and devices utilizing the common struct clk_core use the struct
clk_ops pointer in struct clk_core to perform the hardware-specific parts of
the operations defined in clk-provider.h::
the operations defined in clk-provider.h, and can set one or more
framework-level flags documented below.
struct clk_ops {
int (*prepare)(struct clk_hw *hw);
void (*unprepare)(struct clk_hw *hw);
int (*is_prepared)(struct clk_hw *hw);
void (*unprepare_unused)(struct clk_hw *hw);
int (*enable)(struct clk_hw *hw);
void (*disable)(struct clk_hw *hw);
int (*is_enabled)(struct clk_hw *hw);
void (*disable_unused)(struct clk_hw *hw);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
int (*determine_rate)(struct clk_hw *hw,
struct clk_rate_request *req);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate);
int (*set_rate_and_parent)(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate,
u8 index);
unsigned long (*recalc_accuracy)(struct clk_hw *hw,
unsigned long parent_accuracy);
int (*get_phase)(struct clk_hw *hw);
int (*set_phase)(struct clk_hw *hw, int degrees);
void (*init)(struct clk_hw *hw);
void (*debug_init)(struct clk_hw *hw,
struct dentry *dentry);
};
.. kernel-doc:: include/linux/clk-provider.h
:identifiers: struct clk_ops
Core flags
==========
.. kernel-doc:: include/linux/clk-provider.h
:doc: clk framework flags
Hardware clk implementations
============================
@@ -248,6 +248,7 @@ CLOCK
devm_clk_put()
devm_clk_bulk_get()
devm_clk_bulk_get_all()
devm_clk_bulk_get_enable()
devm_clk_bulk_get_optional()
devm_get_clk_from_child()
devm_clk_hw_register()
+17 -6
View File
@@ -6494,9 +6494,9 @@ F: include/linux/comedi/
F: include/uapi/linux/comedi.h
COMMON CLK FRAMEWORK
M: Michael Turquette <mturquette@baylibre.com>
M: Stephen Boyd <sboyd@kernel.org>
R: Brian Masney <bmasney@redhat.com>
M: Brian Masney <bmasney+clk@redhat.com>
M: Jerome Brunet <jbrunet+clk@baylibre.com>
L: linux-clk@vger.kernel.org
S: Maintained
Q: http://patchwork.kernel.org/project/linux-clk/list/
@@ -9729,9 +9729,10 @@ ESWIN EIC7700 CLOCK DRIVER
M: Yifeng Huang <huangyifeng@eswincomputing.com>
M: Xuyang Dong <dongxuyang@eswincomputing.com>
S: Maintained
F: Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
F: Documentation/devicetree/bindings/clock/eswin,eic7700*
F: drivers/clk/eswin/
F: include/dt-bindings/clock/eswin,eic7700-clock.h
F: include/dt-bindings/clock/eswin,eic7700*
F: include/dt-bindings/reset/eswin,eic7700-hspcrg.h
ET131X NETWORK DRIVER
M: Mark Einon <mark.einon@gmail.com>
@@ -23337,10 +23338,12 @@ L: linux-renesas-soc@vger.kernel.org
S: Maintained
F: drivers/phy/renesas/phy-rcar-gen3-usb*.c
RENESAS VERSACLOCK 7 CLOCK DRIVER
M: Alex Helms <alexander.helms.jy@renesas.com>
RENESAS VERSACLOCK 3 and VERSACLOCK 7 CLOCK DRIVER
M: Biju Das <biju.das.jz@bp.renesas.com>
S: Maintained
F: Documentation/devicetree/bindings/clock/renesas,5p35023.yaml
F: Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml
F: drivers/clk/clk-versaclock3.c
F: drivers/clk/clk-versaclock7.c
RENESAS X9250 DIGITAL POTENTIOMETERS DRIVER
@@ -27967,6 +27970,14 @@ S: Maintained
F: drivers/usb/common/ulpi.c
F: include/linux/ulpi/
ULTRARISC DP1000 CLOCK DRIVER
M: Jia Wang <wangjia@ultrarisc.com>
L: linux-clk@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/clock/ultrarisc,dp1000-clk.yaml
F: drivers/clk/ultrarisc/*
F: include/dt-bindings/clock/ultrarisc,dp1000-clk.h
ULTRARISC DP1000 PINCTRL DRIVER
M: Jia Wang <wangjia@ultrarisc.com>
L: linux-gpio@vger.kernel.org
+18
View File
@@ -6,6 +6,10 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/cix,sky1.h>
#include <dt-bindings/clock/cix,sky1-audss-cru.h>
#include <dt-bindings/reset/cix,sky1-system-control.h>
#include <dt-bindings/reset/cix,sky1-s5-system-control.h>
#include <dt-bindings/reset/cix,sky1-audss-cru.h>
#include "sky1-power.h"
/ {
@@ -572,6 +576,20 @@
cix,mbox-dir = "rx";
};
audss_cru: clock-controller@7110000 {
compatible = "cix,sky1-audss-cru";
reg = <0x0 0x07110000 0x0 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
clocks = <&scmi_clk CLK_TREE_AUDIO_CLK0>,
<&scmi_clk CLK_TREE_AUDIO_CLK2>,
<&scmi_clk CLK_TREE_AUDIO_CLK4>,
<&scmi_clk CLK_TREE_AUDIO_CLK5>;
clock-names = "x8k", "x11k", "sys", "48m";
power-domains = <&smc_devpd SKY1_PD_AUDIO>;
resets = <&s5_syscon SKY1_AUDIO_HIFI5_NOC_RESET_N>;
};
mbox_sfh2ap: mailbox@8090000 {
compatible = "cix,sky1-mbox";
reg = <0x0 0x08090000 0x0 0x10000>;
+1
View File
@@ -4,6 +4,7 @@ CONFIG_OF=y
CONFIG_OF_OVERLAY=y
CONFIG_COMMON_CLK=y
CONFIG_CLK_KUNIT_TEST=y
CONFIG_CLK_DIVIDER_KUNIT_TEST=y
CONFIG_CLK_FIXED_RATE_KUNIT_TEST=y
CONFIG_CLK_GATE_KUNIT_TEST=y
CONFIG_CLK_FD_KUNIT_TEST=y
+14 -4
View File
@@ -155,12 +155,12 @@ config COMMON_CLK_SI514
generator.
config COMMON_CLK_SI544
tristate "Clock driver for SiLabs 544 devices"
tristate "Clock driver for SiLabs 544 and compatible devices"
depends on I2C
select REGMAP_I2C
help
This driver supports the Silicon Labs 544 programmable clock
generator.
This driver supports the Silicon Labs 544/549 programmable clock
generators.
config COMMON_CLK_SI570
tristate "Clock driver for SiLabs 570 and compatible devices"
@@ -278,7 +278,7 @@ config COMMON_CLK_LAN966X
tristate "Generic Clock Controller driver for LAN966X SoC"
depends on HAS_IOMEM
depends on OF
depends on SOC_LAN966 || ARCH_LAN969X || COMPILE_TEST
depends on SOC_LAN966 || ARCH_LAN969X || MCHP_LAN966X_PCI || COMPILE_TEST
help
This driver provides support for Generic Clock Controller(GCK) on
LAN966X SoC. GCK generates and supplies clock to various peripherals
@@ -509,6 +509,7 @@ source "drivers/clk/actions/Kconfig"
source "drivers/clk/analogbits/Kconfig"
source "drivers/clk/aspeed/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/cix/Kconfig"
source "drivers/clk/eswin/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
@@ -541,6 +542,7 @@ source "drivers/clk/tenstorrent/Kconfig"
source "drivers/clk/thead/Kconfig"
source "drivers/clk/stm32/Kconfig"
source "drivers/clk/ti/Kconfig"
source "drivers/clk/ultrarisc/Kconfig"
source "drivers/clk/uniphier/Kconfig"
source "drivers/clk/visconti/Kconfig"
source "drivers/clk/x86/Kconfig"
@@ -579,4 +581,12 @@ config CLK_FD_KUNIT_TEST
help
Kunit test for the clk-fractional-divider type.
config CLK_DIVIDER_KUNIT_TEST
tristate "KUnit tests for clk divider bestdiv" if !KUNIT_ALL_TESTS
depends on KUNIT
depends on !S390
default KUNIT_ALL_TESTS
help
Kunit test for the clk-divider type.
endif
+18 -4
View File
@@ -18,9 +18,20 @@ clk-test-y := clk_test.o \
kunit_clk_assigned_rates_without_consumer.dtbo.o \
kunit_clk_assigned_rates_zero.dtbo.o \
kunit_clk_assigned_rates_zero_consumer.dtbo.o \
kunit_clk_assigned_sscs_one.dtbo.o \
kunit_clk_assigned_sscs_one_consumer.dtbo.o \
kunit_clk_assigned_sscs_multiple.dtbo.o \
kunit_clk_assigned_sscs_multiple_consumer.dtbo.o \
kunit_clk_assigned_sscs_null.dtbo.o \
kunit_clk_assigned_sscs_null_consumer.dtbo.o \
kunit_clk_assigned_sscs_without.dtbo.o \
kunit_clk_assigned_sscs_without_consumer.dtbo.o \
kunit_clk_assigned_sscs_zero.dtbo.o \
kunit_clk_assigned_sscs_zero_consumer.dtbo.o \
kunit_clk_hw_get_dev_of_node.dtbo.o \
kunit_clk_parent_data_test.dtbo.o
obj-$(CONFIG_COMMON_CLK) += clk-divider.o
obj-$(CONFIG_CLK_DIVIDER_KUNIT_TEST) += clk-divider_test.o
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
obj-$(CONFIG_CLK_FIXED_RATE_KUNIT_TEST) += clk-fixed-rate-test.o
@@ -88,7 +99,8 @@ obj-$(CONFIG_COMMON_CLK_RP1) += clk-rp1.o
obj-$(CONFIG_COMMON_CLK_RPMI) += clk-rpmi.o
obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
scmi-clk-y := clk-scmi.o clk-scmi-oem.o
obj-$(CONFIG_COMMON_CLK_SCMI) += scmi-clk.o
obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
obj-$(CONFIG_COMMON_CLK_SI5341) += clk-si5341.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
@@ -119,9 +131,10 @@ obj-$(CONFIG_ARCH_ARTPEC) += axis/
obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-y += cix/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_COMMON_CLK_ESWIN) += eswin/
obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_COMMON_CLK_HISI) += hisilicon/
obj-y += imgtec/
obj-y += imx/
obj-y += ingenic/
@@ -151,14 +164,15 @@ obj-y += spacemit/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-y += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_STM32) += stm32/
obj-$(CONFIG_COMMON_CLK_STM32MP) += stm32/
obj-y += starfive/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-y += sunxi-ng/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += tenstorrent/
obj-$(CONFIG_ARCH_THEAD) += thead/
obj-y += thead/
obj-y += ti/
obj-y += ultrarisc/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-y += versatile/
+10
View File
@@ -272,6 +272,13 @@ static const unsigned int sdclk_parent_ids[] = {
static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)];
static const unsigned int peciclk_parent_ids[] = {
SCU1_CLKIN,
SCU1_CLK_HPLL_DIV4
};
static const struct clk_hw *peciclk_parent_hws[ARRAY_SIZE(peciclk_parent_ids)];
#define FIXED_CLK(_id, _name, _rate) \
{ \
.id = _id, \
@@ -457,6 +464,7 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM),
PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM),
PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM),
FIXED_FACTOR_CLK(SCU1_CLK_HPLL_DIV4, "soc1-hpll_div4", SCU1_CLK_HPLL, 1, 4),
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2),
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4),
FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10),
@@ -480,6 +488,8 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2),
MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2),
MUX_CLK(SCU1_CLK_PECI, "peciclk", peciclk_parent_ids, ARRAY_SIZE(peciclk_parent_ids),
peciclk_parent_hws, SCU1_CLK_SEL2, 16, 1),
DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX,
SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table),
PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL),
+3 -2
View File
@@ -2,6 +2,7 @@
#include <linux/clk-provider.h>
#include <linux/clk/at91_pmc.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -217,7 +218,7 @@ CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
{
struct regmap *regmap_sfr;
u8 bus_id;
u64 bus_id;
const char *parent_names[2];
struct device_node *i2s_mux_np;
struct clk_hw *hw;
@@ -228,7 +229,7 @@ static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
return;
for_each_child_of_node(np, i2s_mux_np) {
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
if (of_property_read_reg(i2s_mux_np, 0, &bus_id, NULL))
continue;
if (bus_id > I2S_BUS_NR)
+1 -2
View File
@@ -1098,8 +1098,7 @@ static u8 kona_peri_clk_get_parent(struct clk_hw *hw)
index = selector_read_index(bcm_clk->ccu, &data->sel);
/* Not all callers would handle an out-of-range value gracefully */
return index == BAD_CLK_INDEX ? 0 : index;
return index;
}
static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+16
View File
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
# Audio subsystem clock support for Cixtech SoC family
menu "Cixtech Audio Subsystem Clock Driver"
config CLK_SKY1_AUDSS
tristate "Cixtech Sky1 Audio Subsystem Clock Driver"
depends on ARCH_CIX || COMPILE_TEST
select AUXILIARY_BUS
select REGMAP_MMIO
select RESET_CONTROLLER
help
Support for the Audio Subsystem clock controller present on
Cixtech Sky1 SoC. This driver provides mux, divider and gate
clocks for DSP, I2S, HDA and related blocks in the audio
subsystem. Say M or Y here if you want to build this driver.
endmenu
+3
View File
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CLK_SKY1_AUDSS) += clk-sky1-audss.o
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -147,12 +147,12 @@ static int bd71837_clk_probe(struct platform_device *pdev)
}
static const struct platform_device_id bd718x7_clk_id[] = {
{ "bd71837-clk", ROHM_CHIP_TYPE_BD71837 },
{ "bd71847-clk", ROHM_CHIP_TYPE_BD71847 },
{ "bd71828-clk", ROHM_CHIP_TYPE_BD71828 },
{ "bd71815-clk", ROHM_CHIP_TYPE_BD71815 },
{ "bd72720-clk", ROHM_CHIP_TYPE_BD72720 },
{ },
{ .name = "bd71837-clk", .driver_data = ROHM_CHIP_TYPE_BD71837 },
{ .name = "bd71847-clk", .driver_data = ROHM_CHIP_TYPE_BD71847 },
{ .name = "bd71828-clk", .driver_data = ROHM_CHIP_TYPE_BD71828 },
{ .name = "bd71815-clk", .driver_data = ROHM_CHIP_TYPE_BD71815 },
{ .name = "bd72720-clk", .driver_data = ROHM_CHIP_TYPE_BD72720 },
{ }
};
MODULE_DEVICE_TABLE(platform, bd718x7_clk_id);
+1 -1
View File
@@ -679,7 +679,7 @@ MODULE_DEVICE_TABLE(of, cdce706_dt_match);
#endif
static const struct i2c_device_id cdce706_id[] = {
{ "cdce706" },
{ .name = "cdce706" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cdce706_id);
+4 -4
View File
@@ -826,10 +826,10 @@ static const struct clk_cdce925_chip_info clk_cdce949_info = {
};
static const struct i2c_device_id cdce925_id[] = {
{ "cdce913", (kernel_ulong_t)&clk_cdce913_info },
{ "cdce925", (kernel_ulong_t)&clk_cdce925_info },
{ "cdce937", (kernel_ulong_t)&clk_cdce937_info },
{ "cdce949", (kernel_ulong_t)&clk_cdce949_info },
{ .name = "cdce913", .driver_data = (kernel_ulong_t)&clk_cdce913_info },
{ .name = "cdce925", .driver_data = (kernel_ulong_t)&clk_cdce925_info },
{ .name = "cdce937", .driver_data = (kernel_ulong_t)&clk_cdce937_info },
{ .name = "cdce949", .driver_data = (kernel_ulong_t)&clk_cdce949_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, cdce925_id);
+1
View File
@@ -462,3 +462,4 @@ struct clk_hw *devm_clk_hw_register_composite_pdata(struct device *dev,
rate_hw, rate_ops, gate_hw,
gate_ops, flags);
}
EXPORT_SYMBOL_GPL(devm_clk_hw_register_composite_pdata);
+76
View File
@@ -155,6 +155,78 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
return 0;
}
static int __set_clk_spread_spectrum(struct device_node *node, bool clk_supplier)
{
u32 elem_size = sizeof(struct clk_spread_spectrum);
struct clk_spread_spectrum *sscs;
struct of_phandle_args clkspec;
int rc, count, index;
struct clk *clk;
/* modfreq, spreadPercent, modmethod */
count = of_property_count_elems_of_size(node, "assigned-clock-sscs", elem_size);
if (count <= 0)
return 0;
sscs = kcalloc(count, elem_size, GFP_KERNEL);
if (!sscs)
return -ENOMEM;
rc = of_property_read_u32_array(node, "assigned-clock-sscs", (u32 *)sscs,
count * 3);
if (rc)
goto free_sscs;
for (index = 0; index < count; index++) {
struct clk_spread_spectrum *conf = &sscs[index];
struct clk_hw *hw;
if (!conf->modfreq_hz && !conf->spread_bp && !conf->method)
continue;
rc = of_parse_phandle_with_args(node, "assigned-clocks", "#clock-cells",
index, &clkspec);
if (rc < 0) {
/* skip empty (null) phandles */
if (rc == -ENOENT) {
rc = 0;
continue;
} else
goto free_sscs;
}
if (clkspec.np == node && !clk_supplier) {
of_node_put(clkspec.np);
goto free_sscs;
}
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",
index, node);
rc = PTR_ERR(clk);
goto free_sscs;
}
hw = __clk_get_hw(clk);
rc = clk_hw_set_spread_spectrum(hw, conf);
if (rc < 0) {
pr_err("clk: couldn't set %s clk spread spectrum %u %u %u: %d\n",
__clk_get_name(clk), conf->modfreq_hz, conf->spread_bp,
conf->method, rc);
/* Do not fail */
rc = 0;
}
clk_put(clk);
}
free_sscs:
kfree(sscs);
return rc;
}
/**
* of_clk_set_defaults() - parse and set assigned clocks configuration
* @node: device node to apply clock settings for
@@ -174,6 +246,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
if (!node)
return 0;
rc = __set_clk_spread_spectrum(node, clk_supplier);
if (rc < 0)
return rc;
rc = __set_clk_parents(node, clk_supplier);
if (rc < 0)
return rc;
+3 -7
View File
@@ -122,8 +122,8 @@ static const struct of_device_id cs2000_of_match[] = {
MODULE_DEVICE_TABLE(of, cs2000_of_match);
static const struct i2c_device_id cs2000_id[] = {
{ "cs2000-cp", },
{}
{ .name = "cs2000-cp" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs2000_id);
@@ -404,11 +404,7 @@ static int cs2000_enable(struct clk_hw *hw)
if (ret < 0)
return ret;
ret = cs2000_wait_pll_lock(priv);
if (ret < 0)
return ret;
return ret;
return cs2000_wait_pll_lock(priv);
}
static void cs2000_disable(struct clk_hw *hw)
+17 -2
View File
@@ -99,6 +99,11 @@ struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
}
EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
static void devm_clk_disable_unprepare(void *data)
{
clk_disable_unprepare(data);
}
struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
const char *id,
unsigned long rate)
@@ -106,8 +111,7 @@ struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
struct clk *clk;
int ret;
clk = __devm_clk_get(dev, id, clk_get_optional, NULL,
clk_disable_unprepare);
clk = devm_clk_get_optional(dev, id);
if (IS_ERR(clk))
return ERR_CAST(clk);
@@ -119,6 +123,10 @@ struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
if (ret)
goto out_put_clk;
ret = devm_add_action_or_reset(dev, devm_clk_disable_unprepare, clk);
if (ret)
goto out_put_clk;
return clk;
out_put_clk:
@@ -222,6 +230,13 @@ err_clk_get:
return ret;
}
int __must_check devm_clk_bulk_get_enable(struct device *dev, int num_clks,
struct clk_bulk_data *clks)
{
return __devm_clk_bulk_get_enable(dev, num_clks, clks, false);
}
EXPORT_SYMBOL_GPL(devm_clk_bulk_get_enable);
int __must_check devm_clk_bulk_get_optional_enable(struct device *dev, int num_clks,
struct clk_bulk_data *clks)
{
+17 -8
View File
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/string.h>
#include <linux/log2.h>
#include <linux/overflow.h>
/*
* DOC: basic adjustable divider clock that cannot gate
@@ -301,6 +302,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
int i, bestdiv = 0;
unsigned long parent_rate, best = 0, now, maxdiv;
unsigned long parent_rate_saved = *best_parent_rate;
unsigned long target_parent_rate;
if (!rate)
rate = 1;
@@ -315,15 +317,11 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
return bestdiv;
}
/*
* The maximum divider we can use without overflowing
* unsigned long in rate * i below
*/
maxdiv = min(ULONG_MAX / rate, maxdiv);
for (i = _next_div(table, 0, flags); i <= maxdiv;
i = _next_div(table, i, flags)) {
if (rate * i == parent_rate_saved) {
bool overflow = check_mul_overflow(rate, (unsigned long)i, &target_parent_rate);
if (!overflow && target_parent_rate == parent_rate_saved) {
/*
* It's the most ideal case if the requested rate can be
* divided from parent clock without needing to change
@@ -332,13 +330,24 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
*best_parent_rate = parent_rate_saved;
return i;
}
parent_rate = clk_hw_round_rate(parent, rate * i);
/*
* Clamp target_parent_rate to ULONG_MAX on overflow. The true
* required parent rate exceeds what can be represented, so ask
* the parent for the highest rate it can produce. There is no
* point continuing the loop past this since larger dividers
* only move further from the requested rate.
*/
if (overflow)
target_parent_rate = ULONG_MAX;
parent_rate = clk_hw_round_rate(parent, target_parent_rate);
now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
if (_is_best_div(rate, now, best, flags)) {
bestdiv = i;
best = now;
*best_parent_rate = parent_rate;
}
if (overflow)
break;
}
if (!bestdiv) {
+153
View File
@@ -0,0 +1,153 @@
// SPDX-License-Identifier: GPL-2.0
/*
* KUnit tests for clk_divider_bestdiv()
*/
#include <kunit/test.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/limits.h>
#include <linux/units.h>
#define PARENT_RATE_1GHZ GIGA
#define PARENT_RATE_2GHZ (2 * GIGA)
#define PARENT_RATE_4GHZ (4 * GIGA)
KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_fixed_rate_wrapper,
clk_hw_unregister_fixed_rate, struct clk_hw *);
KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_divider_wrapper,
clk_hw_unregister_divider, struct clk_hw *);
KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_mux_wrapper,
clk_hw_unregister_mux, struct clk_hw *);
static const struct clk_div_table bestdiv_table[] = {
{ .val = 0, .div = 2 },
{ .val = 1, .div = 4 },
{ .val = 2, .div = 8 },
{ /* sentinel */ }
};
/*
* Test that clk_round_rate(clk, ULONG_MAX) returns the maximum achievable
* rate for a divider clock.
*/
static void clk_divider_bestdiv_ulong_max_returns_max_rate(struct kunit *test)
{
struct clk_hw *parent_hw, *div_hw;
unsigned long rate;
u32 *fake_reg;
fake_reg = kunit_kzalloc(test, sizeof(*fake_reg), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_reg);
parent_hw = clk_hw_register_fixed_rate(NULL, "bestdiv-parent",
NULL, 0, PARENT_RATE_1GHZ);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_hw);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, clk_hw_unregister_fixed_rate_wrapper,
parent_hw));
div_hw = clk_hw_register_divider_table(NULL, "bestdiv-div",
"bestdiv-parent",
CLK_SET_RATE_PARENT,
(void __iomem __force *)fake_reg,
0, 2, 0, bestdiv_table, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, div_hw);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, clk_hw_unregister_divider_wrapper,
div_hw));
/*
* ULONG_MAX is the canonical way to probe the maximum rate a clock
* can produce.
*/
rate = clk_hw_round_rate(div_hw, ULONG_MAX);
KUNIT_EXPECT_EQ(test, rate, PARENT_RATE_1GHZ / 2);
}
/*
* Test that clk_round_rate(clk, ULONG_MAX) returns the correct maximum rate
* when a mux clock sits between a divider and its parent candidates.
*
* Topology:
*
* [fixed 4 GHz] --\
* +--> [mux CLK_SET_RATE_PARENT] --> [div {2,4,8} CLK_SET_RATE_PARENT]
* [fixed 2 GHz] --/
*
*/
static void clk_divider_bestdiv_mux_ulong_max_returns_max_rate(struct kunit *test)
{
static const char * const mux_parents[] = {
"bestdiv-mux-parent-a",
"bestdiv-mux-parent-b",
};
struct clk_hw *parent_a_hw, *parent_b_hw, *mux_hw, *div_hw;
u32 *fake_reg_mux, *fake_reg_div;
unsigned long rate;
fake_reg_mux = kunit_kzalloc(test, sizeof(*fake_reg_mux), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_reg_mux);
fake_reg_div = kunit_kzalloc(test, sizeof(*fake_reg_div), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_reg_div);
/* Higher-rate parent: the mux should select this for ULONG_MAX. */
parent_a_hw = clk_hw_register_fixed_rate(NULL, "bestdiv-mux-parent-a",
NULL, 0, PARENT_RATE_4GHZ);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_a_hw);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, clk_hw_unregister_fixed_rate_wrapper,
parent_a_hw));
/* Lower-rate parent: should not be selected. */
parent_b_hw = clk_hw_register_fixed_rate(NULL, "bestdiv-mux-parent-b",
NULL, 0, PARENT_RATE_2GHZ);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_b_hw);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, clk_hw_unregister_fixed_rate_wrapper,
parent_b_hw));
/*
* 1-bit mux register selects between the two parents.
* CLK_SET_RATE_PARENT allows the divider's rate request to
* propagate into clk_mux_determine_rate().
*/
mux_hw = clk_hw_register_mux(NULL, "bestdiv-mux",
mux_parents, ARRAY_SIZE(mux_parents),
CLK_SET_RATE_PARENT,
(void __iomem __force *)fake_reg_mux,
0, 1, 0, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mux_hw);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, clk_hw_unregister_mux_wrapper,
mux_hw));
div_hw = clk_hw_register_divider_table(NULL, "bestdiv-mux-div",
"bestdiv-mux",
CLK_SET_RATE_PARENT,
(void __iomem __force *)fake_reg_div,
0, 2, 0, bestdiv_table, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, div_hw);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, clk_hw_unregister_divider_wrapper,
div_hw));
rate = clk_hw_round_rate(div_hw, ULONG_MAX);
KUNIT_EXPECT_EQ(test, rate, PARENT_RATE_4GHZ / 2);
}
static struct kunit_case clk_divider_bestdiv_test_cases[] = {
KUNIT_CASE(clk_divider_bestdiv_ulong_max_returns_max_rate),
KUNIT_CASE(clk_divider_bestdiv_mux_ulong_max_returns_max_rate),
{}
};
static struct kunit_suite clk_divider_bestdiv_test_suite = {
.name = "clk_divider_bestdiv",
.test_cases = clk_divider_bestdiv_test_cases,
};
kunit_test_suite(clk_divider_bestdiv_test_suite);
MODULE_DESCRIPTION("KUnit tests for clk divider");
MODULE_LICENSE("GPL");
+33 -10
View File
@@ -57,6 +57,7 @@
#define REG_RST_CTRL2 0x830
#define REG_RST_CTRL1 0x834
#define REG_PCIE_HB_RST BIT(29)
#define EN751221_REG_RST_DMT 0x84
#define EN751221_REG_RST_USB 0xec
@@ -338,6 +339,7 @@ static const struct en_clk_desc en7581_base_clks[] = {
static const u16 en7581_rst_ofs[] = {
REG_RST_CTRL2,
REG_RST_CTRL1,
REG_NP_SCU_PCIC,
};
static const u16 en751221_rst_ofs[] = {
@@ -450,6 +452,11 @@ static const u16 en7581_rst_map[] = {
[EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
[EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
/* RST_PCIC */
[EN7581_PCIC_PERSTOUT0_RST] = 2 * RST_NR_PER_BANK + 29,
[EN7581_PCIC_PERSTOUT1_RST] = 2 * RST_NR_PER_BANK + 26,
[EN7581_PCIC_PERSTOUT2_RST] = 2 * RST_NR_PER_BANK + 16,
};
static const u16 en751221_rst_map[] = {
@@ -635,9 +642,7 @@ static int en7581_pci_enable(struct clk_hw *hw)
void __iomem *np_base = cg->base;
u32 val, mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
REG_PCI_CONTROL_PERSTOUT;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
val = readl(np_base + REG_PCI_CONTROL);
writel(val | mask, np_base + REG_PCI_CONTROL);
@@ -650,9 +655,7 @@ static void en7581_pci_disable(struct clk_hw *hw)
void __iomem *np_base = cg->base;
u32 val, mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
REG_PCI_CONTROL_PERSTOUT;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
val = readl(np_base + REG_PCI_CONTROL);
writel(val & ~mask, np_base + REG_PCI_CONTROL);
usleep_range(1000, 2000);
@@ -754,11 +757,17 @@ static int en7523_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
u32 offset = rst_data->bank_ofs[id / RST_NR_PER_BANK];
void __iomem *addr = rst_data->base + offset;
bool inverted = false;
u32 val;
/* For PCIC reset logic is inverted, 0:assert 1:deassert */
if (offset == REG_NP_SCU_PCIC)
inverted = true;
val = readl(addr);
if (assert)
if (assert ^ inverted)
val |= BIT(id % RST_NR_PER_BANK);
else
val &= ~BIT(id % RST_NR_PER_BANK);
@@ -783,9 +792,17 @@ static int en7523_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
u32 offset = rst_data->bank_ofs[id / RST_NR_PER_BANK];
void __iomem *addr = rst_data->base + offset;
bool inverted = false;
u32 val;
return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
/* For PCIC reset logic is inverted, 0:assert 1:deassert */
if (offset == REG_NP_SCU_PCIC)
inverted = true;
val = readl(addr) & BIT(id % RST_NR_PER_BANK);
return inverted ? !val : !!val;
}
static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
@@ -853,6 +870,12 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
val = readl(base + REG_NP_SCU_PCIC);
writel(val | 3, base + REG_NP_SCU_PCIC);
val = readl(base + REG_RST_CTRL1);
val |= REG_PCIE_HB_RST;
writel(val, base + REG_RST_CTRL1);
val &= ~REG_PCIE_HB_RST;
writel(val, base + REG_RST_CTRL1);
return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
ARRAY_SIZE(en7581_rst_map),
en7581_rst_ofs);
+857 -411
View File
File diff suppressed because it is too large Load Diff
+13 -65
View File
@@ -36,10 +36,14 @@ static int clk_factor_determine_rate(struct clk_hw *hw,
struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
struct clk_hw *parent_hw = clk_hw_get_parent(hw);
unsigned long best_parent;
if (!parent_hw)
return -EINVAL;
best_parent = (req->rate / fix->mult) * fix->div;
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
req->best_parent_rate = clk_hw_round_rate(parent_hw, best_parent);
}
req->rate = (req->best_parent_rate / fix->div) * fix->mult;
@@ -90,7 +94,7 @@ static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *
clk_hw_unregister(&fix->hw);
}
static struct clk_hw *
struct clk_hw *
__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
const char *name, const char *parent_name,
const struct clk_hw *parent_hw, const struct clk_parent_data *pdata,
@@ -124,13 +128,13 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
init.name = name;
init.ops = &clk_fixed_factor_ops;
init.flags = flags;
if (parent_name)
init.parent_names = &parent_name;
else if (parent_hw)
init.parent_hws = &parent_hw;
init.parent_names = parent_name ? &parent_name : NULL;
init.parent_hws = parent_hw ? &parent_hw : NULL;
init.parent_data = pdata;
if (parent_name || parent_hw || pdata)
init.num_parents = 1;
else
init.parent_data = pdata;
init.num_parents = 1;
init.num_parents = 0;
hw = &fix->hw;
if (dev)
@@ -148,6 +152,7 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
return hw;
}
EXPORT_SYMBOL_GPL(__clk_hw_register_fixed_factor);
/**
* devm_clk_hw_register_fixed_factor_index - Register a fixed factor clock with
@@ -173,52 +178,6 @@ struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index);
/**
* devm_clk_hw_register_fixed_factor_parent_hw - Register a fixed factor clock with
* pointer to parent clock
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_hw: pointer to parent clk
* @flags: fixed factor flags
* @mult: multiplier
* @div: divider
*
* Return: Pointer to fixed factor clk_hw structure that was registered or
* an error pointer.
*/
struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev,
const char *name, const struct clk_hw *parent_hw,
unsigned long flags, unsigned int mult, unsigned int div)
{
const struct clk_parent_data pdata = { .index = -1 };
return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw,
&pdata, flags, mult, div, 0, 0, true);
}
EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_parent_hw);
struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev,
const char *name, const struct clk_hw *parent_hw,
unsigned long flags, unsigned int mult, unsigned int div)
{
const struct clk_parent_data pdata = { .index = -1 };
return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw,
&pdata, flags, mult, div, 0, 0, false);
}
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_parent_hw);
struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div)
{
const struct clk_parent_data pdata = { .index = -1 };
return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL,
&pdata, flags, mult, div, 0, 0, false);
}
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
struct clk_hw *clk_hw_register_fixed_factor_fwname(struct device *dev,
struct device_node *np, const char *name, const char *fw_name,
unsigned long flags, unsigned int mult, unsigned int div)
@@ -292,17 +251,6 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div)
{
const struct clk_parent_data pdata = { .index = -1 };
return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL,
&pdata, flags, mult, div, 0, 0, true);
}
EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor);
struct clk_hw *devm_clk_hw_register_fixed_factor_fwname(struct device *dev,
struct device_node *np, const char *name, const char *fw_name,
unsigned long flags, unsigned int mult, unsigned int div)
+4
View File
@@ -2227,6 +2227,7 @@ static int k230_clk_set_rate_mul(struct clk_hw *hw, unsigned long rate,
guard(spinlock)(rate_self->lock);
mul_reg = readl(rate_self->reg + clk->mul_reg_off);
mul_reg &= ~(rate_self->mul_mask << rate_self->mul_shift);
mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
mul_reg |= BIT(rate_self->write_enable_bit);
writel(mul_reg, rate_self->reg + clk->mul_reg_off);
@@ -2257,6 +2258,7 @@ static int k230_clk_set_rate_div(struct clk_hw *hw, unsigned long rate,
guard(spinlock)(rate_self->lock);
div_reg = readl(rate_self->reg + clk->div_reg_off);
div_reg &= ~(rate_self->div_mask << rate_self->div_shift);
div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
div_reg |= BIT(rate_self->write_enable_bit);
writel(div_reg, rate_self->reg + clk->div_reg_off);
@@ -2287,11 +2289,13 @@ static int k230_clk_set_rate_mul_div(struct clk_hw *hw, unsigned long rate,
guard(spinlock)(rate_self->lock);
div_reg = readl(rate_self->reg + clk->div_reg_off);
div_reg &= ~(rate_self->div_mask << rate_self->div_shift);
div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
div_reg |= BIT(rate_self->write_enable_bit);
writel(div_reg, rate_self->reg + clk->div_reg_off);
mul_reg = readl(rate_self->reg + clk->mul_reg_off);
mul_reg &= ~(rate_self->mul_mask << rate_self->mul_shift);
mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
mul_reg |= BIT(rate_self->write_enable_bit);
writel(mul_reg, rate_self->reg + clk->mul_reg_off);
+14 -25
View File
@@ -175,10 +175,6 @@
#define LMK04832_REG_RB_HOLDOVER 0x188
#define LMK04832_REG_SPI_LOCK 0x555
enum lmk04832_device_types {
LMK04832,
};
/**
* struct lmk04832_device_info - Holds static device information that is
* specific to the chip revision
@@ -197,14 +193,12 @@ struct lmk04832_device_info {
unsigned int vco1_range[2];
};
static const struct lmk04832_device_info lmk04832_device_info[] = {
[LMK04832] = {
.pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */
.maskrev = 0x70,
.num_channels = 14,
.vco0_range = { 2440, 2580 },
.vco1_range = { 2945, 3255 },
},
static const struct lmk04832_device_info lmk04832_device_info = {
.pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */
.maskrev = 0x70,
.num_channels = 14,
.vco0_range = { 2440, 2580 },
.vco1_range = { 2945, 3255 },
};
enum lmk04832_rdbk_type {
@@ -422,11 +416,10 @@ static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
*/
static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate)
{
struct spi_device *spi = to_spi_device(lmk->dev);
const struct lmk04832_device_info *info;
unsigned long mhz = rate / 1000000;
info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data];
info = &lmk04832_device_info;
if (mhz >= info->vco0_range[0] && mhz <= info->vco0_range[1])
return LMK04832_VAL_VCO_MUX_VCO0;
@@ -822,13 +815,6 @@ static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk)
if (ret)
return ret;
ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
LMK04832_BIT_SYNC_MODE,
FIELD_PREP(LMK04832_BIT_SYNC_MODE,
lmk->sync_mode));
if (ret)
return ret;
/*
* 9. (optional) if SCLKx_y_DIS_MODE was used to mute SYSREF outputs
* during the SYNC event, restore SCLKx_y_DIS_MODE=0 for active state,
@@ -843,7 +829,10 @@ static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk)
* SYNC pulse to delay the output by some number of VCO counts).
*/
return ret;
return regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
LMK04832_BIT_SYNC_MODE,
FIELD_PREP(LMK04832_BIT_SYNC_MODE,
lmk->sync_mode));
}
static int lmk04832_sclk_is_enabled(struct clk_hw *hw)
@@ -1405,7 +1394,7 @@ static int lmk04832_probe(struct spi_device *spi)
int ret;
int i;
info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data];
info = &lmk04832_device_info;
lmk = devm_kzalloc(&spi->dev, sizeof(struct lmk04832), GFP_KERNEL);
if (!lmk)
@@ -1553,8 +1542,8 @@ static int lmk04832_probe(struct spi_device *spi)
}
static const struct spi_device_id lmk04832_id[] = {
{ "lmk04832", LMK04832 },
{}
{ .name = "lmk04832" },
{ }
};
MODULE_DEVICE_TABLE(spi, lmk04832_id);
+4 -4
View File
@@ -264,10 +264,10 @@ static int max77686_clk_probe(struct platform_device *pdev)
}
static const struct platform_device_id max77686_clk_id[] = {
{ "max77686-clk", .driver_data = CHIP_MAX77686, },
{ "max77802-clk", .driver_data = CHIP_MAX77802, },
{ "max77620-clock", .driver_data = CHIP_MAX77620, },
{},
{ .name = "max77686-clk", .driver_data = CHIP_MAX77686 },
{ .name = "max77802-clk", .driver_data = CHIP_MAX77802 },
{ .name = "max77620-clock", .driver_data = CHIP_MAX77620 },
{ }
};
MODULE_DEVICE_TABLE(platform, max77686_clk_id);
-14
View File
@@ -17,7 +17,6 @@ static void __init moxart_of_pll_clk_init(struct device_node *node)
{
void __iomem *base;
struct clk_hw *hw;
struct clk *ref_clk;
unsigned int mul;
const char *name = node->name;
const char *parent_name;
@@ -34,12 +33,6 @@ static void __init moxart_of_pll_clk_init(struct device_node *node)
mul = readl(base + 0x30) >> 3 & 0x3f;
iounmap(base);
ref_clk = of_clk_get(node, 0);
if (IS_ERR(ref_clk)) {
pr_err("%pOF: of_clk_get failed\n", node);
return;
}
hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
if (IS_ERR(hw)) {
pr_err("%pOF: failed to register clock\n", node);
@@ -56,7 +49,6 @@ static void __init moxart_of_apb_clk_init(struct device_node *node)
{
void __iomem *base;
struct clk_hw *hw;
struct clk *pll_clk;
unsigned int div, val;
unsigned int div_idx[] = { 2, 3, 4, 6, 8};
const char *name = node->name;
@@ -78,12 +70,6 @@ static void __init moxart_of_apb_clk_init(struct device_node *node)
val = 0;
div = div_idx[val] * 2;
pll_clk = of_clk_get(node, 0);
if (IS_ERR(pll_clk)) {
pr_err("%pOF: of_clk_get failed\n", node);
return;
}
hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
if (IS_ERR(hw)) {
pr_err("%pOF: failed to register clock\n", node);
+15 -9
View File
@@ -194,6 +194,13 @@ static void palmas_clks_get_clk_data(struct platform_device *pdev,
cinfo->ext_control_pin = prop;
}
static void palmas_clks_unprepare_ext_control(void *data)
{
struct palmas_clock_info *cinfo = data;
clk_unprepare(cinfo->hw.clk);
}
static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
{
int ret;
@@ -214,13 +221,18 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
return ret;
}
ret = devm_add_action_or_reset(cinfo->dev,
palmas_clks_unprepare_ext_control,
cinfo);
if (ret)
return ret;
ret = palmas_ext_control_req_config(cinfo->palmas,
cinfo->clk_desc->sleep_reqstr_id,
cinfo->ext_control_pin, true);
if (ret < 0) {
dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
cinfo->clk_desc->clk_name, ret);
clk_unprepare(cinfo->hw.clk);
return ret;
}
}
@@ -230,7 +242,6 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
static int palmas_clks_probe(struct platform_device *pdev)
{
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct device_node *node = pdev->dev.of_node;
const struct palmas_clks_of_match_data *match_data;
struct palmas_clock_info *cinfo;
int ret;
@@ -264,24 +275,19 @@ static int palmas_clks_probe(struct platform_device *pdev)
return ret;
}
ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &cinfo->hw);
ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
&cinfo->hw);
if (ret < 0)
dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret);
return ret;
}
static void palmas_clks_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
}
static struct platform_driver palmas_clks_driver = {
.driver = {
.name = "palmas-clk",
.of_match_table = palmas_clks_of_match,
},
.probe = palmas_clks_probe,
.remove = palmas_clks_remove,
};
module_platform_driver(palmas_clks_driver);
+3 -3
View File
@@ -394,9 +394,9 @@ static const struct rs9_chip_info renesas_9fgv0841_info = {
};
static const struct i2c_device_id rs9_id[] = {
{ "9fgv0241", .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info },
{ "9fgv0441", .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info },
{ "9fgv0841", .driver_data = (kernel_ulong_t)&renesas_9fgv0841_info },
{ .name = "9fgv0241", .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info },
{ .name = "9fgv0441", .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info },
{ .name = "9fgv0841", .driver_data = (kernel_ulong_t)&renesas_9fgv0841_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, rs9_id);
+1 -7
View File
@@ -1174,12 +1174,6 @@ static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw,
return clock->cached_rate;
}
static int rp1_varsrc_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return 0;
}
static const struct clk_ops rp1_pll_core_ops = {
.is_prepared = rp1_pll_core_is_on,
.prepare = rp1_pll_core_on,
@@ -1227,7 +1221,7 @@ static const struct clk_ops rp1_clk_ops = {
static const struct clk_ops rp1_varsrc_ops = {
.set_rate = rp1_varsrc_set_rate,
.recalc_rate = rp1_varsrc_recalc_rate,
.determine_rate = rp1_varsrc_determine_rate,
.determine_rate = clk_determine_rate_noop,
};
static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman,
+6 -6
View File
@@ -225,12 +225,12 @@ static void s2mps11_clk_remove(struct platform_device *pdev)
}
static const struct platform_device_id s2mps11_clk_id[] = {
{ "s2mpg10-clk", S2MPG10},
{ "s2mps11-clk", S2MPS11X},
{ "s2mps13-clk", S2MPS13X},
{ "s2mps14-clk", S2MPS14X},
{ "s5m8767-clk", S5M8767X},
{ },
{ .name = "s2mpg10-clk", .driver_data = S2MPG10 },
{ .name = "s2mps11-clk", .driver_data = S2MPS11X },
{ .name = "s2mps13-clk", .driver_data = S2MPS13X },
{ .name = "s2mps14-clk", .driver_data = S2MPS14X },
{ .name = "s5m8767-clk", .driver_data = S5M8767X },
{ }
};
MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
+108
View File
@@ -0,0 +1,108 @@
// SPDX-License-Identifier: GPL-2.0
/*
* The Vendor OEM extension for System Control and Power Interface (SCMI)
* Protocol based clock driver
*
* Copyright 2025 NXP
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/scmi_imx_protocol.h>
#include <linux/scmi_protocol.h>
#include "clk-scmi.h"
#define SCMI_CLOCK_CFG_IMX_SSC 0x80
#define SCMI_CLOCK_IMX_SS_PERCENTAGE_MASK GENMASK(7, 0)
#define SCMI_CLOCK_IMX_SS_MOD_FREQ_MASK GENMASK(23, 8)
#define SCMI_CLOCK_IMX_SS_ENABLE_MASK BIT(24)
/*
* Selection is based on SCMI vendor_id/sub_vendor_id and optional machine
* compatible string, without involving impl_ver. impl_verspecific behavior
* should be considered a bug and handled via SCMI Quirk framework.
*/
struct scmi_clk_oem_info {
char *vendor_id;
char *sub_vendor_id;
char *compatible;
const void *data;
};
static int
scmi_clk_imx_set_spread_spectrum(struct clk_hw *hw,
const struct clk_spread_spectrum *ss_conf)
{
struct scmi_clk *clk = to_scmi_clk(hw);
int ret;
u32 val;
/*
* extConfigValue[7:0] - spread percentage (%)
* extConfigValue[23:8] - Modulation Frequency
* extConfigValue[24] - Enable/Disable
* extConfigValue[31:25] - Reserved
*/
val = FIELD_PREP(SCMI_CLOCK_IMX_SS_PERCENTAGE_MASK, ss_conf->spread_bp / 10000);
val |= FIELD_PREP(SCMI_CLOCK_IMX_SS_MOD_FREQ_MASK, ss_conf->modfreq_hz);
if (ss_conf->method != CLK_SPREAD_NO)
val |= SCMI_CLOCK_IMX_SS_ENABLE_MASK;
ret = scmi_proto_clk_ops->config_oem_set(clk->ph, clk->id,
SCMI_CLOCK_CFG_IMX_SSC,
val, false);
if (ret)
dev_warn(clk->dev,
"Failed to set spread spectrum(%u,%u,%u) for clock ID %d\n",
ss_conf->modfreq_hz, ss_conf->spread_bp, ss_conf->method,
clk->id);
return ret;
}
static int
scmi_clk_imx_query_oem_feats(const struct scmi_protocol_handle *ph, u32 id,
unsigned int *feats_key)
{
int ret;
u32 val;
ret = scmi_proto_clk_ops->config_oem_get(ph, id,
SCMI_CLOCK_CFG_IMX_SSC,
&val, NULL, false);
if (!ret)
*feats_key |= BIT(SCMI_CLK_EXT_OEM_SSC_SUPPORTED);
return 0;
}
static const struct scmi_clk_oem scmi_clk_oem_imx = {
.query_ext_oem_feats = scmi_clk_imx_query_oem_feats,
.set_spread_spectrum = scmi_clk_imx_set_spread_spectrum,
};
static const struct scmi_clk_oem_info info[] = {
{ SCMI_IMX_VENDOR, SCMI_IMX_SUBVENDOR, NULL, &scmi_clk_oem_imx },
};
int scmi_clk_oem_init(struct scmi_device *sdev)
{
const struct scmi_handle *handle = sdev->handle;
int i, size = ARRAY_SIZE(info);
for (i = 0; i < size; i++) {
if (strcmp(handle->version->vendor_id, info[i].vendor_id) ||
strcmp(handle->version->sub_vendor_id, info[i].sub_vendor_id))
continue;
if (info[i].compatible &&
!of_machine_is_compatible(info[i].compatible))
continue;
break;
}
if (i < size)
dev_set_drvdata(&sdev->dev, (void *)info[i].data);
return 0;
}
+16 -28
View File
@@ -13,32 +13,9 @@
#include <linux/module.h>
#include <linux/scmi_protocol.h>
#define NOT_ATOMIC false
#define ATOMIC true
#include "clk-scmi.h"
enum scmi_clk_feats {
SCMI_CLK_ATOMIC_SUPPORTED,
SCMI_CLK_STATE_CTRL_SUPPORTED,
SCMI_CLK_RATE_CTRL_SUPPORTED,
SCMI_CLK_PARENT_CTRL_SUPPORTED,
SCMI_CLK_DUTY_CYCLE_SUPPORTED,
SCMI_CLK_FEATS_COUNT
};
#define SCMI_MAX_CLK_OPS BIT(SCMI_CLK_FEATS_COUNT)
static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
struct scmi_clk {
u32 id;
struct device *dev;
struct clk_hw hw;
const struct scmi_clock_info *info;
const struct scmi_protocol_handle *ph;
struct clk_parent_data *parent_data;
};
#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -235,6 +212,7 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
static const struct clk_ops *
scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
{
struct scmi_clk_oem *oem_data = dev_get_drvdata(dev);
struct clk_ops *ops;
ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
@@ -281,11 +259,15 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
ops->set_duty_cycle = scmi_clk_set_duty_cycle;
}
if (oem_data && (feats_key & BIT(SCMI_CLK_EXT_OEM_SSC_SUPPORTED)))
ops->set_spread_spectrum = oem_data->set_spread_spectrum;
return ops;
}
/**
* scmi_clk_ops_select() - Select a proper set of clock operations
* @sdev: pointer to the SCMI device
* @sclk: A reference to an SCMI clock descriptor
* @atomic_capable: A flag to indicate if atomic mode is supported by the
* transport
@@ -310,8 +292,8 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
* NULL otherwise.
*/
static const struct clk_ops *
scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
unsigned int atomic_threshold_us,
scmi_clk_ops_select(struct scmi_device *sdev, struct scmi_clk *sclk,
bool atomic_capable, unsigned int atomic_threshold_us,
const struct clk_ops **clk_ops_db, size_t db_size)
{
int ret;
@@ -319,6 +301,7 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
const struct scmi_clock_info *ci = sclk->info;
unsigned int feats_key = 0;
const struct clk_ops *ops;
struct scmi_clk_oem *oem_data = dev_get_drvdata(&sdev->dev);
/*
* Note that when transport is atomic but SCMI protocol did not
@@ -343,6 +326,9 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
&val, NULL, false);
if (!ret)
feats_key |= BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED);
if (oem_data && oem_data->query_ext_oem_feats)
oem_data->query_ext_oem_feats(sclk->ph, sclk->id, &feats_key);
}
if (WARN_ON(feats_key >= db_size))
@@ -400,6 +386,8 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
clk_data->num = count;
hws = clk_data->hws;
scmi_clk_oem_init(sdev);
transport_is_atomic = handle->is_transport_atomic(handle,
&atomic_threshold_us);
@@ -431,7 +419,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
* to avoid sharing the devm_ allocated clk_ops between multiple
* SCMI clk driver instances.
*/
scmi_ops = scmi_clk_ops_select(sclk, transport_is_atomic,
scmi_ops = scmi_clk_ops_select(sdev, sclk, transport_is_atomic,
atomic_threshold_us,
scmi_clk_ops_db,
ARRAY_SIZE(scmi_clk_ops_db));
+51
View File
@@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2025 NXP
*/
#ifndef __SCMI_CLK_H
#define __SCMI_CLK_H
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/scmi_protocol.h>
#include <linux/types.h>
#define NOT_ATOMIC false
#define ATOMIC true
enum scmi_clk_feats {
SCMI_CLK_ATOMIC_SUPPORTED,
SCMI_CLK_STATE_CTRL_SUPPORTED,
SCMI_CLK_RATE_CTRL_SUPPORTED,
SCMI_CLK_PARENT_CTRL_SUPPORTED,
SCMI_CLK_DUTY_CYCLE_SUPPORTED,
SCMI_CLK_EXT_OEM_SSC_SUPPORTED,
SCMI_CLK_FEATS_COUNT
};
#define SCMI_MAX_CLK_OPS BIT(SCMI_CLK_FEATS_COUNT)
struct scmi_clk {
u32 id;
struct device *dev;
struct clk_hw hw;
const struct scmi_clock_info *info;
const struct scmi_protocol_handle *ph;
struct clk_parent_data *parent_data;
};
#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
extern const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
struct scmi_clk_oem {
int (*query_ext_oem_feats)(const struct scmi_protocol_handle *ph,
u32 id, unsigned int *feats_key);
int (*set_spread_spectrum)(struct clk_hw *hw,
const struct clk_spread_spectrum *ss_conf);
};
int scmi_clk_oem_init(struct scmi_device *dev);
#endif
+1 -13
View File
@@ -32,18 +32,6 @@ static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw,
return clk->scpi_ops->clk_get_val(clk->id);
}
static int scpi_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/*
* We can't figure out what rate it will be, so just return the
* rate back to the caller. scpi_clk_recalc_rate() will be called
* after the rate is set and we'll know what rate the clock is
* running at then.
*/
return 0;
}
static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
@@ -54,7 +42,7 @@ static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops scpi_clk_ops = {
.recalc_rate = scpi_clk_recalc_rate,
.determine_rate = scpi_clk_determine_rate,
.determine_rate = clk_determine_rate_noop,
.set_rate = scpi_clk_set_rate,
};
+1 -1
View File
@@ -379,7 +379,7 @@ static int si514_probe(struct i2c_client *client)
}
static const struct i2c_device_id si514_id[] = {
{ "si514" },
{ .name = "si514" },
{ }
};
MODULE_DEVICE_TABLE(i2c, si514_id);
+3 -3
View File
@@ -364,9 +364,9 @@ static int __maybe_unused si521xx_resume(struct device *dev)
}
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) },
{ .name = "si52144", .driver_data = SI521XX_OE_MAP(0x5, 0xc0) },
{ .name = "si52146", .driver_data = SI521XX_OE_MAP(0x15, 0xe0) },
{ .name = "si52147", .driver_data = SI521XX_OE_MAP(0x17, 0xf8) },
{ }
};
MODULE_DEVICE_TABLE(i2c, si521xx_id);
+5 -5
View File
@@ -1825,11 +1825,11 @@ static void si5341_remove(struct i2c_client *client)
}
static const struct i2c_device_id si5341_id[] = {
{ "si5340", 0 },
{ "si5341", 1 },
{ "si5342", 2 },
{ "si5344", 4 },
{ "si5345", 5 },
{ .name = "si5340" },
{ .name = "si5341" },
{ .name = "si5342" },
{ .name = "si5344" },
{ .name = "si5345" },
{ }
};
MODULE_DEVICE_TABLE(i2c, si5341_id);
+4 -4
View File
@@ -1425,10 +1425,10 @@ si53351_of_clk_get(struct of_phandle_args *clkspec, void *data)
#endif /* CONFIG_OF */
static const struct i2c_device_id si5351_i2c_ids[] = {
{ "si5351a", SI5351_VARIANT_A },
{ "si5351a-msop", SI5351_VARIANT_A3 },
{ "si5351b", SI5351_VARIANT_B },
{ "si5351c", SI5351_VARIANT_C },
{ .name = "si5351a", .driver_data = SI5351_VARIANT_A },
{ .name = "si5351a-msop", .driver_data = SI5351_VARIANT_A3 },
{ .name = "si5351b", .driver_data = SI5351_VARIANT_B },
{ .name = "si5351c", .driver_data = SI5351_VARIANT_C },
{ }
};
MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
+65 -17
View File
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Silicon Labs Si544 Programmable Oscillator
* Driver for Silicon Labs Si544/Si549 Programmable Oscillator
* Copyright (C) 2018 Topic Embedded Products
* Author: Mike Looijmans <mike.looijmans@topic.nl>
*/
@@ -40,7 +40,9 @@
#define SI544_MIN_FREQ 200000U
/* Si544 Internal oscillator runs at 55.05 MHz */
#define FXO 55050000U
#define SI544_XO_FREQ 55050000U
/* Si549 Internal oscilator runs at 152.60 MHz */
#define SI549_XO_FREQ 152600000U
/* VCO range is 10.8 .. 12.1 GHz, max depends on speed grade */
#define FVCO_MIN 10800000000ULL
@@ -56,11 +58,16 @@
#define DELTA_M_FRAC_NUM 19
#define DELTA_M_FRAC_DEN 20000
struct si544_clk_desc {
unsigned long max_freq;
unsigned long xo_freq;
};
struct clk_si544 {
struct clk_hw hw;
struct regmap *regmap;
struct i2c_client *i2c_client;
unsigned long max_freq;
const struct si544_clk_desc *chip_info;
};
#define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw)
@@ -79,6 +86,7 @@ struct clk_si544_muldiv {
u16 hs_div;
u8 ls_div_bits;
s32 delta_m;
u32 xo_freq;
};
/* Enables or disables the output driver */
@@ -145,6 +153,8 @@ static int si544_get_muldiv(struct clk_si544 *data,
settings->delta_m = reg[0] << 8 | reg[1] << 16 | reg[2] << 24;
settings->delta_m >>= 8;
settings->xo_freq = data->chip_info->xo_freq;
return 0;
}
@@ -193,7 +203,7 @@ static bool is_valid_frequency(const struct clk_si544 *data,
if (frequency < SI544_MIN_FREQ)
return false;
return frequency <= data->max_freq;
return frequency <= data->chip_info->max_freq;
}
/* Calculate divider settings for a given frequency */
@@ -201,6 +211,7 @@ static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
unsigned long frequency)
{
u64 vco;
u32 fxo = settings->xo_freq;
u32 ls_freq;
u32 tmp;
u8 res;
@@ -238,13 +249,13 @@ static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
vco = (u64)ls_freq * settings->hs_div;
/* Calculate the integer part of the feedback divider */
tmp = do_div(vco, FXO);
tmp = do_div(vco, fxo);
settings->fb_div_int = vco;
/* And the fractional bits using the remainder */
vco = (u64)tmp << 32;
vco += FXO / 2; /* Round to nearest multiple */
do_div(vco, FXO);
vco += fxo / 2; /* Round to nearest multiple */
do_div(vco, fxo);
settings->fb_div_frac = vco;
/* Reset the frequency adjustment */
@@ -258,15 +269,16 @@ static unsigned long si544_calc_center_rate(
const struct clk_si544_muldiv *settings)
{
u32 d = settings->hs_div * BIT(settings->ls_div_bits);
u32 fxo = settings->xo_freq;
u64 vco;
/* Calculate VCO from the fractional part */
vco = (u64)settings->fb_div_frac * FXO;
vco += (FXO / 2);
vco = (u64)settings->fb_div_frac * fxo;
vco += (fxo / 2);
vco >>= 32;
/* Add the integer part of the VCO frequency */
vco += (u64)settings->fb_div_int * FXO;
vco += (u64)settings->fb_div_int * fxo;
/* Apply divider to obtain the generated frequency */
do_div(vco, d);
@@ -446,7 +458,7 @@ static int si544_probe(struct i2c_client *client)
init.num_parents = 0;
data->hw.init = &init;
data->i2c_client = client;
data->max_freq = (uintptr_t)i2c_get_match_data(client);
data->chip_info = i2c_get_match_data(client);
if (of_property_read_string(client->dev.of_node, "clock-output-names",
&init.name))
@@ -478,18 +490,54 @@ static int si544_probe(struct i2c_client *client)
return 0;
}
static const struct si544_clk_desc clk_si544a_info = {
.xo_freq = SI544_XO_FREQ,
.max_freq = 1500000000,
};
static const struct si544_clk_desc clk_si544b_info = {
.xo_freq = SI544_XO_FREQ,
.max_freq = 800000000,
};
static const struct si544_clk_desc clk_si544c_info = {
.xo_freq = SI544_XO_FREQ,
.max_freq = 325000000,
};
static const struct si544_clk_desc clk_si549a_info = {
.xo_freq = SI549_XO_FREQ,
.max_freq = 1500000000,
};
static const struct si544_clk_desc clk_si549b_info = {
.xo_freq = SI549_XO_FREQ,
.max_freq = 800000000,
};
static const struct si544_clk_desc clk_si549c_info = {
.xo_freq = SI549_XO_FREQ,
.max_freq = 325000000,
};
static const struct i2c_device_id si544_id[] = {
{ "si544a", 1500000000 },
{ "si544b", 800000000 },
{ "si544c", 350000000 },
{ .name = "si544a", .driver_data = (kernel_ulong_t)&clk_si544a_info },
{ .name = "si544b", .driver_data = (kernel_ulong_t)&clk_si544b_info },
{ .name = "si544c", .driver_data = (kernel_ulong_t)&clk_si544c_info },
{ .name = "si549a", .driver_data = (kernel_ulong_t)&clk_si549a_info },
{ .name = "si549b", .driver_data = (kernel_ulong_t)&clk_si549b_info },
{ .name = "si549c", .driver_data = (kernel_ulong_t)&clk_si549c_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, si544_id);
static const struct of_device_id clk_si544_of_match[] = {
{ .compatible = "silabs,si544a", .data = (void *)1500000000 },
{ .compatible = "silabs,si544b", .data = (void *)800000000 },
{ .compatible = "silabs,si544c", .data = (void *)350000000 },
{ .compatible = "silabs,si544a", .data = &clk_si544a_info },
{ .compatible = "silabs,si544b", .data = &clk_si544b_info },
{ .compatible = "silabs,si544c", .data = &clk_si544c_info },
{ .compatible = "silabs,si549a", .data = &clk_si549a_info },
{ .compatible = "silabs,si549b", .data = &clk_si549b_info },
{ .compatible = "silabs,si549c", .data = &clk_si549c_info },
{ }
};
MODULE_DEVICE_TABLE(of, clk_si544_of_match);
+4 -4
View File
@@ -503,10 +503,10 @@ static const struct clk_si570_info clk_si590_info = {
};
static const struct i2c_device_id si570_id[] = {
{ "si570", (kernel_ulong_t)&clk_si570_info },
{ "si571", (kernel_ulong_t)&clk_si570_info },
{ "si598", (kernel_ulong_t)&clk_si590_info },
{ "si599", (kernel_ulong_t)&clk_si590_info },
{ .name = "si570", .driver_data = (kernel_ulong_t)&clk_si570_info },
{ .name = "si571", .driver_data = (kernel_ulong_t)&clk_si570_info },
{ .name = "si598", .driver_data = (kernel_ulong_t)&clk_si590_info },
{ .name = "si599", .driver_data = (kernel_ulong_t)&clk_si590_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, si570_id);
+8 -8
View File
@@ -1310,14 +1310,14 @@ static const struct vc5_chip_info idt_5p49v6975_info = {
};
static const struct i2c_device_id vc5_id[] = {
{ "5p49v5923", .driver_data = (kernel_ulong_t)&idt_5p49v5923_info },
{ "5p49v5925", .driver_data = (kernel_ulong_t)&idt_5p49v5925_info },
{ "5p49v5933", .driver_data = (kernel_ulong_t)&idt_5p49v5933_info },
{ "5p49v5935", .driver_data = (kernel_ulong_t)&idt_5p49v5935_info },
{ "5p49v60", .driver_data = (kernel_ulong_t)&idt_5p49v60_info },
{ "5p49v6901", .driver_data = (kernel_ulong_t)&idt_5p49v6901_info },
{ "5p49v6965", .driver_data = (kernel_ulong_t)&idt_5p49v6965_info },
{ "5p49v6975", .driver_data = (kernel_ulong_t)&idt_5p49v6975_info },
{ .name = "5p49v5923", .driver_data = (kernel_ulong_t)&idt_5p49v5923_info },
{ .name = "5p49v5925", .driver_data = (kernel_ulong_t)&idt_5p49v5925_info },
{ .name = "5p49v5933", .driver_data = (kernel_ulong_t)&idt_5p49v5933_info },
{ .name = "5p49v5935", .driver_data = (kernel_ulong_t)&idt_5p49v5935_info },
{ .name = "5p49v60", .driver_data = (kernel_ulong_t)&idt_5p49v60_info },
{ .name = "5p49v6901", .driver_data = (kernel_ulong_t)&idt_5p49v6901_info },
{ .name = "5p49v6965", .driver_data = (kernel_ulong_t)&idt_5p49v6965_info },
{ .name = "5p49v6975", .driver_data = (kernel_ulong_t)&idt_5p49v6975_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, vc5_id);
+3 -3
View File
@@ -1197,7 +1197,7 @@ static int vc7_probe(struct i2c_client *client)
if (ret) {
dev_err_probe(&client->dev, ret,
"unable to register output %d\n", i);
return ret;
goto err_clk;
}
switch (bank_src_map.type) {
@@ -1288,8 +1288,8 @@ static const struct regmap_config vc7_regmap_config = {
};
static const struct i2c_device_id vc7_i2c_id[] = {
{ "rc21008a", .driver_data = (kernel_ulong_t)&vc7_rc21008a_info },
{}
{ .name = "rc21008a", .driver_data = (kernel_ulong_t)&vc7_rc21008a_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, vc7_i2c_id);
+104 -8
View File
@@ -63,6 +63,57 @@ struct clk_parent_map {
int index;
};
/**
* struct clk_core - The internal state of a clk in the clk tree.
* @name: Unique name of the clk for identification.
* @ops: Pointer to hardware-specific operations for this clk.
* @hw: Pointer for traversing from a struct clk to its
* corresponding hardware-specific structure.
* @owner: Kernel module owning this clk (for reference counting).
* @dev: Device associated with this clk (optional)
* @rpm_node: Node for runtime power management list management.
* @of_node: Device tree node associated with this clk (if applicable)
* @parent: Pointer to the current parent in the clock tree.
* @parents: Array of possible parents (for muxes/selectable parents).
* @num_parents: Number of possible parents.
* @new_parent_index: Index of the new parent during parent change operations.
* @rate: Current cached clock rate (Hz).
* @req_rate: The last rate requested by a call to clk_set_rate(). It's
* initialized to clk_core->rate. It's also updated to
* clk_core->rate every time the clock is reparented, and
* when we're doing the orphan -> !orphan transition.
* @new_rate: New rate to be set during a rate change operation.
* @new_parent: Pointer to new parent during parent change. This is also
* used when a clk's rate is changed.
* @new_child: Pointer to new child during reparenting. This is also
* used when a clk's rate is changed.
* @flags: Clock property and capability flags. See
* `clk framework flags`.
* @orphan: True if this clk is currently orphaned.
* @rpm_enabled: True if runtime power management is enabled for this clk.
* @enable_count: Reference count of enables.
* @prepare_count: Reference count of prepares.
* @protect_count: Protection reference count against disable.
* @min_rate: Minimum supported clock rate (Hz).
* @max_rate: Maximum supported clock rate (Hz).
* @accuracy: Accuracy of the clock rate (parts per billion).
* @phase: Current phase (degrees).
* @duty: Current duty cycle configuration (as ratio: num/den).
* @children: All of the children of this clk.
* @child_node: Node for linking as a child in the parent's list.
* @hashtable_node: Node for hash table that allows fast clk lookup by name.
* @clks: All of the clk consumers registered.
* @notifier_count: Number of notifiers registered for this clk.
* @dentry: DebugFS entry for this clk.
* @debug_node: DebugFS node for this clk.
* @ref: Reference count for structure lifetime management.
*
* Managed by the clk framework. Clk providers and consumers do not interact
* with this structure directly. Instead, clk operations flow through the
* framework and the framework manipulates this structure to keep track of
* parent/child relationships, rate, enable state, etc.
*
*/
struct clk_core {
const char *name;
const struct clk_ops *ops;
@@ -882,6 +933,24 @@ int clk_hw_determine_rate_no_reparent(struct clk_hw *hw,
}
EXPORT_SYMBOL_GPL(clk_hw_determine_rate_no_reparent);
/**
* clk_determine_rate_noop - clk_ops::determine_rate noop implementation
* @hw: clk to determine rate on
* @req: rate request
*
* Noop determine rate for clocks where the rate rounding is handled by the
* firmware/hardware, or the clock is capable of any rate. The requested rate is
* passed through unchanged, and the actual rate will be learned via
* recalc_rate() after the rate is set.
*
* Returns: 0 always
*/
int clk_determine_rate_noop(struct clk_hw *hw, struct clk_rate_request *req)
{
return 0;
}
EXPORT_SYMBOL_GPL(clk_determine_rate_noop);
/*** clk api ***/
static void clk_core_rate_unprotect(struct clk_core *core)
@@ -1846,10 +1915,10 @@ static int __clk_notify(struct clk_core *core, unsigned long msg,
}
/**
* __clk_recalc_accuracies
* __clk_recalc_accuracies - recalculate all accuracies in the clk subtree
* @core: first clk in the subtree
*
* Walks the subtree of clks starting with clk and recalculates accuracies as
* Walks the subtree of clks starting with @core and recalculates accuracies as
* it goes. Note that if a clk does not implement the .recalc_accuracy
* callback then it is assumed that the clock will take on the accuracy of its
* parent.
@@ -1919,16 +1988,16 @@ static unsigned long clk_recalc(struct clk_core *core,
}
/**
* __clk_recalc_rates
* __clk_recalc_rates - recalculate all rates in the clk subtree
* @core: first clk in the subtree
* @update_req: Whether req_rate should be updated with the new rate
* @msg: notification type (see include/linux/clk.h)
*
* Walks the subtree of clks starting with clk and recalculates rates as it
* Walks the subtree of clks starting with @core and recalculates rates as it
* goes. Note that if a clk does not implement the .recalc_rate callback then
* it is assumed that the clock will take on the rate of its parent.
*
* clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
* __clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
* if necessary.
*/
static void __clk_recalc_rates(struct clk_core *core, bool update_req,
@@ -2191,14 +2260,14 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
}
/**
* __clk_speculate_rates
* __clk_speculate_rates - speculate all rates in the clk subtree
* @core: first clk in the subtree
* @parent_rate: the "future" rate of clk's parent
*
* Walks the subtree of clks starting with clk, speculating rates as it
* Walks the subtree of clks starting with @core, speculating rates as it
* goes and firing off PRE_RATE_CHANGE notifications as necessary.
*
* Unlike clk_recalc_rates, clk_speculate_rates exists only for sending
* Unlike __clk_recalc_rates, __clk_speculate_rates exists only for sending
* pre-rate change notifications and returns early if no clks in the
* subtree have subscribed to the notifications. Note that if a clk does not
* implement the .recalc_rate callback then it is assumed that the clock will
@@ -2774,6 +2843,33 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate)
}
EXPORT_SYMBOL_GPL(clk_set_max_rate);
int clk_hw_set_spread_spectrum(struct clk_hw *hw, const struct clk_spread_spectrum *ss_conf)
{
struct clk_core *core;
int ret;
if (!hw)
return 0;
core = hw->core;
clk_prepare_lock();
ret = clk_pm_runtime_get(core);
if (ret)
goto fail;
if (core->ops->set_spread_spectrum)
ret = core->ops->set_spread_spectrum(hw, ss_conf);
clk_pm_runtime_put(core);
fail:
clk_prepare_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(clk_hw_set_spread_spectrum);
/**
* clk_get_parent - return the parent of a clk
* @clk: the clk whose parent gets returned
+206 -8
View File
@@ -7,6 +7,7 @@
#include <linux/clk/clk-conf.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/units.h>
/* Needed for clk_hw_get_clk() */
#include "clk.h"
@@ -21,13 +22,14 @@
static const struct clk_ops empty_clk_ops = { };
#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000)
#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000)
#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000)
#define DUMMY_CLOCK_INIT_RATE (42 * HZ_PER_MHZ)
#define DUMMY_CLOCK_RATE_1 (142 * HZ_PER_MHZ)
#define DUMMY_CLOCK_RATE_2 (242 * HZ_PER_MHZ)
struct clk_dummy_context {
struct clk_hw hw;
unsigned long rate;
struct clk_spread_spectrum sscs;
};
static unsigned long clk_dummy_recalc_rate(struct clk_hw *hw,
@@ -83,6 +85,17 @@ static int clk_dummy_set_rate(struct clk_hw *hw,
return 0;
}
static int clk_dummy_set_spread_spectrum(struct clk_hw *hw,
const struct clk_spread_spectrum *ss_conf)
{
struct clk_dummy_context *ctx =
container_of(hw, struct clk_dummy_context, hw);
ctx->sscs = *ss_conf;
return 0;
}
static int clk_dummy_single_set_parent(struct clk_hw *hw, u8 index)
{
if (index >= clk_hw_get_num_parents(hw))
@@ -100,18 +113,21 @@ static const struct clk_ops clk_dummy_rate_ops = {
.recalc_rate = clk_dummy_recalc_rate,
.determine_rate = clk_dummy_determine_rate,
.set_rate = clk_dummy_set_rate,
.set_spread_spectrum = clk_dummy_set_spread_spectrum,
};
static const struct clk_ops clk_dummy_maximize_rate_ops = {
.recalc_rate = clk_dummy_recalc_rate,
.determine_rate = clk_dummy_maximize_rate,
.set_rate = clk_dummy_set_rate,
.set_spread_spectrum = clk_dummy_set_spread_spectrum,
};
static const struct clk_ops clk_dummy_minimize_rate_ops = {
.recalc_rate = clk_dummy_recalc_rate,
.determine_rate = clk_dummy_minimize_rate,
.set_rate = clk_dummy_set_rate,
.set_spread_spectrum = clk_dummy_set_spread_spectrum,
};
static const struct clk_ops clk_dummy_single_parent_ops = {
@@ -2232,7 +2248,7 @@ static void
clk_leaf_mux_set_rate_parent_determine_rate_test_case_to_desc(
const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case *t, char *desc)
{
strcpy(desc, t->desc);
strscpy(desc, t->desc, KUNIT_PARAM_DESC_SIZE);
}
static const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case
@@ -2644,7 +2660,7 @@ static void
clk_register_clk_parent_data_test_case_to_desc(
const struct clk_register_clk_parent_data_test_case *t, char *desc)
{
strcpy(desc, t->desc);
strscpy(desc, t->desc, KUNIT_PARAM_DESC_SIZE);
}
static const struct clk_register_clk_parent_data_test_case
@@ -3097,6 +3113,7 @@ struct clk_assigned_rates_context {
* @overlay_end: Pointer to end of DT overlay to apply for test
* @rate0: Initial rate of first clk
* @rate1: Initial rate of second clk
* @sscs: Initial spread spectrum settings
* @consumer_test: true if a consumer is being tested
*/
struct clk_assigned_rates_test_param {
@@ -3105,6 +3122,7 @@ struct clk_assigned_rates_test_param {
u8 *overlay_end;
unsigned long rate0;
unsigned long rate1;
struct clk_spread_spectrum sscs;
bool consumer_test;
};
@@ -3116,7 +3134,7 @@ static void
clk_assigned_rates_register_clk(struct kunit *test,
struct clk_dummy_context *ctx,
struct device_node *np, const char *name,
unsigned long rate)
unsigned long rate, const struct clk_spread_spectrum *sscs)
{
struct clk_init_data init = { };
@@ -3124,6 +3142,7 @@ clk_assigned_rates_register_clk(struct kunit *test,
init.ops = &clk_dummy_rate_ops;
ctx->hw.init = &init;
ctx->rate = rate;
ctx->sscs = *sscs;
KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, np, &ctx->hw));
KUNIT_ASSERT_EQ(test, ctx->rate, rate);
@@ -3167,14 +3186,16 @@ static int clk_assigned_rates_test_init(struct kunit *test)
KUNIT_ASSERT_LT(test, clk_cells, 2);
clk_assigned_rates_register_clk(test, &ctx->clk0, np,
"test_assigned_rate0", test_param->rate0);
"test_assigned_rate0", test_param->rate0,
&test_param->sscs);
if (clk_cells == 0) {
KUNIT_ASSERT_EQ(test, 0,
of_clk_add_hw_provider_kunit(test, np, of_clk_hw_simple_get,
&ctx->clk0.hw));
} else if (clk_cells == 1) {
clk_assigned_rates_register_clk(test, &ctx->clk1, np,
"test_assigned_rate1", test_param->rate1);
"test_assigned_rate1", test_param->rate1,
&test_param->sscs);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
data = kunit_kzalloc(test, struct_size(data, hws, 2), GFP_KERNEL));
@@ -3403,6 +3424,182 @@ static struct kunit_suite clk_assigned_rates_suite = {
.init = clk_assigned_rates_test_init,
};
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_one);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_one_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_multiple);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_multiple_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_without);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_without_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_zero);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_zero_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_null);
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_null_consumer);
static void clk_assigned_sscs_assigns_one(struct kunit *test)
{
struct clk_assigned_rates_context *ctx = test->priv;
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.modfreq_hz, ASSIGNED_SSCS_0_MODFREQ);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.spread_bp, ASSIGNED_SSCS_0_SPREAD);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.method, ASSIGNED_SSCS_0_METHOD);
}
/* Test cases that assign sscs for one clk */
static const struct clk_assigned_rates_test_param clk_assigned_sscs_assigns_one_test_params[] = {
{
/*
* Test that a single cell assigned-clock-sscs property
* assigns the sscs when the property is in the provider.
*/
.desc = "provider assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_one),
},
{
/*
* Test that a single cell assigned-clock-sscs property
* assigns the sscs when the property is in the consumer.
*/
.desc = "consumer assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_one_consumer),
.consumer_test = true,
},
};
KUNIT_ARRAY_PARAM_DESC(clk_assigned_sscs_assigns_one,
clk_assigned_sscs_assigns_one_test_params, desc)
static void clk_assigned_sscs_assigns_multiple(struct kunit *test)
{
struct clk_assigned_rates_context *ctx = test->priv;
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.modfreq_hz, ASSIGNED_SSCS_0_MODFREQ);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.spread_bp, ASSIGNED_SSCS_0_SPREAD);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.method, ASSIGNED_SSCS_0_METHOD);
KUNIT_EXPECT_EQ(test, ctx->clk1.sscs.modfreq_hz, ASSIGNED_SSCS_1_MODFREQ);
KUNIT_EXPECT_EQ(test, ctx->clk1.sscs.spread_bp, ASSIGNED_SSCS_1_SPREAD);
KUNIT_EXPECT_EQ(test, ctx->clk1.sscs.method, ASSIGNED_SSCS_1_METHOD);
}
/* Test cases that assign sscs for multiple clks */
static const
struct clk_assigned_rates_test_param clk_assigned_sscs_assigns_multiple_test_params[] = {
{
/*
* Test that a multiple cell assigned-clock-sscs property
* assigns the sscs when the property is in the provider.
*/
.desc = "provider assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_multiple),
},
{
/*
* Test that a multiple cell assigned-clock-sscs property
* assigns the sscs when the property is in the consumer.
*/
.desc = "consumer assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_multiple_consumer),
.consumer_test = true,
},
};
KUNIT_ARRAY_PARAM_DESC(clk_assigned_sscs_assigns_multiple,
clk_assigned_sscs_assigns_multiple_test_params,
desc)
static void clk_assigned_sscs_skips(struct kunit *test)
{
struct clk_assigned_rates_context *ctx = test->priv;
const struct clk_assigned_rates_test_param *test_param = test->param_value;
KUNIT_EXPECT_NE(test, ctx->clk0.sscs.modfreq_hz, ASSIGNED_SSCS_0_MODFREQ);
KUNIT_EXPECT_NE(test, ctx->clk0.sscs.spread_bp, ASSIGNED_SSCS_0_SPREAD);
KUNIT_EXPECT_NE(test, ctx->clk0.sscs.method, ASSIGNED_SSCS_0_METHOD);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.modfreq_hz, test_param->sscs.modfreq_hz);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.spread_bp, test_param->sscs.spread_bp);
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.method, test_param->sscs.method);
}
/* Test cases that skip changing the sscs due to malformed DT */
static const struct clk_assigned_rates_test_param clk_assigned_sscs_skips_test_params[] = {
{
/*
* Test that an assigned-clock-sscs property without an assigned-clocks
* property fails when the property is in the provider.
*/
.desc = "provider missing assigned-clocks",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_without),
.sscs = {50000, 60000, 3},
},
{
/*
* Test that an assigned-clock-sscs property without an assigned-clocks
* property fails when the property is in the consumer.
*/
.desc = "consumer missing assigned-clocks",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_without_consumer),
.sscs = {50000, 60000, 3},
.consumer_test = true,
},
{
/*
* Test that an assigned-clock-sscs property of zero doesn't
* set sscs when the property is in the provider.
*/
.desc = "provider assigned-clock-sscs of zero",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_zero),
.sscs = {50000, 60000, 3},
},
{
/*
* Test that an assigned-clock-sscs property of zero doesn't
* set sscs when the property is in the consumer.
*/
.desc = "consumer assigned-clock-sscs of zero",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_zero_consumer),
.sscs = {50000, 60000, 3},
.consumer_test = true,
},
{
/*
* Test that an assigned-clocks property with a null phandle
* doesn't set sscs when the property is in the provider.
*/
.desc = "provider assigned-clocks null phandle",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_null),
.sscs = {50000, 60000, 3},
},
{
/*
* Test that an assigned-clocks property with a null phandle
* doesn't set sscs when the property is in the consumer.
*/
.desc = "consumer assigned-clocks null phandle",
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_null_consumer),
.sscs = {50000, 60000, 3},
.consumer_test = true,
},
};
KUNIT_ARRAY_PARAM_DESC(clk_assigned_sscs_skips,
clk_assigned_sscs_skips_test_params,
desc)
static struct kunit_case clk_assigned_sscs_test_cases[] = {
KUNIT_CASE_PARAM(clk_assigned_sscs_assigns_one,
clk_assigned_sscs_assigns_one_gen_params),
KUNIT_CASE_PARAM(clk_assigned_sscs_assigns_multiple,
clk_assigned_sscs_assigns_multiple_gen_params),
KUNIT_CASE_PARAM(clk_assigned_sscs_skips,
clk_assigned_sscs_skips_gen_params),
{}
};
/*
* Test suite for assigned-clock-sscs DT property.
*/
static struct kunit_suite clk_assigned_sscs_suite = {
.name = "clk_assigned_sscs",
.test_cases = clk_assigned_sscs_test_cases,
.init = clk_assigned_rates_test_init,
};
static const struct clk_init_data clk_hw_get_dev_of_node_init_data = {
.name = "clk_hw_get_dev_of_node",
.ops = &empty_clk_ops,
@@ -3544,6 +3741,7 @@ static struct kunit_suite clk_hw_get_dev_of_node_test_suite = {
kunit_test_suites(
&clk_assigned_rates_suite,
&clk_assigned_sscs_suite,
&clk_hw_get_dev_of_node_test_suite,
&clk_leaf_mux_set_rate_parent_test_suite,
&clk_test_suite,
+13
View File
@@ -13,3 +13,16 @@ config COMMON_CLK_EIC7700
SoC. The clock controller generates and supplies clocks to various
peripherals within the SoC.
Say yes here to support the clock controller on the EIC7700 SoC.
config COMMON_CLK_EIC7700_HSP
tristate "EIC7700 HSP Clock Driver"
depends on ARCH_ESWIN || COMPILE_TEST
select AUXILIARY_BUS
select COMMON_CLK_EIC7700
select RESET_EIC7700_HSP if RESET_CONTROLLER
select REGMAP_MMIO
help
This driver provides support for clock controller on ESWIN EIC7700
HSP. The clock controller generates and supplies clocks to high
speed peripherals within the SoC.
Say yes here to support the clock controller on the EIC7700 HSP.
+1
View File
@@ -6,3 +6,4 @@
obj-$(CONFIG_COMMON_CLK_ESWIN) += clk.o
obj-$(CONFIG_COMMON_CLK_EIC7700) += clk-eic7700.o
obj-$(CONFIG_COMMON_CLK_EIC7700_HSP) += clk-eic7700-hsp.o
+345
View File
@@ -0,0 +1,345 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd..
* All rights reserved.
*
* ESWIN EIC7700 HSP Clock Driver
*
* Authors: Xuyang Dong <dongxuyang@eswincomputing.com>
*/
#include <linux/auxiliary_bus.h>
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/eswin,eic7700-hspcrg.h>
#include "common.h"
#define EIC7700_HSP_SATA_REG 0x300
#define EIC7700_HSP_MSHC0_REG 0x510
#define EIC7700_HSP_MSHC1_REG 0x610
#define EIC7700_HSP_MSHC2_REG 0x710
#define EIC7700_HSP_USB0_REG 0x800
#define EIC7700_HSP_USB0_REF_REG 0x83c
#define EIC7700_HSP_USB1_REG 0x900
#define EIC7700_HSP_USB1_REF_REG 0x93c
#define USB_REF_XTAL24M 0x2a
#define EIC7700_HSP_NR_CLKS (EIC7700_HSP_CLK_GATE_SATA + 1)
struct eic7700_hsp_clk_gate {
struct clk_hw hw;
unsigned int id;
struct regmap *regmap;
unsigned int reg;
unsigned int ref_reg;
const char *name;
const struct clk_parent_data *parent_data;
unsigned long flags;
unsigned int offset;
unsigned int ref_offset;
u8 bit_idx;
};
static const struct regmap_config eic7700_hsp_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.max_register = 0x1ffc,
.reg_stride = 4,
.fast_io = true,
.use_raw_spinlock = true,
};
static inline struct eic7700_hsp_clk_gate *to_gate_clk(struct clk_hw *hw)
{
return container_of(hw, struct eic7700_hsp_clk_gate, hw);
}
#define EIC7700_HSP_GATE(_id, _name, _pdata, _flags, _offset, _idx, \
_ref_offset) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.flags = _flags, \
.offset = _offset, \
.ref_offset = _ref_offset, \
.bit_idx = _idx, \
}
static void hsp_clk_gate_endisable(struct clk_hw *hw, bool enable)
{
struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
if (enable) {
/*
* Hardware bug: The USB reference clock must be 24MHz.
* The default register value after reset is invalid.
* Workaround: Rewrite the correct value before enabling
* the USB gate clock.
*/
regmap_update_bits(gate->regmap, gate->ref_reg, 0x3f,
USB_REF_XTAL24M);
}
regmap_assign_bits(gate->regmap, gate->reg, BIT(gate->bit_idx), enable);
}
static int hsp_clk_gate_enable(struct clk_hw *hw)
{
hsp_clk_gate_endisable(hw, true);
return 0;
}
static void hsp_clk_gate_disable(struct clk_hw *hw)
{
hsp_clk_gate_endisable(hw, false);
}
static int hsp_clk_gate_is_enabled(struct clk_hw *hw)
{
struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
unsigned int val;
int ret;
ret = regmap_read(gate->regmap, gate->reg, &val);
if (ret != 0)
return ret;
return !!(val & BIT(gate->bit_idx));
}
static const struct clk_ops hsp_clk_gate_ops = {
.enable = hsp_clk_gate_enable,
.disable = hsp_clk_gate_disable,
.is_enabled = hsp_clk_gate_is_enabled,
};
static struct clk_hw *
hsp_clk_register_gate(struct device *dev, unsigned int id, const char *name,
const struct clk_parent_data *parent_data,
unsigned long flags, struct regmap *regmap,
unsigned int reg, unsigned int ref_reg, u8 bit_idx)
{
struct eic7700_hsp_clk_gate *gate;
struct clk_init_data init = {};
struct clk_hw *hw;
int ret;
gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &hsp_clk_gate_ops;
init.flags = flags;
init.parent_data = parent_data;
init.num_parents = 1;
gate->id = id;
gate->regmap = regmap;
gate->reg = reg;
gate->ref_reg = ref_reg;
gate->bit_idx = bit_idx;
gate->hw.init = &init;
hw = &gate->hw;
ret = devm_clk_hw_register(dev, hw);
if (ret)
hw = ERR_PTR(ret);
return hw;
}
static const struct clk_parent_data hsp_cfg[] = {
{ .index = 0 }
};
static const struct clk_parent_data hsp_mmc[] = {
{ .index = 1 }
};
static const struct clk_parent_data hsp_usb_sata[] = {
{ .index = 2 }
};
static struct eswin_fixed_factor_clock eic7700_hsp_factor_clks[] = {
ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_CFG_DIV2, "factor_hsp_cfg_div2",
hsp_cfg, 1, 2, 0),
ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_CFG_DIV4, "factor_hsp_cfg_div4",
hsp_cfg, 1, 4, 0),
ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_MMC_DIV10, "factor_hsp_mmc_div10",
hsp_mmc, 1, 10, 0),
};
static struct eswin_gate_clock eic7700_hsp_gate_clks[] = {
ESWIN_GATE(EIC7700_HSP_CLK_GATE_SATA, "gate_clk_hsp_sata", hsp_usb_sata,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_SATA_REG, 28, 0),
ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC0_TMR, "gate_clk_hsp_mshc0_tmr",
hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_MSHC0_REG, 8, 0),
ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC1_TMR, "gate_clk_hsp_mshc1_tmr",
hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_MSHC1_REG, 8, 0),
ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC2_TMR, "gate_clk_hsp_mshc2_tmr",
hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_MSHC2_REG, 8, 0),
};
static struct eic7700_hsp_clk_gate eic7700_hsp_spec_gate_clks[] = {
EIC7700_HSP_GATE(EIC7700_HSP_CLK_GATE_USB0, "gate_clk_hsp_usb0",
hsp_usb_sata, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_USB0_REG, 28, EIC7700_HSP_USB0_REF_REG),
EIC7700_HSP_GATE(EIC7700_HSP_CLK_GATE_USB1, "gate_clk_hsp_usb1",
hsp_usb_sata, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_USB1_REG, 28, EIC7700_HSP_USB1_REF_REG),
};
static const struct clk_parent_data mux_mmc_3mux1_p[] = {
{ .fw_name = "cfg" },
{ .hw = &eic7700_hsp_factor_clks[0].hw },
{ .hw = &eic7700_hsp_factor_clks[1].hw },
};
static const struct clk_parent_data mux_mmc_2mux1_p[] = {
{ .fw_name = "mmc" },
{ .hw = &eic7700_hsp_factor_clks[2].hw },
};
static u32 mux_mmc_3mux1_tbl[] = { 0x0, 0x1, 0x3 };
static struct eswin_mux_clock eic7700_hsp_mux_clks[] = {
ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_EMMC_3MUX1, "mux_hsp_emmc_3mux1",
mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC0_REG, 16, 2, 0,
mux_mmc_3mux1_tbl),
ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_SD0_3MUX1, "mux_hsp_sd0_3mux1",
mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC1_REG, 16, 2, 0,
mux_mmc_3mux1_tbl),
ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_SD1_3MUX1, "mux_hsp_sd1_3mux1",
mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC2_REG, 16, 2, 0,
mux_mmc_3mux1_tbl),
ESWIN_MUX(EIC7700_HSP_CLK_MUX_EMMC_CQE_2MUX1, "mux_hsp_emmc_cqe_2mux1",
mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC0_REG, 0, 1, 0),
ESWIN_MUX(EIC7700_HSP_CLK_MUX_SD0_CQE_2MUX1, "mux_hsp_sd0_cqe_2mux1",
mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC1_REG, 0, 1, 0),
ESWIN_MUX(EIC7700_HSP_CLK_MUX_SD1_CQE_2MUX1, "mux_hsp_sd1_cqe_2mux1",
mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC2_REG, 0, 1, 0),
};
static struct eswin_clk_info eic7700_hsp_clks[] = {
ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_EMMC, "gate_clk_hsp_emmc",
EIC7700_HSP_CLK_MUX_EMMC_3MUX1,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_MSHC0_REG, 24, 0),
ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_SD0, "gate_clk_hsp_sd0",
EIC7700_HSP_CLK_MUX_SD0_3MUX1,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_MSHC1_REG, 24, 0),
ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_SD1, "gate_clk_hsp_sd1",
EIC7700_HSP_CLK_MUX_SD1_3MUX1,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_HSP_MSHC2_REG, 24, 0),
};
static int eic7700_hsp_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct auxiliary_device *adev;
struct eswin_clock_data *data;
struct regmap *regmap;
struct clk_hw *hw;
int i, ret;
data = eswin_clk_init(pdev, EIC7700_HSP_NR_CLKS);
if (IS_ERR(data))
return dev_err_probe(dev, PTR_ERR(data),
"failed to get clk data!\n");
regmap = devm_regmap_init_mmio(dev, data->base,
&eic7700_hsp_regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"failed to get regmap!\n");
ret = eswin_clk_register_fixed_factor(dev, eic7700_hsp_factor_clks,
ARRAY_SIZE(eic7700_hsp_factor_clks),
data);
if (ret)
return dev_err_probe(dev, ret,
"failed to register fixed factor clock\n");
ret = eswin_clk_register_gate(dev, eic7700_hsp_gate_clks,
ARRAY_SIZE(eic7700_hsp_gate_clks), data);
if (ret)
return dev_err_probe(dev, ret,
"failed to register gate clock\n");
ret = eswin_clk_register_mux(dev, eic7700_hsp_mux_clks,
ARRAY_SIZE(eic7700_hsp_mux_clks),
data);
if (ret)
return dev_err_probe(dev, ret,
"failed to register mux clock\n");
ret = eswin_clk_register_clks(dev, eic7700_hsp_clks,
ARRAY_SIZE(eic7700_hsp_clks), data);
if (ret)
return dev_err_probe(dev, ret,
"failed to register clock\n");
for (i = 0; i < ARRAY_SIZE(eic7700_hsp_spec_gate_clks); i++) {
struct eic7700_hsp_clk_gate *gate;
gate = &eic7700_hsp_spec_gate_clks[i];
hw = hsp_clk_register_gate(dev, gate->id, gate->name,
gate->parent_data, gate->flags,
regmap, gate->offset,
gate->ref_offset, gate->bit_idx);
if (IS_ERR(hw))
return dev_err_probe(dev, PTR_ERR(hw),
"failed to register gate clock\n");
data->clk_data.hws[gate->id] = hw;
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
&data->clk_data);
if (ret)
return dev_err_probe(dev, ret, "add clk provider failed\n");
adev = devm_auxiliary_device_create(dev, "hsp-reset", NULL);
if (!adev)
return dev_err_probe(dev, -ENODEV,
"register hsp-reset device failed\n");
return 0;
}
static const struct of_device_id eic7700_hsp_clock_dt_ids[] = {
{ .compatible = "eswin,eic7700-hspcrg", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, eic7700_hsp_clock_dt_ids);
static struct platform_driver eic7700_hsp_clock_driver = {
.probe = eic7700_hsp_clk_probe,
.driver = {
.name = "eic7700-hsp-clock",
.of_match_table = eic7700_hsp_clock_dt_ids,
},
};
module_platform_driver(eic7700_hsp_clock_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Xuyang Dong <dongxuyang@eswincomputing.com>");
MODULE_DESCRIPTION("ESWIN EIC7700 HSP clock controller driver");
+2 -1
View File
@@ -791,7 +791,8 @@ static struct eswin_clk_info eic7700_clks[] = {
EIC7700_CLK_MUX_CPU_ROOT_3MUX1_GFREE,
CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_U84, 27, 0),
ESWIN_GATE_TYPE(EIC7700_CLK_GATE_NOC_NSP_CLK, "gate_noc_nsp_clk",
EIC7700_CLK_DIV_NOC_NSP_DYNM, CLK_SET_RATE_PARENT,
EIC7700_CLK_DIV_NOC_NSP_DYNM,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
EIC7700_REG_OFFSET_NOC, 31, 0),
ESWIN_GATE_TYPE(EIC7700_CLK_GATE_BOOTSPI, "gate_clk_bootspi",
EIC7700_CLK_MUX_BOOTSPI_CLK_2MUX1_GFREE,
+2 -2
View File
@@ -204,7 +204,7 @@ int eswin_clk_register_pll(struct device *dev, struct eswin_pll_clock *clks,
int nums, struct eswin_clock_data *data)
{
struct eswin_clk_pll *p_clk = NULL;
struct clk_init_data init;
struct clk_init_data init = {};
struct clk_hw *clk_hw;
int i, ret;
@@ -419,7 +419,7 @@ struct clk_hw *eswin_register_clkdiv(struct device *dev, unsigned int id,
unsigned long priv_flag, spinlock_t *lock)
{
struct eswin_divider_clock *dclk;
struct clk_init_data init;
struct clk_init_data init = {};
struct clk_hw *clk_hw;
int ret;
+14
View File
@@ -1,8 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-only
config COMMON_CLK_HISI
bool
default ARCH_HISI
config COMMON_CLK_HI3516CV300
tristate "HI3516CV300 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select RESET_HISI
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the clock driver for hi3516cv300.
@@ -11,6 +16,7 @@ config COMMON_CLK_HI3519
tristate "Hi3519 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select RESET_HISI
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the clock driver for hi3519.
@@ -19,6 +25,7 @@ config COMMON_CLK_HI3559A
bool "Hi3559A Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select RESET_HISI
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the clock driver for hi3559a.
@@ -26,6 +33,7 @@ config COMMON_CLK_HI3559A
config COMMON_CLK_HI3660
bool "Hi3660 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the clock driver for hi3660.
@@ -33,6 +41,7 @@ config COMMON_CLK_HI3660
config COMMON_CLK_HI3670
bool "Hi3670 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the clock driver for hi3670.
@@ -41,6 +50,7 @@ config COMMON_CLK_HI3798CV200
tristate "Hi3798CV200 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select RESET_HISI
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the clock driver for hi3798cv200.
@@ -48,6 +58,7 @@ config COMMON_CLK_HI3798CV200
config COMMON_CLK_HI6220
bool "Hi6220 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select COMMON_CLK_HISI
default ARCH_HISI
help
Build the Hisilicon Hi6220 clock driver based on the common clock framework.
@@ -55,6 +66,7 @@ config COMMON_CLK_HI6220
config RESET_HISI
bool "HiSilicon Reset Controller Driver"
depends on ARCH_HISI || COMPILE_TEST
select COMMON_CLK_HISI
select RESET_CONTROLLER
help
Build reset controller driver for HiSilicon device chipsets.
@@ -63,6 +75,7 @@ config STUB_CLK_HI6220
bool "Hi6220 Stub Clock Driver" if EXPERT
depends on (COMMON_CLK_HI6220 || COMPILE_TEST)
depends on MAILBOX
select COMMON_CLK_HISI
default COMMON_CLK_HI6220
help
Build the Hisilicon Hi6220 stub clock driver.
@@ -71,6 +84,7 @@ config STUB_CLK_HI3660
bool "Hi3660 Stub Clock Driver" if EXPERT
depends on (COMMON_CLK_HI3660 || COMPILE_TEST)
depends on MAILBOX
select COMMON_CLK_HISI
default COMMON_CLK_HI3660
help
Build the Hisilicon Hi3660 stub clock driver.
+4 -18
View File
@@ -67,16 +67,6 @@ static unsigned long hi3660_stub_clk_recalc_rate(struct clk_hw *hw,
return stub_clk->rate;
}
static int hi3660_stub_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/*
* LPM3 handles rate rounding so just return whatever
* rate is requested.
*/
return 0;
}
static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
@@ -97,7 +87,7 @@ static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops hi3660_stub_clk_ops = {
.recalc_rate = hi3660_stub_clk_recalc_rate,
.determine_rate = hi3660_stub_clk_determine_rate,
.determine_rate = clk_determine_rate_noop,
.set_rate = hi3660_stub_clk_set_rate,
};
@@ -124,7 +114,6 @@ static struct clk_hw *hi3660_stub_clk_hw_get(struct of_phandle_args *clkspec,
static int hi3660_stub_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
unsigned int i;
int ret;
@@ -139,12 +128,9 @@ static int hi3660_stub_clk_probe(struct platform_device *pdev)
if (IS_ERR(stub_clk_chan.mbox))
return PTR_ERR(stub_clk_chan.mbox);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
freq_reg = devm_ioremap(dev, res->start, resource_size(res));
if (!freq_reg)
return -ENOMEM;
freq_reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(freq_reg))
return PTR_ERR(freq_reg);
freq_reg += HI3660_STUB_CLOCK_DATA;
+1 -1
View File
@@ -91,7 +91,7 @@ struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev)
{
struct hisi_reset_controller *rstc;
rstc = devm_kmalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL);
rstc = devm_kzalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL);
if (!rstc)
return NULL;
+6
View File
@@ -300,6 +300,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct clk_hw *audio_pll_hws[2];
void __iomem *base;
int ret;
@@ -610,6 +611,11 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
imx_register_uart_clocks();
/* Add debug interface for audio PLLs */
audio_pll_hws[0] = hws[IMX8MM_AUDIO_PLL1];
audio_pll_hws[1] = hws[IMX8MM_AUDIO_PLL2];
imx_audio_pll_debug_init(audio_pll_hws, ARRAY_SIZE(audio_pll_hws));
return 0;
unregister_hws:
+1
View File
@@ -354,6 +354,7 @@ static const struct of_device_id imx8qxp_lpcg_match[] = {
{ .compatible = "fsl,imx8qxp-lpcg", NULL },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx8qxp_lpcg_match);
static struct platform_driver imx8qxp_lpcg_clk_driver = {
.driver = {
+1
View File
@@ -337,6 +337,7 @@ static const struct of_device_id imx8qxp_match[] = {
{ .compatible = "fsl,imx8qm-clk", &imx_clk_scu_rsrc_imx8qm, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx8qxp_match);
static struct platform_driver imx8qxp_clk_driver = {
.driver = {
+19 -2
View File
@@ -44,6 +44,8 @@ struct imx95_blk_ctl_clk_dev_data {
const char * const *parent_names;
u32 num_parents;
u32 reg;
u32 reg_init_msk;
u32 reg_init_val;
u32 bit_idx;
u32 bit_width;
u32 clk_type;
@@ -286,10 +288,22 @@ static const struct imx95_blk_ctl_dev_data netcmix_dev_data = {
static const struct imx95_blk_ctl_clk_dev_data hsio_blk_ctl_clk_dev_data[] = {
[0] = {
.name = "hsio_blk_ctl_clk",
.parent_names = (const char *[]){ "func_out_en", },
.num_parents = 1,
.reg = 0,
.reg_init_msk = GENMASK(10, 7),
.reg_init_val = GENMASK(10, 7),
.bit_idx = 6,
.bit_width = 1,
.type = CLK_GATE,
.flags = CLK_SET_RATE_PARENT,
},
[1] = {
.name = "func_out_en",
.parent_names = (const char *[]){ "hsio_pll", },
.num_parents = 1,
.reg = 0,
.bit_idx = 6,
.bit_idx = 2,
.bit_width = 1,
.type = CLK_GATE,
.flags = CLK_SET_RATE_PARENT,
@@ -297,7 +311,7 @@ static const struct imx95_blk_ctl_clk_dev_data hsio_blk_ctl_clk_dev_data[] = {
};
static const struct imx95_blk_ctl_dev_data hsio_blk_ctl_dev_data = {
.num_clks = 1,
.num_clks = ARRAY_SIZE(hsio_blk_ctl_clk_dev_data),
.clk_dev_data = hsio_blk_ctl_clk_dev_data,
.clk_reg_offset = 0,
};
@@ -400,6 +414,9 @@ static int imx95_bc_probe(struct platform_device *pdev)
const struct imx95_blk_ctl_clk_dev_data *data = &bc->pdata->clk_dev_data[i];
void __iomem *reg = base + data->reg;
if (data->reg_init_msk)
writel((readl(reg) & ~data->reg_init_msk) | data->reg_init_val, reg);
if (data->type == CLK_MUX) {
hws[i] = clk_hw_register_mux(dev, data->name, data->parent_names,
data->num_parents, data->flags, reg,

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