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

Pull clk updates from Stephen Boyd:
 "It looks like a smaller batch of clk updates this time around.

  In the core framework we just have some minor tweaks and a debugfs
  feature, so not much to see there. The driver updates are fairly well
  split between AT91 and Qualcomm clk support. Adding those two drivers
  together equals about 50% of the diffstat.

  Otherwise, the big amount of work this time was on supporting
  Broadcom's Raspberry Pi firmware clks.

  Highlights:

  Core:
   - Document clk_hw_round_rate() so it gets some more use
   - Remove unused __clk_get_flags()
   - Add a prepare/enable debugfs feature similar to rate setting

  New Drivers:
   - Add support for SAMA7G5 SoC clks
   - Enable CPU clks on Qualcomm IPQ6018 SoCs
   - Enable CPU clks on Qualcomm MSM8996 SoCs
   - GPU clk support for Qualcomm SM8150 and SM8250 SoCs
   - Audio clks on Qualcomm SC7180 SoCs
   - Microchip Sparx5 DPLL clk
   - Add support for the new Renesas RZ/G2H (R8A774E1) SoC

  Updates:
   - Make defines for bcm63xx-gate clks to use in DT
   - Support BCM2711 SoC firmware clks
   - Add HDMI clks for BCM2711 SoCs
   - Add RTC related clks on Ingenic SoCs
   - Support USB PHY clks on Ingenic SoCs
   - Support gate clks on BCM6318 SoCs
   - RMU and DMAC/GPIO clock support for Actions Semi S500 SoCs
   - Use poll_timeout functions in Rockchip clk driver
   - Support Rockchip rk3288w SoC variant
   - Mark mac_lbtest critical on Rockchip rk3188
   - Add CAAM clock support for i.MX vf610 driver
   - Add MU root clock support for i.MX imx8mp driver
   - Amlogic g12: add neural network accelerator clock sources
   - Amlogic meson8: remove critical flag for main PLL divider
   - Amlogic meson8: add video decoder clock gates
   - Convert one more Renesas DT binding to json-schema
   - Enhance critical clock handling on Renesas platforms to only
     consider clocks that were enabled at boot time"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (79 commits)
  clk: qcom: gcc: Make disp gpll0 branch aon for sc7180/sdm845
  ipq806x: gcc: add support for child probe
  clk: qcom: msm8996: Make symbol 'cpu_msm8996_clks' static
  clk: qcom: ipq8074: Add correct index for PCIe clocks
  clk: <linux/clk-provider.h>: drop a duplicated word
  clk: renesas: cpg-mssr: Add r8a774e1 support
  dt-bindings: clock: renesas,cpg-mssr: Document r8a774e1
  clk: Drop duplicate selection in Kconfig
  clk: qcom: smd: Add support for MSM8992/4 rpm clocks
  clk: qcom: ipq8074: Add missing clocks for pcie
  dt-bindings: clock: qcom: ipq8074: Add missing bindings for PCIe
  Replace HTTP links with HTTPS ones: Common CLK framework
  clk: qcom: Add CPU clock driver for msm8996
  dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: meson: meson8b: add the vclk2_en gate clock
  clk: meson: meson8b: add the vclk_en gate clock
  clk: qcom: Fix return value check in apss_ipq6018_probe()
  clk: bcm: dvp: Add missing module informations
  clk: meson: meson8b: Drop CLK_IS_CRITICAL from fclk_div2
  ...
This commit is contained in:
Linus Torvalds
2020-08-07 13:35:51 -07:00
90 changed files with 3542 additions and 684 deletions

View File

@@ -1,14 +0,0 @@
Raspberry Pi VideoCore firmware driver
Required properties:
- compatible: Should be "raspberrypi,bcm2835-firmware"
- mboxes: Phandle to the firmware device's Mailbox.
(See: ../mailbox/mailbox.txt for more information)
Example:
firmware {
compatible = "raspberrypi,bcm2835-firmware";
mboxes = <&mailbox>;
};

View File

@@ -0,0 +1,59 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/bcm/raspberrypi,bcm2835-firmware.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Raspberry Pi VideoCore firmware driver
maintainers:
- Eric Anholt <eric@anholt.net>
- Stefan Wahren <wahrenst@gmx.net>
properties:
compatible:
items:
- const: raspberrypi,bcm2835-firmware
- const: simple-bus
mboxes:
$ref: '/schemas/types.yaml#/definitions/phandle'
description: |
Phandle to the firmware device's Mailbox.
(See: ../mailbox/mailbox.txt for more information)
clocks:
type: object
properties:
compatible:
const: raspberrypi,firmware-clocks
"#clock-cells":
const: 1
description: >
The argument is the ID of the clocks contained by the
firmware messages.
required:
- compatible
- "#clock-cells"
additionalProperties: false
required:
- compatible
- mboxes
examples:
- |
firmware {
compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
mboxes = <&mailbox>;
firmware_clocks: clocks {
compatible = "raspberrypi,firmware-clocks";
#clock-cells = <1>;
};
};
...

View File

@@ -0,0 +1,47 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/brcm,bcm2711-dvp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM2711 HDMI DVP Device Tree Bindings
maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
"#clock-cells":
const: 1
"#reset-cells":
const: 1
compatible:
const: brcm,brcm2711-dvp
reg:
maxItems: 1
clocks:
maxItems: 1
required:
- "#clock-cells"
- "#reset-cells"
- compatible
- reg
- clocks
additionalProperties: false
examples:
- |
dvp: clock@7ef00000 {
compatible = "brcm,brcm2711-dvp";
reg = <0x7ef00000 0x10>;
clocks = <&clk_108MHz>;
#clock-cells = <1>;
#reset-cells = <1>;
};
...

View File

@@ -3,6 +3,8 @@ Gated Clock Controller Bindings for MIPS based BCM63XX SoCs
Required properties: Required properties:
- compatible: must be one of: - compatible: must be one of:
"brcm,bcm3368-clocks" "brcm,bcm3368-clocks"
"brcm,bcm6318-clocks"
"brcm,bcm6318-ubus-clocks"
"brcm,bcm6328-clocks" "brcm,bcm6328-clocks"
"brcm,bcm6358-clocks" "brcm,bcm6358-clocks"
"brcm,bcm6362-clocks" "brcm,bcm6362-clocks"

View File

@@ -9,7 +9,7 @@ specifier is an array of zero, one or more cells identifying the clock
output on a device. The length of a clock specifier is defined by the output on a device. The length of a clock specifier is defined by the
value of a #clock-cells property in the clock provider node. value of a #clock-cells property in the clock provider node.
[1] http://patchwork.ozlabs.org/patch/31551/ [1] https://patchwork.ozlabs.org/patch/31551/
==Clock providers== ==Clock providers==

View File

@@ -31,6 +31,29 @@ Required properties:
- 5p49v5933 and - 5p49v5933 and
- 5p49v5935: (optional) property not present or "clkin". - 5p49v5935: (optional) property not present or "clkin".
For all output ports, a corresponding, optional child node named OUT1,
OUT2, etc. can represent a each output, and the node can be used to
specify the following:
- itd,mode: can be one of the following:
- VC5_LVPECL
- VC5_CMOS
- VC5_HCSL33
- VC5_LVDS
- VC5_CMOS2
- VC5_CMOSD
- VC5_HCSL25
- idt,voltage-microvolts: can be one of the following
- 1800000
- 2500000
- 3300000
- idt,slew-percent: Percent of normal, can be one of
- 80
- 85
- 90
- 100
==Mapping between clock specifier and physical pins== ==Mapping between clock specifier and physical pins==
When referencing the provided clock in the DT using phandle and When referencing the provided clock in the DT using phandle and
@@ -81,6 +104,16 @@ i2c-master-node {
/* Connect XIN input to 25MHz reference */ /* Connect XIN input to 25MHz reference */
clocks = <&ref25m>; clocks = <&ref25m>;
clock-names = "xin"; clock-names = "xin";
OUT1 {
itd,mode = <VC5_CMOS>;
idt,voltage-microvolts = <1800000>;
idt,slew-percent = <80>;
};
OUT2 {
...
};
...
}; };
}; };

View File

@@ -15,7 +15,9 @@ description:
properties: properties:
compatible: compatible:
const: qcom,msm8916-a53pll enum:
- qcom,ipq6018-a53pll
- qcom,msm8916-a53pll
reg: reg:
maxItems: 1 maxItems: 1
@@ -23,6 +25,14 @@ properties:
'#clock-cells': '#clock-cells':
const: 0 const: 0
clocks:
items:
- description: board XO clock
clock-names:
items:
- const: xo
required: required:
- compatible - compatible
- reg - reg
@@ -38,3 +48,12 @@ examples:
reg = <0xb016000 0x40>; reg = <0xb016000 0x40>;
#clock-cells = <0>; #clock-cells = <0>;
}; };
#Example 2 - A53 PLL found on IPQ6018 devices
- |
a53pll_ipq: clock-controller@b116000 {
compatible = "qcom,ipq6018-a53pll";
reg = <0x0b116000 0x40>;
#clock-cells = <0>;
clocks = <&xo>;
clock-names = "xo";
};

View File

@@ -0,0 +1,56 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,kryocc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm clock controller for MSM8996 CPUs
maintainers:
- Loic Poulain <loic.poulain@linaro.org>
description: |
Qualcomm CPU clock controller for MSM8996 CPUs, clock 0 is for Power cluster
and clock 1 is for Perf cluster.
properties:
compatible:
enum:
- qcom,msm8996-apcc
reg:
maxItems: 1
'#clock-cells':
const: 1
clocks:
items:
- description: Primary PLL clock for power cluster (little)
- description: Primary PLL clock for perf cluster (big)
- description: Alternate PLL clock for power cluster (little)
- description: Alternate PLL clock for perf cluster (big)
clock-names:
items:
- const: pwrcl_pll
- const: perfcl_pll
- const: pwrcl_alt_pll
- const: perfcl_alt_pll
required:
- compatible
- reg
- '#clock-cells'
additionalProperties: false
examples:
# Example for msm8996
- |
kryocc: clock-controller@6400000 {
compatible = "qcom,msm8996-apcc";
reg = <0x6400000 0x90000>;
#clock-cells = <1>;
};
...

View File

@@ -13,13 +13,17 @@ Required properties :
"qcom,rpmcc-msm8660", "qcom,rpmcc" "qcom,rpmcc-msm8660", "qcom,rpmcc"
"qcom,rpmcc-apq8060", "qcom,rpmcc" "qcom,rpmcc-apq8060", "qcom,rpmcc"
"qcom,rpmcc-msm8916", "qcom,rpmcc" "qcom,rpmcc-msm8916", "qcom,rpmcc"
"qcom,rpmcc-msm8936", "qcom,rpmcc"
"qcom,rpmcc-msm8974", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc"
"qcom,rpmcc-msm8976", "qcom,rpmcc" "qcom,rpmcc-msm8976", "qcom,rpmcc"
"qcom,rpmcc-apq8064", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc"
"qcom,rpmcc-ipq806x", "qcom,rpmcc" "qcom,rpmcc-ipq806x", "qcom,rpmcc"
"qcom,rpmcc-msm8992",·"qcom,rpmcc"
"qcom,rpmcc-msm8994",·"qcom,rpmcc"
"qcom,rpmcc-msm8996", "qcom,rpmcc" "qcom,rpmcc-msm8996", "qcom,rpmcc"
"qcom,rpmcc-msm8998", "qcom,rpmcc" "qcom,rpmcc-msm8998", "qcom,rpmcc"
"qcom,rpmcc-qcs404", "qcom,rpmcc" "qcom,rpmcc-qcs404", "qcom,rpmcc"
"qcom,rpmcc-sdm660", "qcom,rpmcc"
- #clock-cells : shall contain 1 - #clock-cells : shall contain 1

View File

@@ -0,0 +1,241 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/renesas,cpg-clocks.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas Clock Pulse Generator (CPG)
maintainers:
- Geert Uytterhoeven <geert+renesas@glider.be>
description:
The Clock Pulse Generator (CPG) generates core clocks for the SoC. It
includes PLLs, and fixed and variable ratio dividers.
The CPG may also provide a Clock Domain for SoC devices, in combination with
the CPG Module Stop (MSTP) Clocks.
properties:
compatible:
oneOf:
- const: renesas,r8a73a4-cpg-clocks # R-Mobile APE6
- const: renesas,r8a7740-cpg-clocks # R-Mobile A1
- const: renesas,r8a7778-cpg-clocks # R-Car M1
- const: renesas,r8a7779-cpg-clocks # R-Car H1
- items:
- enum:
- renesas,r7s72100-cpg-clocks # RZ/A1H
- const: renesas,rz-cpg-clocks # RZ/A1
- const: renesas,sh73a0-cpg-clocks # SH-Mobile AG5
reg:
maxItems: 1
clocks: true
'#clock-cells':
const: 1
clock-output-names: true
renesas,mode:
description: Board-specific settings of the MD_CK* bits on R-Mobile A1
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
'#power-domain-cells':
const: 0
required:
- compatible
- reg
- clocks
- '#clock-cells'
- clock-output-names
allOf:
- if:
properties:
compatible:
contains:
const: renesas,r8a73a4-cpg-clocks
then:
properties:
clocks:
items:
- description: extal1
- description: extal2
clock-output-names:
items:
- const: main
- const: pll0
- const: pll1
- const: pll2
- const: pll2s
- const: pll2h
- const: z
- const: z2
- const: i
- const: m3
- const: b
- const: m1
- const: m2
- const: zx
- const: zs
- const: hp
- if:
properties:
compatible:
contains:
const: renesas,r8a7740-cpg-clocks
then:
properties:
clocks:
items:
- description: extal1
- description: extal2
- description: extalr
clock-output-names:
items:
- const: system
- const: pllc0
- const: pllc1
- const: pllc2
- const: r
- const: usb24s
- const: i
- const: zg
- const: b
- const: m1
- const: hp
- const: hpp
- const: usbp
- const: s
- const: zb
- const: m3
- const: cp
required:
- renesas,mode
- if:
properties:
compatible:
contains:
const: renesas,r8a7778-cpg-clocks
then:
properties:
clocks:
maxItems: 1
clock-output-names:
items:
- const: plla
- const: pllb
- const: b
- const: out
- const: p
- const: s
- const: s1
- if:
properties:
compatible:
contains:
const: renesas,r8a7779-cpg-clocks
then:
properties:
clocks:
maxItems: 1
clock-output-names:
items:
- const: plla
- const: z
- const: zs
- const: s
- const: s1
- const: p
- const: b
- const: out
- if:
properties:
compatible:
contains:
const: renesas,r7s72100-cpg-clocks
then:
properties:
clocks:
items:
- description: extal1
- description: usb_x1
clock-output-names:
items:
- const: pll
- const: i
- const: g
- if:
properties:
compatible:
contains:
const: renesas,sh73a0-cpg-clocks
then:
properties:
clocks:
items:
- description: extal1
- description: extal2
clock-output-names:
items:
- const: main
- const: pll0
- const: pll1
- const: pll2
- const: pll3
- const: dsi0phy
- const: dsi1phy
- const: zg
- const: m3
- const: b
- const: m1
- const: m2
- const: z
- const: zx
- const: hp
- if:
properties:
compatible:
contains:
enum:
- renesas,r8a7778-cpg-clocks
- renesas,r8a7779-cpg-clocks
- renesas,rz-cpg-clocks
then:
required:
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a7740-clock.h>
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,r8a7740-cpg-clocks";
reg = <0xe6150000 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>, <&extalr_clk>;
#clock-cells = <1>;
clock-output-names = "system", "pllc0", "pllc1", "pllc2", "r",
"usb24s", "i", "zg", "b", "m1", "hp", "hpp",
"usbp", "s", "zb", "m3", "cp";
renesas,mode = <0x05>;
};

View File

@@ -33,6 +33,7 @@ properties:
- renesas,r8a774a1-cpg-mssr # RZ/G2M - renesas,r8a774a1-cpg-mssr # RZ/G2M
- renesas,r8a774b1-cpg-mssr # RZ/G2N - renesas,r8a774b1-cpg-mssr # RZ/G2N
- renesas,r8a774c0-cpg-mssr # RZ/G2E - renesas,r8a774c0-cpg-mssr # RZ/G2E
- renesas,r8a774e1-cpg-mssr # RZ/G2H
- renesas,r8a7790-cpg-mssr # R-Car H2 - renesas,r8a7790-cpg-mssr # R-Car H2
- renesas,r8a7791-cpg-mssr # R-Car M2-W - renesas,r8a7791-cpg-mssr # R-Car M2-W
- renesas,r8a7792-cpg-mssr # R-Car V2H - renesas,r8a7792-cpg-mssr # R-Car V2H

View File

@@ -1,33 +0,0 @@
* Renesas R8A73A4 Clock Pulse Generator (CPG)
The CPG generates core clocks for the R8A73A4 SoC. It includes five PLLs
and several fixed ratio dividers.
Required Properties:
- compatible: Must be "renesas,r8a73a4-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- clocks: Reference to the parent clocks ("extal1" and "extal2")
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "main",
"pll0", "pll1", "pll2", "pll2s", "pll2h", "z", "z2", "i", "m3", "b",
"m1", "m2", "zx", "zs", and "hp".
Example
-------
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,r8a73a4-cpg-clocks";
reg = <0 0xe6150000 0 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>;
#clock-cells = <1>;
clock-output-names = "main", "pll0", "pll1", "pll2",
"pll2s", "pll2h", "z", "z2",
"i", "m3", "b", "m1", "m2",
"zx", "zs", "hp";
};

View File

@@ -1,41 +0,0 @@
These bindings should be considered EXPERIMENTAL for now.
* Renesas R8A7740 Clock Pulse Generator (CPG)
The CPG generates core clocks for the R8A7740 SoC. It includes three PLLs
and several fixed ratio and variable ratio dividers.
Required Properties:
- compatible: Must be "renesas,r8a7740-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- clocks: Reference to the three parent clocks
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are
"system", "pllc0", "pllc1", "pllc2", "r", "usb24s", "i", "zg", "b",
"m1", "hp", "hpp", "usbp", "s", "zb", "m3", and "cp".
- renesas,mode: board-specific settings of the MD_CK* bits
Example
-------
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,r8a7740-cpg-clocks";
reg = <0xe6150000 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>, <&extalr_clk>;
#clock-cells = <1>;
clock-output-names = "system", "pllc0", "pllc1",
"pllc2", "r",
"usb24s",
"i", "zg", "b", "m1", "hp",
"hpp", "usbp", "s", "zb", "m3",
"cp";
};
&cpg_clocks {
renesas,mode = <0x05>;
};

View File

@@ -1,47 +0,0 @@
* Renesas R8A7778 Clock Pulse Generator (CPG)
The CPG generates core clocks for the R8A7778. It includes two PLLs and
several fixed ratio dividers.
The CPG also provides a Clock Domain for SoC devices, in combination with the
CPG Module Stop (MSTP) Clocks.
Required Properties:
- compatible: Must be "renesas,r8a7778-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are
"plla", "pllb", "b", "out", "p", "s", and "s1".
- #power-domain-cells: Must be 0
SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
through an MSTP clock should refer to the CPG device node in their
"power-domains" property, as documented by the generic PM domain bindings in
Documentation/devicetree/bindings/power/power_domain.txt.
Examples
--------
- CPG device node:
cpg_clocks: cpg_clocks@ffc80000 {
compatible = "renesas,r8a7778-cpg-clocks";
reg = <0xffc80000 0x80>;
#clock-cells = <1>;
clocks = <&extal_clk>;
clock-output-names = "plla", "pllb", "b",
"out", "p", "s", "s1";
#power-domain-cells = <0>;
};
- CPG/MSTP Clock Domain member device node:
sdhi0: sd@ffe4c000 {
compatible = "renesas,sdhi-r8a7778";
reg = <0xffe4c000 0x100>;
interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks R8A7778_CLK_SDHI0>;
power-domains = <&cpg_clocks>;
};

View File

@@ -1,49 +0,0 @@
* Renesas R8A7779 Clock Pulse Generator (CPG)
The CPG generates core clocks for the R8A7779. It includes one PLL and
several fixed ratio dividers.
The CPG also provides a Clock Domain for SoC devices, in combination with the
CPG Module Stop (MSTP) Clocks.
Required Properties:
- compatible: Must be "renesas,r8a7779-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- clocks: Reference to the parent clock
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "plla",
"z", "zs", "s", "s1", "p", "b", "out".
- #power-domain-cells: Must be 0
SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
through an MSTP clock should refer to the CPG device node in their
"power-domains" property, as documented by the generic PM domain bindings in
Documentation/devicetree/bindings/power/power_domain.txt.
Examples
--------
- CPG device node:
cpg_clocks: cpg_clocks@ffc80000 {
compatible = "renesas,r8a7779-cpg-clocks";
reg = <0xffc80000 0x30>;
clocks = <&extal_clk>;
#clock-cells = <1>;
clock-output-names = "plla", "z", "zs", "s", "s1", "p",
"b", "out";
#power-domain-cells = <0>;
};
- CPG/MSTP Clock Domain member device node:
sata: sata@fc600000 {
compatible = "renesas,sata-r8a7779", "renesas,rcar-sata";
reg = <0xfc600000 0x2000>;
interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7779_CLK_SATA>;
power-domains = <&cpg_clocks>;
};

View File

@@ -1,53 +0,0 @@
* Renesas RZ/A1 Clock Pulse Generator (CPG)
The CPG generates core clocks for the RZ/A1 SoCs. It includes the PLL, variable
CPU and GPU clocks, and several fixed ratio dividers.
The CPG also provides a Clock Domain for SoC devices, in combination with the
CPG Module Stop (MSTP) Clocks.
Required Properties:
- compatible: Must be one of
- "renesas,r7s72100-cpg-clocks" for the r7s72100 CPG
and "renesas,rz-cpg-clocks" as a fallback.
- reg: Base address and length of the memory resource used by the CPG
- clocks: References to possible parent clocks. Order must match clock modes
in the datasheet. For the r7s72100, this is extal, usb_x1.
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "pll",
"i", and "g"
- #power-domain-cells: Must be 0
SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
through an MSTP clock should refer to the CPG device node in their
"power-domains" property, as documented by the generic PM domain bindings in
Documentation/devicetree/bindings/power/power_domain.txt.
Examples
--------
- CPG device node:
cpg_clocks: cpg_clocks@fcfe0000 {
#clock-cells = <1>;
compatible = "renesas,r7s72100-cpg-clocks",
"renesas,rz-cpg-clocks";
reg = <0xfcfe0000 0x18>;
clocks = <&extal_clk>, <&usb_x1_clk>;
clock-output-names = "pll", "i", "g";
#power-domain-cells = <0>;
};
- CPG/MSTP Clock Domain member device node:
mtu2: timer@fcff0000 {
compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
reg = <0xfcff0000 0x400>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tgi0a";
clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
clock-names = "fck";
power-domains = <&cpg_clocks>;
};

View File

@@ -1,35 +0,0 @@
These bindings should be considered EXPERIMENTAL for now.
* Renesas SH73A0 Clock Pulse Generator (CPG)
The CPG generates core clocks for the SH73A0 SoC. It includes four PLLs
and several fixed ratio dividers.
Required Properties:
- compatible: Must be "renesas,sh73a0-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- clocks: Reference to the parent clocks ("extal1" and "extal2")
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "main",
"pll0", "pll1", "pll2", "pll3", "dsi0phy", "dsi1phy", "zg", "m3", "b",
"m1", "m2", "z", "zx", and "hp".
Example
-------
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,sh73a0-cpg-clocks";
reg = <0 0xe6150000 0 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>;
#clock-cells = <1>;
clock-output-names = "main", "pll0", "pll1", "pll2",
"pll3", "dsi0phy", "dsi1phy",
"zg", "m3", "b", "m1", "m2",
"z", "zx", "hp";
};

