Commit 28b9aaac authored by Linus Torvalds's avatar Linus Torvalds

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

Pull clk updates from Stephen Boyd:
 "This is all driver updates, the majority of which is a bunch of new
  Qualcomm clk drivers that dominate the diffstat because we add support
  for six SoCs from that particular vendor.

  The other big change is the removal of various clk drivers that are no
  longer used now that the kernel is dropping support for those SoCs.

  Beyond that there's the usual non-critical fixes for existing drivers
  and a good number of patches from Lee Jones that cleanup a bunch of
  W=1 enabled builds.

  Removed Drivers:
   - Remove efm32 clk driver
   - Remove tango4 clk driver
   - Remove zte zx clk driver
   - Remove sirf prima2/atlast clk drivers
   - Remove u300 clk driver

  New Drivers:
   - PLL support on MStar/SigmaStar ARMv7 SoCs
   - CPU clks for Qualcomm SDX55
   - GCC and RPMh clks for Qualcomm SC8180x and SC7280 SoCs
   - GCC clks for Qualcomm SM8350
   - GPU clks for Qualcomm SDM660/SDM630

  Updates:
   - Video clk fixups on Qualcomm SM8250
   - Improvements for multimedia clks on Qualcomm MSM8998
   - Fix many warnings with W=1 enabled builds under drivers/clk/
   - Support crystal load capacitance for Versaclock VC5
   - Add a "skip recall" DT binding for Silicon Labs' si570 to avoid
     glitches at boot
   - Convert Xilinx VCU clk driver to a proper clk provider driver
   - Expose Xilinx ZynqMP clk driver to more platforms
   - Amlogic pll driver fixup
   - Amlogic meson8b clock controller dt support clean up
   - Remove mipi clk from the Amlogic axg clock controller
   - New Rockchip rk3368 clock ids related to camera input
   - Use pr_notice() instead of pr_warn() on i.MX6Q pre-boot ldb_di_clk
     reparenting
   - A series from Liu Ying that adds some SCU clocks support for
     i.MX8qxp DC0/MIPI-LVDS subsystems
   - A series from Lucas Stach that adds PLL monitor clocks for i.MX8MQ,
     and clkout1/2 support for i.MX8MM/MN
   - Add I2c and Ethernet (RAVB) clocks on Renesas R-Car V3U
   - Add timer (TMU) clocks on most Renesas R-Car Gen3 SoCs
   - Add video-related (FCPVD/VSPD/VSPX), watchdog (RWDT), serial
     (HSCIF), pincontrol/GPIO (PFC/GPIO), SPI (MSIOF), SDHI, and DMA
     (SYS-DMAC) clocks on Renesas R-Car V3U
   - Add support for the USB 2.0 clock selector on Renesas RZ/G2 SoCs
   - Allwinner H616 SoC clk support"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (171 commits)
  clk: mstar: msc313-mpll: Fix format specifier
  clk: mstar: Allow MStar clk drivers to be compile tested
  clk: qoriq: use macros to generate pll_mask
  clk: qcom: Add Global Clock controller (GCC) driver for SC7280
  dt-bindings: clock: Add SC7280 GCC clock binding
  clk: qcom: rpmh: Add support for RPMH clocks on SC7280
  dt-bindings: clock: Add RPMHCC bindings for SC7280
  clk: qcom: gcc-sm8350: add gdsc
  dt-bindings: clock: Add QCOM SDM630 and SDM660 graphics clock bindings
  clk: qcom: Add SDM660 GPU Clock Controller (GPUCC) driver
  clk: qcom: mmcc-msm8996: Migrate gfx3d clock to clk_rcg2_gfx3d
  clk: qcom: rcg2: Stop hardcoding gfx3d pingpong parent numbers
  dt-bindings: clock: Add support for the SDM630 and SDM660 mmcc
  clk: qcom: Add SDM660 Multimedia Clock Controller (MMCC) driver
  clk: qcom: gcc-sdm660: Mark GPU CFG AHB clock as critical
  clk: qcom: gcc-sdm660: Mark MMSS NoC CFG AHB clock as critical
  clk: qcom: gpucc-msm8998: Allow fabia gpupll0 rate setting
  clk: qcom: gpucc-msm8998: Add resets, cxc, fix flags on gpu_gx_gdsc
  clk: qcom: gdsc: Implement NO_RET_PERIPH flag
  clk: mstar: MStar/SigmaStar MPLL driver
  ...