View File

@@ -6,7 +6,7 @@ found in the datasheet[2].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Si514 datasheet [2] Si514 datasheet
http://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf https://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf
Required properties: Required properties:
- compatible: Shall be "silabs,si514" - compatible: Shall be "silabs,si514"

View File

@@ -2,7 +2,7 @@ Binding for Silicon Labs Si5351a/b/c programmable i2c clock generator.
Reference Reference
[1] Si5351A/B/C Data Sheet [1] Si5351A/B/C Data Sheet
http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf https://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf
The Si5351a/b/c are programmable i2c clock generators with up to 8 output The Si5351a/b/c are programmable i2c clock generators with up to 8 output
clocks. Si5351a also has a reduced pin-count package (MSOP10) where only clocks. Si5351a also has a reduced pin-count package (MSOP10) where only

View File

@@ -7,9 +7,9 @@ found in the data sheets[2][3].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Si570/571 Data Sheet [2] Si570/571 Data Sheet
http://www.silabs.com/Support%20Documents/TechnicalDocs/si570.pdf https://www.silabs.com/Support%20Documents/TechnicalDocs/si570.pdf
[3] Si598/599 Data Sheet [3] Si598/599 Data Sheet
http://www.silabs.com/Support%20Documents/TechnicalDocs/si598-99.pdf https://www.silabs.com/Support%20Documents/TechnicalDocs/si598-99.pdf
Required properties: Required properties:
- compatible: Shall be one of "silabs,si570", "silabs,si571", - compatible: Shall be one of "silabs,si570", "silabs,si571",

View File

@@ -1,7 +1,7 @@
Bindings for Texas Instruments CDCE706 programmable 3-PLL clock Bindings for Texas Instruments CDCE706 programmable 3-PLL clock
synthesizer/multiplier/divider. synthesizer/multiplier/divider.
Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf Reference: https://www.ti.com/lit/ds/symlink/cdce706.pdf
I2C device node required properties: I2C device node required properties:
- compatible: shall be "ti,cdce706". - compatible: shall be "ti,cdce706".

View File

@@ -4,10 +4,10 @@ Reference
This binding uses the common clock binding[1]. This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] http://www.ti.com/product/cdce913 [2] https://www.ti.com/product/cdce913
[3] http://www.ti.com/product/cdce925 [3] https://www.ti.com/product/cdce925
[4] http://www.ti.com/product/cdce937 [4] https://www.ti.com/product/cdce937
[5] http://www.ti.com/product/cdce949 [5] https://www.ti.com/product/cdce949
The driver provides clock sources for each output Y1 through Y5. The driver provides clock sources for each output Y1 through Y5.

View File

@@ -121,7 +121,6 @@ config COMMON_CLK_SI5351
tristate "Clock driver for SiLabs 5351A/B/C" tristate "Clock driver for SiLabs 5351A/B/C"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
select RATIONAL
help help
This driver supports Silicon Labs 5351A/B/C programmable clock This driver supports Silicon Labs 5351A/B/C programmable clock
generators. generators.
@@ -163,7 +162,6 @@ config COMMON_CLK_CDCE706
tristate "Clock driver for TI CDCE706 clock synthesizer" tristate "Clock driver for TI CDCE706 clock synthesizer"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
select RATIONAL
help help
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer. This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.

View File

@@ -1,4 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
config CLK_BCM2711_DVP
tristate "Broadcom BCM2711 DVP support"
depends on ARCH_BCM2835 ||COMPILE_TEST
depends on COMMON_CLK
default ARCH_BCM2835
select RESET_SIMPLE
help
Enable common clock framework support for the Broadcom BCM2711
DVP Controller.
config CLK_BCM2835 config CLK_BCM2835
bool "Broadcom BCM2835 clock support" bool "Broadcom BCM2835 clock support"
depends on ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST depends on ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST

View File

@@ -6,6 +6,7 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
obj-$(CONFIG_CLK_BCM2711_DVP) += clk-bcm2711-dvp.o
obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835.o obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835.o
obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835-aux.o obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835-aux.o
obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o

View File

@@ -0,0 +1,124 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2020 Cerno
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/reset/reset-simple.h>
#define DVP_HT_RPI_SW_INIT 0x04
#define DVP_HT_RPI_MISC_CONFIG 0x08
#define NR_CLOCKS 2
#define NR_RESETS 6
struct clk_dvp {
struct clk_hw_onecell_data *data;
struct reset_simple_data reset;
};
static const struct clk_parent_data clk_dvp_parent = {
.index = 0,
};
static int clk_dvp_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *data;
struct resource *res;
struct clk_dvp *dvp;
void __iomem *base;
int ret;
dvp = devm_kzalloc(&pdev->dev, sizeof(*dvp), GFP_KERNEL);
if (!dvp)
return -ENOMEM;
platform_set_drvdata(pdev, dvp);
dvp->data = devm_kzalloc(&pdev->dev,
struct_size(dvp->data, hws, NR_CLOCKS),
GFP_KERNEL);
if (!dvp->data)
return -ENOMEM;
data = dvp->data;
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base))
return PTR_ERR(base);
dvp->reset.rcdev.owner = THIS_MODULE;
dvp->reset.rcdev.nr_resets = NR_RESETS;
dvp->reset.rcdev.ops = &reset_simple_ops;
dvp->reset.rcdev.of_node = pdev->dev.of_node;
dvp->reset.membase = base + DVP_HT_RPI_SW_INIT;
spin_lock_init(&dvp->reset.lock);
ret = devm_reset_controller_register(&pdev->dev, &dvp->reset.rcdev);
if (ret)
return ret;
data->hws[0] = clk_hw_register_gate_parent_data(&pdev->dev,
"hdmi0-108MHz",
&clk_dvp_parent, 0,
base + DVP_HT_RPI_MISC_CONFIG, 3,
CLK_GATE_SET_TO_DISABLE,
&dvp->reset.lock);
if (IS_ERR(data->hws[0]))
return PTR_ERR(data->hws[0]);
data->hws[1] = clk_hw_register_gate_parent_data(&pdev->dev,
"hdmi1-108MHz",
&clk_dvp_parent, 0,
base + DVP_HT_RPI_MISC_CONFIG, 4,
CLK_GATE_SET_TO_DISABLE,
&dvp->reset.lock);
if (IS_ERR(data->hws[1])) {
ret = PTR_ERR(data->hws[1]);
goto unregister_clk0;
}
data->num = NR_CLOCKS;
ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
data);
if (ret)
goto unregister_clk1;
return 0;
unregister_clk1:
clk_hw_unregister_gate(data->hws[1]);
unregister_clk0:
clk_hw_unregister_gate(data->hws[0]);
return ret;
};
static int clk_dvp_remove(struct platform_device *pdev)
{
struct clk_dvp *dvp = platform_get_drvdata(pdev);
struct clk_hw_onecell_data *data = dvp->data;
clk_hw_unregister_gate(data->hws[1]);
clk_hw_unregister_gate(data->hws[0]);
return 0;
}
static const struct of_device_id clk_dvp_dt_ids[] = {
{ .compatible = "brcm,brcm2711-dvp", },
{ /* sentinel */ }
};
static struct platform_driver clk_dvp_driver = {
.probe = clk_dvp_probe,
.remove = clk_dvp_remove,
.driver = {
.name = "brcm2711-dvp",
.of_match_table = clk_dvp_dt_ids,
},
};
module_platform_driver(clk_dvp_driver);
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
MODULE_DESCRIPTION("BCM2711 DVP clock driver");
MODULE_LICENSE("GPL");

View File

@@ -421,6 +421,7 @@ struct bcm2835_pll_data {
u32 reference_enable_mask; u32 reference_enable_mask;
/* Bit in CM_LOCK to indicate when the PLL has locked. */ /* Bit in CM_LOCK to indicate when the PLL has locked. */
u32 lock_mask; u32 lock_mask;
u32 flags;
const struct bcm2835_pll_ana_bits *ana; const struct bcm2835_pll_ana_bits *ana;
@@ -1310,7 +1311,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
init.num_parents = 1; init.num_parents = 1;
init.name = pll_data->name; init.name = pll_data->name;
init.ops = &bcm2835_pll_clk_ops; init.ops = &bcm2835_pll_clk_ops;
init.flags = CLK_IGNORE_UNUSED; init.flags = pll_data->flags | CLK_IGNORE_UNUSED;
pll = kzalloc(sizeof(*pll), GFP_KERNEL); pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll) if (!pll)
@@ -1684,10 +1685,33 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1, .fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT), .flags = CLK_SET_RATE_PARENT),
/* /* PLLB is used for the ARM's clock. */
* PLLB is used for the ARM's clock. Controlled by firmware, see [BCM2835_PLLB] = REGISTER_PLL(
* clk-raspberrypi.c. SOC_ALL,
*/ .name = "pllb",
.cm_ctrl_reg = CM_PLLB,
.a2w_ctrl_reg = A2W_PLLB_CTRL,
.frac_reg = A2W_PLLB_FRAC,
.ana_reg_base = A2W_PLLB_ANA0,
.reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
.lock_mask = CM_LOCK_FLOCKB,
.ana = &bcm2835_ana_default,
.min_rate = 600000000u,
.max_rate = 3000000000u,
.max_fb_rate = BCM2835_MAX_FB_RATE,
.flags = CLK_GET_RATE_NOCACHE),
[BCM2835_PLLB_ARM] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "pllb_arm",
.source_pll = "pllb",
.cm_reg = CM_PLLB,
.a2w_reg = A2W_PLLB_ARM,
.load_mask = CM_PLLB_LOADARM,
.hold_mask = CM_PLLB_HOLDARM,
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE),
/* /*
* PLLC is the core PLL, used to drive the core VPU clock. * PLLC is the core PLL, used to drive the core VPU clock.

View File

@@ -6,6 +6,14 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <dt-bindings/clock/bcm3368-clock.h>
#include <dt-bindings/clock/bcm6318-clock.h>
#include <dt-bindings/clock/bcm6328-clock.h>
#include <dt-bindings/clock/bcm6358-clock.h>
#include <dt-bindings/clock/bcm6362-clock.h>
#include <dt-bindings/clock/bcm6368-clock.h>
#include <dt-bindings/clock/bcm63268-clock.h>
struct clk_bcm63xx_table_entry { struct clk_bcm63xx_table_entry {
const char * const name; const char * const name;
u8 bit; u8 bit;
@@ -20,126 +28,458 @@ struct clk_bcm63xx_hw {
}; };
static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = { static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
{ .name = "mac", .bit = 3, }, {
{ .name = "tc", .bit = 5, }, .name = "mac",
{ .name = "us_top", .bit = 6, }, .bit = BCM3368_CLK_MAC,
{ .name = "ds_top", .bit = 7, }, }, {
{ .name = "acm", .bit = 8, }, .name = "tc",
{ .name = "spi", .bit = 9, }, .bit = BCM3368_CLK_TC,
{ .name = "usbs", .bit = 10, }, }, {
{ .name = "bmu", .bit = 11, }, .name = "us_top",
{ .name = "pcm", .bit = 12, }, .bit = BCM3368_CLK_US_TOP,
{ .name = "ntp", .bit = 13, }, }, {
{ .name = "acp_b", .bit = 14, }, .name = "ds_top",
{ .name = "acp_a", .bit = 15, }, .bit = BCM3368_CLK_DS_TOP,
{ .name = "emusb", .bit = 17, }, }, {
{ .name = "enet0", .bit = 18, }, .name = "acm",
{ .name = "enet1", .bit = 19, }, .bit = BCM3368_CLK_ACM,
{ .name = "usbsu", .bit = 20, }, }, {
{ .name = "ephy", .bit = 21, }, .name = "spi",
{ }, .bit = BCM3368_CLK_SPI,
}, {
.name = "usbs",
.bit = BCM3368_CLK_USBS,
}, {
.name = "bmu",
.bit = BCM3368_CLK_BMU,
}, {
.name = "pcm",
.bit = BCM3368_CLK_PCM,
}, {
.name = "ntp",
.bit = BCM3368_CLK_NTP,
}, {
.name = "acp_b",
.bit = BCM3368_CLK_ACP_B,
}, {
.name = "acp_a",
.bit = BCM3368_CLK_ACP_A,
}, {
.name = "emusb",
.bit = BCM3368_CLK_EMUSB,
}, {
.name = "enet0",
.bit = BCM3368_CLK_ENET0,
}, {
.name = "enet1",
.bit = BCM3368_CLK_ENET1,
}, {
.name = "usbsu",
.bit = BCM3368_CLK_USBSU,
}, {
.name = "ephy",
.bit = BCM3368_CLK_EPHY,
}, {
/* sentinel */
},
};
static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = {
{
.name = "adsl_asb",
.bit = BCM6318_CLK_ADSL_ASB,
}, {
.name = "usb_asb",
.bit = BCM6318_CLK_USB_ASB,
}, {
.name = "mips_asb",
.bit = BCM6318_CLK_MIPS_ASB,
}, {
.name = "pcie_asb",
.bit = BCM6318_CLK_PCIE_ASB,
}, {
.name = "phymips_asb",
.bit = BCM6318_CLK_PHYMIPS_ASB,
}, {
.name = "robosw_asb",
.bit = BCM6318_CLK_ROBOSW_ASB,
}, {
.name = "sar_asb",
.bit = BCM6318_CLK_SAR_ASB,
}, {
.name = "sdr_asb",
.bit = BCM6318_CLK_SDR_ASB,
}, {
.name = "swreg_asb",
.bit = BCM6318_CLK_SWREG_ASB,
}, {
.name = "periph_asb",
.bit = BCM6318_CLK_PERIPH_ASB,
}, {
.name = "cpubus160",
.bit = BCM6318_CLK_CPUBUS160,
}, {
.name = "adsl",
.bit = BCM6318_CLK_ADSL,
}, {
.name = "sar125",
.bit = BCM6318_CLK_SAR125,
}, {
.name = "mips",
.bit = BCM6318_CLK_MIPS,
.flags = CLK_IS_CRITICAL,
}, {
.name = "pcie",
.bit = BCM6318_CLK_PCIE,
}, {
.name = "robosw250",
.bit = BCM6318_CLK_ROBOSW250,
}, {
.name = "robosw025",
.bit = BCM6318_CLK_ROBOSW025,
}, {
.name = "sdr",
.bit = BCM6318_CLK_SDR,
.flags = CLK_IS_CRITICAL,
}, {
.name = "usbd",
.bit = BCM6318_CLK_USBD,
}, {
.name = "hsspi",
.bit = BCM6318_CLK_HSSPI,
}, {
.name = "pcie25",
.bit = BCM6318_CLK_PCIE25,
}, {
.name = "phymips",
.bit = BCM6318_CLK_PHYMIPS,
}, {
.name = "afe",
.bit = BCM6318_CLK_AFE,
}, {
.name = "qproc",
.bit = BCM6318_CLK_QPROC,
}, {
/* sentinel */
},
};
static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = {
{
.name = "adsl-ubus",
.bit = BCM6318_UCLK_ADSL,
}, {
.name = "arb-ubus",
.bit = BCM6318_UCLK_ARB,
.flags = CLK_IS_CRITICAL,
}, {
.name = "mips-ubus",
.bit = BCM6318_UCLK_MIPS,
.flags = CLK_IS_CRITICAL,
}, {
.name = "pcie-ubus",
.bit = BCM6318_UCLK_PCIE,
}, {
.name = "periph-ubus",
.bit = BCM6318_UCLK_PERIPH,
.flags = CLK_IS_CRITICAL,
}, {
.name = "phymips-ubus",
.bit = BCM6318_UCLK_PHYMIPS,
}, {
.name = "robosw-ubus",
.bit = BCM6318_UCLK_ROBOSW,
}, {
.name = "sar-ubus",
.bit = BCM6318_UCLK_SAR,
}, {
.name = "sdr-ubus",
.bit = BCM6318_UCLK_SDR,
}, {
.name = "usb-ubus",
.bit = BCM6318_UCLK_USB,
}, {
/* sentinel */
},
}; };
static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = { static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
{ .name = "phy_mips", .bit = 0, }, {
{ .name = "adsl_qproc", .bit = 1, }, .name = "phy_mips",
{ .name = "adsl_afe", .bit = 2, }, .bit = BCM6328_CLK_PHYMIPS,
{ .name = "adsl", .bit = 3, }, }, {
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, }, .name = "adsl_qproc",
{ .name = "sar", .bit = 5, }, .bit = BCM6328_CLK_ADSL_QPROC,
{ .name = "pcm", .bit = 6, }, }, {
{ .name = "usbd", .bit = 7, }, .name = "adsl_afe",
{ .name = "usbh", .bit = 8, }, .bit = BCM6328_CLK_ADSL_AFE,
{ .name = "hsspi", .bit = 9, }, }, {
{ .name = "pcie", .bit = 10, }, .name = "adsl",
{ .name = "robosw", .bit = 11, }, .bit = BCM6328_CLK_ADSL,
{ }, }, {
.name = "mips",
.bit = BCM6328_CLK_MIPS,
.flags = CLK_IS_CRITICAL,
}, {
.name = "sar",
.bit = BCM6328_CLK_SAR,
}, {
.name = "pcm",
.bit = BCM6328_CLK_PCM,
}, {
.name = "usbd",
.bit = BCM6328_CLK_USBD,
}, {
.name = "usbh",
.bit = BCM6328_CLK_USBH,
}, {
.name = "hsspi",
.bit = BCM6328_CLK_HSSPI,
}, {
.name = "pcie",
.bit = BCM6328_CLK_PCIE,
}, {
.name = "robosw",
.bit = BCM6328_CLK_ROBOSW,
}, {
/* sentinel */
},
}; };
static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = { static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
{ .name = "enet", .bit = 4, }, {
{ .name = "adslphy", .bit = 5, }, .name = "enet",
{ .name = "pcm", .bit = 8, }, .bit = BCM6358_CLK_ENET,
{ .name = "spi", .bit = 9, }, }, {
{ .name = "usbs", .bit = 10, }, .name = "adslphy",
{ .name = "sar", .bit = 11, }, .bit = BCM6358_CLK_ADSLPHY,
{ .name = "emusb", .bit = 17, }, }, {
{ .name = "enet0", .bit = 18, }, .name = "pcm",
{ .name = "enet1", .bit = 19, }, .bit = BCM6358_CLK_PCM,
{ .name = "usbsu", .bit = 20, }, }, {
{ .name = "ephy", .bit = 21, }, .name = "spi",
{ }, .bit = BCM6358_CLK_SPI,
}, {
.name = "usbs",
.bit = BCM6358_CLK_USBS,
}, {
.name = "sar",
.bit = BCM6358_CLK_SAR,
}, {
.name = "emusb",
.bit = BCM6358_CLK_EMUSB,
}, {
.name = "enet0",
.bit = BCM6358_CLK_ENET0,
}, {
.name = "enet1",
.bit = BCM6358_CLK_ENET1,
}, {
.name = "usbsu",
.bit = BCM6358_CLK_USBSU,
}, {
.name = "ephy",
.bit = BCM6358_CLK_EPHY,
}, {
/* sentinel */
},
}; };
static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = { static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
{ .name = "adsl_qproc", .bit = 1, }, {
{ .name = "adsl_afe", .bit = 2, }, .name = "adsl_qproc",
{ .name = "adsl", .bit = 3, }, .bit = BCM6362_CLK_ADSL_QPROC,
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, }, }, {
{ .name = "wlan_ocp", .bit = 5, }, .name = "adsl_afe",
{ .name = "swpkt_usb", .bit = 7, }, .bit = BCM6362_CLK_ADSL_AFE,
{ .name = "swpkt_sar", .bit = 8, }, }, {
{ .name = "sar", .bit = 9, }, .name = "adsl",
{ .name = "robosw", .bit = 10, }, .bit = BCM6362_CLK_ADSL,
{ .name = "pcm", .bit = 11, }, }, {
{ .name = "usbd", .bit = 12, }, .name = "mips",
{ .name = "usbh", .bit = 13, }, .bit = BCM6362_CLK_MIPS,
{ .name = "ipsec", .bit = 14, }, .flags = CLK_IS_CRITICAL,
{ .name = "spi", .bit = 15, }, }, {
{ .name = "hsspi", .bit = 16, }, .name = "wlan_ocp",
{ .name = "pcie", .bit = 17, }, .bit = BCM6362_CLK_WLAN_OCP,
{ .name = "fap", .bit = 18, }, }, {
{ .name = "phymips", .bit = 19, }, .name = "swpkt_usb",
{ .name = "nand", .bit = 20, }, .bit = BCM6362_CLK_SWPKT_USB,
{ }, }, {
.name = "swpkt_sar",
.bit = BCM6362_CLK_SWPKT_SAR,
}, {
.name = "sar",
.bit = BCM6362_CLK_SAR,
}, {
.name = "robosw",
.bit = BCM6362_CLK_ROBOSW,
}, {
.name = "pcm",
.bit = BCM6362_CLK_PCM,
}, {
.name = "usbd",
.bit = BCM6362_CLK_USBD,
}, {
.name = "usbh",
.bit = BCM6362_CLK_USBH,
}, {
.name = "ipsec",
.bit = BCM6362_CLK_IPSEC,
}, {
.name = "spi",
.bit = BCM6362_CLK_SPI,
}, {
.name = "hsspi",
.bit = BCM6362_CLK_HSSPI,
}, {
.name = "pcie",
.bit = BCM6362_CLK_PCIE,
}, {
.name = "fap",
.bit = BCM6362_CLK_FAP,
}, {
.name = "phymips",
.bit = BCM6362_CLK_PHYMIPS,
}, {
.name = "nand",
.bit = BCM6362_CLK_NAND,
}, {
/* sentinel */
},
}; };
static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = { static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
{ .name = "vdsl_qproc", .bit = 2, }, {
{ .name = "vdsl_afe", .bit = 3, }, .name = "vdsl_qproc",
{ .name = "vdsl_bonding", .bit = 4, }, .bit = BCM6368_CLK_VDSL_QPROC,
{ .name = "vdsl", .bit = 5, }, }, {
{ .name = "phymips", .bit = 6, }, .name = "vdsl_afe",
{ .name = "swpkt_usb", .bit = 7, }, .bit = BCM6368_CLK_VDSL_AFE,
{ .name = "swpkt_sar", .bit = 8, }, }, {
{ .name = "spi", .bit = 9, }, .name = "vdsl_bonding",
{ .name = "usbd", .bit = 10, }, .bit = BCM6368_CLK_VDSL_BONDING,
{ .name = "sar", .bit = 11, }, }, {
{ .name = "robosw", .bit = 12, }, .name = "vdsl",
{ .name = "utopia", .bit = 13, }, .bit = BCM6368_CLK_VDSL,
{ .name = "pcm", .bit = 14, }, }, {
{ .name = "usbh", .bit = 15, }, .name = "phymips",
{ .name = "disable_gless", .bit = 16, }, .bit = BCM6368_CLK_PHYMIPS,
{ .name = "nand", .bit = 17, }, }, {
{ .name = "ipsec", .bit = 18, }, .name = "swpkt_usb",
{ }, .bit = BCM6368_CLK_SWPKT_USB,
}, {
.name = "swpkt_sar",
.bit = BCM6368_CLK_SWPKT_SAR,
}, {
.name = "spi",
.bit = BCM6368_CLK_SPI,
}, {
.name = "usbd",
.bit = BCM6368_CLK_USBD,
}, {
.name = "sar",
.bit = BCM6368_CLK_SAR,
}, {
.name = "robosw",
.bit = BCM6368_CLK_ROBOSW,
}, {
.name = "utopia",
.bit = BCM6368_CLK_UTOPIA,
}, {
.name = "pcm",
.bit = BCM6368_CLK_PCM,
}, {
.name = "usbh",
.bit = BCM6368_CLK_USBH,
}, {
.name = "disable_gless",
.bit = BCM6368_CLK_DIS_GLESS,
}, {
.name = "nand",
.bit = BCM6368_CLK_NAND,
}, {
.name = "ipsec",
.bit = BCM6368_CLK_IPSEC,
}, {
/* sentinel */
},
}; };
static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = { static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
{ .name = "disable_gless", .bit = 0, }, {
{ .name = "vdsl_qproc", .bit = 1, }, .name = "disable_gless",
{ .name = "vdsl_afe", .bit = 2, }, .bit = BCM63268_CLK_DIS_GLESS,
{ .name = "vdsl", .bit = 3, }, }, {
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, }, .name = "vdsl_qproc",
{ .name = "wlan_ocp", .bit = 5, }, .bit = BCM63268_CLK_VDSL_QPROC,
{ .name = "dect", .bit = 6, }, }, {
{ .name = "fap0", .bit = 7, }, .name = "vdsl_afe",
{ .name = "fap1", .bit = 8, }, .bit = BCM63268_CLK_VDSL_AFE,
{ .name = "sar", .bit = 9, }, }, {
{ .name = "robosw", .bit = 10, }, .name = "vdsl",
{ .name = "pcm", .bit = 11, }, .bit = BCM63268_CLK_VDSL,
{ .name = "usbd", .bit = 12, }, }, {
{ .name = "usbh", .bit = 13, }, .name = "mips",
{ .name = "ipsec", .bit = 14, }, .bit = BCM63268_CLK_MIPS,
{ .name = "spi", .bit = 15, }, .flags = CLK_IS_CRITICAL,
{ .name = "hsspi", .bit = 16, }, }, {
{ .name = "pcie", .bit = 17, }, .name = "wlan_ocp",
{ .name = "phymips", .bit = 18, }, .bit = BCM63268_CLK_WLAN_OCP,
{ .name = "gmac", .bit = 19, }, }, {
{ .name = "nand", .bit = 20, }, .name = "dect",
{ .name = "tbus", .bit = 27, }, .bit = BCM63268_CLK_DECT,
{ .name = "robosw250", .bit = 31, }, }, {
{ }, .name = "fap0",
.bit = BCM63268_CLK_FAP0,
}, {
.name = "fap1",
.bit = BCM63268_CLK_FAP1,
}, {
.name = "sar",
.bit = BCM63268_CLK_SAR,
}, {
.name = "robosw",
.bit = BCM63268_CLK_ROBOSW,
}, {
.name = "pcm",
.bit = BCM63268_CLK_PCM,
}, {
.name = "usbd",
.bit = BCM63268_CLK_USBD,
}, {
.name = "usbh",
.bit = BCM63268_CLK_USBH,
}, {
.name = "ipsec",
.bit = BCM63268_CLK_IPSEC,
}, {
.name = "spi",
.bit = BCM63268_CLK_SPI,
}, {
.name = "hsspi",
.bit = BCM63268_CLK_HSSPI,
}, {
.name = "pcie",
.bit = BCM63268_CLK_PCIE,
}, {
.name = "phymips",
.bit = BCM63268_CLK_PHYMIPS,
}, {
.name = "gmac",
.bit = BCM63268_CLK_GMAC,
}, {
.name = "nand",
.bit = BCM63268_CLK_NAND,
}, {
.name = "tbus",
.bit = BCM63268_CLK_TBUS,
}, {
.name = "robosw250",
.bit = BCM63268_CLK_ROBOSW250,
}, {
/* sentinel */
},
}; };
static int clk_bcm63xx_probe(struct platform_device *pdev) static int clk_bcm63xx_probe(struct platform_device *pdev)
@@ -155,6 +495,7 @@ static int clk_bcm63xx_probe(struct platform_device *pdev)
for (entry = table; entry->name; entry++) for (entry = table; entry->name; entry++)
maxbit = max_t(u8, maxbit, entry->bit); maxbit = max_t(u8, maxbit, entry->bit);
maxbit++;
hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit), hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
GFP_KERNEL); GFP_KERNEL);
@@ -217,6 +558,8 @@ static int clk_bcm63xx_remove(struct platform_device *pdev)
static const struct of_device_id clk_bcm63xx_dt_ids[] = { static const struct of_device_id clk_bcm63xx_dt_ids[] = {
{ .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, }, { .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
{ .compatible = "brcm,bcm6318-clocks", .data = &bcm6318_clocks, },
{ .compatible = "brcm,bcm6318-ubus-clocks", .data = &bcm6318_ubus_clocks, },
{ .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, }, { .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
{ .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, }, { .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
{ .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, }, { .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },

View File

@@ -18,30 +18,56 @@
#include <soc/bcm2835/raspberrypi-firmware.h> #include <soc/bcm2835/raspberrypi-firmware.h>
#define RPI_FIRMWARE_ARM_CLK_ID 0x00000003 enum rpi_firmware_clk_id {
RPI_FIRMWARE_EMMC_CLK_ID = 1,
RPI_FIRMWARE_UART_CLK_ID,
RPI_FIRMWARE_ARM_CLK_ID,
RPI_FIRMWARE_CORE_CLK_ID,
RPI_FIRMWARE_V3D_CLK_ID,
RPI_FIRMWARE_H264_CLK_ID,
RPI_FIRMWARE_ISP_CLK_ID,
RPI_FIRMWARE_SDRAM_CLK_ID,
RPI_FIRMWARE_PIXEL_CLK_ID,
RPI_FIRMWARE_PWM_CLK_ID,
RPI_FIRMWARE_HEVC_CLK_ID,
RPI_FIRMWARE_EMMC2_CLK_ID,
RPI_FIRMWARE_M2MC_CLK_ID,
RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
RPI_FIRMWARE_NUM_CLK_ID,
};
static char *rpi_firmware_clk_names[] = {
[RPI_FIRMWARE_EMMC_CLK_ID] = "emmc",
[RPI_FIRMWARE_UART_CLK_ID] = "uart",
[RPI_FIRMWARE_ARM_CLK_ID] = "arm",
[RPI_FIRMWARE_CORE_CLK_ID] = "core",
[RPI_FIRMWARE_V3D_CLK_ID] = "v3d",
[RPI_FIRMWARE_H264_CLK_ID] = "h264",
[RPI_FIRMWARE_ISP_CLK_ID] = "isp",
[RPI_FIRMWARE_SDRAM_CLK_ID] = "sdram",
[RPI_FIRMWARE_PIXEL_CLK_ID] = "pixel",
[RPI_FIRMWARE_PWM_CLK_ID] = "pwm",
[RPI_FIRMWARE_HEVC_CLK_ID] = "hevc",
[RPI_FIRMWARE_EMMC2_CLK_ID] = "emmc2",
[RPI_FIRMWARE_M2MC_CLK_ID] = "m2mc",
[RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb",
};
#define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
#define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1) #define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1)
/*
* Even though the firmware interface alters 'pllb' the frequencies are
* provided as per 'pllb_arm'. We need to scale before passing them trough.
*/
#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE 2
#define A2W_PLL_FRAC_BITS 20
struct raspberrypi_clk { struct raspberrypi_clk {
struct device *dev; struct device *dev;
struct rpi_firmware *firmware; struct rpi_firmware *firmware;
struct platform_device *cpufreq; struct platform_device *cpufreq;
};
unsigned long min_rate; struct raspberrypi_clk_data {
unsigned long max_rate; struct clk_hw hw;
struct clk_hw pllb; unsigned int id;
struct clk_hw *pllb_arm;
struct clk_lookup *pllb_arm_lookup; struct raspberrypi_clk *rpi;
}; };
/* /*
@@ -64,11 +90,12 @@ struct raspberrypi_firmware_prop {
__le32 disable_turbo; __le32 disable_turbo;
} __packed; } __packed;
static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag, static int raspberrypi_clock_property(struct rpi_firmware *firmware,
u32 clk, u32 *val) const struct raspberrypi_clk_data *data,
u32 tag, u32 *val)
{ {
struct raspberrypi_firmware_prop msg = { struct raspberrypi_firmware_prop msg = {
.id = cpu_to_le32(clk), .id = cpu_to_le32(data->id),
.val = cpu_to_le32(*val), .val = cpu_to_le32(*val),
.disable_turbo = cpu_to_le32(1), .disable_turbo = cpu_to_le32(1),
}; };
@@ -83,16 +110,16 @@ static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
return 0; return 0;
} }
static int raspberrypi_fw_pll_is_on(struct clk_hw *hw) static int raspberrypi_fw_is_prepared(struct clk_hw *hw)
{ {
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, struct raspberrypi_clk_data *data =
pllb); container_of(hw, struct raspberrypi_clk_data, hw);
struct raspberrypi_clk *rpi = data->rpi;
u32 val = 0; u32 val = 0;
int ret; int ret;
ret = raspberrypi_clock_property(rpi->firmware, ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_CLOCK_STATE, RPI_FIRMWARE_GET_CLOCK_STATE, &val);
RPI_FIRMWARE_ARM_CLK_ID, &val);
if (ret) if (ret)
return 0; return 0;
@@ -100,36 +127,34 @@ static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
} }
static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, struct raspberrypi_clk_data *data =
pllb); container_of(hw, struct raspberrypi_clk_data, hw);
struct raspberrypi_clk *rpi = data->rpi;
u32 val = 0; u32 val = 0;
int ret; int ret;
ret = raspberrypi_clock_property(rpi->firmware, ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_CLOCK_RATE, RPI_FIRMWARE_GET_CLOCK_RATE, &val);
RPI_FIRMWARE_ARM_CLK_ID,
&val);
if (ret) if (ret)
return ret; return ret;
return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE; return val;
} }
static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, struct raspberrypi_clk_data *data =
pllb); container_of(hw, struct raspberrypi_clk_data, hw);
u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE; struct raspberrypi_clk *rpi = data->rpi;
u32 _rate = rate;
int ret; int ret;
ret = raspberrypi_clock_property(rpi->firmware, ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_SET_CLOCK_RATE, RPI_FIRMWARE_SET_CLOCK_RATE, &_rate);
RPI_FIRMWARE_ARM_CLK_ID,
&new_rate);
if (ret) if (ret)
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d", dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
clk_hw_get_name(hw), ret); clk_hw_get_name(hw), ret);
@@ -137,111 +162,128 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return ret; return ret;
} }
/* static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
* Sadly there is no firmware rate rounding interface. We borrowed it from struct clk_rate_request *req)
* clk-bcm2835.
*/
static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{ {
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, /*
pllb); * The firmware will do the rounding but that isn't part of
u64 div, final_rate; * the interface with the firmware, so we just do our best
u32 ndiv, fdiv; * here.
*/
/* We can't use req->rate directly as it would overflow */ req->rate = clamp(req->rate, req->min_rate, req->max_rate);
final_rate = clamp(req->rate, rpi->min_rate, rpi->max_rate);
div = (u64)final_rate << A2W_PLL_FRAC_BITS;
do_div(div, req->best_parent_rate);
ndiv = div >> A2W_PLL_FRAC_BITS;
fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
final_rate = ((u64)req->best_parent_rate *
((ndiv << A2W_PLL_FRAC_BITS) + fdiv));
req->rate = final_rate >> A2W_PLL_FRAC_BITS;
return 0; return 0;
} }
static const struct clk_ops raspberrypi_firmware_pll_clk_ops = { static const struct clk_ops raspberrypi_firmware_clk_ops = {
.is_prepared = raspberrypi_fw_pll_is_on, .is_prepared = raspberrypi_fw_is_prepared,
.recalc_rate = raspberrypi_fw_pll_get_rate, .recalc_rate = raspberrypi_fw_get_rate,
.set_rate = raspberrypi_fw_pll_set_rate, .determine_rate = raspberrypi_fw_dumb_determine_rate,
.determine_rate = raspberrypi_pll_determine_rate, .set_rate = raspberrypi_fw_set_rate,
}; };
static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
unsigned int parent,
unsigned int id)
{ {
u32 min_rate = 0, max_rate = 0; struct raspberrypi_clk_data *data;
struct clk_init_data init; struct clk_init_data init = {};
u32 min_rate, max_rate;
int ret; int ret;
memset(&init, 0, sizeof(init)); data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
data->rpi = rpi;
data->id = id;
/* All of the PLLs derive from the external oscillator. */ init.name = devm_kasprintf(rpi->dev, GFP_KERNEL,
init.parent_names = (const char *[]){ "osc" }; "fw-clk-%s",
init.num_parents = 1; rpi_firmware_clk_names[id]);
init.name = "pllb"; init.ops = &raspberrypi_firmware_clk_ops;
init.ops = &raspberrypi_firmware_pll_clk_ops; init.flags = CLK_GET_RATE_NOCACHE;
init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;
/* Get min & max rates set by the firmware */ data->hw.init = &init;
ret = raspberrypi_clock_property(rpi->firmware,
ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MIN_CLOCK_RATE, RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
RPI_FIRMWARE_ARM_CLK_ID,
&min_rate); &min_rate);
if (ret) { if (ret) {
dev_err(rpi->dev, "Failed to get %s min freq: %d\n", dev_err(rpi->dev, "Failed to get clock %d min freq: %d",
init.name, ret); id, ret);
return ret; return ERR_PTR(ret);
} }
ret = raspberrypi_clock_property(rpi->firmware, ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MAX_CLOCK_RATE, RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
RPI_FIRMWARE_ARM_CLK_ID,
&max_rate); &max_rate);
if (ret) { if (ret) {
dev_err(rpi->dev, "Failed to get %s max freq: %d\n", dev_err(rpi->dev, "Failed to get clock %d max freq: %d\n",
init.name, ret); id, ret);
return ret; return ERR_PTR(ret);
} }
if (!min_rate || !max_rate) { ret = devm_clk_hw_register(rpi->dev, &data->hw);
dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n", if (ret)
min_rate, max_rate); return ERR_PTR(ret);
return -EINVAL;
clk_hw_set_rate_range(&data->hw, min_rate, max_rate);
if (id == RPI_FIRMWARE_ARM_CLK_ID) {
ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw,
NULL, "cpu0");
if (ret) {
dev_err(rpi->dev, "Failed to initialize clkdev\n");
return ERR_PTR(ret);
}
} }
dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n", return &data->hw;
min_rate, max_rate);
rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
rpi->pllb.init = &init;
return devm_clk_hw_register(rpi->dev, &rpi->pllb);
} }
static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) struct rpi_firmware_get_clocks_response {
{ u32 parent;
rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev, u32 id;
"pllb_arm", "pllb", };
CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
1, 2);
if (IS_ERR(rpi->pllb_arm)) {
dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
return PTR_ERR(rpi->pllb_arm);
}
rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0"); static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
if (!rpi->pllb_arm_lookup) { struct clk_hw_onecell_data *data)
dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n"); {
clk_hw_unregister_fixed_factor(rpi->pllb_arm); struct rpi_firmware_get_clocks_response *clks;
int ret;
clks = devm_kcalloc(rpi->dev,
sizeof(*clks), RPI_FIRMWARE_NUM_CLK_ID,
GFP_KERNEL);
if (!clks)
return -ENOMEM; return -ENOMEM;
ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
clks,
sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID);
if (ret)
return ret;
while (clks->id) {
struct clk_hw *hw;
switch (clks->id) {
case RPI_FIRMWARE_ARM_CLK_ID:
case RPI_FIRMWARE_CORE_CLK_ID:
case RPI_FIRMWARE_M2MC_CLK_ID:
case RPI_FIRMWARE_V3D_CLK_ID:
hw = raspberrypi_clk_register(rpi, clks->parent,
clks->id);
if (IS_ERR(hw))
return PTR_ERR(hw);
data->hws[clks->id] = hw;
data->num = clks->id + 1;
fallthrough;
default:
clks++;
break;
}
} }
return 0; return 0;
@@ -249,14 +291,23 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
static int raspberrypi_clk_probe(struct platform_device *pdev) static int raspberrypi_clk_probe(struct platform_device *pdev)
{ {
struct clk_hw_onecell_data *clk_data;
struct device_node *firmware_node; struct device_node *firmware_node;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct rpi_firmware *firmware; struct rpi_firmware *firmware;
struct raspberrypi_clk *rpi; struct raspberrypi_clk *rpi;
int ret; int ret;
firmware_node = of_find_compatible_node(NULL, NULL, /*
"raspberrypi,bcm2835-firmware"); * We can be probed either through the an old-fashioned
* platform device registration or through a DT node that is a
* child of the firmware node. Handle both cases.
*/
if (dev->of_node)
firmware_node = of_get_parent(dev->of_node);
else
firmware_node = of_find_compatible_node(NULL, NULL,
"raspberrypi,bcm2835-firmware");
if (!firmware_node) { if (!firmware_node) {
dev_err(dev, "Missing firmware node\n"); dev_err(dev, "Missing firmware node\n");
return -ENOENT; return -ENOENT;
@@ -275,13 +326,18 @@ static int raspberrypi_clk_probe(struct platform_device *pdev)
rpi->firmware = firmware; rpi->firmware = firmware;
platform_set_drvdata(pdev, rpi); platform_set_drvdata(pdev, rpi);
ret = raspberrypi_register_pllb(rpi); clk_data = devm_kzalloc(dev, struct_size(clk_data, hws,
if (ret) { RPI_FIRMWARE_NUM_CLK_ID),
dev_err(dev, "Failed to initialize pllb, %d\n", ret); GFP_KERNEL);
return ret; if (!clk_data)
} return -ENOMEM;
ret = raspberrypi_register_pllb_arm(rpi); ret = raspberrypi_discover_clocks(rpi, clk_data);
if (ret)
return ret;
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
clk_data);
if (ret) if (ret)
return ret; return ret;
@@ -300,9 +356,16 @@ static int raspberrypi_clk_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id raspberrypi_clk_match[] = {
{ .compatible = "raspberrypi,firmware-clocks" },
{ },
};
MODULE_DEVICE_TABLE(of, raspberrypi_clk_match);
static struct platform_driver raspberrypi_clk_driver = { static struct platform_driver raspberrypi_clk_driver = {
.driver = { .driver = {
.name = "raspberrypi-clk", .name = "raspberrypi-clk",
.of_match_table = raspberrypi_clk_match,
}, },
.probe = raspberrypi_clk_probe, .probe = raspberrypi_clk_probe,
.remove = raspberrypi_clk_remove, .remove = raspberrypi_clk_remove,

View File

@@ -4,7 +4,7 @@
* *
* Copyright (c) 2014 Cadence Design Systems Inc. * Copyright (c) 2014 Cadence Design Systems Inc.
* *
* Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf * Reference: https://www.ti.com/lit/ds/symlink/cdce706.pdf
*/ */
#include <linux/clk.h> #include <linux/clk.h>

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - https://www.ti.com
* *
* Authors: * Authors:
* Jyri Sarha <jsarha@ti.com> * Jyri Sarha <jsarha@ti.com>

View File

@@ -7,9 +7,9 @@
* *
* References: * References:
* [1] "Si5351A/B/C Data Sheet" * [1] "Si5351A/B/C Data Sheet"
* http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf * https://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf
* [2] "Manually Generating an Si5351 Register Map" * [2] "Manually Generating an Si5351 Register Map"
* http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf * https://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf
*/ */
#include <linux/module.h> #include <linux/module.h>

View File

@@ -24,6 +24,8 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <dt-bindings/clk/versaclock.h>
/* VersaClock5 registers */ /* VersaClock5 registers */
#define VC5_OTP_CONTROL 0x00 #define VC5_OTP_CONTROL 0x00
@@ -89,6 +91,28 @@
/* Clock control register for clock 1,2 */ /* Clock control register for clock 1,2 */
#define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n)) #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n))
#define VC5_CLK_OUTPUT_CFG0_CFG_SHIFT 5
#define VC5_CLK_OUTPUT_CFG0_CFG_MASK GENMASK(7, VC5_CLK_OUTPUT_CFG0_CFG_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_CFG_LVPECL (VC5_LVPECL)
#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS (VC5_CMOS)
#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL33 (VC5_HCSL33)
#define VC5_CLK_OUTPUT_CFG0_CFG_LVDS (VC5_LVDS)
#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS2 (VC5_CMOS2)
#define VC5_CLK_OUTPUT_CFG0_CFG_CMOSD (VC5_CMOSD)
#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL25 (VC5_HCSL25)
#define VC5_CLK_OUTPUT_CFG0_PWR_SHIFT 3
#define VC5_CLK_OUTPUT_CFG0_PWR_MASK GENMASK(4, VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_PWR_18 (0<<VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_PWR_25 (2<<VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_PWR_33 (3<<VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT 0
#define VC5_CLK_OUTPUT_CFG0_SLEW_MASK GENMASK(1, VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_SLEW_80 (0<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_SLEW_85 (1<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_SLEW_90 (2<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
#define VC5_CLK_OUTPUT_CFG0_SLEW_100 (3<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
#define VC5_CLK_OUTPUT_CFG1_EN_CLKBUF BIT(0) #define VC5_CLK_OUTPUT_CFG1_EN_CLKBUF BIT(0)
#define VC5_CLK_OE_SHDN 0x68 #define VC5_CLK_OE_SHDN 0x68
@@ -143,6 +167,8 @@ struct vc5_hw_data {
u32 div_int; u32 div_int;
u32 div_frc; u32 div_frc;
unsigned int num; unsigned int num;
unsigned int clk_output_cfg0;
unsigned int clk_output_cfg0_mask;
}; };
struct vc5_driver_data { struct vc5_driver_data {
@@ -161,30 +187,6 @@ struct vc5_driver_data {
struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM];
}; };
static const char * const vc5_mux_names[] = {
"mux"
};
static const char * const vc5_dbl_names[] = {
"dbl"
};
static const char * const vc5_pfd_names[] = {
"pfd"
};
static const char * const vc5_pll_names[] = {
"pll"
};
static const char * const vc5_fod_names[] = {
"fod0", "fod1", "fod2", "fod3",
};
static const char * const vc5_clk_out_names[] = {
"out0_sel_i2cb", "out1", "out2", "out3", "out4",
};
/* /*
* VersaClock5 i2c regmap * VersaClock5 i2c regmap
*/ */
@@ -591,6 +593,17 @@ static int vc5_clk_out_prepare(struct clk_hw *hw)
regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1),
VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, VC5_CLK_OUTPUT_CFG1_EN_CLKBUF,
VC5_CLK_OUTPUT_CFG1_EN_CLKBUF); VC5_CLK_OUTPUT_CFG1_EN_CLKBUF);
if (hwdata->clk_output_cfg0_mask) {
dev_dbg(&vc5->client->dev, "Update output %d mask 0x%0X val 0x%0X\n",
hwdata->num, hwdata->clk_output_cfg0_mask,
hwdata->clk_output_cfg0);
regmap_update_bits(vc5->regmap,
VC5_CLK_OUTPUT_CFG(hwdata->num, 0),
hwdata->clk_output_cfg0_mask,
hwdata->clk_output_cfg0);
}
return 0; return 0;
} }
@@ -690,10 +703,123 @@ static int vc5_map_index_to_output(const enum vc5_model model,
} }
} }
static int vc5_update_mode(struct device_node *np_output,
struct vc5_hw_data *clk_out)
{
u32 value;
if (!of_property_read_u32(np_output, "idt,mode", &value)) {
clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_CFG_MASK;
switch (value) {
case VC5_CLK_OUTPUT_CFG0_CFG_LVPECL:
case VC5_CLK_OUTPUT_CFG0_CFG_CMOS:
case VC5_CLK_OUTPUT_CFG0_CFG_HCSL33:
case VC5_CLK_OUTPUT_CFG0_CFG_LVDS:
case VC5_CLK_OUTPUT_CFG0_CFG_CMOS2:
case VC5_CLK_OUTPUT_CFG0_CFG_CMOSD:
case VC5_CLK_OUTPUT_CFG0_CFG_HCSL25:
clk_out->clk_output_cfg0 |=
value << VC5_CLK_OUTPUT_CFG0_CFG_SHIFT;
break;
default:
return -EINVAL;
}
}
return 0;
}
static int vc5_update_power(struct device_node *np_output,
struct vc5_hw_data *clk_out)
{
u32 value;
if (!of_property_read_u32(np_output,
"idt,voltage-microvolts", &value)) {
clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_PWR_MASK;
switch (value) {
case 1800000:
clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_18;
break;
case 2500000:
clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_25;
break;
case 3300000:
clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_33;
break;
default:
return -EINVAL;
}
}
return 0;
}
static int vc5_update_slew(struct device_node *np_output,
struct vc5_hw_data *clk_out)
{
u32 value;
if (!of_property_read_u32(np_output, "idt,slew-percent", &value)) {
clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_SLEW_MASK;
switch (value) {
case 80:
clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_80;
break;
case 85:
clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_85;
break;
case 90:
clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_90;
break;
case 100:
clk_out->clk_output_cfg0 |=
VC5_CLK_OUTPUT_CFG0_SLEW_100;
break;
default:
return -EINVAL;
}
}
return 0;
}
static int vc5_get_output_config(struct i2c_client *client,
struct vc5_hw_data *clk_out)
{
struct device_node *np_output;
char *child_name;
int ret = 0;
child_name = kasprintf(GFP_KERNEL, "OUT%d", clk_out->num + 1);
np_output = of_get_child_by_name(client->dev.of_node, child_name);
kfree(child_name);
if (!np_output)
goto output_done;
ret = vc5_update_mode(np_output, clk_out);
if (ret)
goto output_error;
ret = vc5_update_power(np_output, clk_out);
if (ret)
goto output_error;
ret = vc5_update_slew(np_output, clk_out);
output_error:
if (ret) {
dev_err(&client->dev,
"Invalid clock output configuration OUT%d\n",
clk_out->num + 1);
}
of_node_put(np_output);
output_done:
return ret;
}
static const struct of_device_id clk_vc5_of_match[]; static const struct of_device_id clk_vc5_of_match[];
static int vc5_probe(struct i2c_client *client, static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
const struct i2c_device_id *id)
{ {
struct vc5_driver_data *vc5; struct vc5_driver_data *vc5;
struct clk_init_data init; struct clk_init_data init;
@@ -742,7 +868,7 @@ static int vc5_probe(struct i2c_client *client,
if (!IS_ERR(vc5->pin_clkin)) { if (!IS_ERR(vc5->pin_clkin)) {
vc5->clk_mux_ins |= VC5_MUX_IN_CLKIN; vc5->clk_mux_ins |= VC5_MUX_IN_CLKIN;
parent_names[init.num_parents++] = parent_names[init.num_parents++] =
__clk_get_name(vc5->pin_clkin); __clk_get_name(vc5->pin_clkin);
} }
if (!init.num_parents) { if (!init.num_parents) {
@@ -750,12 +876,13 @@ static int vc5_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
init.name = vc5_mux_names[0]; init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node);
init.ops = &vc5_mux_ops; init.ops = &vc5_mux_ops;
init.flags = 0; init.flags = 0;
init.parent_names = parent_names; init.parent_names = parent_names;
vc5->clk_mux.init = &init; vc5->clk_mux.init = &init;
ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux); ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux);
kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", init.name); dev_err(&client->dev, "unable to register %s\n", init.name);
goto err_clk; goto err_clk;
@@ -764,13 +891,16 @@ static int vc5_probe(struct i2c_client *client,
if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) {
/* Register frequency doubler */ /* Register frequency doubler */
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = vc5_dbl_names[0]; init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl",
client->dev.of_node);
init.ops = &vc5_dbl_ops; init.ops = &vc5_dbl_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = vc5_mux_names; init.parent_names = parent_names;
parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
init.num_parents = 1; init.num_parents = 1;
vc5->clk_mul.init = &init; vc5->clk_mul.init = &init;
ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul);
kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n",
init.name); init.name);
@@ -780,16 +910,18 @@ static int vc5_probe(struct i2c_client *client,
/* Register PFD */ /* Register PFD */
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = vc5_pfd_names[0]; init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node);
init.ops = &vc5_pfd_ops; init.ops = &vc5_pfd_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL)
init.parent_names = vc5_dbl_names; parent_names[0] = clk_hw_get_name(&vc5->clk_mul);
else else
init.parent_names = vc5_mux_names; parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
init.num_parents = 1; init.num_parents = 1;
vc5->clk_pfd.init = &init; vc5->clk_pfd.init = &init;
ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd);
kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", init.name); dev_err(&client->dev, "unable to register %s\n", init.name);
goto err_clk; goto err_clk;
@@ -797,15 +929,17 @@ static int vc5_probe(struct i2c_client *client,
/* Register PLL */ /* Register PLL */
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = vc5_pll_names[0]; init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node);
init.ops = &vc5_pll_ops; init.ops = &vc5_pll_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = vc5_pfd_names; init.parent_names = parent_names;
parent_names[0] = clk_hw_get_name(&vc5->clk_pfd);
init.num_parents = 1; init.num_parents = 1;
vc5->clk_pll.num = 0; vc5->clk_pll.num = 0;
vc5->clk_pll.vc5 = vc5; vc5->clk_pll.vc5 = vc5;
vc5->clk_pll.hw.init = &init; vc5->clk_pll.hw.init = &init;
ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw); ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw);
kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", init.name); dev_err(&client->dev, "unable to register %s\n", init.name);
goto err_clk; goto err_clk;
@@ -815,15 +949,18 @@ static int vc5_probe(struct i2c_client *client,
for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) { for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {
idx = vc5_map_index_to_output(vc5->chip_info->model, n); idx = vc5_map_index_to_output(vc5->chip_info->model, n);
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = vc5_fod_names[idx]; init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d",
client->dev.of_node, idx);
init.ops = &vc5_fod_ops; init.ops = &vc5_fod_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = vc5_pll_names; init.parent_names = parent_names;
parent_names[0] = clk_hw_get_name(&vc5->clk_pll.hw);
init.num_parents = 1; init.num_parents = 1;
vc5->clk_fod[n].num = idx; vc5->clk_fod[n].num = idx;
vc5->clk_fod[n].vc5 = vc5; vc5->clk_fod[n].vc5 = vc5;
vc5->clk_fod[n].hw.init = &init; vc5->clk_fod[n].hw.init = &init;
ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw); ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw);
kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n",
init.name); init.name);
@@ -833,32 +970,36 @@ static int vc5_probe(struct i2c_client *client,
/* Register MUX-connected OUT0_I2C_SELB output */ /* Register MUX-connected OUT0_I2C_SELB output */
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = vc5_clk_out_names[0]; init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb",
client->dev.of_node);
init.ops = &vc5_clk_out_ops; init.ops = &vc5_clk_out_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = vc5_mux_names; init.parent_names = parent_names;
parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
init.num_parents = 1; init.num_parents = 1;
vc5->clk_out[0].num = idx; vc5->clk_out[0].num = idx;
vc5->clk_out[0].vc5 = vc5; vc5->clk_out[0].vc5 = vc5;
vc5->clk_out[0].hw.init = &init; vc5->clk_out[0].hw.init = &init;
ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw); ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw);
kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n", init.name);
init.name);
goto err_clk; goto err_clk;
} }
/* Register FOD-connected OUTx outputs */ /* Register FOD-connected OUTx outputs */
for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) { for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {
idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1); idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1);
parent_names[0] = vc5_fod_names[idx]; parent_names[0] = clk_hw_get_name(&vc5->clk_fod[idx].hw);
if (n == 1) if (n == 1)
parent_names[1] = vc5_mux_names[0]; parent_names[1] = clk_hw_get_name(&vc5->clk_mux);
else else
parent_names[1] = vc5_clk_out_names[n - 1]; parent_names[1] =
clk_hw_get_name(&vc5->clk_out[n - 1].hw);
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = vc5_clk_out_names[idx + 1]; init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d",
client->dev.of_node, idx + 1);
init.ops = &vc5_clk_out_ops; init.ops = &vc5_clk_out_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names; init.parent_names = parent_names;
@@ -866,13 +1007,18 @@ static int vc5_probe(struct i2c_client *client,
vc5->clk_out[n].num = idx; vc5->clk_out[n].num = idx;
vc5->clk_out[n].vc5 = vc5; vc5->clk_out[n].vc5 = vc5;
vc5->clk_out[n].hw.init = &init; vc5->clk_out[n].hw.init = &init;
ret = devm_clk_hw_register(&client->dev, ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw);
&vc5->clk_out[n].hw); kfree(init.name); /* clock framework made a copy of the name */
if (ret) { if (ret) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n",
init.name); init.name);
goto err_clk; goto err_clk;
} }
/* Fetch Clock Output configuration from DT (if specified) */
ret = vc5_get_output_config(client, &vc5->clk_out[n]);
if (ret)
goto err_clk;
} }
ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5); ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5);

View File

@@ -1400,6 +1400,21 @@ int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
} }
EXPORT_SYMBOL_GPL(__clk_determine_rate); EXPORT_SYMBOL_GPL(__clk_determine_rate);
/**
* clk_hw_round_rate() - round the given rate for a hw clk
* @hw: the hw clk for which we are rounding a rate
* @rate: the rate which is to be rounded
*
* Takes in a rate as input and rounds it to a rate that the clk can actually
* use.
*
* Context: prepare_lock must be held.
* For clk providers to call from within clk_ops such as .round_rate,
* .determine_rate.
*
* Return: returns rounded rate of hw clk if clk supports round_rate operation
* else returns the parent rate.
*/
unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate) unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
{ {
int ret; int ret;

View File

@@ -1,7 +1,7 @@
/* /*
* SCI Clock driver for keystone based devices * SCI Clock driver for keystone based devices
* *
* Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
* Tero Kristo <t-kristo@ti.com> * Tero Kristo <t-kristo@ti.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
*/ */
#include <linux/clk-provider.h> #include <linux/clk-provider.h>

View File

@@ -3981,6 +3981,113 @@ static struct clk_regmap g12a_spicc1_sclk = {
}, },
}; };
/* Neural Network Accelerator source clock */
static const struct clk_parent_data nna_clk_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &g12a_gp0_pll.hw, },
{ .hw = &g12a_hifi_pll.hw, },
{ .hw = &g12a_fclk_div2p5.hw, },
{ .hw = &g12a_fclk_div3.hw, },
{ .hw = &g12a_fclk_div4.hw, },
{ .hw = &g12a_fclk_div5.hw, },
{ .hw = &g12a_fclk_div7.hw },
};
static struct clk_regmap sm1_nna_axi_clk_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_NNA_CLK_CNTL,
.mask = 7,
.shift = 9,
},
.hw.init = &(struct clk_init_data){
.name = "nna_axi_clk_sel",
.ops = &clk_regmap_mux_ops,
.parent_data = nna_clk_parent_data,
.num_parents = ARRAY_SIZE(nna_clk_parent_data),
},
};
static struct clk_regmap sm1_nna_axi_clk_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_NNA_CLK_CNTL,
.shift = 0,
.width = 7,
},
.hw.init = &(struct clk_init_data){
.name = "nna_axi_clk_div",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_nna_axi_clk_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap sm1_nna_axi_clk = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_NNA_CLK_CNTL,
.bit_idx = 8,
},
.hw.init = &(struct clk_init_data){
.name = "nna_axi_clk",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_nna_axi_clk_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap sm1_nna_core_clk_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_NNA_CLK_CNTL,
.mask = 7,
.shift = 25,
},
.hw.init = &(struct clk_init_data){
.name = "nna_core_clk_sel",
.ops = &clk_regmap_mux_ops,
.parent_data = nna_clk_parent_data,
.num_parents = ARRAY_SIZE(nna_clk_parent_data),
},
};
static struct clk_regmap sm1_nna_core_clk_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_NNA_CLK_CNTL,
.shift = 16,
.width = 7,
},
.hw.init = &(struct clk_init_data){
.name = "nna_core_clk_div",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_nna_core_clk_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap sm1_nna_core_clk = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_NNA_CLK_CNTL,
.bit_idx = 24,
},
.hw.init = &(struct clk_init_data){
.name = "nna_core_clk",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_nna_core_clk_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
#define MESON_GATE(_name, _reg, _bit) \ #define MESON_GATE(_name, _reg, _bit) \
MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw) MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw)
@@ -4779,6 +4886,12 @@ static struct clk_hw_onecell_data sm1_hw_onecell_data = {
[CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw,
[CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw,
[CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw,
[CLKID_NNA_AXI_CLK_SEL] = &sm1_nna_axi_clk_sel.hw,
[CLKID_NNA_AXI_CLK_DIV] = &sm1_nna_axi_clk_div.hw,
[CLKID_NNA_AXI_CLK] = &sm1_nna_axi_clk.hw,
[CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel.hw,
[CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div.hw,
[CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk.hw,
[NR_CLKS] = NULL, [NR_CLKS] = NULL,
}, },
.num = NR_CLKS, .num = NR_CLKS,
@@ -5020,6 +5133,12 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
&g12a_spicc1_sclk_sel, &g12a_spicc1_sclk_sel,
&g12a_spicc1_sclk_div, &g12a_spicc1_sclk_div,
&g12a_spicc1_sclk, &g12a_spicc1_sclk,
&sm1_nna_axi_clk_sel,
&sm1_nna_axi_clk_div,
&sm1_nna_axi_clk,
&sm1_nna_core_clk_sel,
&sm1_nna_core_clk_div,
&sm1_nna_core_clk,
}; };
static const struct reg_sequence g12a_init_regs[] = { static const struct reg_sequence g12a_init_regs[] = {

View File

@@ -70,6 +70,7 @@
#define HHI_MALI_CLK_CNTL 0x1b0 #define HHI_MALI_CLK_CNTL 0x1b0
#define HHI_VPU_CLKC_CNTL 0x1b4 #define HHI_VPU_CLKC_CNTL 0x1b4
#define HHI_VPU_CLK_CNTL 0x1bC #define HHI_VPU_CLK_CNTL 0x1bC
#define HHI_NNA_CLK_CNTL 0x1C8
#define HHI_HDMI_CLK_CNTL 0x1CC #define HHI_HDMI_CLK_CNTL 0x1CC
#define HHI_VDEC_CLK_CNTL 0x1E0 #define HHI_VDEC_CLK_CNTL 0x1E0
#define HHI_VDEC2_CLK_CNTL 0x1E4 #define HHI_VDEC2_CLK_CNTL 0x1E4
@@ -259,8 +260,12 @@
#define CLKID_SPICC0_SCLK_DIV 257 #define CLKID_SPICC0_SCLK_DIV 257
#define CLKID_SPICC1_SCLK_SEL 259 #define CLKID_SPICC1_SCLK_SEL 259
#define CLKID_SPICC1_SCLK_DIV 260 #define CLKID_SPICC1_SCLK_DIV 260
#define CLKID_NNA_AXI_CLK_SEL 262
#define CLKID_NNA_AXI_CLK_DIV 263
#define CLKID_NNA_CORE_CLK_SEL 265
#define CLKID_NNA_CORE_CLK_DIV 266
#define NR_CLKS 262 #define NR_CLKS 268
/* include the CLKIDs that have been made part of the DT binding */ /* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/g12a-clkc.h> #include <dt-bindings/clock/g12a-clkc.h>

View File

@@ -293,13 +293,6 @@ static struct clk_regmap meson8b_fclk_div2 = {
&meson8b_fclk_div2_div.hw &meson8b_fclk_div2_div.hw
}, },
.num_parents = 1, .num_parents = 1,
/*
* FIXME: Ethernet with a RGMII PHYs is not working if
* fclk_div2 is disabled. it is currently unclear why this
* is. keep it enabled until the Ethernet driver knows how
* to manage this clock.
*/
.flags = CLK_IS_CRITICAL,
}, },
}; };
@@ -1211,6 +1204,22 @@ static struct clk_regmap meson8b_vclk_in_en = {
}, },
}; };
static struct clk_regmap meson8b_vclk_en = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL,
.bit_idx = 19,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk_in_en.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk_div1_gate = { static struct clk_regmap meson8b_vclk_div1_gate = {
.data = &(struct clk_regmap_gate_data){ .data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL, .offset = HHI_VID_CLK_CNTL,
@@ -1220,7 +1229,7 @@ static struct clk_regmap meson8b_vclk_div1_gate = {
.name = "vclk_div1_en", .name = "vclk_div1_en",
.ops = &clk_regmap_gate_ro_ops, .ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk_in_en.hw &meson8b_vclk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1234,7 +1243,7 @@ static struct clk_fixed_factor meson8b_vclk_div2_div = {
.name = "vclk_div2", .name = "vclk_div2",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk_in_en.hw &meson8b_vclk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1264,7 +1273,7 @@ static struct clk_fixed_factor meson8b_vclk_div4_div = {
.name = "vclk_div4", .name = "vclk_div4",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk_in_en.hw &meson8b_vclk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1294,7 +1303,7 @@ static struct clk_fixed_factor meson8b_vclk_div6_div = {
.name = "vclk_div6", .name = "vclk_div6",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk_in_en.hw &meson8b_vclk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1324,7 +1333,7 @@ static struct clk_fixed_factor meson8b_vclk_div12_div = {
.name = "vclk_div12", .name = "vclk_div12",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk_in_en.hw &meson8b_vclk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1378,6 +1387,22 @@ static struct clk_regmap meson8b_vclk2_clk_in_en = {
}, },
}; };
static struct clk_regmap meson8b_vclk2_clk_en = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 19,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk2_clk_in_en.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk2_div1_gate = { static struct clk_regmap meson8b_vclk2_div1_gate = {
.data = &(struct clk_regmap_gate_data){ .data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV, .offset = HHI_VIID_CLK_DIV,
@@ -1387,7 +1412,7 @@ static struct clk_regmap meson8b_vclk2_div1_gate = {
.name = "vclk2_div1_en", .name = "vclk2_div1_en",
.ops = &clk_regmap_gate_ro_ops, .ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk2_clk_in_en.hw &meson8b_vclk2_clk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1401,7 +1426,7 @@ static struct clk_fixed_factor meson8b_vclk2_div2_div = {
.name = "vclk2_div2", .name = "vclk2_div2",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk2_clk_in_en.hw &meson8b_vclk2_clk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1431,7 +1456,7 @@ static struct clk_fixed_factor meson8b_vclk2_div4_div = {
.name = "vclk2_div4", .name = "vclk2_div4",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk2_clk_in_en.hw &meson8b_vclk2_clk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1461,7 +1486,7 @@ static struct clk_fixed_factor meson8b_vclk2_div6_div = {
.name = "vclk2_div6", .name = "vclk2_div6",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk2_clk_in_en.hw &meson8b_vclk2_clk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -1491,7 +1516,7 @@ static struct clk_fixed_factor meson8b_vclk2_div12_div = {
.name = "vclk2_div12", .name = "vclk2_div12",
.ops = &clk_fixed_factor_ops, .ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_hws = (const struct clk_hw *[]) {
&meson8b_vclk2_clk_in_en.hw &meson8b_vclk2_clk_en.hw
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
@@ -2827,6 +2852,7 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = {
[CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw, [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw,
[CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw, [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw,
[CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw, [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw,
[CLKID_VCLK_EN] = &meson8b_vclk_en.hw,
[CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw, [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw,
[CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw, [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw,
[CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw, [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw,
@@ -2838,6 +2864,7 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = {
[CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw, [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw,
[CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw, [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw,
[CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw, [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw,
[CLKID_VCLK2_EN] = &meson8b_vclk2_clk_en.hw,
[CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw, [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw,
[CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw, [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw,
[CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw, [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw,
@@ -3032,6 +3059,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw, [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw,
[CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw, [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw,
[CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw, [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw,
[CLKID_VCLK_EN] = &meson8b_vclk_en.hw,
[CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw, [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw,
[CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw, [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw,
[CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw, [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw,
@@ -3043,6 +3071,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw, [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw,
[CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw, [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw,
[CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw, [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw,
[CLKID_VCLK2_EN] = &meson8b_vclk2_clk_en.hw,
[CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw, [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw,
[CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw, [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw,
[CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw, [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw,
@@ -3248,6 +3277,7 @@ static struct clk_hw_onecell_data meson8m2_hw_onecell_data = {
[CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw, [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw,
[CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw, [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw,
[CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw, [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw,
[CLKID_VCLK_EN] = &meson8b_vclk_en.hw,
[CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw, [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw,
[CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw, [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw,
[CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw, [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw,
@@ -3259,6 +3289,7 @@ static struct clk_hw_onecell_data meson8m2_hw_onecell_data = {
[CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw, [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw,
[CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw, [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw,
[CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw, [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw,
[CLKID_VCLK2_EN] = &meson8b_vclk2_clk_en.hw,
[CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw, [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw,
[CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw, [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw,
[CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw, [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw,
@@ -3450,6 +3481,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_vid_pll_final_div, &meson8b_vid_pll_final_div,
&meson8b_vclk_in_sel, &meson8b_vclk_in_sel,
&meson8b_vclk_in_en, &meson8b_vclk_in_en,
&meson8b_vclk_en,
&meson8b_vclk_div1_gate, &meson8b_vclk_div1_gate,
&meson8b_vclk_div2_div_gate, &meson8b_vclk_div2_div_gate,
&meson8b_vclk_div4_div_gate, &meson8b_vclk_div4_div_gate,
@@ -3457,6 +3489,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_vclk_div12_div_gate, &meson8b_vclk_div12_div_gate,
&meson8b_vclk2_in_sel, &meson8b_vclk2_in_sel,
&meson8b_vclk2_clk_in_en, &meson8b_vclk2_clk_in_en,
&meson8b_vclk2_clk_en,
&meson8b_vclk2_div1_gate, &meson8b_vclk2_div1_gate,
&meson8b_vclk2_div2_div_gate, &meson8b_vclk2_div2_div_gate,
&meson8b_vclk2_div4_div_gate, &meson8b_vclk2_div4_div_gate,

View File

@@ -17,7 +17,7 @@
* blocks below. Those offsets must be multiplied by 4 before adding them to * blocks below. Those offsets must be multiplied by 4 before adding them to
* the base address to get the right value * the base address to get the right value
* *
* [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf * [0] https://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
*/ */
#define HHI_GP_PLL_CNTL 0x40 /* 0x10 offset in data sheet */ #define HHI_GP_PLL_CNTL 0x40 /* 0x10 offset in data sheet */
#define HHI_GP_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */ #define HHI_GP_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */
@@ -180,8 +180,10 @@
#define CLKID_CTS_AMCLK_DIV 208 #define CLKID_CTS_AMCLK_DIV 208
#define CLKID_CTS_MCLK_I958_SEL 210 #define CLKID_CTS_MCLK_I958_SEL 210
#define CLKID_CTS_MCLK_I958_DIV 211 #define CLKID_CTS_MCLK_I958_DIV 211
#define CLKID_VCLK_EN 214
#define CLKID_VCLK2_EN 215
#define CLK_NR_CLKS 214 #define CLK_NR_CLKS 216
/* /*
* include the CLKID and RESETID that have * include the CLKID and RESETID that have

View File

@@ -37,6 +37,15 @@ config QCOM_CLK_APCS_MSM8916
Say Y if you want to support CPU frequency scaling on devices Say Y if you want to support CPU frequency scaling on devices
such as msm8916. such as msm8916.
config QCOM_CLK_APCC_MSM8996
tristate "MSM8996 CPU Clock Controller"
select QCOM_KRYO_L2_ACCESSORS
depends on ARM64
help
Support for the CPU clock controller on msm8996 devices.
Say Y if you want to support CPU clock scaling using CPUfreq
drivers for dyanmic power management.
config QCOM_CLK_RPM config QCOM_CLK_RPM
tristate "RPM based Clock Controller" tristate "RPM based Clock Controller"
depends on MFD_QCOM_RPM depends on MFD_QCOM_RPM
@@ -89,6 +98,25 @@ config APQ_MMCC_8084
Say Y if you want to support multimedia devices such as display, Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc. graphics, video encode/decode, camera, etc.
config IPQ_APSS_PLL
tristate "IPQ APSS PLL"
help
Support for APSS PLL on ipq devices. The APSS PLL is the main
clock that feeds the CPUs on ipq based devices.
Say Y if you want to support CPU frequency scaling on ipq based
devices.
config IPQ_APSS_6018
tristate "IPQ APSS Clock Controller"
select IPQ_APSS_PLL
depends on QCOM_APCS_IPC || COMPILE_TEST
help
Support for APSS clock controller on IPQ platforms. The
APSS clock controller manages the Mux and enable block that feeds the
CPUs.
Say Y if you want to support CPU frequency scaling on
ipq based devices.
config IPQ_GCC_4019 config IPQ_GCC_4019
tristate "IPQ4019 Global Clock Controller" tristate "IPQ4019 Global Clock Controller"
help help

View File

@@ -19,6 +19,8 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
# Keep alphabetically sorted by config # Keep alphabetically sorted by config
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
@@ -42,6 +44,7 @@ obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
obj-$(CONFIG_MSM_MMCC_8998) += mmcc-msm8998.o obj-$(CONFIG_MSM_MMCC_8998) += mmcc-msm8998.o
obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o

View File

@@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "clk-alpha-pll.h"
static const u8 ipq_pll_offsets[] = {
[PLL_OFF_L_VAL] = 0x08,
[PLL_OFF_ALPHA_VAL] = 0x10,
[PLL_OFF_USER_CTL] = 0x18,
[PLL_OFF_CONFIG_CTL] = 0x20,
[PLL_OFF_CONFIG_CTL_U] = 0x24,
[PLL_OFF_STATUS] = 0x28,
[PLL_OFF_TEST_CTL] = 0x30,
[PLL_OFF_TEST_CTL_U] = 0x34,
};
static struct clk_alpha_pll ipq_pll = {
.offset = 0x0,
.regs = ipq_pll_offsets,
.flags = SUPPORTS_DYNAMIC_UPDATE,
.clkr = {
.enable_reg = 0x0,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "a53pll",
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_huayra_ops,
},
},
};
static const struct alpha_pll_config ipq_pll_config = {
.l = 0x37,
.config_ctl_val = 0x04141200,
.config_ctl_hi_val = 0x0,
.early_output_mask = BIT(3),
.main_output_mask = BIT(0),
};
static const struct regmap_config ipq_pll_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x40,
.fast_io = true,
};
static int apss_ipq_pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regmap *regmap;
void __iomem *base;
int ret;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(dev, base, &ipq_pll_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
clk_alpha_pll_configure(&ipq_pll, regmap, &ipq_pll_config);
ret = devm_clk_register_regmap(dev, &ipq_pll.clkr);
if (ret)
return ret;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&ipq_pll.clkr.hw);
}
static const struct of_device_id apss_ipq_pll_match_table[] = {
{ .compatible = "qcom,ipq6018-a53pll" },
{ }
};
static struct platform_driver apss_ipq_pll_driver = {
.probe = apss_ipq_pll_probe,
.driver = {
.name = "qcom-ipq-apss-pll",
.of_match_table = apss_ipq_pll_match_table,
},
};
module_platform_driver(apss_ipq_pll_driver);
MODULE_DESCRIPTION("Qualcomm technology Inc APSS ALPHA PLL Driver");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/module.h>
#include <dt-bindings/clock/qcom,apss-ipq.h>
#include "common.h"
#include "clk-regmap.h"
#include "clk-branch.h"
#include "clk-alpha-pll.h"
#include "clk-regmap-mux.h"
enum {
P_XO,
P_APSS_PLL_EARLY,
};
static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
{ .fw_name = "xo" },
{ .fw_name = "pll" },
};
static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
{ P_XO, 0 },
{ P_APSS_PLL_EARLY, 5 },
};
static struct clk_regmap_mux apcs_alias0_clk_src = {
.reg = 0x0050,
.width = 3,
.shift = 7,
.parent_map = parents_apcs_alias0_clk_src_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "apcs_alias0_clk_src",
.parent_data = parents_apcs_alias0_clk_src,
.num_parents = 2,
.ops = &clk_regmap_mux_closest_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_branch apcs_alias0_core_clk = {
.halt_reg = 0x0058,
.clkr = {
.enable_reg = 0x0058,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "apcs_alias0_core_clk",
.parent_hws = (const struct clk_hw *[]){
&apcs_alias0_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static const struct regmap_config apss_ipq6018_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x1000,
.fast_io = true,
};
static struct clk_regmap *apss_ipq6018_clks[] = {
[APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr,
[APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr,
};
static const struct qcom_cc_desc apss_ipq6018_desc = {
.config = &apss_ipq6018_regmap_config,
.clks = apss_ipq6018_clks,
.num_clks = ARRAY_SIZE(apss_ipq6018_clks),
};
static int apss_ipq6018_probe(struct platform_device *pdev)
{
struct regmap *regmap;
regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!regmap)
return -ENODEV;
return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap);
}
static struct platform_driver apss_ipq6018_driver = {
.probe = apss_ipq6018_probe,
.driver = {
.name = "qcom,apss-ipq6018-clk",
},
};
module_platform_driver(apss_ipq6018_driver);
MODULE_DESCRIPTION("QCOM APSS IPQ 6018 CLK Driver");
MODULE_LICENSE("GPL v2");

View File

@@ -47,6 +47,12 @@ struct pll_vco {
u32 val; u32 val;
}; };
#define VCO(a, b, c) { \
.val = a,\
.min_freq = b,\
.max_freq = c,\
}
/** /**
* struct clk_alpha_pll - phase locked loop (PLL) * struct clk_alpha_pll - phase locked loop (PLL)
* @offset: base address of registers * @offset: base address of registers

View File

@@ -0,0 +1,538 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
/*
* Each of the CPU clusters (Power and Perf) on msm8996 are
* clocked via 2 PLLs, a primary and alternate. There are also
* 2 Mux'es, a primary and secondary all connected together
* as shown below
*
* +-------+
* XO | |
* +------------------>0 |
* | |
* PLL/2 | SMUX +----+
* +------->1 | |
* | | | |
* | +-------+ | +-------+
* | +---->0 |
* | | |
* +---------------+ | +----------->1 | CPU clk
* |Primary PLL +----+ PLL_EARLY | | +------>
* | +------+-----------+ +------>2 PMUX |
* +---------------+ | | | |
* | +------+ | +-->3 |
* +--^+ ACD +-----+ | +-------+
* +---------------+ +------+ |
* |Alt PLL | |
* | +---------------------------+
* +---------------+ PLL_EARLY
*
* The primary PLL is what drives the CPU clk, except for times
* when we are reprogramming the PLL itself (for rate changes) when
* we temporarily switch to an alternate PLL.
*
* The primary PLL operates on a single VCO range, between 600MHz
* and 3GHz. However the CPUs do support OPPs with frequencies
* between 300MHz and 600MHz. In order to support running the CPUs
* at those frequencies we end up having to lock the PLL at twice
* the rate and drive the CPU clk via the PLL/2 output and SMUX.
*
* So for frequencies above 600MHz we follow the following path
* Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk
* and for frequencies between 300MHz and 600MHz we follow
* Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk
*
* ACD stands for Adaptive Clock Distribution and is used to
* detect voltage droops.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <soc/qcom/kryo-l2-accessors.h>
#include "clk-alpha-pll.h"
#include "clk-regmap.h"
enum _pmux_input {
DIV_2_INDEX = 0,
PLL_INDEX,
ACD_INDEX,
ALT_INDEX,
NUM_OF_PMUX_INPUTS
};
#define DIV_2_THRESHOLD 600000000
#define PWRCL_REG_OFFSET 0x0
#define PERFCL_REG_OFFSET 0x80000
#define MUX_OFFSET 0x40
#define ALT_PLL_OFFSET 0x100
#define SSSCTL_OFFSET 0x160
static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
[PLL_OFF_USER_CTL] = 0x10,
[PLL_OFF_CONFIG_CTL] = 0x18,
[PLL_OFF_CONFIG_CTL_U] = 0x1c,
[PLL_OFF_TEST_CTL] = 0x20,
[PLL_OFF_TEST_CTL_U] = 0x24,
[PLL_OFF_STATUS] = 0x28,
};
static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
[PLL_OFF_ALPHA_VAL_U] = 0x0c,
[PLL_OFF_USER_CTL] = 0x10,
[PLL_OFF_USER_CTL_U] = 0x14,
[PLL_OFF_CONFIG_CTL] = 0x18,
[PLL_OFF_TEST_CTL] = 0x20,
[PLL_OFF_TEST_CTL_U] = 0x24,
[PLL_OFF_STATUS] = 0x28,
};
/* PLLs */
static const struct alpha_pll_config hfpll_config = {
.l = 60,
.config_ctl_val = 0x200d4aa8,
.config_ctl_hi_val = 0x006,
.pre_div_mask = BIT(12),
.post_div_mask = 0x3 << 8,
.post_div_val = 0x1 << 8,
.main_output_mask = BIT(0),
.early_output_mask = BIT(3),
};
static struct clk_alpha_pll perfcl_pll = {
.offset = PERFCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
.name = "perfcl_pll",
.parent_names = (const char *[]){ "xo" },
.num_parents = 1,
.ops = &clk_alpha_pll_huayra_ops,
},
};
static struct clk_alpha_pll pwrcl_pll = {
.offset = PWRCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
.name = "pwrcl_pll",
.parent_names = (const char *[]){ "xo" },
.num_parents = 1,
.ops = &clk_alpha_pll_huayra_ops,
},
};
static const struct pll_vco alt_pll_vco_modes[] = {
VCO(3, 250000000, 500000000),
VCO(2, 500000000, 750000000),
VCO(1, 750000000, 1000000000),
VCO(0, 1000000000, 2150400000),
};
static const struct alpha_pll_config altpll_config = {
.l = 16,
.vco_val = 0x3 << 20,
.vco_mask = 0x3 << 20,
.config_ctl_val = 0x4001051b,
.post_div_mask = 0x3 << 8,
.post_div_val = 0x1 << 8,
.main_output_mask = BIT(0),
.early_output_mask = BIT(3),
};
static struct clk_alpha_pll perfcl_alt_pll = {
.offset = PERFCL_REG_OFFSET + ALT_PLL_OFFSET,
.regs = alt_pll_regs,
.vco_table = alt_pll_vco_modes,
.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_alt_pll",
.parent_names = (const char *[]){ "xo" },
.num_parents = 1,
.ops = &clk_alpha_pll_hwfsm_ops,
},
};
static struct clk_alpha_pll pwrcl_alt_pll = {
.offset = PWRCL_REG_OFFSET + ALT_PLL_OFFSET,
.regs = alt_pll_regs,
.vco_table = alt_pll_vco_modes,
.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data) {
.name = "pwrcl_alt_pll",
.parent_names = (const char *[]){ "xo" },
.num_parents = 1,
.ops = &clk_alpha_pll_hwfsm_ops,
},
};
struct clk_cpu_8996_mux {
u32 reg;
u8 shift;
u8 width;
struct notifier_block nb;
struct clk_hw *pll;
struct clk_hw *pll_div_2;
struct clk_regmap clkr;
};
static int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data);
#define to_clk_cpu_8996_mux_nb(_nb) \
container_of(_nb, struct clk_cpu_8996_mux, nb)
static inline struct clk_cpu_8996_mux *to_clk_cpu_8996_mux_hw(struct clk_hw *hw)
{
return container_of(to_clk_regmap(hw), struct clk_cpu_8996_mux, clkr);
}
static u8 clk_cpu_8996_mux_get_parent(struct clk_hw *hw)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
u32 mask = GENMASK(cpuclk->width - 1, 0);
u32 val;
regmap_read(clkr->regmap, cpuclk->reg, &val);
val >>= cpuclk->shift;
return val & mask;
}
static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
u32 mask = GENMASK(cpuclk->width + cpuclk->shift - 1, cpuclk->shift);
u32 val;
val = index;
val <<= cpuclk->shift;
return regmap_update_bits(clkr->regmap, cpuclk->reg, mask, val);
}
static int clk_cpu_8996_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
struct clk_hw *parent = cpuclk->pll;
if (cpuclk->pll_div_2 && req->rate < DIV_2_THRESHOLD) {
if (req->rate < (DIV_2_THRESHOLD / 2))
return -EINVAL;
parent = cpuclk->pll_div_2;
}
req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
req->best_parent_hw = parent;
return 0;
}
static const struct clk_ops clk_cpu_8996_mux_ops = {
.set_parent = clk_cpu_8996_mux_set_parent,
.get_parent = clk_cpu_8996_mux_get_parent,
.determine_rate = clk_cpu_8996_mux_determine_rate,
};
static struct clk_cpu_8996_mux pwrcl_smux = {
.reg = PWRCL_REG_OFFSET + MUX_OFFSET,
.shift = 2,
.width = 2,
.clkr.hw.init = &(struct clk_init_data) {
.name = "pwrcl_smux",
.parent_names = (const char *[]){
"xo",
"pwrcl_pll_main",
},
.num_parents = 2,
.ops = &clk_cpu_8996_mux_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_cpu_8996_mux perfcl_smux = {
.reg = PERFCL_REG_OFFSET + MUX_OFFSET,
.shift = 2,
.width = 2,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_smux",
.parent_names = (const char *[]){
"xo",
"perfcl_pll_main",
},
.num_parents = 2,
.ops = &clk_cpu_8996_mux_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_cpu_8996_mux pwrcl_pmux = {
.reg = PWRCL_REG_OFFSET + MUX_OFFSET,
.shift = 0,
.width = 2,
.pll = &pwrcl_pll.clkr.hw,
.pll_div_2 = &pwrcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "pwrcl_pmux",
.parent_names = (const char *[]){
"pwrcl_smux",
"pwrcl_pll",
"pwrcl_pll_acd",
"pwrcl_alt_pll",
},
.num_parents = 4,
.ops = &clk_cpu_8996_mux_ops,
/* CPU clock is critical and should never be gated */
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
},
};
static struct clk_cpu_8996_mux perfcl_pmux = {
.reg = PERFCL_REG_OFFSET + MUX_OFFSET,
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
.pll_div_2 = &perfcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
.parent_names = (const char *[]){
"perfcl_smux",
"perfcl_pll",
"perfcl_pll_acd",
"perfcl_alt_pll",
},
.num_parents = 4,
.ops = &clk_cpu_8996_mux_ops,
/* CPU clock is critical and should never be gated */
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
},
};
static const struct regmap_config cpu_msm8996_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x80210,
.fast_io = true,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
};
static struct clk_regmap *cpu_msm8996_clks[] = {
&perfcl_pll.clkr,
&pwrcl_pll.clkr,
&perfcl_alt_pll.clkr,
&pwrcl_alt_pll.clkr,
&perfcl_smux.clkr,
&pwrcl_smux.clkr,
&perfcl_pmux.clkr,
&pwrcl_pmux.clkr,
};
static int qcom_cpu_clk_msm8996_register_clks(struct device *dev,
struct regmap *regmap)
{
int i, ret;
perfcl_smux.pll = clk_hw_register_fixed_factor(dev, "perfcl_pll_main",
"perfcl_pll",
CLK_SET_RATE_PARENT,
1, 2);
if (IS_ERR(perfcl_smux.pll)) {
dev_err(dev, "Failed to initialize perfcl_pll_main\n");
return PTR_ERR(perfcl_smux.pll);
}
pwrcl_smux.pll = clk_hw_register_fixed_factor(dev, "pwrcl_pll_main",
"pwrcl_pll",
CLK_SET_RATE_PARENT,
1, 2);
if (IS_ERR(pwrcl_smux.pll)) {
dev_err(dev, "Failed to initialize pwrcl_pll_main\n");
clk_hw_unregister(perfcl_smux.pll);
return PTR_ERR(pwrcl_smux.pll);
}
for (i = 0; i < ARRAY_SIZE(cpu_msm8996_clks); i++) {
ret = devm_clk_register_regmap(dev, cpu_msm8996_clks[i]);
if (ret) {
clk_hw_unregister(perfcl_smux.pll);
clk_hw_unregister(pwrcl_smux.pll);
return ret;
}
}
clk_alpha_pll_configure(&perfcl_pll, regmap, &hfpll_config);
clk_alpha_pll_configure(&pwrcl_pll, regmap, &hfpll_config);
clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
/* Enable alt PLLs */
clk_prepare_enable(pwrcl_alt_pll.clkr.hw.clk);
clk_prepare_enable(perfcl_alt_pll.clkr.hw.clk);
clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
clk_notifier_register(perfcl_pmux.clkr.hw.clk, &perfcl_pmux.nb);
return ret;
}
static int qcom_cpu_clk_msm8996_unregister_clks(void)
{
int ret = 0;
ret = clk_notifier_unregister(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
if (ret)
return ret;
ret = clk_notifier_unregister(perfcl_pmux.clkr.hw.clk, &perfcl_pmux.nb);
if (ret)
return ret;
clk_hw_unregister(perfcl_smux.pll);
clk_hw_unregister(pwrcl_smux.pll);
return 0;
}
#define CPU_AFINITY_MASK 0xFFF
#define PWRCL_CPU_REG_MASK 0x3
#define PERFCL_CPU_REG_MASK 0x103
#define L2ACDCR_REG 0x580ULL
#define L2ACDTD_REG 0x581ULL
#define L2ACDDVMRC_REG 0x584ULL
#define L2ACDSSCR_REG 0x589ULL
static DEFINE_SPINLOCK(qcom_clk_acd_lock);
static void __iomem *base;
static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base)
{
u64 hwid;
unsigned long flags;
spin_lock_irqsave(&qcom_clk_acd_lock, flags);
hwid = read_cpuid_mpidr() & CPU_AFINITY_MASK;
kryo_l2_set_indirect_reg(L2ACDTD_REG, 0x00006a11);
kryo_l2_set_indirect_reg(L2ACDDVMRC_REG, 0x000e0f0f);
kryo_l2_set_indirect_reg(L2ACDSSCR_REG, 0x00000601);
if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
writel(0xf, base + PWRCL_REG_OFFSET + SSSCTL_OFFSET);
kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002c5ffd);
}
if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) {
kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002c5ffd);
writel(0xf, base + PERFCL_REG_OFFSET + SSSCTL_OFFSET);
}
spin_unlock_irqrestore(&qcom_clk_acd_lock, flags);
}
static int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data)
{
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_nb(nb);
struct clk_notifier_data *cnd = data;
int ret;
switch (event) {
case PRE_RATE_CHANGE:
ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX);
qcom_cpu_clk_msm8996_acd_init(base);
break;
case POST_RATE_CHANGE:
if (cnd->new_rate < DIV_2_THRESHOLD)
ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
DIV_2_INDEX);
else
ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
ACD_INDEX);
break;
default:
ret = 0;
break;
}
return notifier_from_errno(ret);
};
static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
{
struct regmap *regmap;
struct clk_hw_onecell_data *data;
struct device *dev = &pdev->dev;
int ret;
data = devm_kzalloc(dev, struct_size(data, hws, 2), GFP_KERNEL);
if (!data)
return -ENOMEM;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(dev, base, &cpu_msm8996_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
ret = qcom_cpu_clk_msm8996_register_clks(dev, regmap);
if (ret)
return ret;
qcom_cpu_clk_msm8996_acd_init(base);
data->hws[0] = &pwrcl_pmux.clkr.hw;
data->hws[1] = &perfcl_pmux.clkr.hw;
data->num = 2;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
}
static int qcom_cpu_clk_msm8996_driver_remove(struct platform_device *pdev)
{
return qcom_cpu_clk_msm8996_unregister_clks();
}
static const struct of_device_id qcom_cpu_clk_msm8996_match_table[] = {
{ .compatible = "qcom,msm8996-apcc" },
{}
};
MODULE_DEVICE_TABLE(of, qcom_cpu_clk_msm8996_match_table);
static struct platform_driver qcom_cpu_clk_msm8996_driver = {
.probe = qcom_cpu_clk_msm8996_driver_probe,
.remove = qcom_cpu_clk_msm8996_driver_remove,
.driver = {
.name = "qcom-msm8996-apcc",
.of_match_table = qcom_cpu_clk_msm8996_match_table,
},
};
module_platform_driver(qcom_cpu_clk_msm8996_driver);
MODULE_DESCRIPTION("QCOM MSM8996 CPU Clock Driver");
MODULE_LICENSE("GPL v2");

View File

@@ -452,6 +452,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8916 = {
.num_clks = ARRAY_SIZE(msm8916_clks), .num_clks = ARRAY_SIZE(msm8916_clks),
}; };
/* msm8936 */
DEFINE_CLK_SMD_RPM(msm8936, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8936, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8936, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8936, sysmmnoc_clk, sysmmnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
DEFINE_CLK_SMD_RPM_QDSS(msm8936, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk1, bb_clk1_a, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk2, bb_clk2_a, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk1, rf_clk1_a, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk2, rf_clk2_a, 5);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk1_pin, bb_clk1_a_pin, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk2_pin, bb_clk2_a_pin, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk1_pin, rf_clk1_a_pin, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk2_pin, rf_clk2_a_pin, 5);
static struct clk_smd_rpm *msm8936_clks[] = {
[RPM_SMD_PCNOC_CLK] = &msm8936_pcnoc_clk,
[RPM_SMD_PCNOC_A_CLK] = &msm8936_pcnoc_a_clk,
[RPM_SMD_SNOC_CLK] = &msm8936_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &msm8936_snoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8936_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &msm8936_bimc_a_clk,
[RPM_SMD_SYSMMNOC_CLK] = &msm8936_sysmmnoc_clk,
[RPM_SMD_SYSMMNOC_A_CLK] = &msm8936_sysmmnoc_a_clk,
[RPM_SMD_QDSS_CLK] = &msm8936_qdss_clk,
[RPM_SMD_QDSS_A_CLK] = &msm8936_qdss_a_clk,
[RPM_SMD_BB_CLK1] = &msm8936_bb_clk1,
[RPM_SMD_BB_CLK1_A] = &msm8936_bb_clk1_a,
[RPM_SMD_BB_CLK2] = &msm8936_bb_clk2,
[RPM_SMD_BB_CLK2_A] = &msm8936_bb_clk2_a,
[RPM_SMD_RF_CLK1] = &msm8936_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &msm8936_rf_clk1_a,
[RPM_SMD_RF_CLK2] = &msm8936_rf_clk2,
[RPM_SMD_RF_CLK2_A] = &msm8936_rf_clk2_a,
[RPM_SMD_BB_CLK1_PIN] = &msm8936_bb_clk1_pin,
[RPM_SMD_BB_CLK1_A_PIN] = &msm8936_bb_clk1_a_pin,
[RPM_SMD_BB_CLK2_PIN] = &msm8936_bb_clk2_pin,
[RPM_SMD_BB_CLK2_A_PIN] = &msm8936_bb_clk2_a_pin,
[RPM_SMD_RF_CLK1_PIN] = &msm8936_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8936_rf_clk1_a_pin,
[RPM_SMD_RF_CLK2_PIN] = &msm8936_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8936_rf_clk2_a_pin,
};
static const struct rpm_smd_clk_desc rpm_clk_msm8936 = {
.clks = msm8936_clks,
.num_clks = ARRAY_SIZE(msm8936_clks),
};
/* msm8974 */ /* msm8974 */
DEFINE_CLK_SMD_RPM(msm8974, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8974, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8974, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8974, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
@@ -574,6 +623,175 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8976 = {
.num_clks = ARRAY_SIZE(msm8976_clks), .num_clks = ARRAY_SIZE(msm8976_clks),
}; };
/* msm8992 */
DEFINE_CLK_SMD_RPM(msm8992, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8992, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2);
DEFINE_CLK_SMD_RPM(msm8992, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8992, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
DEFINE_CLK_SMD_RPM(msm8992, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8992, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk1, bb_clk1_a, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk1_pin, bb_clk1_a_pin, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk2, bb_clk2_a, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk2_pin, bb_clk2_a_pin, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk1, div_clk1_a, 11);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk2, div_clk2_a, 12);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk3, div_clk3_a, 13);
DEFINE_CLK_SMD_RPM(msm8992, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, ln_bb_clk, ln_bb_a_clk, 8);
DEFINE_CLK_SMD_RPM(msm8992, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk,
QCOM_SMD_RPM_BUS_CLK, 3);
DEFINE_CLK_SMD_RPM_QDSS(msm8992, qdss_clk, qdss_a_clk,
QCOM_SMD_RPM_MISC_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk1, rf_clk1_a, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk2, rf_clk2_a, 5);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk1_pin, rf_clk1_a_pin, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk2_pin, rf_clk2_a_pin, 5);
DEFINE_CLK_SMD_RPM(msm8992, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8992, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1);
static struct clk_smd_rpm *msm8992_clks[] = {
[RPM_SMD_PNOC_CLK] = &msm8992_pnoc_clk,
[RPM_SMD_PNOC_A_CLK] = &msm8992_pnoc_a_clk,
[RPM_SMD_OCMEMGX_CLK] = &msm8992_ocmemgx_clk,
[RPM_SMD_OCMEMGX_A_CLK] = &msm8992_ocmemgx_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8992_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &msm8992_bimc_a_clk,
[RPM_SMD_CNOC_CLK] = &msm8992_cnoc_clk,
[RPM_SMD_CNOC_A_CLK] = &msm8992_cnoc_a_clk,
[RPM_SMD_GFX3D_CLK_SRC] = &msm8992_gfx3d_clk_src,
[RPM_SMD_GFX3D_A_CLK_SRC] = &msm8992_gfx3d_a_clk_src,
[RPM_SMD_SNOC_CLK] = &msm8992_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &msm8992_snoc_a_clk,
[RPM_SMD_BB_CLK1] = &msm8992_bb_clk1,
[RPM_SMD_BB_CLK1_A] = &msm8992_bb_clk1_a,
[RPM_SMD_BB_CLK1_PIN] = &msm8992_bb_clk1_pin,
[RPM_SMD_BB_CLK1_A_PIN] = &msm8992_bb_clk1_a_pin,
[RPM_SMD_BB_CLK2] = &msm8992_bb_clk2,
[RPM_SMD_BB_CLK2_A] = &msm8992_bb_clk2_a,
[RPM_SMD_BB_CLK2_PIN] = &msm8992_bb_clk2_pin,
[RPM_SMD_BB_CLK2_A_PIN] = &msm8992_bb_clk2_a_pin,
[RPM_SMD_DIV_CLK1] = &msm8992_div_clk1,
[RPM_SMD_DIV_A_CLK1] = &msm8992_div_clk1_a,
[RPM_SMD_DIV_CLK2] = &msm8992_div_clk2,
[RPM_SMD_DIV_A_CLK2] = &msm8992_div_clk2_a,
[RPM_SMD_DIV_CLK3] = &msm8992_div_clk3,
[RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a,
[RPM_SMD_IPA_CLK] = &msm8992_ipa_clk,
[RPM_SMD_IPA_A_CLK] = &msm8992_ipa_a_clk,
[RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk,
[RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk,
[RPM_SMD_MMSSNOC_AHB_CLK] = &msm8992_mmssnoc_ahb_clk,
[RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8992_mmssnoc_ahb_a_clk,
[RPM_SMD_QDSS_CLK] = &msm8992_qdss_clk,
[RPM_SMD_QDSS_A_CLK] = &msm8992_qdss_a_clk,
[RPM_SMD_RF_CLK1] = &msm8992_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &msm8992_rf_clk1_a,
[RPM_SMD_RF_CLK2] = &msm8992_rf_clk2,
[RPM_SMD_RF_CLK2_A] = &msm8992_rf_clk2_a,
[RPM_SMD_RF_CLK1_PIN] = &msm8992_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8992_rf_clk1_a_pin,
[RPM_SMD_RF_CLK2_PIN] = &msm8992_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8992_rf_clk2_a_pin,
[RPM_SMD_CE1_CLK] = &msm8992_ce1_clk,
[RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
[RPM_SMD_CE2_CLK] = &msm8992_ce2_clk,
[RPM_SMD_CE2_A_CLK] = &msm8992_ce2_a_clk,
};
static const struct rpm_smd_clk_desc rpm_clk_msm8992 = {
.clks = msm8992_clks,
.num_clks = ARRAY_SIZE(msm8992_clks),
};
/* msm8994 */
DEFINE_CLK_SMD_RPM(msm8994, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8994, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2);
DEFINE_CLK_SMD_RPM(msm8994, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8994, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
DEFINE_CLK_SMD_RPM(msm8994, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8994, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk1, bb_clk1_a, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk1_pin, bb_clk1_a_pin, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk2, bb_clk2_a, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk2_pin, bb_clk2_a_pin, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk1, div_clk1_a, 11);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk2, div_clk2_a, 12);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk3, div_clk3_a, 13);
DEFINE_CLK_SMD_RPM(msm8994, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, ln_bb_clk, ln_bb_a_clk, 8);
DEFINE_CLK_SMD_RPM(msm8994, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk,
QCOM_SMD_RPM_BUS_CLK, 3);
DEFINE_CLK_SMD_RPM_QDSS(msm8994, qdss_clk, qdss_a_clk,
QCOM_SMD_RPM_MISC_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk1, rf_clk1_a, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk2, rf_clk2_a, 5);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk1_pin, rf_clk1_a_pin, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk2_pin, rf_clk2_a_pin, 5);
DEFINE_CLK_SMD_RPM(msm8994, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8994, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8994, ce3_clk, ce3_a_clk, QCOM_SMD_RPM_CE_CLK, 2);
static struct clk_smd_rpm *msm8994_clks[] = {
[RPM_SMD_PNOC_CLK] = &msm8994_pnoc_clk,
[RPM_SMD_PNOC_A_CLK] = &msm8994_pnoc_a_clk,
[RPM_SMD_OCMEMGX_CLK] = &msm8994_ocmemgx_clk,
[RPM_SMD_OCMEMGX_A_CLK] = &msm8994_ocmemgx_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8994_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &msm8994_bimc_a_clk,
[RPM_SMD_CNOC_CLK] = &msm8994_cnoc_clk,
[RPM_SMD_CNOC_A_CLK] = &msm8994_cnoc_a_clk,
[RPM_SMD_GFX3D_CLK_SRC] = &msm8994_gfx3d_clk_src,
[RPM_SMD_GFX3D_A_CLK_SRC] = &msm8994_gfx3d_a_clk_src,
[RPM_SMD_SNOC_CLK] = &msm8994_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &msm8994_snoc_a_clk,
[RPM_SMD_BB_CLK1] = &msm8994_bb_clk1,
[RPM_SMD_BB_CLK1_A] = &msm8994_bb_clk1_a,
[RPM_SMD_BB_CLK1_PIN] = &msm8994_bb_clk1_pin,
[RPM_SMD_BB_CLK1_A_PIN] = &msm8994_bb_clk1_a_pin,
[RPM_SMD_BB_CLK2] = &msm8994_bb_clk2,
[RPM_SMD_BB_CLK2_A] = &msm8994_bb_clk2_a,
[RPM_SMD_BB_CLK2_PIN] = &msm8994_bb_clk2_pin,
[RPM_SMD_BB_CLK2_A_PIN] = &msm8994_bb_clk2_a_pin,
[RPM_SMD_DIV_CLK1] = &msm8994_div_clk1,
[RPM_SMD_DIV_A_CLK1] = &msm8994_div_clk1_a,
[RPM_SMD_DIV_CLK2] = &msm8994_div_clk2,
[RPM_SMD_DIV_A_CLK2] = &msm8994_div_clk2_a,
[RPM_SMD_DIV_CLK3] = &msm8994_div_clk3,
[RPM_SMD_DIV_A_CLK3] = &msm8994_div_clk3_a,
[RPM_SMD_IPA_CLK] = &msm8994_ipa_clk,
[RPM_SMD_IPA_A_CLK] = &msm8994_ipa_a_clk,
[RPM_SMD_LN_BB_CLK] = &msm8994_ln_bb_clk,
[RPM_SMD_LN_BB_A_CLK] = &msm8994_ln_bb_a_clk,
[RPM_SMD_MMSSNOC_AHB_CLK] = &msm8994_mmssnoc_ahb_clk,
[RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8994_mmssnoc_ahb_a_clk,
[RPM_SMD_QDSS_CLK] = &msm8994_qdss_clk,
[RPM_SMD_QDSS_A_CLK] = &msm8994_qdss_a_clk,
[RPM_SMD_RF_CLK1] = &msm8994_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &msm8994_rf_clk1_a,
[RPM_SMD_RF_CLK2] = &msm8994_rf_clk2,
[RPM_SMD_RF_CLK2_A] = &msm8994_rf_clk2_a,
[RPM_SMD_RF_CLK1_PIN] = &msm8994_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8994_rf_clk1_a_pin,
[RPM_SMD_RF_CLK2_PIN] = &msm8994_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8994_rf_clk2_a_pin,
[RPM_SMD_CE1_CLK] = &msm8994_ce1_clk,
[RPM_SMD_CE1_A_CLK] = &msm8994_ce1_a_clk,
[RPM_SMD_CE2_CLK] = &msm8994_ce2_clk,
[RPM_SMD_CE2_A_CLK] = &msm8994_ce2_a_clk,
[RPM_SMD_CE3_CLK] = &msm8994_ce3_clk,
[RPM_SMD_CE3_A_CLK] = &msm8994_ce3_a_clk,
};
static const struct rpm_smd_clk_desc rpm_clk_msm8994 = {
.clks = msm8994_clks,
.num_clks = ARRAY_SIZE(msm8994_clks),
};
/* msm8996 */ /* msm8996 */
DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
@@ -766,13 +984,92 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = {
.num_clks = ARRAY_SIZE(msm8998_clks), .num_clks = ARRAY_SIZE(msm8998_clks),
}; };
/* sdm660 */
DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
19200000);
DEFINE_CLK_SMD_RPM(sdm660, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
DEFINE_CLK_SMD_RPM(sdm660, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
DEFINE_CLK_SMD_RPM(sdm660, cnoc_periph_clk, cnoc_periph_a_clk,
QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(sdm660, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
DEFINE_CLK_SMD_RPM(sdm660, mmssnoc_axi_clk, mmssnoc_axi_a_clk,
QCOM_SMD_RPM_MMAXI_CLK, 0);
DEFINE_CLK_SMD_RPM(sdm660, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
DEFINE_CLK_SMD_RPM(sdm660, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
DEFINE_CLK_SMD_RPM(sdm660, aggre2_noc_clk, aggre2_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 2);
DEFINE_CLK_SMD_RPM_QDSS(sdm660, qdss_clk, qdss_a_clk,
QCOM_SMD_RPM_MISC_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, rf_clk1, rf_clk1_a, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, div_clk1, div_clk1_a, 11);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk1, ln_bb_clk1_a, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk2, ln_bb_clk2_a, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, rf_clk1_pin, rf_clk1_a_pin, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk1_pin,
ln_bb_clk1_pin_a, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk2_pin,
ln_bb_clk2_pin_a, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin,
ln_bb_clk3_pin_a, 3);
static struct clk_smd_rpm *sdm660_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &sdm660_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &sdm660_snoc_a_clk,
[RPM_SMD_CNOC_CLK] = &sdm660_cnoc_clk,
[RPM_SMD_CNOC_A_CLK] = &sdm660_cnoc_a_clk,
[RPM_SMD_CNOC_PERIPH_CLK] = &sdm660_cnoc_periph_clk,
[RPM_SMD_CNOC_PERIPH_A_CLK] = &sdm660_cnoc_periph_a_clk,
[RPM_SMD_BIMC_CLK] = &sdm660_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &sdm660_bimc_a_clk,
[RPM_SMD_MMSSNOC_AXI_CLK] = &sdm660_mmssnoc_axi_clk,
[RPM_SMD_MMSSNOC_AXI_CLK_A] = &sdm660_mmssnoc_axi_a_clk,
[RPM_SMD_IPA_CLK] = &sdm660_ipa_clk,
[RPM_SMD_IPA_A_CLK] = &sdm660_ipa_a_clk,
[RPM_SMD_CE1_CLK] = &sdm660_ce1_clk,
[RPM_SMD_CE1_A_CLK] = &sdm660_ce1_a_clk,
[RPM_SMD_AGGR2_NOC_CLK] = &sdm660_aggre2_noc_clk,
[RPM_SMD_AGGR2_NOC_A_CLK] = &sdm660_aggre2_noc_a_clk,
[RPM_SMD_QDSS_CLK] = &sdm660_qdss_clk,
[RPM_SMD_QDSS_A_CLK] = &sdm660_qdss_a_clk,
[RPM_SMD_RF_CLK1] = &sdm660_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &sdm660_rf_clk1_a,
[RPM_SMD_DIV_CLK1] = &sdm660_div_clk1,
[RPM_SMD_DIV_A_CLK1] = &sdm660_div_clk1_a,
[RPM_SMD_LN_BB_CLK] = &sdm660_ln_bb_clk1,
[RPM_SMD_LN_BB_A_CLK] = &sdm660_ln_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &sdm660_ln_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &sdm660_ln_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
[RPM_SMD_RF_CLK1_PIN] = &sdm660_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &sdm660_rf_clk1_a_pin,
[RPM_SMD_LN_BB_CLK1_PIN] = &sdm660_ln_bb_clk1_pin,
[RPM_SMD_LN_BB_CLK1_A_PIN] = &sdm660_ln_bb_clk1_pin_a,
[RPM_SMD_LN_BB_CLK2_PIN] = &sdm660_ln_bb_clk2_pin,
[RPM_SMD_LN_BB_CLK2_A_PIN] = &sdm660_ln_bb_clk2_pin_a,
[RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a,
};
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
.clks = sdm660_clks,
.num_clks = ARRAY_SIZE(sdm660_clks),
};
static const struct of_device_id rpm_smd_clk_match_table[] = { static const struct of_device_id rpm_smd_clk_match_table[] = {
{ .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
{ .compatible = "qcom,rpmcc-msm8936", .data = &rpm_clk_msm8936 },
{ .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 },
{ .compatible = "qcom,rpmcc-msm8976", .data = &rpm_clk_msm8976 }, { .compatible = "qcom,rpmcc-msm8976", .data = &rpm_clk_msm8976 },
{ .compatible = "qcom,rpmcc-msm8992", .data = &rpm_clk_msm8992 },
{ .compatible = "qcom,rpmcc-msm8994", .data = &rpm_clk_msm8994 },
{ .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 },
{ .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 }, { .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 },
{ .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 },
{ .compatible = "qcom,rpmcc-sdm660", .data = &rpm_clk_sdm660 },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);

View File

@@ -3089,7 +3089,7 @@ static int gcc_ipq806x_probe(struct platform_device *pdev)
regmap_write(regmap, 0x3cf8, 8); regmap_write(regmap, 0x3cf8, 8);
regmap_write(regmap, 0x3d18, 8); regmap_write(regmap, 0x3d18, 8);
return 0; return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
} }
static struct platform_driver gcc_ipq806x_driver = { static struct platform_driver gcc_ipq806x_driver = {

View File

@@ -4316,6 +4316,62 @@ static struct clk_branch gcc_gp3_clk = {
}, },
}; };
static const struct freq_tbl ftbl_pcie_rchng_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
F(100000000, P_GPLL0, 8, 0, 0),
{ }
};
struct clk_rcg2 pcie0_rchng_clk_src = {
.cmd_rcgr = 0x75070,
.freq_tbl = ftbl_pcie_rchng_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "pcie0_rchng_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&gpll0.clkr.hw },
.num_parents = 2,
.ops = &clk_rcg2_ops,
},
};
static struct clk_branch gcc_pcie0_rchng_clk = {
.halt_reg = 0x75070,
.halt_bit = 31,
.clkr = {
.enable_reg = 0x75070,
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_rchng_clk",
.parent_hws = (const struct clk_hw *[]){
&pcie0_rchng_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie0_axi_s_bridge_clk = {
.halt_reg = 0x75048,
.halt_bit = 31,
.clkr = {
.enable_reg = 0x75048,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_axi_s_bridge_clk",
.parent_hws = (const struct clk_hw *[]){
&pcie0_axi_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_hw *gcc_ipq8074_hws[] = { static struct clk_hw *gcc_ipq8074_hws[] = {
&gpll0_out_main_div2.hw, &gpll0_out_main_div2.hw,
&gpll6_out_main_div2.hw, &gpll6_out_main_div2.hw,
@@ -4551,6 +4607,9 @@ static struct clk_regmap *gcc_ipq8074_clks[] = {
[GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
[GCC_GP2_CLK] = &gcc_gp2_clk.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
[GCC_GP3_CLK] = &gcc_gp3_clk.clkr, [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
[GCC_PCIE0_RCHNG_CLK_SRC] = &pcie0_rchng_clk_src.clkr,
[GCC_PCIE0_RCHNG_CLK] = &gcc_pcie0_rchng_clk.clkr,
[GCC_PCIE0_AXI_S_BRIDGE_CLK] = &gcc_pcie0_axi_s_bridge_clk.clkr,
}; };
static const struct qcom_reset_map gcc_ipq8074_resets[] = { static const struct qcom_reset_map gcc_ipq8074_resets[] = {
@@ -4678,6 +4737,7 @@ static const struct qcom_reset_map gcc_ipq8074_resets[] = {
[GCC_PCIE0_AXI_SLAVE_ARES] = { 0x75040, 4 }, [GCC_PCIE0_AXI_SLAVE_ARES] = { 0x75040, 4 },
[GCC_PCIE0_AHB_ARES] = { 0x75040, 5 }, [GCC_PCIE0_AHB_ARES] = { 0x75040, 5 },
[GCC_PCIE0_AXI_MASTER_STICKY_ARES] = { 0x75040, 6 }, [GCC_PCIE0_AXI_MASTER_STICKY_ARES] = { 0x75040, 6 },
[GCC_PCIE0_AXI_SLAVE_STICKY_ARES] = { 0x75040, 7 },
[GCC_PCIE1_PIPE_ARES] = { 0x76040, 0 }, [GCC_PCIE1_PIPE_ARES] = { 0x76040, 0 },
[GCC_PCIE1_SLEEP_ARES] = { 0x76040, 1 }, [GCC_PCIE1_SLEEP_ARES] = { 0x76040, 1 },
[GCC_PCIE1_CORE_STICKY_ARES] = { 0x76040, 2 }, [GCC_PCIE1_CORE_STICKY_ARES] = { 0x76040, 2 },

View File

@@ -1061,7 +1061,7 @@ static struct clk_branch gcc_disp_gpll0_clk_src = {
.hw = &gpll0.clkr.hw, .hw = &gpll0.clkr.hw,
}, },
.num_parents = 1, .num_parents = 1,
.ops = &clk_branch2_ops, .ops = &clk_branch2_aon_ops,
}, },
}, },
}; };

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@@ -1344,7 +1344,7 @@ static struct clk_branch gcc_disp_gpll0_clk_src = {
"gpll0", "gpll0",
}, },
.num_parents = 1, .num_parents = 1,
.ops = &clk_branch2_ops, .ops = &clk_branch2_aon_ops,
}, },
}, },
}; };

View File

@@ -15,6 +15,7 @@ config CLK_RENESAS
select CLK_R8A774A1 if ARCH_R8A774A1 select CLK_R8A774A1 if ARCH_R8A774A1
select CLK_R8A774B1 if ARCH_R8A774B1 select CLK_R8A774B1 if ARCH_R8A774B1
select CLK_R8A774C0 if ARCH_R8A774C0 select CLK_R8A774C0 if ARCH_R8A774C0
select CLK_R8A774E1 if ARCH_R8A774E1
select CLK_R8A7778 if ARCH_R8A7778 select CLK_R8A7778 if ARCH_R8A7778
select CLK_R8A7779 if ARCH_R8A7779 select CLK_R8A7779 if ARCH_R8A7779
select CLK_R8A7790 if ARCH_R8A7790 select CLK_R8A7790 if ARCH_R8A7790
@@ -84,6 +85,10 @@ config CLK_R8A774C0
bool "RZ/G2E clock support" if COMPILE_TEST bool "RZ/G2E clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG select CLK_RCAR_GEN3_CPG
config CLK_R8A774E1
bool "RZ/G2H clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG
config CLK_R8A7778 config CLK_R8A7778
bool "R-Car M1A clock support" if COMPILE_TEST bool "R-Car M1A clock support" if COMPILE_TEST
select CLK_RENESAS_CPG_MSTP select CLK_RENESAS_CPG_MSTP

View File

@@ -12,6 +12,7 @@ obj-$(CONFIG_CLK_R8A77470) += r8a77470-cpg-mssr.o
obj-$(CONFIG_CLK_R8A774A1) += r8a774a1-cpg-mssr.o obj-$(CONFIG_CLK_R8A774A1) += r8a774a1-cpg-mssr.o
obj-$(CONFIG_CLK_R8A774B1) += r8a774b1-cpg-mssr.o obj-$(CONFIG_CLK_R8A774B1) += r8a774b1-cpg-mssr.o
obj-$(CONFIG_CLK_R8A774C0) += r8a774c0-cpg-mssr.o obj-$(CONFIG_CLK_R8A774C0) += r8a774c0-cpg-mssr.o
obj-$(CONFIG_CLK_R8A774E1) += r8a774e1-cpg-mssr.o
obj-$(CONFIG_CLK_R8A7778) += clk-r8a7778.o obj-$(CONFIG_CLK_R8A7778) += clk-r8a7778.o
obj-$(CONFIG_CLK_R8A7779) += clk-r8a7779.o obj-$(CONFIG_CLK_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o

View File

@@ -237,6 +237,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
}; };
static const unsigned int r8a774a1_crit_mod_clks[] __initconst = { static const unsigned int r8a774a1_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };

View File

@@ -233,6 +233,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = {
}; };
static const unsigned int r8a774b1_crit_mod_clks[] __initconst = { static const unsigned int r8a774b1_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };

View File

@@ -238,6 +238,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
}; };
static const unsigned int r8a774c0_crit_mod_clks[] __initconst = { static const unsigned int r8a774c0_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };

View File

@@ -0,0 +1,349 @@
// SPDX-License-Identifier: GPL-2.0
/*
* r8a774e1 Clock Pulse Generator / Module Standby and Software Reset
*
* Copyright (C) 2020 Renesas Electronics Corp.
*
* Based on r8a7795-cpg-mssr.c
*
* Copyright (C) 2015 Glider bvba
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a774e1-cpg-mssr.h>
#include "renesas-cpg-mssr.h"
#include "rcar-gen3-cpg.h"
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R8A774E1_CLK_CANFD,
/* External Input Clocks */
CLK_EXTAL,
CLK_EXTALR,
/* Internal Core Clocks */
CLK_MAIN,
CLK_PLL0,
CLK_PLL1,
CLK_PLL2,
CLK_PLL3,
CLK_PLL4,
CLK_PLL1_DIV2,
CLK_PLL1_DIV4,
CLK_S0,
CLK_S1,
CLK_S2,
CLK_S3,
CLK_SDSRC,
CLK_RPCSRC,
CLK_RINT,
/* Module Clocks */
MOD_CLK_BASE
};
static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("extal", CLK_EXTAL),
DEF_INPUT("extalr", CLK_EXTALR),
/* Internal Core Clocks */
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
DEF_BASE("rpc", R8A774E1_CLK_RPC, CLK_TYPE_GEN3_RPC,
CLK_RPCSRC),
DEF_BASE("rpcd2", R8A774E1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
R8A774E1_CLK_RPC),
DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
/* Core Clock Outputs */
DEF_GEN3_Z("z", R8A774E1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
DEF_GEN3_Z("z2", R8A774E1_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0),
DEF_FIXED("ztr", R8A774E1_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
DEF_FIXED("ztrd2", R8A774E1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
DEF_FIXED("zt", R8A774E1_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
DEF_FIXED("zx", R8A774E1_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
DEF_FIXED("s0d1", R8A774E1_CLK_S0D1, CLK_S0, 1, 1),
DEF_FIXED("s0d2", R8A774E1_CLK_S0D2, CLK_S0, 2, 1),
DEF_FIXED("s0d3", R8A774E1_CLK_S0D3, CLK_S0, 3, 1),
DEF_FIXED("s0d4", R8A774E1_CLK_S0D4, CLK_S0, 4, 1),
DEF_FIXED("s0d6", R8A774E1_CLK_S0D6, CLK_S0, 6, 1),
DEF_FIXED("s0d8", R8A774E1_CLK_S0D8, CLK_S0, 8, 1),
DEF_FIXED("s0d12", R8A774E1_CLK_S0D12, CLK_S0, 12, 1),
DEF_FIXED("s1d2", R8A774E1_CLK_S1D2, CLK_S1, 2, 1),
DEF_FIXED("s1d4", R8A774E1_CLK_S1D4, CLK_S1, 4, 1),
DEF_FIXED("s2d1", R8A774E1_CLK_S2D1, CLK_S2, 1, 1),
DEF_FIXED("s2d2", R8A774E1_CLK_S2D2, CLK_S2, 2, 1),
DEF_FIXED("s2d4", R8A774E1_CLK_S2D4, CLK_S2, 4, 1),
DEF_FIXED("s3d1", R8A774E1_CLK_S3D1, CLK_S3, 1, 1),
DEF_FIXED("s3d2", R8A774E1_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A774E1_CLK_S3D4, CLK_S3, 4, 1),
DEF_GEN3_SD("sd0", R8A774E1_CLK_SD0, CLK_SDSRC, 0x074),
DEF_GEN3_SD("sd1", R8A774E1_CLK_SD1, CLK_SDSRC, 0x078),
DEF_GEN3_SD("sd2", R8A774E1_CLK_SD2, CLK_SDSRC, 0x268),
DEF_GEN3_SD("sd3", R8A774E1_CLK_SD3, CLK_SDSRC, 0x26c),
DEF_FIXED("cl", R8A774E1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
DEF_FIXED("cr", R8A774E1_CLK_CR, CLK_PLL1_DIV4, 2, 1),
DEF_FIXED("cp", R8A774E1_CLK_CP, CLK_EXTAL, 2, 1),
DEF_FIXED("cpex", R8A774E1_CLK_CPEX, CLK_EXTAL, 2, 1),
DEF_DIV6P1("canfd", R8A774E1_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
DEF_DIV6P1("csi0", R8A774E1_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
DEF_DIV6P1("mso", R8A774E1_CLK_MSO, CLK_PLL1_DIV4, 0x014),
DEF_DIV6P1("hdmi", R8A774E1_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
DEF_GEN3_OSC("osc", R8A774E1_CLK_OSC, CLK_EXTAL, 8),
DEF_BASE("r", R8A774E1_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
};
static const struct mssr_mod_clk r8a774e1_mod_clks[] __initconst = {
DEF_MOD("fdp1-1", 118, R8A774E1_CLK_S0D1),
DEF_MOD("fdp1-0", 119, R8A774E1_CLK_S0D1),
DEF_MOD("tmu4", 121, R8A774E1_CLK_S0D6),
DEF_MOD("tmu3", 122, R8A774E1_CLK_S3D2),
DEF_MOD("tmu2", 123, R8A774E1_CLK_S3D2),
DEF_MOD("tmu1", 124, R8A774E1_CLK_S3D2),
DEF_MOD("tmu0", 125, R8A774E1_CLK_CP),
DEF_MOD("vcplf", 130, R8A774E1_CLK_S2D1),
DEF_MOD("vdpb", 131, R8A774E1_CLK_S2D1),
DEF_MOD("scif5", 202, R8A774E1_CLK_S3D4),
DEF_MOD("scif4", 203, R8A774E1_CLK_S3D4),
DEF_MOD("scif3", 204, R8A774E1_CLK_S3D4),
DEF_MOD("scif1", 206, R8A774E1_CLK_S3D4),
DEF_MOD("scif0", 207, R8A774E1_CLK_S3D4),
DEF_MOD("msiof3", 208, R8A774E1_CLK_MSO),
DEF_MOD("msiof2", 209, R8A774E1_CLK_MSO),
DEF_MOD("msiof1", 210, R8A774E1_CLK_MSO),
DEF_MOD("msiof0", 211, R8A774E1_CLK_MSO),
DEF_MOD("sys-dmac2", 217, R8A774E1_CLK_S3D1),
DEF_MOD("sys-dmac1", 218, R8A774E1_CLK_S3D1),
DEF_MOD("sys-dmac0", 219, R8A774E1_CLK_S0D3),
DEF_MOD("cmt3", 300, R8A774E1_CLK_R),
DEF_MOD("cmt2", 301, R8A774E1_CLK_R),
DEF_MOD("cmt1", 302, R8A774E1_CLK_R),
DEF_MOD("cmt0", 303, R8A774E1_CLK_R),
DEF_MOD("tpu0", 304, R8A774E1_CLK_S3D4),
DEF_MOD("scif2", 310, R8A774E1_CLK_S3D4),
DEF_MOD("sdif3", 311, R8A774E1_CLK_SD3),
DEF_MOD("sdif2", 312, R8A774E1_CLK_SD2),
DEF_MOD("sdif1", 313, R8A774E1_CLK_SD1),
DEF_MOD("sdif0", 314, R8A774E1_CLK_SD0),
DEF_MOD("pcie1", 318, R8A774E1_CLK_S3D1),
DEF_MOD("pcie0", 319, R8A774E1_CLK_S3D1),
DEF_MOD("usb3-if0", 328, R8A774E1_CLK_S3D1),
DEF_MOD("usb-dmac0", 330, R8A774E1_CLK_S3D1),
DEF_MOD("usb-dmac1", 331, R8A774E1_CLK_S3D1),
DEF_MOD("rwdt", 402, R8A774E1_CLK_R),
DEF_MOD("intc-ex", 407, R8A774E1_CLK_CP),
DEF_MOD("intc-ap", 408, R8A774E1_CLK_S0D3),
DEF_MOD("audmac1", 501, R8A774E1_CLK_S1D2),
DEF_MOD("audmac0", 502, R8A774E1_CLK_S1D2),
DEF_MOD("hscif4", 516, R8A774E1_CLK_S3D1),
DEF_MOD("hscif3", 517, R8A774E1_CLK_S3D1),
DEF_MOD("hscif2", 518, R8A774E1_CLK_S3D1),
DEF_MOD("hscif1", 519, R8A774E1_CLK_S3D1),
DEF_MOD("hscif0", 520, R8A774E1_CLK_S3D1),
DEF_MOD("thermal", 522, R8A774E1_CLK_CP),
DEF_MOD("pwm", 523, R8A774E1_CLK_S0D12),
DEF_MOD("fcpvd1", 602, R8A774E1_CLK_S0D2),
DEF_MOD("fcpvd0", 603, R8A774E1_CLK_S0D2),
DEF_MOD("fcpvb1", 606, R8A774E1_CLK_S0D1),
DEF_MOD("fcpvb0", 607, R8A774E1_CLK_S0D1),
DEF_MOD("fcpvi1", 610, R8A774E1_CLK_S0D1),
DEF_MOD("fcpvi0", 611, R8A774E1_CLK_S0D1),
DEF_MOD("fcpf1", 614, R8A774E1_CLK_S0D1),
DEF_MOD("fcpf0", 615, R8A774E1_CLK_S0D1),
DEF_MOD("fcpcs", 619, R8A774E1_CLK_S0D1),
DEF_MOD("vspd1", 622, R8A774E1_CLK_S0D2),
DEF_MOD("vspd0", 623, R8A774E1_CLK_S0D2),
DEF_MOD("vspbc", 624, R8A774E1_CLK_S0D1),
DEF_MOD("vspbd", 626, R8A774E1_CLK_S0D1),
DEF_MOD("vspi1", 630, R8A774E1_CLK_S0D1),
DEF_MOD("vspi0", 631, R8A774E1_CLK_S0D1),
DEF_MOD("ehci1", 702, R8A774E1_CLK_S3D2),
DEF_MOD("ehci0", 703, R8A774E1_CLK_S3D2),
DEF_MOD("hsusb", 704, R8A774E1_CLK_S3D2),
DEF_MOD("csi20", 714, R8A774E1_CLK_CSI0),
DEF_MOD("csi40", 716, R8A774E1_CLK_CSI0),
DEF_MOD("du3", 721, R8A774E1_CLK_S2D1),
DEF_MOD("du1", 723, R8A774E1_CLK_S2D1),
DEF_MOD("du0", 724, R8A774E1_CLK_S2D1),
DEF_MOD("lvds", 727, R8A774E1_CLK_S0D4),
DEF_MOD("hdmi0", 729, R8A774E1_CLK_HDMI),
DEF_MOD("vin7", 804, R8A774E1_CLK_S0D2),
DEF_MOD("vin6", 805, R8A774E1_CLK_S0D2),
DEF_MOD("vin5", 806, R8A774E1_CLK_S0D2),
DEF_MOD("vin4", 807, R8A774E1_CLK_S0D2),
DEF_MOD("vin3", 808, R8A774E1_CLK_S0D2),
DEF_MOD("vin2", 809, R8A774E1_CLK_S0D2),
DEF_MOD("vin1", 810, R8A774E1_CLK_S0D2),
DEF_MOD("vin0", 811, R8A774E1_CLK_S0D2),
DEF_MOD("etheravb", 812, R8A774E1_CLK_S0D6),
DEF_MOD("sata0", 815, R8A774E1_CLK_S3D2),
DEF_MOD("gpio7", 905, R8A774E1_CLK_S3D4),
DEF_MOD("gpio6", 906, R8A774E1_CLK_S3D4),
DEF_MOD("gpio5", 907, R8A774E1_CLK_S3D4),
DEF_MOD("gpio4", 908, R8A774E1_CLK_S3D4),
DEF_MOD("gpio3", 909, R8A774E1_CLK_S3D4),
DEF_MOD("gpio2", 910, R8A774E1_CLK_S3D4),
DEF_MOD("gpio1", 911, R8A774E1_CLK_S3D4),
DEF_MOD("gpio0", 912, R8A774E1_CLK_S3D4),
DEF_MOD("can-fd", 914, R8A774E1_CLK_S3D2),
DEF_MOD("can-if1", 915, R8A774E1_CLK_S3D4),
DEF_MOD("can-if0", 916, R8A774E1_CLK_S3D4),
DEF_MOD("rpc-if", 917, R8A774E1_CLK_RPCD2),
DEF_MOD("i2c6", 918, R8A774E1_CLK_S0D6),
DEF_MOD("i2c5", 919, R8A774E1_CLK_S0D6),
DEF_MOD("adg", 922, R8A774E1_CLK_S0D1),
DEF_MOD("i2c-dvfs", 926, R8A774E1_CLK_CP),
DEF_MOD("i2c4", 927, R8A774E1_CLK_S0D6),
DEF_MOD("i2c3", 928, R8A774E1_CLK_S0D6),
DEF_MOD("i2c2", 929, R8A774E1_CLK_S3D2),
DEF_MOD("i2c1", 930, R8A774E1_CLK_S3D2),
DEF_MOD("i2c0", 931, R8A774E1_CLK_S3D2),
DEF_MOD("ssi-all", 1005, R8A774E1_CLK_S3D4),
DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
DEF_MOD("scu-all", 1017, R8A774E1_CLK_S3D4),
DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
};
static const unsigned int r8a774e1_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
/*
* CPG Clock Data
*/
/*
* MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 OSC
* 14 13 19 17 (MHz)
*-------------------------------------------------------------------------
* 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 /16
* 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 /16
* 0 0 1 0 Prohibited setting
* 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 /16
* 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 /19
* 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 /19
* 0 1 1 0 Prohibited setting
* 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 /19
* 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 /24
* 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 /24
* 1 0 1 0 Prohibited setting
* 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 /24
* 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 /32
* 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 /32
* 1 1 1 0 Prohibited setting
* 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 /32
*/
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
(((md) & BIT(13)) >> 11) | \
(((md) & BIT(19)) >> 18) | \
(((md) & BIT(17)) >> 17))
static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
/* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
{ 1, 192, 1, 192, 1, 16, },
{ 1, 192, 1, 128, 1, 16, },
{ 0, /* Prohibited setting */ },
{ 1, 192, 1, 192, 1, 16, },
{ 1, 160, 1, 160, 1, 19, },
{ 1, 160, 1, 106, 1, 19, },
{ 0, /* Prohibited setting */ },
{ 1, 160, 1, 160, 1, 19, },
{ 1, 128, 1, 128, 1, 24, },
{ 1, 128, 1, 84, 1, 24, },
{ 0, /* Prohibited setting */ },
{ 1, 128, 1, 128, 1, 24, },
{ 2, 192, 1, 192, 1, 32, },
{ 2, 192, 1, 128, 1, 32, },
{ 0, /* Prohibited setting */ },
{ 2, 192, 1, 192, 1, 32, },
};
static int __init r8a774e1_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
u32 cpg_mode;
int error;
error = rcar_rst_read_mode_pins(&cpg_mode);
if (error)
return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
if (!cpg_pll_config->extal_div) {
dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
return -EINVAL;
}
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
}
const struct cpg_mssr_info r8a774e1_cpg_mssr_info __initconst = {
/* Core Clocks */
.core_clks = r8a774e1_core_clks,
.num_core_clks = ARRAY_SIZE(r8a774e1_core_clks),
.last_dt_core_clk = LAST_DT_CORE_CLK,
.num_total_core_clks = MOD_CLK_BASE,
/* Module Clocks */
.mod_clks = r8a774e1_mod_clks,
.num_mod_clks = ARRAY_SIZE(r8a774e1_mod_clks),
.num_hw_mod_clks = 12 * 32,
/* Critical Module Clocks */
.crit_mod_clks = r8a774e1_crit_mod_clks,
.num_crit_mod_clks = ARRAY_SIZE(r8a774e1_crit_mod_clks),
/* Callbacks */
.init = r8a774e1_cpg_mssr_init,
.cpg_clk_register = rcar_gen3_cpg_clk_register,
};

View File

@@ -287,10 +287,10 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
}; };
static const unsigned int r8a7795_crit_mod_clks[] __initconst = { static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };
/* /*
* CPG Clock Data * CPG Clock Data
*/ */

View File

@@ -262,10 +262,10 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = {
}; };
static const unsigned int r8a7796_crit_mod_clks[] __initconst = { static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };
/* /*
* CPG Clock Data * CPG Clock Data
*/ */

View File

@@ -263,6 +263,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
}; };
static const unsigned int r8a77965_crit_mod_clks[] __initconst = { static const unsigned int r8a77965_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };

View File

@@ -165,10 +165,10 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = {
}; };
static const unsigned int r8a77970_crit_mod_clks[] __initconst = { static const unsigned int r8a77970_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };
/* /*
* CPG Clock Data * CPG Clock Data
*/ */

View File

@@ -180,10 +180,10 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = {
}; };
static const unsigned int r8a77980_crit_mod_clks[] __initconst = { static const unsigned int r8a77980_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };
/* /*
* CPG Clock Data * CPG Clock Data
*/ */

View File

@@ -245,6 +245,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
}; };
static const unsigned int r8a77990_crit_mod_clks[] __initconst = { static const unsigned int r8a77990_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };

View File

@@ -183,10 +183,10 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
}; };
static const unsigned int r8a77995_crit_mod_clks[] __initconst = { static const unsigned int r8a77995_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */ MOD_CLK_ID(408), /* INTC-AP (GIC) */
}; };
/* /*
* CPG Clock Data * CPG Clock Data
*/ */

View File

@@ -416,14 +416,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
init.name = mod->name; init.name = mod->name;
init.ops = &cpg_mstp_clock_ops; init.ops = &cpg_mstp_clock_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
for (i = 0; i < info->num_crit_mod_clks; i++)
if (id == info->crit_mod_clks[i]) {
dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
mod->name);
init.flags |= CLK_IS_CRITICAL;
break;
}
parent_name = __clk_get_name(parent); parent_name = __clk_get_name(parent);
init.parent_names = &parent_name; init.parent_names = &parent_name;
init.num_parents = 1; init.num_parents = 1;
@@ -432,6 +424,15 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
clock->priv = priv; clock->priv = priv;
clock->hw.init = &init; clock->hw.init = &init;
for (i = 0; i < info->num_crit_mod_clks; i++)
if (id == info->crit_mod_clks[i] &&
cpg_mstp_clock_is_enabled(&clock->hw)) {
dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
mod->name);
init.flags |= CLK_IS_CRITICAL;
break;
}
clk = clk_register(NULL, &clock->hw); clk = clk_register(NULL, &clock->hw);
if (IS_ERR(clk)) if (IS_ERR(clk))
goto fail; goto fail;
@@ -720,6 +721,12 @@ static const struct of_device_id cpg_mssr_match[] = {
.data = &r8a774c0_cpg_mssr_info, .data = &r8a774c0_cpg_mssr_info,
}, },
#endif #endif
#ifdef CONFIG_CLK_R8A774E1
{
.compatible = "renesas,r8a774e1-cpg-mssr",
.data = &r8a774e1_cpg_mssr_info,
},
#endif
#ifdef CONFIG_CLK_R8A7790 #ifdef CONFIG_CLK_R8A7790
{ {
.compatible = "renesas,r8a7790-cpg-mssr", .compatible = "renesas,r8a7790-cpg-mssr",

View File

@@ -162,6 +162,7 @@ extern const struct cpg_mssr_info r8a77470_cpg_mssr_info;
extern const struct cpg_mssr_info r8a774a1_cpg_mssr_info; extern const struct cpg_mssr_info r8a774a1_cpg_mssr_info;
extern const struct cpg_mssr_info r8a774b1_cpg_mssr_info; extern const struct cpg_mssr_info r8a774b1_cpg_mssr_info;
extern const struct cpg_mssr_info r8a774c0_cpg_mssr_info; extern const struct cpg_mssr_info r8a774c0_cpg_mssr_info;
extern const struct cpg_mssr_info r8a774e1_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7790_cpg_mssr_info; extern const struct cpg_mssr_info r8a7790_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7791_cpg_mssr_info; extern const struct cpg_mssr_info r8a7791_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; extern const struct cpg_mssr_info r8a7792_cpg_mssr_info;

View File

@@ -252,7 +252,7 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
0, 0, 0, 0, 0x30, 0, 0}, 0, 0, 0, 0, 0x30, 0, 0},
{ AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24, { AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24,
0, 0, 0, 0, 0, 0, 4}, 0, 0, 0, 0, 0, 0, 4},
{ AGILEX_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x24, { AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24,
0, 0, 0, 0, 0, 0, 2}, 0, 0, 0, 0, 0, 0, 2},
{ AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24, { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24,
1, 0x44, 0, 2, 0, 0, 0}, 1, 0x44, 0, 2, 0, 0, 0},
@@ -294,8 +294,12 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
8, 0, 0, 0, 0, 0, 0}, 8, 0, 0, 0, 0, 0, 0},
{ AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
9, 0, 0, 0, 0, 0, 0}, 9, 0, 0, 0, 0, 0, 0},
{ AGILEX_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0x7C, { AGILEX_NAND_X_CLK, "nand_x_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
10, 0, 0, 0, 0, 0, 0}, 10, 0, 0, 0, 0, 0, 0},
{ AGILEX_NAND_CLK, "nand_clk", "nand_x_clk", NULL, 1, 0, 0x7C,
10, 0, 0, 0, 0, 0, 4},
{ AGILEX_NAND_ECC_CLK, "nand_ecc_clk", "nand_x_clk", NULL, 1, 0, 0x7C,
10, 0, 0, 0, 0, 0, 4},
}; };
static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,

View File

@@ -5,7 +5,7 @@
* Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
* *
* Support functions for calculating clocks/divisors for the ICST307 * Support functions for calculating clocks/divisors for the ICST307
* clock generators. See http://www.idt.com/ for more information * clock generators. See https://www.idt.com/ for more information
* on these devices. * on these devices.
* *
* This is an almost identical implementation to the ICST525 clock generator. * This is an almost identical implementation to the ICST525 clock generator.

View File

@@ -3,7 +3,7 @@
* Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
* *
* Support functions for calculating clocks/divisors for the ICST * Support functions for calculating clocks/divisors for the ICST
* clock generators. See http://www.idt.com/ for more information * clock generators. See https://www.idt.com/ for more information
* on these devices. * on these devices.
*/ */
#ifndef ICST_H #ifndef ICST_H

View File

@@ -211,6 +211,20 @@ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
static void rpi_register_clk_driver(struct device *dev) static void rpi_register_clk_driver(struct device *dev)
{ {
struct device_node *firmware;
/*
* Earlier DTs don't have a node for the firmware clocks but
* rely on us creating a platform device by hand. If we do
* have a node for the firmware clocks, just bail out here.
*/
firmware = of_get_compatible_child(dev->of_node,
"raspberrypi,firmware-clocks");
if (firmware) {
of_node_put(firmware);
return;
}
rpi_clk = platform_device_register_data(dev, "raspberrypi-clk", rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
-1, NULL, 0); -1, NULL, 0);
} }

View File

@@ -82,6 +82,7 @@ config FSL_IMX8_DDR_PMU
config QCOM_L2_PMU config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU" bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI depends on ARCH_QCOM && ARM64 && ACPI
select QCOM_KRYO_L2_ACCESSORS
help help
Provides support for the L2 cache performance monitor unit (PMU) Provides support for the L2 cache performance monitor unit (PMU)
in Qualcomm Technologies processors. in Qualcomm Technologies processors.

View File

@@ -23,6 +23,7 @@
#include <asm/barrier.h> #include <asm/barrier.h>
#include <asm/local64.h> #include <asm/local64.h>
#include <asm/sysreg.h> #include <asm/sysreg.h>
#include <soc/qcom/kryo-l2-accessors.h>
#define MAX_L2_CTRS 9 #define MAX_L2_CTRS 9
@@ -79,8 +80,6 @@
#define L2_COUNTER_RELOAD BIT_ULL(31) #define L2_COUNTER_RELOAD BIT_ULL(31)
#define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63) #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
#define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE) #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
@@ -99,48 +98,7 @@
#define L2_EVENT_STREX 0x421 #define L2_EVENT_STREX 0x421
#define L2_EVENT_CLREX 0x422 #define L2_EVENT_CLREX 0x422
static DEFINE_RAW_SPINLOCK(l2_access_lock);
/**
* set_l2_indirect_reg: write value to an L2 register
* @reg: Address of L2 register.
* @value: Value to be written to register.
*
* Use architecturally required barriers for ordering between system register
* accesses
*/
static void set_l2_indirect_reg(u64 reg, u64 val)
{
unsigned long flags;
raw_spin_lock_irqsave(&l2_access_lock, flags);
write_sysreg_s(reg, L2CPUSRSELR_EL1);
isb();
write_sysreg_s(val, L2CPUSRDR_EL1);
isb();
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
}
/**
* get_l2_indirect_reg: read an L2 register value
* @reg: Address of L2 register.
*
* Use architecturally required barriers for ordering between system register
* accesses
*/
static u64 get_l2_indirect_reg(u64 reg)
{
u64 val;
unsigned long flags;
raw_spin_lock_irqsave(&l2_access_lock, flags);
write_sysreg_s(reg, L2CPUSRSELR_EL1);
isb();
val = read_sysreg_s(L2CPUSRDR_EL1);
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
return val;
}
struct cluster_pmu; struct cluster_pmu;
@@ -211,28 +169,28 @@ static inline struct cluster_pmu *get_cluster_pmu(
static void cluster_pmu_reset(void) static void cluster_pmu_reset(void)
{ {
/* Reset all counters */ /* Reset all counters */
set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL); kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask); kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask); kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask); kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
} }
static inline void cluster_pmu_enable(void) static inline void cluster_pmu_enable(void)
{ {
set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE); kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
} }
static inline void cluster_pmu_disable(void) static inline void cluster_pmu_disable(void)
{ {
set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE); kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
} }
static inline void cluster_pmu_counter_set_value(u32 idx, u64 value) static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
{ {
if (idx == l2_cycle_ctr_idx) if (idx == l2_cycle_ctr_idx)
set_l2_indirect_reg(L2PMCCNTR, value); kryo_l2_set_indirect_reg(L2PMCCNTR, value);
else else
set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value); kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
} }
static inline u64 cluster_pmu_counter_get_value(u32 idx) static inline u64 cluster_pmu_counter_get_value(u32 idx)
@@ -240,46 +198,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx)
u64 value; u64 value;
if (idx == l2_cycle_ctr_idx) if (idx == l2_cycle_ctr_idx)
value = get_l2_indirect_reg(L2PMCCNTR); value = kryo_l2_get_indirect_reg(L2PMCCNTR);
else else
value = get_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx)); value = kryo_l2_get_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx));
return value; return value;
} }
static inline void cluster_pmu_counter_enable(u32 idx) static inline void cluster_pmu_counter_enable(u32 idx)
{ {
set_l2_indirect_reg(L2PMCNTENSET, idx_to_reg_bit(idx)); kryo_l2_set_indirect_reg(L2PMCNTENSET, idx_to_reg_bit(idx));
} }
static inline void cluster_pmu_counter_disable(u32 idx) static inline void cluster_pmu_counter_disable(u32 idx)
{ {
set_l2_indirect_reg(L2PMCNTENCLR, idx_to_reg_bit(idx)); kryo_l2_set_indirect_reg(L2PMCNTENCLR, idx_to_reg_bit(idx));
} }
static inline void cluster_pmu_counter_enable_interrupt(u32 idx) static inline void cluster_pmu_counter_enable_interrupt(u32 idx)
{ {
set_l2_indirect_reg(L2PMINTENSET, idx_to_reg_bit(idx)); kryo_l2_set_indirect_reg(L2PMINTENSET, idx_to_reg_bit(idx));
} }
static inline void cluster_pmu_counter_disable_interrupt(u32 idx) static inline void cluster_pmu_counter_disable_interrupt(u32 idx)
{ {
set_l2_indirect_reg(L2PMINTENCLR, idx_to_reg_bit(idx)); kryo_l2_set_indirect_reg(L2PMINTENCLR, idx_to_reg_bit(idx));
} }
static inline void cluster_pmu_set_evccntcr(u32 val) static inline void cluster_pmu_set_evccntcr(u32 val)
{ {
set_l2_indirect_reg(L2PMCCNTCR, val); kryo_l2_set_indirect_reg(L2PMCCNTCR, val);
} }
static inline void cluster_pmu_set_evcntcr(u32 ctr, u32 val) static inline void cluster_pmu_set_evcntcr(u32 ctr, u32 val)
{ {
set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTCR, ctr), val); kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTCR, ctr), val);
} }
static inline void cluster_pmu_set_evtyper(u32 ctr, u32 val) static inline void cluster_pmu_set_evtyper(u32 ctr, u32 val)
{ {
set_l2_indirect_reg(reg_idx(IA_L2PMXEVTYPER, ctr), val); kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVTYPER, ctr), val);
} }
static void cluster_pmu_set_resr(struct cluster_pmu *cluster, static void cluster_pmu_set_resr(struct cluster_pmu *cluster,
@@ -295,11 +253,11 @@ static void cluster_pmu_set_resr(struct cluster_pmu *cluster,
spin_lock_irqsave(&cluster->pmu_lock, flags); spin_lock_irqsave(&cluster->pmu_lock, flags);
resr_val = get_l2_indirect_reg(L2PMRESR); resr_val = kryo_l2_get_indirect_reg(L2PMRESR);
resr_val &= ~(L2PMRESR_GROUP_MASK << shift); resr_val &= ~(L2PMRESR_GROUP_MASK << shift);
resr_val |= field; resr_val |= field;
resr_val |= L2PMRESR_EN; resr_val |= L2PMRESR_EN;
set_l2_indirect_reg(L2PMRESR, resr_val); kryo_l2_set_indirect_reg(L2PMRESR, resr_val);
spin_unlock_irqrestore(&cluster->pmu_lock, flags); spin_unlock_irqrestore(&cluster->pmu_lock, flags);
} }
@@ -315,14 +273,14 @@ static inline void cluster_pmu_set_evfilter_sys_mode(u32 ctr)
L2PMXEVFILTER_ORGFILTER_IDINDEP | L2PMXEVFILTER_ORGFILTER_IDINDEP |
L2PMXEVFILTER_ORGFILTER_ALL; L2PMXEVFILTER_ORGFILTER_ALL;
set_l2_indirect_reg(reg_idx(IA_L2PMXEVFILTER, ctr), val); kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVFILTER, ctr), val);
} }
static inline u32 cluster_pmu_getreset_ovsr(void) static inline u32 cluster_pmu_getreset_ovsr(void)
{ {
u32 result = get_l2_indirect_reg(L2PMOVSSET); u32 result = kryo_l2_get_indirect_reg(L2PMOVSSET);
set_l2_indirect_reg(L2PMOVSCLR, result); kryo_l2_set_indirect_reg(L2PMOVSCLR, result);
return result; return result;
} }
@@ -767,7 +725,7 @@ static int get_num_counters(void)
{ {
int val; int val;
val = get_l2_indirect_reg(L2PMCR); val = kryo_l2_get_indirect_reg(L2PMCR);
/* /*
* Read number of counters from L2PMCR and add 1 * Read number of counters from L2PMCR and add 1

View File

@@ -53,6 +53,10 @@ config QCOM_LLCC
SDM845. This provides interfaces to clients that use the LLCC. SDM845. This provides interfaces to clients that use the LLCC.
Say yes here to enable LLCC slice driver. Say yes here to enable LLCC slice driver.
config QCOM_KRYO_L2_ACCESSORS
bool
depends on ARCH_QCOM && ARM64 || COMPILE_TEST
config QCOM_MDT_LOADER config QCOM_MDT_LOADER
tristate tristate
select QCOM_SCM select QCOM_SCM

View File

@@ -24,3 +24,4 @@ obj-$(CONFIG_QCOM_APR) += apr.o
obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o

View File

@@ -0,0 +1,57 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
#include <linux/spinlock.h>
#include <asm/barrier.h>
#include <asm/sysreg.h>
#include <soc/qcom/kryo-l2-accessors.h>
#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
static DEFINE_RAW_SPINLOCK(l2_access_lock);
/**
* kryo_l2_set_indirect_reg() - write value to an L2 register
* @reg: Address of L2 register.
* @value: Value to be written to register.
*
* Use architecturally required barriers for ordering between system register
* accesses, and system registers with respect to device memory
*/
void kryo_l2_set_indirect_reg(u64 reg, u64 val)
{
unsigned long flags;
raw_spin_lock_irqsave(&l2_access_lock, flags);
write_sysreg_s(reg, L2CPUSRSELR_EL1);
isb();
write_sysreg_s(val, L2CPUSRDR_EL1);
isb();
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
}
EXPORT_SYMBOL(kryo_l2_set_indirect_reg);
/**
* kryo_l2_get_indirect_reg() - read an L2 register value
* @reg: Address of L2 register.
*
* Use architecturally required barriers for ordering between system register
* accesses, and system registers with respect to device memory
*/
u64 kryo_l2_get_indirect_reg(u64 reg)
{
u64 val;
unsigned long flags;
raw_spin_lock_irqsave(&l2_access_lock, flags);
write_sysreg_s(reg, L2CPUSRSELR_EL1);
isb();
val = read_sysreg_s(L2CPUSRDR_EL1);
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
return val;
}
EXPORT_SYMBOL(kryo_l2_get_indirect_reg);

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* This file defines field values used by the versaclock 6 family
* for defining output type
*/
#define VC5_LVPECL 0
#define VC5_CMOS 1
#define VC5_HCSL33 2
#define VC5_LVDS 3
#define VC5_CMOS2 4
#define VC5_CMOSD 5
#define VC5_HCSL25 6

View File

@@ -65,6 +65,8 @@
#define AGILEX_SDMMC_CLK 50 #define AGILEX_SDMMC_CLK 50
#define AGILEX_SPI_M_CLK 51 #define AGILEX_SPI_M_CLK 51
#define AGILEX_USB_CLK 52 #define AGILEX_USB_CLK 52
#define AGILEX_NUM_CLKS 53 #define AGILEX_NAND_X_CLK 53
#define AGILEX_NAND_ECC_CLK 54
#define AGILEX_NUM_CLKS 55
#endif /* __AGILEX_CLOCK_H */ #endif /* __AGILEX_CLOCK_H */

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM3368_H
#define __DT_BINDINGS_CLOCK_BCM3368_H
#define BCM3368_CLK_MAC 3
#define BCM3368_CLK_TC 5
#define BCM3368_CLK_US_TOP 6
#define BCM3368_CLK_DS_TOP 7
#define BCM3368_CLK_ACM 8
#define BCM3368_CLK_SPI 9
#define BCM3368_CLK_USBS 10
#define BCM3368_CLK_BMU 11
#define BCM3368_CLK_PCM 12
#define BCM3368_CLK_NTP 13
#define BCM3368_CLK_ACP_B 14
#define BCM3368_CLK_ACP_A 15
#define BCM3368_CLK_EMUSB 17
#define BCM3368_CLK_ENET0 18
#define BCM3368_CLK_ENET1 19
#define BCM3368_CLK_USBSU 20
#define BCM3368_CLK_EPHY 21
#endif /* __DT_BINDINGS_CLOCK_BCM3368_H */

View File

@@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM6318_H
#define __DT_BINDINGS_CLOCK_BCM6318_H
#define BCM6318_CLK_ADSL_ASB 0
#define BCM6318_CLK_USB_ASB 1
#define BCM6318_CLK_MIPS_ASB 2
#define BCM6318_CLK_PCIE_ASB 3
#define BCM6318_CLK_PHYMIPS_ASB 4
#define BCM6318_CLK_ROBOSW_ASB 5
#define BCM6318_CLK_SAR_ASB 6
#define BCM6318_CLK_SDR_ASB 7
#define BCM6318_CLK_SWREG_ASB 8
#define BCM6318_CLK_PERIPH_ASB 9
#define BCM6318_CLK_CPUBUS160 10
#define BCM6318_CLK_ADSL 11
#define BCM6318_CLK_SAR125 12
#define BCM6318_CLK_MIPS 13
#define BCM6318_CLK_PCIE 14
#define BCM6318_CLK_ROBOSW250 16
#define BCM6318_CLK_ROBOSW025 17
#define BCM6318_CLK_SDR 19
#define BCM6318_CLK_USBD 20
#define BCM6318_CLK_HSSPI 25
#define BCM6318_CLK_PCIE25 27
#define BCM6318_CLK_PHYMIPS 28
#define BCM6318_CLK_AFE 29
#define BCM6318_CLK_QPROC 30
#define BCM6318_UCLK_ADSL 0
#define BCM6318_UCLK_ARB 1
#define BCM6318_UCLK_MIPS 2
#define BCM6318_UCLK_PCIE 3
#define BCM6318_UCLK_PERIPH 4
#define BCM6318_UCLK_PHYMIPS 5
#define BCM6318_UCLK_ROBOSW 6
#define BCM6318_UCLK_SAR 7
#define BCM6318_UCLK_SDR 8
#define BCM6318_UCLK_USB 9
#endif /* __DT_BINDINGS_CLOCK_BCM6318_H */

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM63268_H
#define __DT_BINDINGS_CLOCK_BCM63268_H
#define BCM63268_CLK_DIS_GLESS 0
#define BCM63268_CLK_VDSL_QPROC 1
#define BCM63268_CLK_VDSL_AFE 2
#define BCM63268_CLK_VDSL 3
#define BCM63268_CLK_MIPS 4
#define BCM63268_CLK_WLAN_OCP 5
#define BCM63268_CLK_DECT 6
#define BCM63268_CLK_FAP0 7
#define BCM63268_CLK_FAP1 8
#define BCM63268_CLK_SAR 9
#define BCM63268_CLK_ROBOSW 10
#define BCM63268_CLK_PCM 11
#define BCM63268_CLK_USBD 12
#define BCM63268_CLK_USBH 13
#define BCM63268_CLK_IPSEC 14
#define BCM63268_CLK_SPI 15
#define BCM63268_CLK_HSSPI 16
#define BCM63268_CLK_PCIE 17
#define BCM63268_CLK_PHYMIPS 18
#define BCM63268_CLK_GMAC 19
#define BCM63268_CLK_NAND 20
#define BCM63268_CLK_TBUS 27
#define BCM63268_CLK_ROBOSW250 31
#endif /* __DT_BINDINGS_CLOCK_BCM63268_H */

View File

@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM6328_H
#define __DT_BINDINGS_CLOCK_BCM6328_H
#define BCM6328_CLK_PHYMIPS 0
#define BCM6328_CLK_ADSL_QPROC 1
#define BCM6328_CLK_ADSL_AFE 2
#define BCM6328_CLK_ADSL 3
#define BCM6328_CLK_MIPS 4
#define BCM6328_CLK_SAR 5
#define BCM6328_CLK_PCM 6
#define BCM6328_CLK_USBD 7
#define BCM6328_CLK_USBH 8
#define BCM6328_CLK_HSSPI 9
#define BCM6328_CLK_PCIE 10
#define BCM6328_CLK_ROBOSW 11
#endif /* __DT_BINDINGS_CLOCK_BCM6328_H */

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM6358_H
#define __DT_BINDINGS_CLOCK_BCM6358_H
#define BCM6358_CLK_ENET 4
#define BCM6358_CLK_ADSLPHY 5
#define BCM6358_CLK_PCM 8
#define BCM6358_CLK_SPI 9
#define BCM6358_CLK_USBS 10
#define BCM6358_CLK_SAR 11
#define BCM6358_CLK_EMUSB 17
#define BCM6358_CLK_ENET0 18
#define BCM6358_CLK_ENET1 19
#define BCM6358_CLK_USBSU 20
#define BCM6358_CLK_EPHY 21
#endif /* __DT_BINDINGS_CLOCK_BCM6358_H */

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM6362_H
#define __DT_BINDINGS_CLOCK_BCM6362_H
#define BCM6362_CLK_ADSL_QPROC 1
#define BCM6362_CLK_ADSL_AFE 2
#define BCM6362_CLK_ADSL 3
#define BCM6362_CLK_MIPS 4
#define BCM6362_CLK_WLAN_OCP 5
#define BCM6362_CLK_SWPKT_USB 7
#define BCM6362_CLK_SWPKT_SAR 8
#define BCM6362_CLK_SAR 9
#define BCM6362_CLK_ROBOSW 10
#define BCM6362_CLK_PCM 11
#define BCM6362_CLK_USBD 12
#define BCM6362_CLK_USBH 13
#define BCM6362_CLK_IPSEC 14
#define BCM6362_CLK_SPI 15
#define BCM6362_CLK_HSSPI 16
#define BCM6362_CLK_PCIE 17
#define BCM6362_CLK_FAP 18
#define BCM6362_CLK_PHYMIPS 19
#define BCM6362_CLK_NAND 20
#endif /* __DT_BINDINGS_CLOCK_BCM6362_H */

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __DT_BINDINGS_CLOCK_BCM6368_H
#define __DT_BINDINGS_CLOCK_BCM6368_H
#define BCM6368_CLK_VDSL_QPROC 2
#define BCM6368_CLK_VDSL_AFE 3
#define BCM6368_CLK_VDSL_BONDING 4
#define BCM6368_CLK_VDSL 5
#define BCM6368_CLK_PHYMIPS 6
#define BCM6368_CLK_SWPKT_USB 7
#define BCM6368_CLK_SWPKT_SAR 8
#define BCM6368_CLK_SPI 9
#define BCM6368_CLK_USBD 10
#define BCM6368_CLK_SAR 11
#define BCM6368_CLK_ROBOSW 12
#define BCM6368_CLK_UTOPIA 13
#define BCM6368_CLK_PCM 14
#define BCM6368_CLK_USBH 15
#define BCM6368_CLK_DIS_GLESS 16
#define BCM6368_CLK_NAND 17
#define BCM6368_CLK_IPSEC 18
#endif /* __DT_BINDINGS_CLOCK_BCM6368_H */

View File

@@ -145,5 +145,7 @@
#define CLKID_CPU3_CLK 255 #define CLKID_CPU3_CLK 255
#define CLKID_SPICC0_SCLK 258 #define CLKID_SPICC0_SCLK 258
#define CLKID_SPICC1_SCLK 261 #define CLKID_SPICC1_SCLK 261
#define CLKID_NNA_AXI_CLK 264
#define CLKID_NNA_CORE_CLK 267
#endif /* __G12A_CLKC_H */ #endif /* __G12A_CLKC_H */

View File

@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
#ifndef _DT_BINDINGS_CLOCK_QCA_APSS_IPQ6018_H
#define _DT_BINDINGS_CLOCK_QCA_APSS_IPQ6018_H
#define APCS_ALIAS0_CLK_SRC 0
#define APCS_ALIAS0_CORE_CLK 1
#endif

View File

@@ -230,6 +230,9 @@
#define GCC_GP1_CLK 221 #define GCC_GP1_CLK 221
#define GCC_GP2_CLK 222 #define GCC_GP2_CLK 222
#define GCC_GP3_CLK 223 #define GCC_GP3_CLK 223
#define GCC_PCIE0_AXI_S_BRIDGE_CLK 224
#define GCC_PCIE0_RCHNG_CLK_SRC 225
#define GCC_PCIE0_RCHNG_CLK 226
#define GCC_BLSP1_BCR 0 #define GCC_BLSP1_BCR 0
#define GCC_BLSP1_QUP1_BCR 1 #define GCC_BLSP1_QUP1_BCR 1
@@ -362,5 +365,6 @@
#define GCC_PCIE1_AXI_SLAVE_ARES 128 #define GCC_PCIE1_AXI_SLAVE_ARES 128
#define GCC_PCIE1_AHB_ARES 129 #define GCC_PCIE1_AHB_ARES 129
#define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130
#define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131
#endif #endif

View File

@@ -133,5 +133,21 @@
#define RPM_SMD_RF_CLK3_A 87 #define RPM_SMD_RF_CLK3_A 87
#define RPM_SMD_RF_CLK3_PIN 88 #define RPM_SMD_RF_CLK3_PIN 88
#define RPM_SMD_RF_CLK3_A_PIN 89 #define RPM_SMD_RF_CLK3_A_PIN 89
#define RPM_SMD_MMSSNOC_AXI_CLK 90
#define RPM_SMD_MMSSNOC_AXI_CLK_A 91
#define RPM_SMD_CNOC_PERIPH_CLK 92
#define RPM_SMD_CNOC_PERIPH_A_CLK 93
#define RPM_SMD_LN_BB_CLK3 94
#define RPM_SMD_LN_BB_CLK3_A 95
#define RPM_SMD_LN_BB_CLK1_PIN 96
#define RPM_SMD_LN_BB_CLK1_A_PIN 97
#define RPM_SMD_LN_BB_CLK2_PIN 98
#define RPM_SMD_LN_BB_CLK2_A_PIN 99
#define RPM_SMD_SYSMMNOC_CLK 100
#define RPM_SMD_SYSMMNOC_A_CLK 101
#define RPM_SMD_CE2_CLK 102
#define RPM_SMD_CE2_A_CLK 103
#define RPM_SMD_CE3_CLK 104
#define RPM_SMD_CE3_A_CLK 105
#endif #endif

View File

@@ -189,7 +189,7 @@ struct clk_duty {
* and >= numerator) Return 0 on success, otherwise -EERROR. * and >= numerator) Return 0 on success, otherwise -EERROR.
* *
* @init: Perform platform-specific initialization magic. * @init: Perform platform-specific initialization magic.
* This is not not used by any of the basic clock types. * This is not used by any of the basic clock types.
* This callback exist for HW which needs to perform some * This callback exist for HW which needs to perform some
* initialisation magic for CCF to get an accurate view of the * initialisation magic for CCF to get an accurate view of the
* clock. It may also be used dynamic resource allocation is * clock. It may also be used dynamic resource allocation is

View File

@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
#ifndef __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H
#define __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H
void kryo_l2_set_indirect_reg(u64 reg, u64 val);
u64 kryo_l2_get_indirect_reg(u64 reg);
#endif