parents 5d26c176 4d5c4ae3
......@@ -20,6 +20,7 @@ properties:
compatible:
enum:
- adi,axi-clkgen-2.00.a
- adi,zynqmp-axi-clkgen-2.00.a
clocks:
description:
......
......@@ -41,6 +41,8 @@ properties:
- allwinner,sun50i-h5-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h6-r-ccu
- allwinner,sun50i-h616-ccu
- allwinner,sun50i-h616-r-ccu
- allwinner,suniv-f1c100s-ccu
- nextthing,gr8-ccu
......@@ -82,6 +84,7 @@ if:
- allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-r-ccu
- allwinner,sun50i-h6-r-ccu
- allwinner,sun50i-h616-r-ccu
then:
properties:
......@@ -100,6 +103,7 @@ else:
enum:
- allwinner,sun50i-a100-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h616-ccu
then:
properties:
......
* Clock and reset bindings for CSR atlas7
Required properties:
- compatible: Should be "sirf,atlas7-car"
- reg: Address and length of the register set
- #clock-cells: Should be <1>
- #reset-cells: Should be <1>
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell.
The ID list atlas7_clks defined in drivers/clk/sirf/clk-atlas7.c
The reset consumer should specify the desired reset by having the reset
ID in its "reset" phandle cell.
The ID list atlas7_reset_unit defined in drivers/clk/sirf/clk-atlas7.c
Examples: Clock and reset controller node:
car: clock-controller@18620000 {
compatible = "sirf,atlas7-car";
reg = <0x18620000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
Examples: Consumers using clock or reset:
timer@10dc0000 {
compatible = "sirf,macro-tick";
reg = <0x10dc0000 0x1000>;
clocks = <&car 54>;
interrupts = <0 0 0>,
<0 1 0>,
<0 2 0>,
<0 49 0>,
<0 50 0>,
<0 51 0>;
};
uart1: uart@18020000 {
cell-index = <1>;
compatible = "sirf,macro-uart";
reg = <0x18020000 0x1000>;
clocks = <&clks 95>;
interrupts = <0 18 0>;
fifosize = <32>;
};
vpp@13110000 {
compatible = "sirf,prima2-vpp";
reg = <0x13110000 0x10000>;
interrupts = <0 31 0>;
clocks = <&car 85>;
resets = <&car 29>;
};
......@@ -59,6 +59,12 @@ properties:
minItems: 1
maxItems: 2
idt,xtal-load-femtofarads:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 9000
maximum: 22760
description: Optional load capacitor for XTAL1 and XTAL2
patternProperties:
"^OUT[1-4]$":
type: object
......
......@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Clock bindings for Freescale i.MX27
maintainers:
- Fabio Estevam <fabio.estevam@nxp.com>
- Fabio Estevam <festevam@gmail.com>
description: |
The clock consumer should specify the desired clock by having the clock
......
......@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Clock bindings for Freescale i.MX31
maintainers:
- Fabio Estevam <fabio.estevam@nxp.com>
- Fabio Estevam <festevam@gmail.com>
description: |
The clock consumer should specify the desired clock by having the clock
......
......@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Clock bindings for Freescale i.MX5
maintainers:
- Fabio Estevam <fabio.estevam@nxp.com>
- Fabio Estevam <festevam@gmail.com>
description: |
The clock consumer should specify the desired clock by having the clock
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/intel,easic-n5x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel SoCFPGA eASIC N5X platform clock controller binding
maintainers:
- Dinh Nguyen <dinguyen@kernel.org>
description:
The Intel eASIC N5X Clock controller is an integrated clock controller, which
generates and supplies to all modules.
properties:
compatible:
const: intel,easic-n5x-clkmgr
'#clock-cells':
const: 1
reg:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
# Clock controller node:
- |
clkmgr: clock-controller@ffd10000 {
compatible = "intel,easic-n5x-clkmgr";
reg = <0xffd10000 0x1000>;
clocks = <&osc1>;
#clock-cells = <1>;
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/mstar,msc313-mpll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MStar/Sigmastar MSC313 MPLL
maintainers:
- Daniel Palmer <daniel@thingy.jp>
description: |
The MStar/SigmaStar MSC313 and later ARMv7 chips have an MPLL block that
takes the external xtal input and multiplies it to create a high
frequency clock and divides that down into a number of clocks that
peripherals use.
properties:
compatible:
const: mstar,msc313-mpll
"#clock-cells":
const: 1
clocks:
maxItems: 1
reg:
maxItems: 1
required:
- compatible
- "#clock-cells"
- clocks
- reg
additionalProperties: false
examples:
- |
mpll@206000 {
compatible = "mstar,msc313-mpll";
reg = <0x206000 0x200>;
#clock-cells = <1>;
clocks = <&xtal>;
};
* Clock bindings for CSR SiRFprimaII
Required properties:
- compatible: Should be "sirf,prima2-clkc"
- reg: Address and length of the register set
- interrupts: Should contain clock controller interrupt
- #clock-cells: Should be <1>
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. The following is a full list of prima2
clocks and IDs.
Clock ID
---------------------------
rtc 0
osc 1
pll1 2
pll2 3
pll3 4
mem 5
sys 6
security 7
dsp 8
gps 9
mf 10
io 11
cpu 12
uart0 13
uart1 14
uart2 15
tsc 16
i2c0 17
i2c1 18
spi0 19
spi1 20
pwmc 21
efuse 22
pulse 23
dmac0 24
dmac1 25
nand 26
audio 27
usp0 28
usp1 29
usp2 30
vip 31
gfx 32
mm 33
lcd 34
vpp 35
mmc01 36
mmc23 37
mmc45 38
usbpll 39
usb0 40
usb1 41
Examples:
clks: clock-controller@88000000 {
compatible = "sirf,prima2-clkc";
reg = <0x88000000 0x1000>;
interrupts = <3>;
#clock-cells = <1>;
};
i2c0: i2c@b00e0000 {
cell-index = <0>;
compatible = "sirf,prima2-i2c";
reg = <0xb00e0000 0x10000>;
interrupts = <24>;
clocks = <&clks 17>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,a7pll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm A7 PLL Binding
maintainers:
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
description:
The A7 PLL on the Qualcomm platforms like SDX55 is used to provide high
frequency clock to the CPU.
properties:
compatible:
enum:
- qcom,sdx55-a7pll
reg:
maxItems: 1
'#clock-cells':
const: 0
clocks:
items:
- description: board XO clock
clock-names:
items:
- const: bi_tcxo
required:
- compatible
- reg
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
a7pll: clock@17808000 {
compatible = "qcom,sdx55-a7pll";
reg = <0x17808000 0x1000>;
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "bi_tcxo";
#clock-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,gcc-sc7280.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller Binding for SC7280
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
Qualcomm global clock control module which supports the clocks, resets and
power domains on SC7280.
See also:
- dt-bindings/clock/qcom,gcc-sc7280.h
properties:
compatible:
const: qcom,gcc-sc7280
clocks:
items:
- description: Board XO source
- description: Board active XO source
- description: Sleep clock source
- description: PCIE-0 pipe clock source
- description: PCIE-1 pipe clock source
- description: USF phy rx symbol 0 clock source
- description: USF phy rx symbol 1 clock source
- description: USF phy tx symbol 0 clock source
- description: USB30 phy wrapper pipe clock source
clock-names:
items:
- const: bi_tcxo
- const: bi_tcxo_ao
- const: sleep_clk
- const: pcie_0_pipe_clk
- const: pcie_1_pipe_clk
- const: ufs_phy_rx_symbol_0_clk
- const: ufs_phy_rx_symbol_1_clk
- const: ufs_phy_tx_symbol_0_clk
- const: usb3_phy_wrapper_gcc_usb30_pipe_clk
'#clock-cells':
const: 1
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
reg:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- reg
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@100000 {
compatible = "qcom,gcc-sc7280";
reg = <0x00100000 0x1f0000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&rpmhcc RPMH_CXO_CLK_A>,
<&sleep_clk>,
<&pcie_0_pipe_clk>, <&pcie_1_pipe_clk>,
<&ufs_phy_rx_symbol_0_clk>, <&ufs_phy_rx_symbol_1_clk>,
<&ufs_phy_tx_symbol_0_clk>,
<&usb3_phy_wrapper_gcc_usb30_pipe_clk>;
clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk", "pcie_0_pipe_clk",
"pcie_1_pipe_clk", "ufs_phy_rx_symbol_0_clk",
"ufs_phy_rx_symbol_1_clk", "ufs_phy_tx_symbol_0_clk",
"usb3_phy_wrapper_gcc_usb30_pipe_clk";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,gcc-sc8180x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller Binding for SC8180x
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
Qualcomm global clock control module which supports the clocks, resets and
power domains on SC8180x.
See also:
- dt-bindings/clock/qcom,gcc-sc8180x.h
properties:
compatible:
const: qcom,gcc-sc8180x
clocks:
items:
- description: Board XO source
- description: Board active XO source
- description: Sleep clock source
clock-names:
items:
- const: bi_tcxo
- const: bi_tcxo_ao
- const: sleep_clk
'#clock-cells':
const: 1
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
reg:
maxItems: 1
protected-clocks:
description:
Protected clock specifier list as per common clock binding.
required:
- compatible
- clocks
- clock-names
- reg
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@100000 {
compatible = "qcom,gcc-sc8180x";
reg = <0x00100000 0x1f0000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&rpmhcc RPMH_CXO_CLK_A>,
<&sleep_clk>;
clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8350.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller Binding for SM8350
maintainers:
- Vinod Koul <vkoul@kernel.org>
description: |
Qualcomm global clock control module which supports the clocks, resets and
power domains on SM8350.
See also:
- dt-bindings/clock/qcom,gcc-sm8350.h
properties:
compatible:
const: qcom,gcc-sm8350
clocks:
items:
- description: Board XO source
- description: Sleep clock source
- description: PLL test clock source (Optional clock)
- description: PCIE 0 Pipe clock source (Optional clock)
- description: PCIE 1 Pipe clock source (Optional clock)
- description: UFS card Rx symbol 0 clock source (Optional clock)
- description: UFS card Rx symbol 1 clock source (Optional clock)
- description: UFS card Tx symbol 0 clock source (Optional clock)
- description: UFS phy Rx symbol 0 clock source (Optional clock)
- description: UFS phy Rx symbol 1 clock source (Optional clock)
- description: UFS phy Tx symbol 0 clock source (Optional clock)
- description: USB3 phy wrapper pipe clock source (Optional clock)
- description: USB3 phy sec pipe clock source (Optional clock)
minItems: 2
maxItems: 13
clock-names:
items:
- const: bi_tcxo
- const: sleep_clk
- const: core_bi_pll_test_se # Optional clock
- const: pcie_0_pipe_clk # Optional clock
- const: pcie_1_pipe_clk # Optional clock
- const: ufs_card_rx_symbol_0_clk # Optional clock
- const: ufs_card_rx_symbol_1_clk # Optional clock
- const: ufs_card_tx_symbol_0_clk # Optional clock
- const: ufs_phy_rx_symbol_0_clk # Optional clock
- const: ufs_phy_rx_symbol_1_clk # Optional clock
- const: ufs_phy_tx_symbol_0_clk # Optional clock
- const: usb3_phy_wrapper_gcc_usb30_pipe_clk # Optional clock
- const: usb3_uni_phy_sec_gcc_usb30_pipe_clk # Optional clock
minItems: 2
maxItems: 13
'#clock-cells':
const: 1
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
reg:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- reg
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@100000 {
compatible = "qcom,gcc-sm8350";
reg = <0x00100000 0x1f0000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&sleep_clk>;
clock-names = "bi_tcxo", "sleep_clk";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,gpucc-sdm660.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Graphics Clock & Reset Controller Binding for SDM630 and SDM660
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
description: |
Qualcomm graphics clock control module which supports the clocks, resets and
power domains on SDM630 and SDM660.
See also dt-bindings/clock/qcom,gpucc-sdm660.h.
properties:
compatible:
enum:
- qcom,gpucc-sdm630
- qcom,gpucc-sdm660
clocks:
items:
- description: Board XO source
- description: GPLL0 main gpu branch
- description: GPLL0 divider gpu branch
clock-names:
items:
- const: xo
- const: gcc_gpu_gpll0_clk
- const: gcc_gpu_gpll0_div_clk
'#clock-cells':
const: 1
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
reg:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sdm660.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
clock-controller@5065000 {
compatible = "qcom,gpucc-sdm660";
reg = <0x05065000 0x9038>;
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
<&gcc GCC_GPU_GPLL0_CLK>,
<&gcc GCC_GPU_GPLL0_DIV_CLK>;
clock-names = "xo", "gcc_gpu_gpll0_clk",
"gcc_gpu_gpll0_div_clk";
#clock-cells = <1>;
#power-domain-cells = <1>;
#reset-cells = <1>;
};
...
......@@ -24,6 +24,8 @@ properties:
- qcom,mmcc-msm8974
- qcom,mmcc-msm8996
- qcom,mmcc-msm8998
- qcom,mmcc-sdm630
- qcom,mmcc-sdm660
clocks:
items:
......
......@@ -18,6 +18,8 @@ properties:
compatible:
enum:
- qcom,sc7180-rpmh-clk
- qcom,sc7280-rpmh-clk
- qcom,sc8180x-rpmh-clk
- qcom,sdm845-rpmh-clk
- qcom,sdx55-rpmh-clk
- qcom,sm8150-rpmh-clk
......
......@@ -35,6 +35,9 @@ properties:
compatible:
items:
- enum:
- renesas,r8a774a1-rcar-usb2-clock-sel # RZ/G2M
- renesas,r8a774b1-rcar-usb2-clock-sel # RZ/G2N
- renesas,r8a774e1-rcar-usb2-clock-sel # RZ/G2H
- renesas,r8a7795-rcar-usb2-clock-sel # R-Car H3
- renesas,r8a7796-rcar-usb2-clock-sel # R-Car M3-W
- renesas,r8a77961-rcar-usb2-clock-sel # R-Car M3-W+
......
......@@ -28,6 +28,8 @@ Optional properties:
- clock-frequency: Output frequency to generate. This defines the output
frequency set during boot. It can be reprogrammed during
runtime through the common clock framework.
- silabs,skip-recall: Do not perform NVM->RAM recall operation. It will rely
on hardware loading of RAM from NVM at power on.
Example:
si570: clock-generator@5d {
......
Clock bindings for ST-Ericsson U300 System Controller Clocks
Bindings for the gated system controller clocks:
Required properties:
- compatible: must be "stericsson,u300-syscon-clk"
- #clock-cells: must be <0>
- clock-type: specifies the type of clock:
0 = slow clock
1 = fast clock
2 = rest/remaining clock
- clock-id: specifies the clock in the type range
Optional properties:
- clocks: parent clock(s)
The available clocks per type are as follows:
Type: ID: Clock:
-------------------
0 0 Slow peripheral bridge clock
0 1 UART0 clock
0 4 GPIO clock
0 6 RTC clock
0 7 Application timer clock
0 8 Access timer clock
1 0 Fast peripheral bridge clock
1 1 I2C bus 0 clock
1 2 I2C bus 1 clock
1 5 MMC interface peripheral (silicon) clock
1 6 SPI clock
2 3 CPU clock
2 4 DMA controller clock
2 5 External Memory Interface (EMIF) clock
2 6 NAND flask interface clock
2 8 XGAM graphics engine clock
2 9 Shared External Memory Interface (SEMI) clock
2 10 AHB Subsystem Bridge clock
2 12 Interrupt controller clock
Example:
gpio_clk: gpio_clk@13M {
#clock-cells = <0>;
compatible = "stericsson,u300-syscon-clk";
clock-type = <0>; /* Slow */
clock-id = <4>;
clocks = <&slow_clk>;
};
gpio: gpio@c0016000 {
compatible = "stericsson,gpio-coh901";
(...)
clocks = <&gpio_clk>;
};
Bindings for the MMC/SD card clock:
Required properties:
- compatible: must be "stericsson,u300-syscon-mclk"
- #clock-cells: must be <0>
Optional properties:
- clocks: parent clock(s)
mmc_mclk: mmc_mclk {
#clock-cells = <0>;
compatible = "stericsson,u300-syscon-mclk";
clocks = <&mmc_pclk>;
};
mmcsd: mmcsd@c0001000 {
compatible = "arm,pl18x", "arm,primecell";
clocks = <&mmc_pclk>, <&mmc_mclk>;
clock-names = "apb_pclk", "mclk";
(...)
};
* Sigma Designs Tango4 Clock Generator
The Tango4 clock generator outputs cpu_clk and sys_clk (the latter is used
for RAM and various peripheral devices). The clock binding described here
is applicable to all Tango4 SoCs.
Required Properties:
- compatible: should be "sigma,tango4-clkgen".
- reg: physical base address of the device and length of memory mapped region.
- clocks: phandle of the input clock (crystal oscillator).
- clock-output-names: should be "cpuclk" and "sysclk".
- #clock-cells: should be set to 1.
Example:
clkgen: clkgen@10000 {
compatible = "sigma,tango4-clkgen";
reg = <0x10000 0x40>;
clocks = <&xtal>;
clock-output-names = "cpuclk", "sysclk";
#clock-cells = <1>;
};
Device Tree Clock bindings for ZTE zx296702
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be one of the following:
"zte,zx296702-topcrm-clk":
zx296702 top clock selection, divider and gating
"zte,zx296702-lsp0crpm-clk" and
"zte,zx296702-lsp1crpm-clk":
zx296702 device level clock selection and gating
- reg: Address and length of the register set
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/zx296702-clock.h
for the full list of zx296702 clock IDs.
topclk: topcrm@09800000 {
compatible = "zte,zx296702-topcrm-clk";
reg = <0x09800000 0x1000>;
#clock-cells = <1>;
};
uart0: serial@09405000 {
compatible = "zte,zx296702-uart";
reg = <0x09405000 0x1000>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&lsp1clk ZX296702_UART0_PCLK>;
};
Device Tree Clock bindings for ZTE zx296718
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be one of the following:
"zte,zx296718-topcrm":
zx296718 top clock selection, divider and gating
"zte,zx296718-lsp0crm" and
"zte,zx296718-lsp1crm":
zx296718 device level clock selection and gating
"zte,zx296718-audiocrm":
zx296718 audio clock selection, divider and gating
- reg: Address and length of the register set
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/zx296718-clock.h
for the full list of zx296718 clock IDs.
topclk: topcrm@1461000 {
compatible = "zte,zx296718-topcrm-clk";
reg = <0x01461000 0x1000>;
#clock-cells = <1>;
};
usbphy0:usb-phy0 {
compatible = "zte,zx296718-usb-phy";
#phy-cells = <0>;
clocks = <&topclk USB20_PHY_CLK>;
clock-names = "phyclk";
};
......@@ -2126,10 +2126,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
W: http://linux-chenxing.org/
F: Documentation/devicetree/bindings/arm/mstar/*
F: Documentation/devicetree/bindings/clock/mstar,msc313-mpll.yaml
F: Documentation/devicetree/bindings/gpio/mstar,msc313-gpio.yaml
F: arch/arm/boot/dts/mstar-*
F: arch/arm/mach-mstar/
F: drivers/clk/mstar/
F: drivers/gpio/gpio-msc313.c
F: include/dt-bindings/clock/mstar-*
F: include/dt-bindings/gpio/msc313-gpio.h
ARM/NEC MOBILEPRO 900/c MACHINE SUPPORT
......@@ -12774,6 +12777,13 @@ F: drivers/iio/gyro/fxas21002c_core.c
F: drivers/iio/gyro/fxas21002c_i2c.c
F: drivers/iio/gyro/fxas21002c_spi.c
NXP i.MX CLOCK DRIVERS
M: Abel Vesa <abel.vesa@nxp.com>
L: linux-clk@vger.kernel.org
L: linux-imx@nxp.com
S: Maintained
F: drivers/clk/imx/
NXP i.MX 8MQ DCSS DRIVER
M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
R: Lucas Stach <l.stach@pengutronix.de>
......
......@@ -85,7 +85,6 @@ void imx_anatop_pre_suspend(void);
void imx_anatop_post_resume(void);
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
int imx_mmdc_get_ddr_type(void);
int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);
......
......@@ -3,6 +3,7 @@
* Copyright (C) 2014 Freescale Semiconductor, Inc.
*/
#include <linux/clk/imx.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/cpuidle.h>
......
......@@ -4,6 +4,7 @@
* Copyright 2011 Linaro Ltd.
*/
#include <linux/clk/imx.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
......
......@@ -43,16 +43,4 @@ void spear13xx_cpu_die(unsigned int cpu);
extern const struct smp_operations spear13xx_smp_ops;
#ifdef CONFIG_MACH_SPEAR1310
void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base);
#else
static inline void spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) {}
#endif
#ifdef CONFIG_MACH_SPEAR1340
void __init spear1340_clk_init(void __iomem *misc_base);
#else
static inline void spear1340_clk_init(void __iomem *misc_base) {}
#endif
#endif /* __MACH_GENERIC_H */
......@@ -15,6 +15,7 @@
#include <linux/amba/pl022.h>
#include <linux/clk.h>
#include <linux/clk/spear.h>
#include <linux/clocksource.h>
#include <linux/err.h>
#include <linux/of.h>
......
......@@ -247,7 +247,8 @@ config CLK_TWL6040
config COMMON_CLK_AXI_CLKGEN
tristate "AXI clkgen driver"
depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
depends on HAS_IOMEM || COMPILE_TEST
depends on OF
help
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
FPGAs. It is commonly used in Analog Devices' reference designs.
......@@ -379,6 +380,7 @@ source "drivers/clk/ingenic/Kconfig"
source "drivers/clk/keystone/Kconfig"
source "drivers/clk/mediatek/Kconfig"
source "drivers/clk/meson/Kconfig"
source "drivers/clk/mstar/Kconfig"
source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
......@@ -392,6 +394,7 @@ source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
source "drivers/clk/uniphier/Kconfig"
source "drivers/clk/x86/Kconfig"
source "drivers/clk/xilinx/Kconfig"
source "drivers/clk/zynqmp/Kconfig"
endif
......@@ -27,7 +27,6 @@ obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o
obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o
obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI) += clk-fsl-flexspi.o
......@@ -63,9 +62,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_U300) += clk-u300.o
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
......@@ -95,6 +92,7 @@ obj-$(CONFIG_MACH_PIC32) += microchip/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
endif
obj-y += mstar/
obj-y += mvebu/
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
......@@ -105,7 +103,6 @@ obj-y += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_CLK_SIFIVE) += sifive/
obj-$(CONFIG_ARCH_SIRF) += sirf/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_ARCH_AGILEX) += socfpga/
obj-$(CONFIG_ARCH_STRATIX10) += socfpga/
......@@ -122,6 +119,6 @@ obj-y += versatile/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_X86) += x86/
endif
obj-$(CONFIG_ARCH_ZX) += zte/
obj-y += xilinx/
obj-$(CONFIG_ARCH_ZYNQ) += zynq/
obj-$(CONFIG_COMMON_CLK_ZYNQMP) += zynqmp/
......@@ -215,5 +215,4 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
* deferring properly. Once this is fixed, this can be switched to a platform
* driver.
*/
CLK_OF_DECLARE_DRIVER(at91rm9200_pmc, "atmel,at91rm9200-pmc",
at91rm9200_pmc_setup);
CLK_OF_DECLARE(at91rm9200_pmc, "atmel,at91rm9200-pmc", at91rm9200_pmc_setup);
......@@ -491,26 +491,26 @@ static void __init at91sam9260_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9260_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9260_pmc, "atmel,at91sam9260-pmc",
at91sam9260_pmc_setup);
CLK_OF_DECLARE(at91sam9260_pmc, "atmel,at91sam9260-pmc", at91sam9260_pmc_setup);
static void __init at91sam9261_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9261_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9261_pmc, "atmel,at91sam9261-pmc",
at91sam9261_pmc_setup);
CLK_OF_DECLARE(at91sam9261_pmc, "atmel,at91sam9261-pmc", at91sam9261_pmc_setup);
static void __init at91sam9263_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9263_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9263_pmc, "atmel,at91sam9263-pmc",
at91sam9263_pmc_setup);
CLK_OF_DECLARE(at91sam9263_pmc, "atmel,at91sam9263-pmc", at91sam9263_pmc_setup);
static void __init at91sam9g20_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9g20_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9g20_pmc, "atmel,at91sam9g20-pmc",
at91sam9g20_pmc_setup);
CLK_OF_DECLARE(at91sam9g20_pmc, "atmel,at91sam9g20-pmc", at91sam9g20_pmc_setup);
......@@ -228,5 +228,4 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
* The TCB is used as the clocksource so its clock is needed early. This means
* this can't be a platform driver.
*/
CLK_OF_DECLARE_DRIVER(at91sam9g45_pmc, "atmel,at91sam9g45-pmc",
at91sam9g45_pmc_setup);
CLK_OF_DECLARE(at91sam9g45_pmc, "atmel,at91sam9g45-pmc", at91sam9g45_pmc_setup);
......@@ -255,5 +255,4 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
* The TCB is used as the clocksource so its clock is needed early. This means
* this can't be a platform driver.
*/
CLK_OF_DECLARE_DRIVER(at91sam9n12_pmc, "atmel,at91sam9n12-pmc",
at91sam9n12_pmc_setup);
CLK_OF_DECLARE(at91sam9n12_pmc, "atmel,at91sam9n12-pmc", at91sam9n12_pmc_setup);
......@@ -186,4 +186,5 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
err_free:
kfree(at91sam9rl_pmc);
}
CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
CLK_OF_DECLARE(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
......@@ -302,33 +302,33 @@ static void __init at91sam9g15_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc",
at91sam9g15_pmc_setup);
CLK_OF_DECLARE(at91sam9g15_pmc, "atmel,at91sam9g15-pmc", at91sam9g15_pmc_setup);
static void __init at91sam9g25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
}
CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc",
at91sam9g25_pmc_setup);
CLK_OF_DECLARE(at91sam9g25_pmc, "atmel,at91sam9g25-pmc", at91sam9g25_pmc_setup);
static void __init at91sam9g35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc",
at91sam9g35_pmc_setup);
CLK_OF_DECLARE(at91sam9g35_pmc, "atmel,at91sam9g35-pmc", at91sam9g35_pmc_setup);
static void __init at91sam9x25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
}
CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc",
at91sam9x25_pmc_setup);
CLK_OF_DECLARE(at91sam9x25_pmc, "atmel,at91sam9x25-pmc", at91sam9x25_pmc_setup);
static void __init at91sam9x35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc",
at91sam9x35_pmc_setup);
CLK_OF_DECLARE(at91sam9x35_pmc, "atmel,at91sam9x35-pmc", at91sam9x35_pmc_setup);
......@@ -372,4 +372,5 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
err_free:
kfree(sama5d2_pmc);
}
CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
CLK_OF_DECLARE(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
......@@ -255,4 +255,4 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
* The TCB is used as the clocksource so its clock is needed early. This means
* this can't be a platform driver.
*/
CLK_OF_DECLARE_DRIVER(sama5d3_pmc, "atmel,sama5d3-pmc", sama5d3_pmc_setup);
CLK_OF_DECLARE(sama5d3_pmc, "atmel,sama5d3-pmc", sama5d3_pmc_setup);
......@@ -286,4 +286,5 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
err_free:
kfree(sama5d4_pmc);
}
CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
CLK_OF_DECLARE(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
......@@ -704,7 +704,7 @@ static const struct clk_ops iproc_clk_ops = {
.set_rate = iproc_clk_set_rate,
};
/**
/*
* Some PLLs require the PLL SW override bit to be set before changes can be
* applied to the PLL
*/
......
......@@ -17,7 +17,8 @@
#define ASPEED_G6_NUM_CLKS 71
#define ASPEED_G6_SILICON_REV 0x004
#define ASPEED_G6_SILICON_REV 0x014
#define CHIP_REVISION_ID GENMASK(23, 16)
#define ASPEED_G6_RESET_CTRL 0x040
#define ASPEED_G6_RESET_CTRL2 0x050
......@@ -190,18 +191,34 @@ static struct clk_hw *ast2600_calc_pll(const char *name, u32 val)
static struct clk_hw *ast2600_calc_apll(const char *name, u32 val)
{
unsigned int mult, div;
u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV);
if (val & BIT(20)) {
/* Pass through mode */
mult = div = 1;
if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) {
if (val & BIT(24)) {
/* Pass through mode */
mult = div = 1;
} else {
/* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */
u32 m = val & 0x1fff;
u32 n = (val >> 13) & 0x3f;
u32 p = (val >> 19) & 0xf;
mult = (m + 1);
div = (n + 1) * (p + 1);
}
} else {
/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
u32 m = (val >> 5) & 0x3f;
u32 od = (val >> 4) & 0x1;
u32 n = val & 0xf;
if (val & BIT(20)) {
/* Pass through mode */
mult = div = 1;
} else {
/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
u32 m = (val >> 5) & 0x3f;
u32 od = (val >> 4) & 0x1;
u32 n = val & 0xf;
mult = (2 - od) * (m + 2);
div = n + 1;
mult = (2 - od) * (m + 2);
div = n + 1;
}
}
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
mult, div);
......
......@@ -108,6 +108,13 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
return 0x1f1f00fa;
}
static const struct axi_clkgen_limits axi_clkgen_zynqmp_default_limits = {
.fpfd_min = 10000,
.fpfd_max = 450000,
.fvco_min = 800000,
.fvco_max = 1600000,
};
static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = {
.fpfd_min = 10000,
.fpfd_max = 300000,
......@@ -503,7 +510,6 @@ static int axi_clkgen_probe(struct platform_device *pdev)
struct clk_init_data init;
const char *parent_names[2];
const char *clk_name;
struct resource *mem;
unsigned int i;
int ret;
......@@ -515,8 +521,7 @@ static int axi_clkgen_probe(struct platform_device *pdev)
if (!axi_clkgen)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem);
axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(axi_clkgen->base))
return PTR_ERR(axi_clkgen->base);
......@@ -560,6 +565,10 @@ static int axi_clkgen_remove(struct platform_device *pdev)
}
static const struct of_device_id axi_clkgen_ids[] = {
{
.compatible = "adi,zynqmp-axi-clkgen-2.00.a",
.data = &axi_clkgen_zynqmp_default_limits,
},
{
.compatible = "adi,axi-clkgen-2.00.a",
.data = &axi_clkgen_zynq_default_limits,
......
......@@ -31,12 +31,12 @@ struct bd718xx_clk {
u8 reg;
u8 mask;
struct platform_device *pdev;
struct rohm_regmap_dev *mfd;
struct regmap *regmap;
};
static int bd71837_clk_set(struct bd718xx_clk *c, unsigned int status)
{
return regmap_update_bits(c->mfd->regmap, c->reg, c->mask, status);
return regmap_update_bits(c->regmap, c->reg, c->mask, status);
}
static void bd71837_clk_disable(struct clk_hw *hw)
......@@ -62,7 +62,7 @@ static int bd71837_clk_is_enabled(struct clk_hw *hw)
int rval;
struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
rval = regmap_read(c->mfd->regmap, c->reg, &enabled);
rval = regmap_read(c->regmap, c->reg, &enabled);
if (rval)
return rval;
......@@ -82,7 +82,6 @@ static int bd71837_clk_probe(struct platform_device *pdev)
int rval = -ENOMEM;
const char *parent_clk;
struct device *parent = pdev->dev.parent;
struct rohm_regmap_dev *mfd = dev_get_drvdata(parent);
struct clk_init_data init = {
.name = "bd718xx-32k-out",
.ops = &bd71837_clk_ops,
......@@ -93,6 +92,10 @@ static int bd71837_clk_probe(struct platform_device *pdev)
if (!c)
return -ENOMEM;
c->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!c->regmap)
return -ENODEV;
init.num_parents = 1;
parent_clk = of_clk_get_parent_name(parent->of_node, 0);
......@@ -119,7 +122,6 @@ static int bd71837_clk_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unknown clk chip\n");
return -EINVAL;
}
c->mfd = mfd;
c->pdev = pdev;
c->hw.init = &init;
......
......@@ -494,8 +494,13 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
else
init.ops = &clk_divider_ops;
init.flags = flags;
init.parent_names = (parent_name ? &parent_name: NULL);
init.num_parents = (parent_name ? 1 : 0);
init.parent_names = parent_name ? &parent_name : NULL;
init.parent_hws = parent_hw ? &parent_hw : NULL;
init.parent_data = parent_data;
if (parent_name || parent_hw || parent_data)
init.num_parents = 1;
else
init.num_parents = 0;
/* struct clk_divider assignments */
div->reg = reg;
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 Pengutronix
* Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
*/
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <dt-bindings/clock/efm32-cmu.h>
#define CMU_HFPERCLKEN0 0x44
#define CMU_MAX_CLKS 37
static struct clk_hw_onecell_data *clk_data;
static void __init efm32gg_cmu_init(struct device_node *np)
{
int i;
void __iomem *base;
struct clk_hw **hws;
clk_data = kzalloc(struct_size(clk_data, hws, CMU_MAX_CLKS),
GFP_KERNEL);
if (!clk_data)
return;
hws = clk_data->hws;
for (i = 0; i < CMU_MAX_CLKS; ++i)
hws[i] = ERR_PTR(-ENOENT);
base = of_iomap(np, 0);
if (!base) {
pr_warn("Failed to map address range for efm32gg,cmu node\n");
return;
}
hws[clk_HFXO] = clk_hw_register_fixed_rate(NULL, "HFXO", NULL, 0,
48000000);
hws[clk_HFPERCLKUSART0] = clk_hw_register_gate(NULL, "HFPERCLK.USART0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL);
hws[clk_HFPERCLKUSART1] = clk_hw_register_gate(NULL, "HFPERCLK.USART1",
"HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL);
hws[clk_HFPERCLKUSART2] = clk_hw_register_gate(NULL, "HFPERCLK.USART2",
"HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL);
hws[clk_HFPERCLKUART0] = clk_hw_register_gate(NULL, "HFPERCLK.UART0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL);
hws[clk_HFPERCLKUART1] = clk_hw_register_gate(NULL, "HFPERCLK.UART1",
"HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL);
hws[clk_HFPERCLKTIMER0] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL);
hws[clk_HFPERCLKTIMER1] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER1",
"HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL);
hws[clk_HFPERCLKTIMER2] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER2",
"HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL);
hws[clk_HFPERCLKTIMER3] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER3",
"HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL);
hws[clk_HFPERCLKACMP0] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL);
hws[clk_HFPERCLKACMP1] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP1",
"HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL);
hws[clk_HFPERCLKI2C0] = clk_hw_register_gate(NULL, "HFPERCLK.I2C0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL);
hws[clk_HFPERCLKI2C1] = clk_hw_register_gate(NULL, "HFPERCLK.I2C1",
"HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL);
hws[clk_HFPERCLKGPIO] = clk_hw_register_gate(NULL, "HFPERCLK.GPIO",
"HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL);
hws[clk_HFPERCLKVCMP] = clk_hw_register_gate(NULL, "HFPERCLK.VCMP",
"HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL);
hws[clk_HFPERCLKPRS] = clk_hw_register_gate(NULL, "HFPERCLK.PRS",
"HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL);
hws[clk_HFPERCLKADC0] = clk_hw_register_gate(NULL, "HFPERCLK.ADC0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL);
hws[clk_HFPERCLKDAC0] = clk_hw_register_gate(NULL, "HFPERCLK.DAC0",
"HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL);
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
}
CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init);
......@@ -64,10 +64,16 @@ const struct clk_ops clk_fixed_factor_ops = {
};
EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *res)
{
clk_hw_unregister_fixed_factor(&((struct clk_fixed_factor *)res)->hw);
}
static struct clk_hw *
__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
const char *name, const char *parent_name, int index,
unsigned long flags, unsigned int mult, unsigned int div)
unsigned long flags, unsigned int mult, unsigned int div,
bool devm)
{
struct clk_fixed_factor *fix;
struct clk_init_data init = { };
......@@ -75,7 +81,15 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
struct clk_hw *hw;
int ret;
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
/* You can't use devm without a dev */
if (devm && !dev)
return ERR_PTR(-EINVAL);
if (devm)
fix = devres_alloc(devm_clk_hw_register_fixed_factor_release,
sizeof(*fix), GFP_KERNEL);
else
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
if (!fix)
return ERR_PTR(-ENOMEM);
......@@ -99,9 +113,13 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
else
ret = of_clk_hw_register(np, hw);
if (ret) {
kfree(fix);
if (devm)
devres_free(fix);
else
kfree(fix);
hw = ERR_PTR(ret);
}
} else if (devm)
devres_add(dev, fix);
return hw;
}
......@@ -111,7 +129,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
unsigned int mult, unsigned int div)
{
return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1,
flags, mult, div);
flags, mult, div, false);
}
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
......@@ -153,6 +171,15 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div)
{
return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1,
flags, mult, div, true);
}
EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor);
#ifdef CONFIG_OF
static const struct of_device_id set_rate_parent_matches[] = {
{ .compatible = "allwinner,sun4i-a10-pll3-2x-clk" },
......@@ -185,7 +212,7 @@ static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
flags |= CLK_SET_RATE_PARENT;
hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, 0,
flags, mult, div);
flags, mult, div, false);
if (IS_ERR(hw)) {
/*
* Clear OF_POPULATED flag so that clock registration can be
......
......@@ -55,7 +55,7 @@ static void __init of_fixed_mmio_clk_setup(struct device_node *node)
}
CLK_OF_DECLARE(fixed_mmio_clk, "fixed-mmio-clock", of_fixed_mmio_clk_setup);
/**
/*
* This is not executed when of_fixed_mmio_clk_setup succeeded.
*/
static int of_fixed_mmio_clk_probe(struct platform_device *pdev)
......
......@@ -361,13 +361,6 @@ static const struct npcm7xx_clk_mux_data npcm7xx_muxes[] __initconst = {
dvcssel_mux_parents, ARRAY_SIZE(dvcssel_mux_parents), 0, -1},
};
/* fixed ratio dividers (no register): */
static const struct npcm7xx_clk_div_fixed_data npcm7xx_divs_fx[] __initconst = {
{ 1, 2, NPCM7XX_CLK_S_MC, NPCM7XX_CLK_S_MC_MUX, 0, NPCM7XX_CLK_MC},
{ 1, 2, NPCM7XX_CLK_S_PLL1_DIV2, NPCM7XX_CLK_S_PLL1, 0, -1},
{ 1, 2, NPCM7XX_CLK_S_PLL2_DIV2, NPCM7XX_CLK_S_PLL2, 0, -1},
};
/* configurable dividers: */
static const struct npcm7xx_clk_div_data npcm7xx_divs[] __initconst = {
{NPCM7XX_CLKDIV1, 28, 3, NPCM7XX_CLK_S_ADC,
......@@ -435,107 +428,6 @@ static const struct npcm7xx_clk_div_data npcm7xx_divs[] __initconst = {
};
static const struct npcm7xx_clk_gate_data npcm7xx_gates[] __initconst = {
{NPCM7XX_CLKEN1, 31, "smb1-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 30, "smb0-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 29, "smb7-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 28, "smb6-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 27, "adc-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN1, 26, "wdt-gate", NPCM7XX_CLK_S_TIMER, 0},
{NPCM7XX_CLKEN1, 25, "usbdev3-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 24, "usbdev6-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 23, "usbdev5-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 22, "usbdev4-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 21, "emc2-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 20, "timer5_9-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN1, 19, "timer0_4-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN1, 18, "pwmm0-gate", NPCM7XX_CLK_S_APB3, 0},
{NPCM7XX_CLKEN1, 17, "huart-gate", NPCM7XX_CLK_S_UART, 0},
{NPCM7XX_CLKEN1, 16, "smb5-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 15, "smb4-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 14, "smb3-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 13, "smb2-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN1, 12, "mc-gate", NPCM7XX_CLK_S_MC, 0},
{NPCM7XX_CLKEN1, 11, "uart01-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN1, 10, "aes-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 9, "peci-gate", NPCM7XX_CLK_S_APB3, 0},
{NPCM7XX_CLKEN1, 8, "usbdev2-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 7, "uart23-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN1, 6, "emc1-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 5, "usbdev1-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 4, "shm-gate", NPCM7XX_CLK_S_AHB, 0},
/* bit 3 is reserved */
{NPCM7XX_CLKEN1, 2, "kcs-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN1, 1, "spi3-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN1, 0, "spi0-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 31, "cp-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 30, "tock-gate", NPCM7XX_CLK_S_TOCK, 0},
/* bit 29 is reserved */
{NPCM7XX_CLKEN2, 28, "gmac1-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 27, "usbif-gate", NPCM7XX_CLK_S_USBIF, 0},
{NPCM7XX_CLKEN2, 26, "usbhost-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 25, "gmac2-gate", NPCM7XX_CLK_S_AHB, 0},
/* bit 24 is reserved */
{NPCM7XX_CLKEN2, 23, "pspi2-gate", NPCM7XX_CLK_S_APB5, 0},
{NPCM7XX_CLKEN2, 22, "pspi1-gate", NPCM7XX_CLK_S_APB5, 0},
{NPCM7XX_CLKEN2, 21, "3des-gate", NPCM7XX_CLK_S_AHB, 0},
/* bit 20 is reserved */
{NPCM7XX_CLKEN2, 19, "siox2-gate", NPCM7XX_CLK_S_APB3, 0},
{NPCM7XX_CLKEN2, 18, "siox1-gate", NPCM7XX_CLK_S_APB3, 0},
/* bit 17 is reserved */
{NPCM7XX_CLKEN2, 16, "fuse-gate", NPCM7XX_CLK_S_APB4, 0},
/* bit 15 is reserved */
{NPCM7XX_CLKEN2, 14, "vcd-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 13, "ece-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 12, "vdma-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 11, "ahbpcibrg-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 10, "gfxsys-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN2, 9, "sdhc-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 8, "mmc-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN2, 7, "mft7-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 6, "mft6-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 5, "mft5-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 4, "mft4-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 3, "mft3-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 2, "mft2-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 1, "mft1-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN2, 0, "mft0-gate", NPCM7XX_CLK_S_APB4, 0},
{NPCM7XX_CLKEN3, 31, "gpiom7-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 30, "gpiom6-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 29, "gpiom5-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 28, "gpiom4-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 27, "gpiom3-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 26, "gpiom2-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 25, "gpiom1-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 24, "gpiom0-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 23, "espi-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 22, "smb11-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 21, "smb10-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 20, "smb9-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 19, "smb8-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 18, "smb15-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 17, "rng-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 16, "timer10_14-gate", NPCM7XX_CLK_S_APB1, 0},
{NPCM7XX_CLKEN3, 15, "pcirc-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 14, "sececc-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 13, "sha-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 12, "smb14-gate", NPCM7XX_CLK_S_APB2, 0},
/* bit 11 is reserved */
/* bit 10 is reserved */
{NPCM7XX_CLKEN3, 9, "pcimbx-gate", NPCM7XX_CLK_S_AHB, 0},
/* bit 8 is reserved */
{NPCM7XX_CLKEN3, 7, "usbdev9-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 6, "usbdev8-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 5, "usbdev7-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 4, "usbdev0-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 3, "smb13-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 2, "spix-gate", NPCM7XX_CLK_S_AHB, 0},
{NPCM7XX_CLKEN3, 1, "smb12-gate", NPCM7XX_CLK_S_APB2, 0},
{NPCM7XX_CLKEN3, 0, "pwmm1-gate", NPCM7XX_CLK_S_APB3, 0},
};
static DEFINE_SPINLOCK(npcm7xx_clk_lock);
static void __init npcm7xx_clk_init(struct device_node *clk_np)
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2013 Freescale Semiconductor, Inc.
* Copyright 2021 NXP
*
* clock driver for Freescale QorIQ SoCs.
*/
......@@ -564,7 +565,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 1, 1, 1, -1
},
.pll_mask = 0x3f,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) |
BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_PLL_8BIT,
},
{
......@@ -580,7 +583,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 1, 1, 1, -1
},
.pll_mask = 0x3f,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) |
BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_PLL_8BIT,
},
{
......@@ -591,7 +596,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
.pll_mask = 0x03,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,ls1028a-clockgen",
......@@ -605,7 +611,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 0, 0, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
......@@ -620,7 +627,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
......@@ -635,7 +643,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
......@@ -649,7 +658,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
......@@ -660,7 +670,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
.pll_mask = 0x03,
.pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1),
},
{
.compat = "fsl,ls2080a-clockgen",
......@@ -670,7 +680,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
.pll_mask = 0x37,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) |
BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
......@@ -681,7 +693,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 0, 0, 1, 1, 1, 1, -1
},
.pll_mask = 0x37,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) |
BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
......@@ -694,7 +708,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,p3041-clockgen",
......@@ -706,7 +721,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,p4080-clockgen",
......@@ -718,7 +734,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 0, 0, 1, 1, 1, 1, -1
},
.pll_mask = 0x1f,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) |
BIT(CGA_PLL3) | BIT(CGA_PLL4),
},
{
.compat = "fsl,p5020-clockgen",
......@@ -730,7 +748,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 1, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,p5040-clockgen",
......@@ -742,7 +761,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
.pll_mask = 0x0f,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3),
},
{
.compat = "fsl,t1023-clockgen",
......@@ -757,7 +777,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, -1
},
.pll_mask = 0x03,
.pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1),
.flags = CG_PLL_8BIT,
},
{
......@@ -770,7 +790,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 0, 0, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
......@@ -786,7 +807,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
.pll_mask = 0x07,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
......@@ -802,7 +824,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, -1
},
.pll_mask = 0x3f,
.pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) |
BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_PLL_8BIT,
},
{},
......
......@@ -4,7 +4,7 @@
*
* Copyright (C) 2010, 2011 Ericsson AB.
* Copyright (C) 2011 Guenter Roeck.
* Copyright (C) 2011 - 2013 Xilinx Inc.
* Copyright (C) 2011 - 2021 Xilinx Inc.
*
* Author: Guenter Roeck <guenter.roeck@ericsson.com>
* Sören Brinkmann <soren.brinkmann@xilinx.com>
......@@ -123,14 +123,18 @@ static int si570_get_divs(struct clk_si570 *data, u64 *rfreq,
* si570_get_defaults() - Get default values
* @data: Driver data structure
* @fout: Factory frequency output
* @skip_recall: If true, don't recall NVM into RAM
* Returns 0 on success, negative errno otherwise.
*/
static int si570_get_defaults(struct clk_si570 *data, u64 fout)
static int si570_get_defaults(struct clk_si570 *data, u64 fout,
bool skip_recall)
{
int err;
u64 fdco;
regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_RECALL);
if (!skip_recall)
regmap_write(data->regmap, SI570_REG_CONTROL,
SI570_CNTRL_RECALL);
err = si570_get_divs(data, &data->rfreq, &data->n1, &data->hs_div);
if (err)
......@@ -400,6 +404,7 @@ static int si570_probe(struct i2c_client *client,
struct clk_si570 *data;
struct clk_init_data init;
u32 initial_fout, factory_fout, stability;
bool skip_recall;
int err;
enum clk_si570_variant variant = id->driver_data;
......@@ -441,6 +446,9 @@ static int si570_probe(struct i2c_client *client,
return err;
}
skip_recall = of_property_read_bool(client->dev.of_node,
"silabs,skip-recall");
data->regmap = devm_regmap_init_i2c(client, &si570_regmap_config);
if (IS_ERR(data->regmap)) {
dev_err(&client->dev, "failed to allocate register map\n");
......@@ -448,7 +456,7 @@ static int si570_probe(struct i2c_client *client,
}
i2c_set_clientdata(client, data);
err = si570_get_defaults(data, factory_fout);
err = si570_get_defaults(data, factory_fout, skip_recall);
if (err)
return err;
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <linux/init.h>
#include <linux/io.h>
#define CLK_COUNT 4 /* cpu_clk, sys_clk, usb_clk, sdio_clk */
static struct clk *clks[CLK_COUNT];
static struct clk_onecell_data clk_data = { clks, CLK_COUNT };
#define SYSCLK_DIV 0x20
#define CPUCLK_DIV 0x24
#define DIV_BYPASS BIT(23)
/*** CLKGEN_PLL ***/
#define extract_pll_n(val) ((val >> 0) & ((1u << 7) - 1))
#define extract_pll_k(val) ((val >> 13) & ((1u << 3) - 1))
#define extract_pll_m(val) ((val >> 16) & ((1u << 3) - 1))
#define extract_pll_isel(val) ((val >> 24) & ((1u << 3) - 1))
static void __init make_pll(int idx, const char *parent, void __iomem *base)
{
char name[8];
u32 val, mul, div;
sprintf(name, "pll%d", idx);
val = readl(base + idx * 8);
mul = extract_pll_n(val) + 1;
div = (extract_pll_m(val) + 1) << extract_pll_k(val);
clk_register_fixed_factor(NULL, name, parent, 0, mul, div);
if (extract_pll_isel(val) != 1)
panic("%s: input not set to XTAL_IN\n", name);
}
static void __init make_cd(int idx, void __iomem *base)
{
char name[8];
u32 val, mul, div;
sprintf(name, "cd%d", idx);
val = readl(base + idx * 8);
mul = 1 << 27;
div = (2 << 27) + val;
clk_register_fixed_factor(NULL, name, "pll2", 0, mul, div);
if (val > 0xf0000000)
panic("%s: unsupported divider %x\n", name, val);
}
static void __init tango4_clkgen_setup(struct device_node *np)
{
struct clk **pp = clk_data.clks;
void __iomem *base = of_iomap(np, 0);
const char *parent = of_clk_get_parent_name(np, 0);
if (!base)
panic("%pOFn: invalid address\n", np);
if (readl(base + CPUCLK_DIV) & DIV_BYPASS)
panic("%pOFn: unsupported cpuclk setup\n", np);
if (readl(base + SYSCLK_DIV) & DIV_BYPASS)
panic("%pOFn: unsupported sysclk setup\n", np);
writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */
make_pll(0, parent, base);
make_pll(1, parent, base);
make_pll(2, parent, base);
make_cd(2, base + 0x80);
make_cd(6, base + 0x80);
pp[0] = clk_register_divider(NULL, "cpu_clk", "pll0", 0,
base + CPUCLK_DIV, 8, 8, CLK_DIVIDER_ONE_BASED, NULL);
pp[1] = clk_register_fixed_factor(NULL, "sys_clk", "pll1", 0, 1, 4);
pp[2] = clk_register_fixed_factor(NULL, "usb_clk", "cd2", 0, 1, 2);
pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2);
if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3]))
panic("%pOFn: clk registration failed\n", np);
if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data))
panic("%pOFn: clk provider registration failed\n", np);
}
CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup);
This diff is collapsed.
......@@ -759,6 +759,63 @@ static int vc5_update_power(struct device_node *np_output,
return 0;
}
static int vc5_map_cap_value(u32 femtofarads)
{
int mapped_value;
/*
* The datasheet explicitly states 9000 - 25000 with 0.5pF
* steps, but the Programmer's guide shows the steps are 0.430pF.
* After getting feedback from Renesas, the .5pF steps were the
* goal, but 430nF was the actual values.
* Because of this, the actual range goes to 22760 instead of 25000
*/
if (femtofarads < 9000 || femtofarads > 22760)
return -EINVAL;
/*
* The Programmer's guide shows XTAL[5:0] but in reality,
* XTAL[0] and XTAL[1] are both LSB which makes the math
* strange. With clarfication from Renesas, setting the
* values should be simpler by ignoring XTAL[0]
*/
mapped_value = DIV_ROUND_CLOSEST(femtofarads - 9000, 430);
/*
* Since the calculation ignores XTAL[0], there is one
* special case where mapped_value = 32. In reality, this means
* the real mapped value should be 111111b. In other cases,
* the mapped_value needs to be shifted 1 to the left.
*/
if (mapped_value > 31)
mapped_value = 0x3f;
else
mapped_value <<= 1;
return mapped_value;
}
static int vc5_update_cap_load(struct device_node *node, struct vc5_driver_data *vc5)
{
u32 value;
int mapped_value;
if (!of_property_read_u32(node, "idt,xtal-load-femtofarads", &value)) {
mapped_value = vc5_map_cap_value(value);
if (mapped_value < 0)
return mapped_value;
/*
* The mapped_value is really the high 6 bits of
* VC5_XTAL_X1_LOAD_CAP and VC5_XTAL_X2_LOAD_CAP, so
* shift the value 2 places.
*/
regmap_update_bits(vc5->regmap, VC5_XTAL_X1_LOAD_CAP, ~0x03, mapped_value << 2);
regmap_update_bits(vc5->regmap, VC5_XTAL_X2_LOAD_CAP, ~0x03, mapped_value << 2);
}
return 0;
}
static int vc5_update_slew(struct device_node *np_output,
struct vc5_out_data *clk_out)
{
......@@ -884,6 +941,13 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -EINVAL;
}
/* Configure Optional Loading Capacitance for external XTAL */
if (!(vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)) {
ret = vc5_update_cap_load(client->dev.of_node, vc5);
if (ret)
goto err_clk_register;
}
init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node);
init.ops = &vc5_mux_ops;
init.flags = 0;
......
......@@ -206,17 +206,16 @@ static void xgene_pcppllclk_init(struct device_node *np)
* @hw: handle between common and hardware-specific interfaces
* @reg: register containing the fractional scale multiplier (scaler)
* @shift: shift to the unit bit field
* @mask: mask to the unit bit field
* @denom: 1/denominator unit
* @lock: register lock
* Flags:
* XGENE_CLK_PMD_SCALE_INVERTED - By default the scaler is the value read
* @flags: XGENE_CLK_PMD_SCALE_INVERTED - By default the scaler is the value read
* from the register plus one. For example,
* 0 for (0 + 1) / denom,
* 1 for (1 + 1) / denom and etc.
* If this flag is set, it is
* 0 for (denom - 0) / denom,
* 1 for (denom - 1) / denom and etc.
*
*/
struct xgene_clk_pmd {
struct clk_hw hw;
......
......@@ -51,16 +51,6 @@ enum mx31_clks {
static struct clk *clk[clk_max];
static struct clk_onecell_data clk_data;
static struct clk ** const uart_clks[] __initconst = {
&clk[ipg],
&clk[uart1_gate],
&clk[uart2_gate],
&clk[uart3_gate],
&clk[uart4_gate],
&clk[uart5_gate],
NULL
};
static void __init _mx31_clocks_init(void __iomem *base, unsigned long fref)
{
clk[dummy] = imx_clk_fixed("dummy", 0);
......
......@@ -338,10 +338,10 @@ static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
for (i = 0; i < 2; i++) {
/* Warn if a glitch might have been introduced already */
/* Print a notice if a glitch might have been introduced already */
if (sel[i][0] != 3) {
pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
i, sel[i][0]);
pr_notice("ccm: possible glitch: ldb_di%d_sel already changed from reset value: %d\n",
i, sel[i][0]);
}
if (sel[i][0] == sel[i][3])
......
......@@ -6,6 +6,7 @@
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk/imx.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_address.h>
......
......@@ -288,6 +288,11 @@ static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", "
static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", "sys_pll2_166m",
"sys_pll3_out", "audio_pll1_out", "video_pll1_out", "osc_32k", };
static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
"dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
"arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
"dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
static struct clk_hw_onecell_data *clk_hw_data;
static struct clk_hw **hws;
......@@ -410,6 +415,13 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_clk_hw_mux("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MM_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4);
hws[IMX8MM_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
hws[IMX8MM_CLK_CLKOUT2_SEL] = imx_clk_hw_mux("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MM_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4);
hws[IMX8MM_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base)))
......
......@@ -281,6 +281,11 @@ static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sy
"sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
"video_pll1_out", "osc_32k", };
static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
"dummy", "dummy", "gpu_pll_out", "dummy",
"arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
"dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
static struct clk_hw_onecell_data *clk_hw_data;
static struct clk_hw **hws;
......@@ -405,6 +410,13 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
hws[IMX8MN_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_hw_mux("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MN_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4);
hws[IMX8MN_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
hws[IMX8MN_CLK_CLKOUT2_SEL] = imx_clk_hw_mux("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MN_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4);
hws[IMX8MN_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base))) {
......
......@@ -270,6 +270,14 @@ static const char * const imx8mq_clko1_sels[] = {"osc_25m", "sys1_pll_800m", "os
static const char * const imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_400m", "sys2_pll_166m",
"sys3_pll_out", "audio_pll1_out", "video_pll1_out", "ckil", };
static const char * const pllout_monitor_sels[] = {"osc_25m", "osc_27m", "dummy", "dummy", "ckil",
"audio_pll1_out_monitor", "audio_pll2_out_monitor",
"video_pll1_out_monitor", "gpu_pll_out_monitor",
"vpu_pll_out_monitor", "arm_pll_out_monitor",
"sys_pll1_out_monitor", "sys_pll2_out_monitor",
"sys_pll3_out_monitor", "dram_pll_out_monitor",
"video_pll2_out_monitor", };
static struct clk_hw_onecell_data *clk_hw_data;
static struct clk_hw **hws;
......@@ -399,6 +407,20 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_500m_cg", 1, 2);
hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1);
hws[IMX8MQ_CLK_MON_AUDIO_PLL1_DIV] = imx_clk_hw_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3);
hws[IMX8MQ_CLK_MON_AUDIO_PLL2_DIV] = imx_clk_hw_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3);
hws[IMX8MQ_CLK_MON_VIDEO_PLL1_DIV] = imx_clk_hw_divider("video_pll1_out_monitor", "video_pll1_bypass", base + 0x78, 8, 3);
hws[IMX8MQ_CLK_MON_GPU_PLL_DIV] = imx_clk_hw_divider("gpu_pll_out_monitor", "gpu_pll_bypass", base + 0x78, 12, 3);
hws[IMX8MQ_CLK_MON_VPU_PLL_DIV] = imx_clk_hw_divider("vpu_pll_out_monitor", "vpu_pll_bypass", base + 0x78, 16, 3);
hws[IMX8MQ_CLK_MON_ARM_PLL_DIV] = imx_clk_hw_divider("arm_pll_out_monitor", "arm_pll_bypass", base + 0x78, 20, 3);
hws[IMX8MQ_CLK_MON_SYS_PLL1_DIV] = imx_clk_hw_divider("sys_pll1_out_monitor", "sys1_pll_out", base + 0x7c, 0, 3);
hws[IMX8MQ_CLK_MON_SYS_PLL2_DIV] = imx_clk_hw_divider("sys_pll2_out_monitor", "sys2_pll_out", base + 0x7c, 4, 3);
hws[IMX8MQ_CLK_MON_SYS_PLL3_DIV] = imx_clk_hw_divider("sys_pll3_out_monitor", "sys3_pll_out", base + 0x7c, 8, 3);
hws[IMX8MQ_CLK_MON_DRAM_PLL_DIV] = imx_clk_hw_divider("dram_pll_out_monitor", "dram_pll_out", base + 0x7c, 12, 3);
hws[IMX8MQ_CLK_MON_VIDEO_PLL2_DIV] = imx_clk_hw_divider("video_pll2_out_monitor", "video2_pll_out", base + 0x7c, 16, 3);
hws[IMX8MQ_CLK_MON_SEL] = imx_clk_hw_mux("pllout_monitor_sel", base + 0x74, 0, 4, pllout_monitor_sels, ARRAY_SIZE(pllout_monitor_sels));
hws[IMX8MQ_CLK_MON_CLK2_OUT] = imx_clk_hw_gate("pllout_monitor_clk2", "pllout_monitor_sel", base + 0x74, 4);
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base)))
......
......@@ -17,6 +17,14 @@
#include <dt-bindings/clock/imx8-clock.h>
#include <dt-bindings/firmware/imx/rsrc.h>
static const char *dc0_sels[] = {
"clk_dummy",
"clk_dummy",
"dc0_pll0_clk",
"dc0_pll1_clk",
"dc0_bypass0_clk",
};
static int imx8qxp_clk_probe(struct platform_device *pdev)
{
struct device_node *ccm_node = pdev->dev.of_node;
......@@ -115,12 +123,26 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells);
/* Display controller SS */
clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells);
clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells);
clks[IMX_DC0_DISP0_CLK] = imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells);
clks[IMX_DC0_DISP1_CLK] = imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells);
clks[IMX_DC0_PLL0_CLK] = imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL, clk_cells);
clks[IMX_DC0_PLL1_CLK] = imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL, clk_cells);
clks[IMX_DC0_BYPASS0_CLK] = imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS, clk_cells);
clks[IMX_DC0_BYPASS1_CLK] = imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS, clk_cells);
/* MIPI-LVDS SS */
clks[IMX_MIPI0_LVDS_PIXEL_CLK] = imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2, clk_cells);
clks[IMX_MIPI0_LVDS_BYPASS_CLK] = imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS, clk_cells);
clks[IMX_MIPI0_LVDS_PHY_CLK] = imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3, clk_cells);
clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells);
clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells);
clks[IMX_MIPI0_PWM0_CLK] = imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
clks[IMX_MIPI1_LVDS_PIXEL_CLK] = imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2, clk_cells);
clks[IMX_MIPI1_LVDS_BYPASS_CLK] = imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS, clk_cells);
clks[IMX_MIPI1_LVDS_PHY_CLK] = imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3, clk_cells);
clks[IMX_MIPI1_I2C0_CLK] = imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells);
clks[IMX_MIPI1_I2C1_CLK] = imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells);
clks[IMX_MIPI1_PWM0_CLK] = imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
/* MIPI CSI SS */
clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells);
......
......@@ -426,66 +426,77 @@ config COMMON_CLK_MT8183
config COMMON_CLK_MT8183_AUDIOSYS
bool "Clock driver for MediaTek MT8183 audiosys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 audiosys clocks.
config COMMON_CLK_MT8183_CAMSYS
bool "Clock driver for MediaTek MT8183 camsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 camsys clocks.
config COMMON_CLK_MT8183_IMGSYS
bool "Clock driver for MediaTek MT8183 imgsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 imgsys clocks.
config COMMON_CLK_MT8183_IPU_CORE0
bool "Clock driver for MediaTek MT8183 ipu_core0"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_core0 clocks.
config COMMON_CLK_MT8183_IPU_CORE1
bool "Clock driver for MediaTek MT8183 ipu_core1"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_core1 clocks.
config COMMON_CLK_MT8183_IPU_ADL
bool "Clock driver for MediaTek MT8183 ipu_adl"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_adl clocks.
config COMMON_CLK_MT8183_IPU_CONN
bool "Clock driver for MediaTek MT8183 ipu_conn"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 ipu_conn clocks.
config COMMON_CLK_MT8183_MFGCFG
bool "Clock driver for MediaTek MT8183 mfgcfg"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 mfgcfg clocks.
config COMMON_CLK_MT8183_MMSYS
bool "Clock driver for MediaTek MT8183 mmsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 mmsys clocks.
config COMMON_CLK_MT8183_VDECSYS
bool "Clock driver for MediaTek MT8183 vdecsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 vdecsys clocks.
config COMMON_CLK_MT8183_VENCSYS
bool "Clock driver for MediaTek MT8183 vencsys"
depends on COMMON_CLK_MT8183
default COMMON_CLK_MT8183
help
This driver supports MediaTek MT8183 vencsys clocks.
......
......@@ -17,29 +17,36 @@ static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
return container_of(hw, struct mtk_clk_mux, hw);
}
static int mtk_clk_mux_enable(struct clk_hw *hw)
static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
u32 mask = BIT(mux->data->gate_shift);
return regmap_update_bits(mux->regmap, mux->data->mux_ofs,
mask, ~mask);
}
unsigned long flags = 0;
static void mtk_clk_mux_disable(struct clk_hw *hw)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
u32 mask = BIT(mux->data->gate_shift);
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
else
__acquire(mux->lock);
regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask, mask);
}
regmap_write(mux->regmap, mux->data->clr_ofs,
BIT(mux->data->gate_shift));
/*
* If the parent has been changed when the clock was disabled, it will
* not be effective yet. Set the update bit to ensure the mux gets
* updated.
*/
if (mux->reparent && mux->data->upd_shift >= 0) {
regmap_write(mux->regmap, mux->data->upd_ofs,
BIT(mux->data->upd_shift));
mux->reparent = false;
}
static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
else
__release(mux->lock);
return regmap_write(mux->regmap, mux->data->clr_ofs,
BIT(mux->data->gate_shift));
return 0;
}
static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
......@@ -72,28 +79,6 @@ static u8 mtk_clk_mux_get_parent(struct clk_hw *hw)
return val;
}
static int mtk_clk_mux_set_parent_lock(struct clk_hw *hw, u8 index)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
u32 mask = GENMASK(mux->data->mux_width - 1, 0);
unsigned long flags = 0;
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
else
__acquire(mux->lock);
regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask,
index << mux->data->mux_shift);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
else
__release(mux->lock);
return 0;
}
static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
......@@ -116,9 +101,11 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
regmap_write(mux->regmap, mux->data->set_ofs,
index << mux->data->mux_shift);
if (mux->data->upd_shift >= 0)
if (mux->data->upd_shift >= 0) {
regmap_write(mux->regmap, mux->data->upd_ofs,
BIT(mux->data->upd_shift));
mux->reparent = true;
}
}
if (mux->lock)
......@@ -129,25 +116,7 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
return 0;
}
const struct clk_ops mtk_mux_ops = {
.get_parent = mtk_clk_mux_get_parent,
.set_parent = mtk_clk_mux_set_parent_lock,
};
const struct clk_ops mtk_mux_clr_set_upd_ops = {
.get_parent = mtk_clk_mux_get_parent,
.set_parent = mtk_clk_mux_set_parent_setclr_lock,
};
const struct clk_ops mtk_mux_gate_ops = {
.enable = mtk_clk_mux_enable,
.disable = mtk_clk_mux_disable,
.is_enabled = mtk_clk_mux_is_enabled,
.get_parent = mtk_clk_mux_get_parent,
.set_parent = mtk_clk_mux_set_parent_lock,
};
const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
static const struct clk_ops mtk_mux_ops = {
.enable = mtk_clk_mux_enable_setclr,
.disable = mtk_clk_mux_disable_setclr,
.is_enabled = mtk_clk_mux_is_enabled,
......@@ -171,7 +140,7 @@ static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
init.flags = mux->flags | CLK_SET_RATE_PARENT;
init.parent_names = mux->parent_names;
init.num_parents = mux->num_parents;
init.ops = mux->ops;
init.ops = &mtk_mux_ops;
clk_mux->regmap = regmap;
clk_mux->data = mux;
......
......@@ -14,6 +14,7 @@ struct mtk_clk_mux {
struct regmap *regmap;
const struct mtk_mux *data;
spinlock_t *lock;
bool reparent;
};
struct mtk_mux {
......@@ -32,19 +33,12 @@ struct mtk_mux {
u8 gate_shift;
s8 upd_shift;
const struct clk_ops *ops;
signed char num_parents;
};
extern const struct clk_ops mtk_mux_ops;
extern const struct clk_ops mtk_mux_clr_set_upd_ops;
extern const struct clk_ops mtk_mux_gate_ops;
extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
_gate, _upd_ofs, _upd, _flags, _ops) { \
_gate, _upd_ofs, _upd, _flags) { \
.id = _id, \
.name = _name, \
.mux_ofs = _mux_ofs, \
......@@ -58,7 +52,6 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
.parent_names = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.flags = _flags, \
.ops = &_ops, \
}
#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
......@@ -66,8 +59,7 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
_gate, _upd_ofs, _upd, _flags) \
GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
_gate, _upd_ofs, _upd, _flags, \
mtk_mux_gate_clr_set_upd_ops)
_gate, _upd_ofs, _upd, _flags) \
#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
......
......@@ -1879,7 +1879,6 @@ static MESON_GATE(axg_mmc_pclk, HHI_GCLK_MPEG2, 11);
static MESON_GATE(axg_vpu_intr, HHI_GCLK_MPEG2, 25);
static MESON_GATE(axg_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
static MESON_GATE(axg_gic, HHI_GCLK_MPEG2, 30);
static MESON_GATE(axg_mipi_enable, HHI_MIPI_CNTL0, 29);
/* Always On (AO) domain gates */
......@@ -1974,7 +1973,6 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
[CLKID_PCIE_REF] = &axg_pcie_ref.hw,
[CLKID_PCIE_CML_EN0] = &axg_pcie_cml_en0.hw,
[CLKID_PCIE_CML_EN1] = &axg_pcie_cml_en1.hw,
[CLKID_MIPI_ENABLE] = &axg_mipi_enable.hw,
[CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw,
[CLKID_GEN_CLK] = &axg_gen_clk.hw,
......@@ -2115,7 +2113,6 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_pcie_ref,
&axg_pcie_cml_en0,
&axg_pcie_cml_en1,
&axg_mipi_enable,
&axg_gen_clk_sel,
&axg_gen_clk_div,
&axg_gen_clk,
......
......@@ -16,7 +16,6 @@
* Register offsets from the data sheet must be multiplied by 4 before
* adding them to the base address to get the right value.
*/
#define HHI_MIPI_CNTL0 0x00
#define HHI_GP0_PLL_CNTL 0x40
#define HHI_GP0_PLL_CNTL2 0x44
#define HHI_GP0_PLL_CNTL3 0x48
......
......@@ -365,13 +365,14 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
unsigned int enabled, m, n, frac = 0, ret;
unsigned int enabled, m, n, frac = 0;
unsigned long old_rate;
int ret;
if (parent_rate == 0 || rate == 0)
return -EINVAL;
old_rate = rate;
old_rate = clk_hw_get_rate(hw);
ret = meson_clk_get_pll_settings(rate, parent_rate, &m, &n, pll);
if (ret)
......@@ -393,7 +394,8 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
if (!enabled)
return 0;
if (meson_clk_pll_enable(hw)) {
ret = meson_clk_pll_enable(hw);
if (ret) {
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
__func__, old_rate);
/*
......@@ -405,7 +407,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
meson_clk_pll_set_rate(hw, old_rate, parent_rate);
}
return 0;
return ret;
}
/*
......
......@@ -52,15 +52,6 @@ static const struct pll_params_table sys_pll_params_table[] = {
{ /* sentinel */ },
};
static struct clk_fixed_rate meson8b_xtal = {
.fixed_rate = 24000000,
.hw.init = &(struct clk_init_data){
.name = "xtal",
.num_parents = 0,
.ops = &clk_fixed_rate_ops,
},
};
static struct clk_regmap meson8b_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
......@@ -2715,7 +2706,6 @@ static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3);
static struct clk_hw_onecell_data meson8_hw_onecell_data = {
.hws = {
[CLKID_XTAL] = &meson8b_xtal.hw,
[CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
[CLKID_PLL_VID] = &meson8b_vid_pll.hw,
[CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
......@@ -2922,7 +2912,6 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = {
static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
.hws = {
[CLKID_XTAL] = &meson8b_xtal.hw,
[CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
[CLKID_PLL_VID] = &meson8b_vid_pll.hw,
[CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
......@@ -3140,7 +3129,6 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
static struct clk_hw_onecell_data meson8m2_hw_onecell_data = {
.hws = {
[CLKID_XTAL] = &meson8b_xtal.hw,
[CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
[CLKID_PLL_VID] = &meson8b_vid_pll.hw,
[CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
......@@ -3725,36 +3713,19 @@ static struct meson8b_nb_data meson8b_cpu_nb_data = {
.nb.notifier_call = meson8b_cpu_clk_notifier_cb,
};
static const struct regmap_config clkc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static void __init meson8b_clkc_init_common(struct device_node *np,
struct clk_hw_onecell_data *clk_hw_onecell_data)
{
struct meson8b_clk_reset *rstc;
const char *notifier_clk_name;
struct clk *notifier_clk;
void __iomem *clk_base;
struct regmap *map;
int i, ret;
map = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(map)) {
pr_info("failed to get HHI regmap - Trying obsolete regs\n");
/* Generic clocks, PLLs and some of the reset-bits */
clk_base = of_iomap(np, 1);
if (!clk_base) {
pr_err("%s: Unable to map clk base\n", __func__);
return;
}
map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config);
if (IS_ERR(map))
return;
pr_err("failed to get HHI regmap - Trying obsolete regs\n");
return;
}
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
......@@ -3778,16 +3749,10 @@ static void __init meson8b_clkc_init_common(struct device_node *np,
meson8b_clk_regmaps[i]->map = map;
/*
* always skip CLKID_UNUSED and also skip XTAL if the .dtb provides the
* XTAL clock as input.
* register all clks and start with the first used ID (which is
* CLKID_PLL_FIXED)
*/
if (!IS_ERR(of_clk_get_by_name(np, "xtal")))
i = CLKID_PLL_FIXED;
else
i = CLKID_XTAL;
/* register all clks */
for (; i < CLK_NR_CLKS; i++) {
for (i = CLKID_PLL_FIXED; i < CLK_NR_CLKS; i++) {
/* array might be sparse */
if (!clk_hw_onecell_data->hws[i])
continue;
......
# SPDX-License-Identifier: GPL-2.0-only
config MSTAR_MSC313_MPLL
bool "MStar MPLL driver"
depends on ARCH_MSTARV7 || COMPILE_TEST
default ARCH_MSTARV7
select REGMAP_MMIO
help
Support for the MPLL PLL and dividers block present on
MStar/Sigmastar SoCs.
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for mstar specific clk
#
obj-$(CONFIG_MSTAR_MSC313_MPLL) += clk-msc313-mpll.o
// SPDX-License-Identifier: GPL-2.0
/*
* MStar MSC313 MPLL driver
*
* Copyright (C) 2020 Daniel Palmer <daniel@thingy.jp>
*/
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#define REG_CONFIG1 0x8
#define REG_CONFIG2 0xc
static const struct regmap_config msc313_mpll_regmap_config = {
.reg_bits = 16,
.val_bits = 16,
.reg_stride = 4,
};
static const struct reg_field config1_loop_div_first = REG_FIELD(REG_CONFIG1, 8, 9);
static const struct reg_field config1_input_div_first = REG_FIELD(REG_CONFIG1, 4, 5);
static const struct reg_field config2_output_div_first = REG_FIELD(REG_CONFIG2, 12, 13);
static const struct reg_field config2_loop_div_second = REG_FIELD(REG_CONFIG2, 0, 7);
static const unsigned int output_dividers[] = {
2, 3, 4, 5, 6, 7, 10
};
#define NUMOUTPUTS (ARRAY_SIZE(output_dividers) + 1)
struct msc313_mpll {
struct clk_hw clk_hw;
struct regmap_field *input_div;
struct regmap_field *loop_div_first;
struct regmap_field *loop_div_second;
struct regmap_field *output_div;
struct clk_hw_onecell_data *clk_data;
};
#define to_mpll(_hw) container_of(_hw, struct msc313_mpll, clk_hw)
static unsigned long msc313_mpll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct msc313_mpll *mpll = to_mpll(hw);
unsigned int input_div, output_div, loop_first, loop_second;
unsigned long output_rate;
regmap_field_read(mpll->input_div, &input_div);
regmap_field_read(mpll->output_div, &output_div);
regmap_field_read(mpll->loop_div_first, &loop_first);
regmap_field_read(mpll->loop_div_second, &loop_second);
output_rate = parent_rate / (1 << input_div);
output_rate *= (1 << loop_first) * max(loop_second, 1U);
output_rate /= max(output_div, 1U);
return output_rate;
}
static const struct clk_ops msc313_mpll_ops = {
.recalc_rate = msc313_mpll_recalc_rate,
};
static const struct clk_parent_data mpll_parent = {
.index = 0,
};
static int msc313_mpll_probe(struct platform_device *pdev)
{
void __iomem *base;
struct msc313_mpll *mpll;
struct clk_init_data clk_init = { };
struct device *dev = &pdev->dev;
struct regmap *regmap;
char *outputname;
struct clk_hw *divhw;
int ret, i;
mpll = devm_kzalloc(dev, sizeof(*mpll), GFP_KERNEL);
if (!mpll)
return -ENOMEM;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(dev, base, &msc313_mpll_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
mpll->input_div = devm_regmap_field_alloc(dev, regmap, config1_input_div_first);
if (IS_ERR(mpll->input_div))
return PTR_ERR(mpll->input_div);
mpll->output_div = devm_regmap_field_alloc(dev, regmap, config2_output_div_first);
if (IS_ERR(mpll->output_div))
return PTR_ERR(mpll->output_div);
mpll->loop_div_first = devm_regmap_field_alloc(dev, regmap, config1_loop_div_first);
if (IS_ERR(mpll->loop_div_first))
return PTR_ERR(mpll->loop_div_first);
mpll->loop_div_second = devm_regmap_field_alloc(dev, regmap, config2_loop_div_second);
if (IS_ERR(mpll->loop_div_second))
return PTR_ERR(mpll->loop_div_second);
mpll->clk_data = devm_kzalloc(dev, struct_size(mpll->clk_data, hws,
ARRAY_SIZE(output_dividers)), GFP_KERNEL);
if (!mpll->clk_data)
return -ENOMEM;
clk_init.name = dev_name(dev);
clk_init.ops = &msc313_mpll_ops;
clk_init.parent_data = &mpll_parent;
clk_init.num_parents = 1;
mpll->clk_hw.init = &clk_init;
ret = devm_clk_hw_register(dev, &mpll->clk_hw);
if (ret)
return ret;
mpll->clk_data->num = NUMOUTPUTS;
mpll->clk_data->hws[0] = &mpll->clk_hw;
for (i = 0; i < ARRAY_SIZE(output_dividers); i++) {
outputname = devm_kasprintf(dev, GFP_KERNEL, "%s_div_%u",
clk_init.name, output_dividers[i]);
if (!outputname)
return -ENOMEM;
divhw = devm_clk_hw_register_fixed_factor(dev, outputname,
clk_init.name, 0, 1, output_dividers[i]);
if (IS_ERR(divhw))
return PTR_ERR(divhw);
mpll->clk_data->hws[i + 1] = divhw;
}
platform_set_drvdata(pdev, mpll);
return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
mpll->clk_data);
}
static const struct of_device_id msc313_mpll_of_match[] = {
{ .compatible = "mstar,msc313-mpll", },
{}
};
static struct platform_driver msc313_mpll_driver = {
.driver = {
.name = "mstar-msc313-mpll",
.of_match_table = msc313_mpll_of_match,
},
.probe = msc313_mpll_probe,
};
builtin_platform_driver(msc313_mpll_driver);
......@@ -30,7 +30,7 @@
#define APN806_MAX_DIVIDER 32
/**
/*
* struct cpu_dfs_regs: CPU DFS register mapping
* @divider_reg: full integer ratio from PLL frequency to CPU clock frequency
* @force_reg: request to force new ratio regardless of relation to other clocks
......
......@@ -28,6 +28,14 @@ config QCOM_A53PLL
Say Y if you want to support higher CPU frequencies on MSM8916
devices.
config QCOM_A7PLL
tristate "SDX55 A7 PLL"
help
Support for the A7 PLL on SDX55 devices. It provides the CPU with
frequencies above 1GHz.
Say Y if you want to support higher CPU frequencies on SDX55
devices.
config QCOM_CLK_APCS_MSM8916
tristate "MSM8916 APCS Clock Controller"
depends on QCOM_APCS_IPC || COMPILE_TEST
......@@ -46,6 +54,15 @@ config QCOM_CLK_APCC_MSM8996
Say Y if you want to support CPU clock scaling using CPUfreq
drivers for dynamic power management.
config QCOM_CLK_APCS_SDX55
tristate "SDX55 APCS Clock Controller"
depends on QCOM_APCS_IPC || COMPILE_TEST
help
Support for the APCS Clock Controller on SDX55 platform. The
APCS is managing the mux and divider which feeds the CPUs.
Say Y if you want to support CPU frequency scaling on devices
such as SDX55.
config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on MFD_QCOM_RPM
......@@ -317,6 +334,24 @@ config SC_GCC_7180
Say Y if you want to use peripheral devices such as UART, SPI,
I2C, USB, UFS, SDCC, etc.
config SC_GCC_7280
tristate "SC7280 Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on SC7280 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
I2C, USB, UFS, SDCC, PCIe etc.
config SC_GCC_8180X
tristate "SC8180X Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on SC8180X devices.
Say Y if you want to use peripheral devices such as UART, SPI,
I2C, USB, UFS, SDCC, etc.
config SC_LPASS_CORECC_7180
tristate "SC7180 LPASS Core Clock Controller"
select SC_GCC_7180
......@@ -366,6 +401,24 @@ config SDM_GCC_660
Say Y if you want to use peripheral devices such as UART, SPI,
i2C, USB, UFS, SDDC, PCIe, etc.
config SDM_MMCC_660
tristate "SDM660 Multimedia Clock Controller"
select SDM_GCC_660
select QCOM_GDSC
help
Support for the multimedia clock controller on SDM660 devices.
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
config SDM_GPUCC_660
tristate "SDM660 Graphics Clock Controller"
select SDM_GCC_660
select QCOM_GDSC
help
Support for the graphics clock controller on SDM630/636/660 devices.
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics
config QCS_TURING_404
tristate "QCS404 Turing Clock Controller"
help
......@@ -454,6 +507,14 @@ config SM_GCC_8250
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
config SM_GCC_8350
tristate "SM8350 Global Clock Controller"
select QCOM_GDSC
help
Support for the global clock controller on SM8350 devices.
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
config SM_GPUCC_8150
tristate "SM8150 Graphics Clock Controller"
select SM_GCC_8150
......
......@@ -44,8 +44,10 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
obj-$(CONFIG_MSM_MMCC_8998) += mmcc-msm8998.o
obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
obj-$(CONFIG_QCOM_A7PLL) += a7-pll.o
obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
obj-$(CONFIG_QCOM_CLK_APCS_SDX55) += apcs-sdx55.o
obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
......@@ -55,6 +57,8 @@ obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
obj-$(CONFIG_SC_CAMCC_7180) += camcc-sc7180.o
obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o
obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o
obj-$(CONFIG_SC_GCC_7280) += gcc-sc7280.o
obj-$(CONFIG_SC_GCC_8180X) += gcc-sc8180x.o
obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o
obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o
obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o
......@@ -62,6 +66,8 @@ obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o
obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
obj-$(CONFIG_SDM_MMCC_660) += mmcc-sdm660.o
obj-$(CONFIG_SDM_GPUCC_660) += gpucc-sdm660.o
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o
obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
......@@ -70,6 +76,7 @@ obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Qualcomm A7 PLL driver
*
* Copyright (c) 2020, Linaro Limited
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "clk-alpha-pll.h"
#define LUCID_PLL_OFF_L_VAL 0x04
static const struct pll_vco lucid_vco[] = {
{ 249600000, 2000000000, 0 },
};
static struct clk_alpha_pll a7pll = {
.offset = 0x100,
.vco_table = lucid_vco,
.num_vco = ARRAY_SIZE(lucid_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "a7pll",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_lucid_ops,
},
},
};
static const struct alpha_pll_config a7pll_config = {
.l = 0x39,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x2261,
.config_ctl_hi1_val = 0x029A699C,
.user_ctl_val = 0x1,
.user_ctl_hi_val = 0x805,
};
static const struct regmap_config a7pll_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x1000,
.fast_io = true,
};
static int qcom_a7pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regmap *regmap;
void __iomem *base;
u32 l_val;
int ret;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(dev, base, &a7pll_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
/* Configure PLL only if the l_val is zero */
regmap_read(regmap, a7pll.offset + LUCID_PLL_OFF_L_VAL, &l_val);
if (!l_val)
clk_lucid_pll_configure(&a7pll, regmap, &a7pll_config);
ret = devm_clk_register_regmap(dev, &a7pll.clkr);
if (ret)
return ret;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&a7pll.clkr.hw);
}
static const struct of_device_id qcom_a7pll_match_table[] = {
{ .compatible = "qcom,sdx55-a7pll" },
{ }
};
static struct platform_driver qcom_a7pll_driver = {
.probe = qcom_a7pll_probe,
.driver = {
.name = "qcom-a7pll",
.of_match_table = qcom_a7pll_match_table,
},
};
module_platform_driver(qcom_a7pll_driver);
MODULE_DESCRIPTION("Qualcomm A7 PLL Driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0
/*
* Qualcomm SDX55 APCS clock controller driver
*
* Copyright (c) 2020, Linaro Limited
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/cpu.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "clk-regmap.h"
#include "clk-regmap-mux-div.h"
static const u32 apcs_mux_clk_parent_map[] = { 0, 1, 5 };
static const struct clk_parent_data pdata[] = {
{ .fw_name = "ref" },
{ .fw_name = "aux" },
{ .fw_name = "pll" },
};
/*
* We use the notifier function for switching to a temporary safe configuration
* (mux and divider), while the A7 PLL is reconfigured.
*/
static int a7cc_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data)
{
int ret = 0;
struct clk_regmap_mux_div *md = container_of(nb,
struct clk_regmap_mux_div,
clk_nb);
if (event == PRE_RATE_CHANGE)
/* set the mux and divider to safe frequency (400mhz) */
ret = mux_div_set_src_div(md, 1, 2);
return notifier_from_errno(ret);
}
static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent = dev->parent;
struct device *cpu_dev;
struct clk_regmap_mux_div *a7cc;
struct regmap *regmap;
struct clk_init_data init = { };
int ret;
regmap = dev_get_regmap(parent, NULL);
if (!regmap) {
dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n");
return -ENODEV;
}
a7cc = devm_kzalloc(dev, sizeof(*a7cc), GFP_KERNEL);
if (!a7cc)
return -ENOMEM;
init.name = "a7mux";
init.parent_data = pdata;
init.num_parents = ARRAY_SIZE(pdata);
init.ops = &clk_regmap_mux_div_ops;
a7cc->clkr.hw.init = &init;
a7cc->clkr.regmap = regmap;
a7cc->reg_offset = 0x8;
a7cc->hid_width = 5;
a7cc->hid_shift = 0;
a7cc->src_width = 3;
a7cc->src_shift = 8;
a7cc->parent_map = apcs_mux_clk_parent_map;
a7cc->pclk = devm_clk_get(parent, "pll");
if (IS_ERR(a7cc->pclk)) {
ret = PTR_ERR(a7cc->pclk);
if (ret != -EPROBE_DEFER)
dev_err_probe(dev, ret, "Failed to get PLL clk\n");
return ret;
}
a7cc->clk_nb.notifier_call = a7cc_notifier_cb;
ret = clk_notifier_register(a7cc->pclk, &a7cc->clk_nb);
if (ret) {
dev_err_probe(dev, ret, "Failed to register clock notifier\n");
return ret;
}
ret = devm_clk_register_regmap(dev, &a7cc->clkr);
if (ret) {
dev_err_probe(dev, ret, "Failed to register regmap clock\n");
goto err;
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&a7cc->clkr.hw);
if (ret) {
dev_err_probe(dev, ret, "Failed to add clock provider\n");
goto err;
}
platform_set_drvdata(pdev, a7cc);
/*
* Attach the power domain to cpudev. Since there is no dedicated driver
* for CPUs and the SDX55 platform lacks hardware specific CPUFreq
* driver, there seems to be no better place to do this. So do it here!
*/
cpu_dev = get_cpu_device(0);
dev_pm_domain_attach(cpu_dev, true);
return 0;
err:
clk_notifier_unregister(a7cc->pclk, &a7cc->clk_nb);
return ret;
}
static int qcom_apcs_sdx55_clk_remove(struct platform_device *pdev)
{
struct device *cpu_dev = get_cpu_device(0);
struct clk_regmap_mux_div *a7cc = platform_get_drvdata(pdev);
clk_notifier_unregister(a7cc->pclk, &a7cc->clk_nb);
dev_pm_domain_detach(cpu_dev, true);
return 0;
}
static struct platform_driver qcom_apcs_sdx55_clk_driver = {
.probe = qcom_apcs_sdx55_clk_probe,
.remove = qcom_apcs_sdx55_clk_remove,
.driver = {
.name = "qcom-sdx55-acps-clk",
},
};
module_platform_driver(qcom_apcs_sdx55_clk_driver);
MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Qualcomm SDX55 APCS clock driver");
......@@ -156,6 +156,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
/* LUCID PLL specific settings and offsets */
#define LUCID_PCAL_DONE BIT(27)
/* LUCID 5LPE PLL specific settings and offsets */
#define LUCID_5LPE_PCAL_DONE BIT(11)
#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH BIT(13)
#define LUCID_5LPE_PLL_LATCH_INPUT BIT(14)
#define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21)
#define pll_alpha_width(p) \
((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
......@@ -777,15 +783,15 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,
static int trion_pll_is_enabled(struct clk_alpha_pll *pll,
struct regmap *regmap)
{
u32 mode_regval, opmode_regval;
u32 mode_val, opmode_val;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval);
ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval);
ret = regmap_read(regmap, PLL_MODE(pll), &mode_val);
ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_val);
if (ret)
return 0;
return ((opmode_regval & PLL_RUN) && (mode_regval & PLL_OUTCTRL));
return ((opmode_val & PLL_RUN) && (mode_val & PLL_OUTCTRL));
}
static int clk_trion_pll_is_enabled(struct clk_hw *hw)
......@@ -1445,12 +1451,12 @@ EXPORT_SYMBOL_GPL(clk_trion_pll_configure);
static int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
u32 regval;
u32 val;
int ret;
/* Return early if calibration is not needed. */
regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &regval);
if (regval & pcal_done)
regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &val);
if (val & pcal_done)
return 0;
/* On/off to calibrate */
......@@ -1471,12 +1477,12 @@ static int alpha_pll_lucid_prepare(struct clk_hw *hw)
return __alpha_pll_trion_prepare(hw, LUCID_PCAL_DONE);
}
static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
static int __alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate, u32 latch_bit, u32 latch_ack)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
unsigned long rrate;
u32 regval, l, alpha_width = pll_alpha_width(pll);
u32 val, l, alpha_width = pll_alpha_width(pll);
u64 a;
int ret;
......@@ -1490,22 +1496,20 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
/* Latch the PLL input */
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_UPDATE, PLL_UPDATE);
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), latch_bit, latch_bit);
if (ret)
return ret;
/* Wait for 2 reference cycles before checking the ACK bit. */
udelay(1);
regmap_read(pll->clkr.regmap, PLL_MODE(pll), &regval);
if (!(regval & ALPHA_PLL_ACK_LATCH)) {
regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (!(val & latch_ack)) {
pr_err("Lucid PLL latch failed. Output may be unstable!\n");
return -EINVAL;
}
/* Return the latch input to 0 */
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_UPDATE, 0);
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), latch_bit, 0);
if (ret)
return ret;
......@@ -1520,6 +1524,12 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
return __alpha_pll_trion_set_rate(hw, rate, prate, PLL_UPDATE, ALPHA_PLL_ACK_LATCH);
}
const struct clk_ops clk_alpha_pll_trion_ops = {
.prepare = alpha_pll_trion_prepare,
.enable = clk_trion_pll_enable,
......@@ -1600,3 +1610,170 @@ const struct clk_ops clk_alpha_pll_agera_ops = {
.set_rate = clk_alpha_pll_agera_set_rate,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
u32 val;
int ret;
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
if (ret)
return ret;
/* If in FSM mode, just vote for it */
if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
ret = clk_enable_regmap(hw);
if (ret)
return ret;
return wait_for_pll_enable_lock(pll);
}
/* Check if PLL is already enabled, return if enabled */
ret = trion_pll_is_enabled(pll, pll->clkr.regmap);
if (ret < 0)
return ret;
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
if (ret)
return ret;
regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN);
ret = wait_for_pll_enable_lock(pll);
if (ret)
return ret;
/* Enable the PLL outputs */
ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
if (ret)
return ret;
/* Enable the global PLL outputs */
return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
}
static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
u32 val;
int ret;
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
if (ret)
return;
/* If in FSM mode, just unvote it */
if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
clk_disable_regmap(hw);
return;
}
/* Disable the global PLL output */
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
if (ret)
return;
/* Disable the PLL outputs */
ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
if (ret)
return;
/* Place the PLL mode in STANDBY */
regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY);
}
/*
* The Lucid 5LPE PLL requires a power-on self-calibration which happens
* when the PLL comes out of reset. Calibrate in case it is not completed.
*/
static int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct clk_hw *p;
u32 val = 0;
int ret;
/* Return early if calibration is not needed. */
regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (val & LUCID_5LPE_PCAL_DONE)
return 0;
p = clk_hw_get_parent(hw);
if (!p)
return -EINVAL;
ret = alpha_pll_lucid_5lpe_enable(hw);
if (ret)
return ret;
alpha_pll_lucid_5lpe_disable(hw);
return 0;
}
static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
return __alpha_pll_trion_set_rate(hw, rate, prate,
LUCID_5LPE_PLL_LATCH_INPUT,
LUCID_5LPE_ALPHA_PLL_ACK_LATCH);
}
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
int i, val = 0, div, ret;
u32 mask;
/*
* If the PLL is in FSM mode, then treat set_rate callback as a
* no-operation.
*/
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
if (ret)
return ret;
if (val & LUCID_5LPE_ENABLE_VOTE_RUN)
return 0;
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].div == div) {
val = pll->post_div_table[i].val;
break;
}
}
mask = GENMASK(pll->width + pll->post_div_shift - 1, pll->post_div_shift);
return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
mask, val << pll->post_div_shift);
}
const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
.prepare = alpha_pll_lucid_5lpe_prepare,
.enable = alpha_pll_lucid_5lpe_enable,
.disable = alpha_pll_lucid_5lpe_disable,
.is_enabled = clk_trion_pll_is_enabled,
.recalc_rate = clk_trion_pll_recalc_rate,
.round_rate = clk_alpha_pll_round_rate,
.set_rate = alpha_pll_lucid_5lpe_set_rate,
};
EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops);
const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops = {
.enable = alpha_pll_lucid_5lpe_enable,
.disable = alpha_pll_lucid_5lpe_disable,
.is_enabled = clk_trion_pll_is_enabled,
.recalc_rate = clk_trion_pll_recalc_rate,
.round_rate = clk_alpha_pll_round_rate,
};
EXPORT_SYMBOL(clk_alpha_pll_fixed_lucid_5lpe_ops);
const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = {
.recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,
.round_rate = clk_alpha_pll_postdiv_fabia_round_rate,
.set_rate = clk_lucid_5lpe_pll_postdiv_set_rate,
};
EXPORT_SYMBOL(clk_alpha_pll_postdiv_lucid_5lpe_ops);
......@@ -144,6 +144,10 @@ extern const struct clk_ops clk_alpha_pll_lucid_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
extern const struct clk_ops clk_alpha_pll_agera_ops;
extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops;
extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
......
......@@ -153,6 +153,15 @@ struct clk_rcg2 {
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
struct clk_rcg2_gfx3d {
u8 div;
struct clk_rcg2 rcg;
struct clk_hw **hws;
};
#define to_clk_rcg2_gfx3d(_hw) \
container_of(to_clk_rcg2(_hw), struct clk_rcg2_gfx3d, rcg)
extern const struct clk_ops clk_rcg2_ops;
extern const struct clk_ops clk_rcg2_floor_ops;
extern const struct clk_ops clk_edp_pixel_ops;
......
......@@ -728,40 +728,51 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_rate_request parent_req = { };
struct clk_hw *p2, *p8, *p9, *xo;
unsigned long p9_rate;
struct clk_rcg2_gfx3d *cgfx = to_clk_rcg2_gfx3d(hw);
struct clk_hw *xo, *p0, *p1, *p2;
unsigned long request, p0_rate;
int ret;
p0 = cgfx->hws[0];
p1 = cgfx->hws[1];
p2 = cgfx->hws[2];
/*
* This function does ping-pong the RCG between PLLs: if we don't
* have at least one fixed PLL and two variable ones,
* then it's not going to work correctly.
*/
if (WARN_ON(!p0 || !p1 || !p2))
return -EINVAL;
xo = clk_hw_get_parent_by_index(hw, 0);
if (req->rate == clk_hw_get_rate(xo)) {
req->best_parent_hw = xo;
return 0;
}
p9 = clk_hw_get_parent_by_index(hw, 2);
p2 = clk_hw_get_parent_by_index(hw, 3);
p8 = clk_hw_get_parent_by_index(hw, 4);
request = req->rate;
if (cgfx->div > 1)
parent_req.rate = request = request * cgfx->div;
/* PLL9 is a fixed rate PLL */
p9_rate = clk_hw_get_rate(p9);
/* This has to be a fixed rate PLL */
p0_rate = clk_hw_get_rate(p0);
parent_req.rate = req->rate = min(req->rate, p9_rate);
if (req->rate == p9_rate) {
req->rate = req->best_parent_rate = p9_rate;
req->best_parent_hw = p9;
if (request == p0_rate) {
req->rate = req->best_parent_rate = p0_rate;
req->best_parent_hw = p0;
return 0;
}
if (req->best_parent_hw == p9) {
if (req->best_parent_hw == p0) {
/* Are we going back to a previously used rate? */
if (clk_hw_get_rate(p8) == req->rate)
req->best_parent_hw = p8;
else
if (clk_hw_get_rate(p2) == request)
req->best_parent_hw = p2;
} else if (req->best_parent_hw == p8) {
req->best_parent_hw = p2;
else
req->best_parent_hw = p1;
} else if (req->best_parent_hw == p2) {
req->best_parent_hw = p1;
} else {
req->best_parent_hw = p8;
req->best_parent_hw = p2;
}
ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
......@@ -769,6 +780,8 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw,
return ret;
req->rate = req->best_parent_rate = parent_req.rate;
if (cgfx->div > 1)
req->rate /= cgfx->div;
return 0;
}
......@@ -776,12 +789,16 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw,
static int clk_gfx3d_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate, u8 index)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
struct clk_rcg2_gfx3d *cgfx = to_clk_rcg2_gfx3d(hw);
struct clk_rcg2 *rcg = &cgfx->rcg;
u32 cfg;
int ret;
/* Just mux it, we don't use the division or m/n hardware */
cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
/* On some targets, the GFX3D RCG may need to divide PLL frequency */
if (cgfx->div > 1)
cfg |= ((2 * cgfx->div) - 1) << CFG_SRC_DIV_SHIFT;
ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg);
if (ret)
return ret;
......
......@@ -87,6 +87,7 @@ EXPORT_SYMBOL_GPL(clk_disable_regmap);
/**
* devm_clk_register_regmap - register a clk_regmap clock
*
* @dev: reference to the caller's device
* @rclk: clk to operate on
*
* Clocks that use regmap for their register I/O should register their
......
......@@ -73,62 +73,6 @@
}, \
}
#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \
static struct clk_rpm _platform##_##_active; \
static struct clk_rpm _platform##_##_name = { \
.rpm_clk_id = (r_id), \
.active_only = true, \
.peer = &_platform##_##_active, \
.rate = (r), \
.branch = true, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_branch_ops, \
.name = #_name, \
.parent_names = (const char *[]){ "pxo_board" }, \
.num_parents = 1, \
}, \
}; \
static struct clk_rpm _platform##_##_active = { \
.rpm_clk_id = (r_id), \
.peer = &_platform##_##_name, \
.rate = (r), \
.branch = true, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_branch_ops, \
.name = #_active, \
.parent_names = (const char *[]){ "pxo_board" }, \
.num_parents = 1, \
}, \
}
#define DEFINE_CLK_RPM_CXO_BRANCH(_platform, _name, _active, r_id, r) \
static struct clk_rpm _platform##_##_active; \
static struct clk_rpm _platform##_##_name = { \
.rpm_clk_id = (r_id), \
.peer = &_platform##_##_active, \
.rate = (r), \
.branch = true, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_branch_ops, \
.name = #_name, \
.parent_names = (const char *[]){ "cxo_board" }, \
.num_parents = 1, \
}, \
}; \
static struct clk_rpm _platform##_##_active = { \
.rpm_clk_id = (r_id), \
.active_only = true, \
.peer = &_platform##_##_name, \
.rate = (r), \
.branch = true, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_branch_ops, \
.name = #_active, \
.parent_names = (const char *[]){ "cxo_board" }, \
.num_parents = 1, \
}, \
}
#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
struct rpm_cc;
......@@ -450,13 +394,6 @@ static const struct clk_ops clk_rpm_ops = {
.recalc_rate = clk_rpm_recalc_rate,
};
static const struct clk_ops clk_rpm_branch_ops = {
.prepare = clk_rpm_prepare,
.unprepare = clk_rpm_unprepare,
.round_rate = clk_rpm_round_rate,
.recalc_rate = clk_rpm_recalc_rate,
};
/* MSM8660/APQ8060 */
DEFINE_CLK_RPM(msm8660, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
DEFINE_CLK_RPM(msm8660, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
......@@ -348,6 +348,10 @@ DEFINE_CLK_RPMH_VRM(sdm845, rf_clk1, rf_clk1_ao, "rfclka1", 1);
DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1);
DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk3, rf_clk3_ao, "rfclkd3", 1);
DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk4, rf_clk4_ao, "rfclkd4", 1);
DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0");
DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0");
......@@ -431,6 +435,26 @@ static const struct clk_rpmh_desc clk_rpmh_sc7180 = {
.num_clks = ARRAY_SIZE(sc7180_rpmh_clocks),
};
static struct clk_hw *sc8180x_rpmh_clocks[] = {
[RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
[RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
[RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
[RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
[RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
[RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
[RPMH_RF_CLK1] = &sc8180x_rf_clk1.hw,
[RPMH_RF_CLK1_A] = &sc8180x_rf_clk1_ao.hw,
[RPMH_RF_CLK2] = &sc8180x_rf_clk2.hw,
[RPMH_RF_CLK2_A] = &sc8180x_rf_clk2_ao.hw,
[RPMH_RF_CLK3] = &sc8180x_rf_clk3.hw,
[RPMH_RF_CLK3_A] = &sc8180x_rf_clk3_ao.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sc8180x = {
.clks = sc8180x_rpmh_clocks,
.num_clks = ARRAY_SIZE(sc8180x_rpmh_clocks),
};
DEFINE_CLK_RPMH_VRM(sm8250, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 2);
static struct clk_hw *sm8250_rpmh_clocks[] = {
......@@ -486,6 +510,27 @@ static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
.num_clks = ARRAY_SIZE(sm8350_rpmh_clocks),
};
static struct clk_hw *sc7280_rpmh_clocks[] = {
[RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
[RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
[RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
[RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
[RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
[RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
[RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
[RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
[RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
[RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
[RPMH_IPA_CLK] = &sdm845_ipa.hw,
[RPMH_PKA_CLK] = &sm8350_pka.hw,
[RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sc7280 = {
.clks = sc7280_rpmh_clocks,
.num_clks = ARRAY_SIZE(sc7280_rpmh_clocks),
};
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
......@@ -570,11 +615,13 @@ static int clk_rpmh_probe(struct platform_device *pdev)
static const struct of_device_id clk_rpmh_match_table[] = {
{ .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180},
{ .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
{ .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
{ .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
{ .compatible = "qcom,sc7280-rpmh-clk", .data = &clk_rpmh_sc7280},
{ }
};
MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);
......
......@@ -1276,16 +1276,15 @@ static int clk_cpu_div_set_rate(struct clk_hw *hw, unsigned long rate,
struct clk_fepll *pll = to_clk_fepll(hw);
const struct freq_tbl *f;
u32 mask;
int ret;
f = qcom_find_freq(pll->freq_tbl, rate);
if (!f)
return -EINVAL;
mask = (BIT(pll->cdiv.width) - 1) << pll->cdiv.shift;
ret = regmap_update_bits(pll->cdiv.clkr.regmap,
pll->cdiv.reg, mask,
f->pre_div << pll->cdiv.shift);
regmap_update_bits(pll->cdiv.clkr.regmap,
pll->cdiv.reg, mask,
f->pre_div << pll->cdiv.shift);
/*
* There is no status bit which can be checked for successful CPU
* divider update operation so using delay for the same.
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
......@@ -919,19 +919,6 @@ static struct clk_branch gcc_camera_throttle_hf_axi_clk = {
},
};
static struct clk_branch gcc_camera_xo_clk = {
.halt_reg = 0xb02c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0xb02c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_camera_xo_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ce1_ahb_clk = {
.halt_reg = 0x4100c,
.halt_check = BRANCH_HALT_VOTED,
......@@ -1096,19 +1083,6 @@ static struct clk_branch gcc_disp_throttle_hf_axi_clk = {
},
};
static struct clk_branch gcc_disp_xo_clk = {
.halt_reg = 0xb030,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0xb030,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_disp_xo_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_gp1_clk = {
.halt_reg = 0x64000,
.halt_check = BRANCH_HALT,
......@@ -2159,19 +2133,6 @@ static struct clk_branch gcc_video_throttle_axi_clk = {
},
};
static struct clk_branch gcc_video_xo_clk = {
.halt_reg = 0xb028,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0xb028,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_video_xo_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_mss_cfg_ahb_clk = {
.halt_reg = 0x8a000,
.halt_check = BRANCH_HALT,
......@@ -2304,7 +2265,6 @@ static struct clk_regmap *gcc_sc7180_clocks[] = {
[GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
[GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr,
[GCC_CAMERA_THROTTLE_HF_AXI_CLK] = &gcc_camera_throttle_hf_axi_clk.clkr,
[GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr,
[GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr,
[GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr,
[GCC_CE1_CLK] = &gcc_ce1_clk.clkr,
......@@ -2317,7 +2277,6 @@ static struct clk_regmap *gcc_sc7180_clocks[] = {
[GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr,
[GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr,
[GCC_DISP_THROTTLE_HF_AXI_CLK] = &gcc_disp_throttle_hf_axi_clk.clkr,
[GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr,
[GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
[GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr,
[GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
......@@ -2413,7 +2372,6 @@ static struct clk_regmap *gcc_sc7180_clocks[] = {
[GCC_VIDEO_AXI_CLK] = &gcc_video_axi_clk.clkr,
[GCC_VIDEO_GPLL0_DIV_CLK_SRC] = &gcc_video_gpll0_div_clk_src.clkr,
[GCC_VIDEO_THROTTLE_AXI_CLK] = &gcc_video_throttle_axi_clk.clkr,
[GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr,
[GPLL0] = &gpll0.clkr,
[GPLL0_OUT_EVEN] = &gpll0_out_even.clkr,
[GPLL6] = &gpll6.clkr,
......@@ -2510,6 +2468,9 @@ static int gcc_sc7180_probe(struct platform_device *pdev)
regmap_update_bits(regmap, 0x0b004, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x0b008, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x0b00c, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x0b02c, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x0b028, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x0b030, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0));
ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
......
This diff is collapsed.
This diff is collapsed.
......@@ -1571,6 +1571,7 @@ static struct clk_branch gcc_gpu_cfg_ahb_clk = {
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_cfg_ahb_clk",
.ops = &clk_branch2_ops,
.flags = CLK_IS_CRITICAL,
},
},
};
......@@ -1684,6 +1685,12 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
.hw.init = &(struct clk_init_data){
.name = "gcc_mmss_noc_cfg_ahb_clk",
.ops = &clk_branch2_ops,
/*
* Any access to mmss depends on this clock.
* Gating this clock has been shown to crash the system
* when mmssnoc_axi_rpm_clk is inited in rpmcc.
*/
.flags = CLK_IS_CRITICAL,
},
},
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment