Merge 8653b778e4 ("Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux") into android-mainline
Steps on the way to 5.11-rc1 Change-Id: If3b02fe9ca1069cdd0416a9623cb90535c7977f6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
53
Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
Normal file
53
Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
Normal file
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/adi,axi-clkgen.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Binding for Analog Devices AXI clkgen pcore clock generator
|
||||
|
||||
maintainers:
|
||||
- Lars-Peter Clausen <lars@metafoo.de>
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
|
||||
description: |
|
||||
The axi_clkgen IP core is a software programmable clock generator,
|
||||
that can be synthesized on various FPGA platforms.
|
||||
|
||||
Link: https://wiki.analog.com/resources/fpga/docs/axi_clkgen
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,axi-clkgen-2.00.a
|
||||
|
||||
clocks:
|
||||
description:
|
||||
Specifies the reference clock(s) from which the output frequency is
|
||||
derived. This must either reference one clock if only the first clock
|
||||
input is connected or two if both clock inputs are connected.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@ff000000 {
|
||||
compatible = "adi,axi-clkgen-2.00.a";
|
||||
#clock-cells = <0>;
|
||||
reg = <0xff000000 0x1000>;
|
||||
clocks = <&osc 1>;
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
Binding for the axi-clkgen clock generator
|
||||
|
||||
This binding uses the common clock binding[1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be "adi,axi-clkgen-1.00.a" or "adi,axi-clkgen-2.00.a".
|
||||
- #clock-cells : from common clock binding; Should always be set to 0.
|
||||
- reg : Address and length of the axi-clkgen register set.
|
||||
- clocks : Phandle and clock specifier for the parent clock(s). This must
|
||||
either reference one clock if only the first clock input is connected or two
|
||||
if both clock inputs are connected. For the later case the clock connected
|
||||
to the first input must be specified first.
|
||||
|
||||
Optional properties:
|
||||
- clock-output-names : From common clock binding.
|
||||
|
||||
Example:
|
||||
clock@ff000000 {
|
||||
compatible = "adi,axi-clkgen";
|
||||
#clock-cells = <0>;
|
||||
reg = <0xff000000 0x1000>;
|
||||
clocks = <&osc 1>;
|
||||
};
|
||||
54
Documentation/devicetree/bindings/clock/canaan,k210-clk.yaml
Normal file
54
Documentation/devicetree/bindings/clock/canaan,k210-clk.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/canaan,k210-clk.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Canaan Kendryte K210 Clock Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Damien Le Moal <damien.lemoal@wdc.com>
|
||||
|
||||
description: |
|
||||
Canaan Kendryte K210 SoC clocks driver bindings. The clock
|
||||
controller node must be defined as a child node of the K210
|
||||
system controller node.
|
||||
|
||||
See also:
|
||||
- dt-bindings/clock/k210-clk.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: canaan,k210-clk
|
||||
|
||||
clocks:
|
||||
description:
|
||||
Phandle of the SoC 26MHz fixed-rate oscillator clock.
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#clock-cells'
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/k210-clk.h>
|
||||
clocks {
|
||||
in0: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <26000000>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ... */
|
||||
sysclk: clock-controller {
|
||||
#clock-cells = <1>;
|
||||
compatible = "canaan,k210-clk";
|
||||
clocks = <&in0>;
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/fsl,flexspi-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale FlexSPI clock driver for Layerscape SoCs
|
||||
|
||||
maintainers:
|
||||
- Michael Walle <michael@walle.cc>
|
||||
|
||||
description:
|
||||
The Freescale Layerscape SoCs have a special FlexSPI clock which is
|
||||
derived from the platform PLL.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,ls1028a-flexspi-clk
|
||||
- fsl,lx2160a-flexspi-clk
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dcfg {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
fspi_clk: clock-controller@900 {
|
||||
compatible = "fsl,ls1028a-flexspi-clk";
|
||||
reg = <0x900 0x4>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&parentclk>;
|
||||
clock-output-names = "fspi_clk";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,aoncc-sm8250.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Clock bindings for LPASS Always ON Clock Controller on SM8250 SoCs
|
||||
|
||||
maintainers:
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
|
||||
description: |
|
||||
The clock consumer should specify the desired clock by having the clock
|
||||
ID in its "clocks" phandle cell.
|
||||
See include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h for the full list
|
||||
of Audio Clock controller clock IDs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8250-lpass-aon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: LPASS Core voting clock
|
||||
- description: Glitch Free Mux register clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: bus
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#clock-cells'
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
|
||||
#include <dt-bindings/sound/qcom,q6afe.h>
|
||||
clock-controller@3800000 {
|
||||
#clock-cells = <1>;
|
||||
compatible = "qcom,sm8250-lpass-aon";
|
||||
reg = <0x03380000 0x40000>;
|
||||
clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
|
||||
clock-names = "core", "bus";
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,audiocc-sm8250.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Clock bindings for LPASS Audio Clock Controller on SM8250 SoCs
|
||||
|
||||
maintainers:
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
|
||||
description: |
|
||||
The clock consumer should specify the desired clock by having the clock
|
||||
ID in its "clocks" phandle cell.
|
||||
See include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h for the full list
|
||||
of Audio Clock controller clock IDs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8250-lpass-audiocc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: LPASS Core voting clock
|
||||
- description: Glitch Free Mux register clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: bus
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#clock-cells'
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,sm8250-lpass-audiocc.h>
|
||||
#include <dt-bindings/sound/qcom,q6afe.h>
|
||||
clock-controller@3300000 {
|
||||
#clock-cells = <1>;
|
||||
compatible = "qcom,sm8250-lpass-audiocc";
|
||||
reg = <0x03300000 0x30000>;
|
||||
clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
|
||||
clock-names = "core", "bus";
|
||||
};
|
||||
77
Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml
Normal file
77
Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,gcc-sdx55.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Global Clock & Reset Controller Binding for SDX55
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
description: |
|
||||
Qualcomm global clock control module which supports the clocks, resets and
|
||||
power domains on SDX55
|
||||
|
||||
See also:
|
||||
- dt-bindings/clock/qcom,gcc-sdx55.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,gcc-sdx55
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Board XO source
|
||||
- description: Sleep clock source
|
||||
- description: PLL test clock source (Optional clock)
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bi_tcxo
|
||||
- const: sleep_clk
|
||||
- const: core_bi_pll_test_se # Optional clock
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
'#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-sdx55";
|
||||
reg = <0x00100000 0x1f0000>;
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>,
|
||||
<&sleep_clk>, <&pll_test_clk>;
|
||||
clock-names = "bi_tcxo", "sleep_clk", "core_bi_pll_test_se";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
...
|
||||
@@ -19,8 +19,10 @@ properties:
|
||||
enum:
|
||||
- qcom,sc7180-rpmh-clk
|
||||
- qcom,sdm845-rpmh-clk
|
||||
- qcom,sdx55-rpmh-clk
|
||||
- qcom,sm8150-rpmh-clk
|
||||
- qcom,sm8250-rpmh-clk
|
||||
- qcom,sm8350-rpmh-clk
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,sc7180-camcc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Camera Clock & Reset Controller Binding for SC7180
|
||||
|
||||
maintainers:
|
||||
- Taniya Das <tdas@codeaurora.org>
|
||||
|
||||
description: |
|
||||
Qualcomm camera clock control module which supports the clocks, resets and
|
||||
power domains on SC7180.
|
||||
|
||||
See also:
|
||||
- dt-bindings/clock/qcom,camcc-sc7180.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sc7180-camcc
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Board XO source
|
||||
- description: Camera_ahb clock from GCC
|
||||
- description: Camera XO clock from GCC
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bi_tcxo
|
||||
- const: iface
|
||||
- const: xo
|
||||
|
||||
'#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-sc7180.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
clock-controller@ad00000 {
|
||||
compatible = "qcom,sc7180-camcc";
|
||||
reg = <0x0ad00000 0x10000>;
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>,
|
||||
<&gcc GCC_CAMERA_AHB_CLK>,
|
||||
<&gcc GCC_CAMERA_XO_CLK>;
|
||||
clock-names = "bi_tcxo", "iface", "xo";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
...
|
||||
@@ -1,68 +0,0 @@
|
||||
* Renesas R-Car USB 2.0 clock selector
|
||||
|
||||
This file provides information on what the device node for the R-Car USB 2.0
|
||||
clock selector.
|
||||
|
||||
If you connect an external clock to the USB_EXTAL pin only, you should set
|
||||
the clock rate to "usb_extal" node only.
|
||||
If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module
|
||||
is not needed because this is default setting. (Of course, you can set the
|
||||
clock rates to both "usb_extal" and "usb_xtal" nodes.
|
||||
|
||||
Case 1: An external clock connects to R-Car SoC
|
||||
+----------+ +--- R-Car ---------------------+
|
||||
|External |---|USB_EXTAL ---> all usb channels|
|
||||
|clock | |USB_XTAL |
|
||||
+----------+ +-------------------------------+
|
||||
In this case, we need this driver with "usb_extal" clock.
|
||||
|
||||
Case 2: An oscillator connects to R-Car SoC
|
||||
+----------+ +--- R-Car ---------------------+
|
||||
|Oscillator|---|USB_EXTAL -+-> all usb channels|
|
||||
| |---|USB_XTAL --+ |
|
||||
+----------+ +-------------------------------+
|
||||
In this case, we don't need this selector.
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,r8a7795-rcar-usb2-clock-sel" if the device is a part of
|
||||
an R8A7795 SoC.
|
||||
"renesas,r8a7796-rcar-usb2-clock-sel" if the device if a part of
|
||||
an R8A77960 SoC.
|
||||
"renesas,r8a77961-rcar-usb2-clock-sel" if the device if a part of
|
||||
an R8A77961 SoC.
|
||||
"renesas,rcar-gen3-usb2-clock-sel" for a generic R-Car Gen3
|
||||
compatible device.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first
|
||||
followed by the generic version.
|
||||
|
||||
- reg: offset and length of the USB 2.0 clock selector register block.
|
||||
- clocks: A list of phandles and specifier pairs.
|
||||
- clock-names: Name of the clocks.
|
||||
- The functional clock of USB 2.0 host side must be "ehci_ohci"
|
||||
- The functional clock of HS-USB side must be "hs-usb-if"
|
||||
- The USB_EXTAL clock pin must be "usb_extal"
|
||||
- The USB_XTAL clock pin must be "usb_xtal"
|
||||
- #clock-cells: Must be 0
|
||||
- power-domains: A phandle and symbolic PM domain specifier.
|
||||
See power/renesas,rcar-sysc.yaml.
|
||||
- resets: A list of phandles and specifier pairs.
|
||||
- reset-names: Name of the resets.
|
||||
- The reset of USB 2.0 host side must be "ehci_ohci"
|
||||
- The reset of HS-USB side must be "hs-usb-if"
|
||||
|
||||
Example (R-Car H3):
|
||||
|
||||
usb2_clksel: clock-controller@e6590630 {
|
||||
compatible = "renesas,r8a7795-rcar-usb2-clock-sel",
|
||||
"renesas,rcar-gen3-usb2-clock-sel";
|
||||
reg = <0 0xe6590630 0 0x02>;
|
||||
clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>,
|
||||
<&usb_extal>, <&usb_xtal>;
|
||||
clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal";
|
||||
#clock-cells = <0>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 703>, <&cpg 704>;
|
||||
reset-names = "ehci_ohci", "hs-usb-if";
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/clock/renesas,rcar-usb2-clock-sel.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Renesas R-Car USB 2.0 clock selector
|
||||
|
||||
maintainers:
|
||||
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
|
||||
description: |
|
||||
If you connect an external clock to the USB_EXTAL pin only, you should set
|
||||
the clock rate to "usb_extal" node only.
|
||||
If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module
|
||||
is not needed because this is default setting. (Of course, you can set the
|
||||
clock rates to both "usb_extal" and "usb_xtal" nodes.
|
||||
|
||||
Case 1: An external clock connects to R-Car SoC
|
||||
+----------+ +--- R-Car ---------------------+
|
||||
|External |---|USB_EXTAL ---> all usb channels|
|
||||
|clock | |USB_XTAL |
|
||||
+----------+ +-------------------------------+
|
||||
|
||||
In this case, we need this driver with "usb_extal" clock.
|
||||
|
||||
Case 2: An oscillator connects to R-Car SoC
|
||||
+----------+ +--- R-Car ---------------------+
|
||||
|Oscillator|---|USB_EXTAL -+-> all usb channels|
|
||||
| |---|USB_XTAL --+ |
|
||||
+----------+ +-------------------------------+
|
||||
In this case, we don't need this selector.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- 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+
|
||||
- const: renesas,rcar-gen3-usb2-clock-sel
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ehci_ohci
|
||||
- const: hs-usb-if
|
||||
- const: usb_extal
|
||||
- const: usb_xtal
|
||||
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: ehci_ohci
|
||||
- const: hs-usb-if
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- power-domains
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
usb2_clksel: clock-controller@e6590630 {
|
||||
compatible = "renesas,r8a7795-rcar-usb2-clock-sel",
|
||||
"renesas,rcar-gen3-usb2-clock-sel";
|
||||
reg = <0xe6590630 0x02>;
|
||||
clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>,
|
||||
<&usb_extal>, <&usb_xtal>;
|
||||
clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal";
|
||||
#clock-cells = <0>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 703>, <&cpg 704>;
|
||||
reset-names = "ehci_ohci", "hs-usb-if";
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2020 SiFive, Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/sifive/fu740-prci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SiFive FU740 Power Reset Clock Interrupt Controller (PRCI)
|
||||
|
||||
maintainers:
|
||||
- Zong Li <zong.li@sifive.com>
|
||||
- Paul Walmsley <paul.walmsley@sifive.com>
|
||||
|
||||
description:
|
||||
On the FU740 family of SoCs, most system-wide clock and reset integration
|
||||
is via the PRCI IP block.
|
||||
The clock consumer should specify the desired clock via the clock ID
|
||||
macros defined in include/dt-bindings/clock/sifive-fu740-prci.h.
|
||||
These macros begin with PRCI_CLK_.
|
||||
|
||||
The hfclk and rtcclk nodes are required, and represent physical
|
||||
crystals or resonators located on the PCB. These nodes should be present
|
||||
underneath /, rather than /soc.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sifive,fu740-c000-prci
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: high frequency clock.
|
||||
- description: RTL clock.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: hfclk
|
||||
- const: rtcclk
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- "#clock-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
prci: clock-controller@10000000 {
|
||||
compatible = "sifive,fu740-c000-prci";
|
||||
reg = <0x10000000 0x1000>;
|
||||
clocks = <&hfclk>, <&rtcclk>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
@@ -187,6 +187,8 @@ patternProperties:
|
||||
description: CALAO Systems SAS
|
||||
"^calxeda,.*":
|
||||
description: Calxeda
|
||||
"^canaan,.*":
|
||||
description: Canaan, Inc.
|
||||
"^caninos,.*":
|
||||
description: Caninos Loucos Program
|
||||
"^capella,.*":
|
||||
|
||||
@@ -15121,7 +15121,7 @@ RENESAS CLOCK DRIVERS
|
||||
M: Geert Uytterhoeven <geert+renesas@glider.be>
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git clk-renesas
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git renesas-clk
|
||||
F: Documentation/devicetree/bindings/clock/renesas,*
|
||||
F: drivers/clk/renesas/
|
||||
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
|
||||
# 68328, 68EZ328, 68VZ328
|
||||
|
||||
obj-y += entry.o ints.o timers.o
|
||||
obj-$(CONFIG_M68328) += m68328.o
|
||||
obj-$(CONFIG_M68EZ328) += m68EZ328.o
|
||||
obj-$(CONFIG_M68VZ328) += m68VZ328.o
|
||||
obj-y += entry.o ints.o timers.o m68328.o
|
||||
obj-$(CONFIG_ROM) += romvec.o
|
||||
|
||||
obj-$(CONFIG_DRAGEN2) += dragen2.o
|
||||
obj-$(CONFIG_UCSIMM) += ucsimm.o
|
||||
obj-$(CONFIG_UCDIMM) += ucsimm.o
|
||||
|
||||
extra-y := head.o
|
||||
|
||||
100
arch/m68k/68000/dragen2.c
Normal file
100
arch/m68k/68000/dragen2.c
Normal file
@@ -0,0 +1,100 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 1993 Hamish Macdonald
|
||||
* Copyright (C) 1999 D. Jeff Dionne
|
||||
* Copyright (C) 2001 Georges Menie, Ken Desmet
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/MC68VZ328.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Init Drangon Engine hardware */
|
||||
/***************************************************************************/
|
||||
|
||||
static void dragen2_reset(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
#ifdef CONFIG_INIT_LCD
|
||||
PBDATA |= 0x20; /* disable CCFL light */
|
||||
PKDATA |= 0x4; /* disable LCD controller */
|
||||
LCKCON = 0;
|
||||
#endif
|
||||
|
||||
__asm__ __volatile__(
|
||||
"reset\n\t"
|
||||
"moveal #0x04000000, %a0\n\t"
|
||||
"moveal 0(%a0), %sp\n\t"
|
||||
"moveal 4(%a0), %a0\n\t"
|
||||
"jmp (%a0)"
|
||||
);
|
||||
}
|
||||
|
||||
void __init init_dragen2(char *command, int size)
|
||||
{
|
||||
mach_reset = dragen2_reset;
|
||||
|
||||
#ifdef CONFIG_DIRECT_IO_ACCESS
|
||||
SCR = 0x10; /* allow user access to internal registers */
|
||||
#endif
|
||||
|
||||
/* CSGB Init */
|
||||
CSGBB = 0x4000;
|
||||
CSB = 0x1a1;
|
||||
|
||||
/* CS8900 init */
|
||||
/* PK3: hardware sleep function pin, active low */
|
||||
PKSEL |= PK(3); /* select pin as I/O */
|
||||
PKDIR |= PK(3); /* select pin as output */
|
||||
PKDATA |= PK(3); /* set pin high */
|
||||
|
||||
/* PF5: hardware reset function pin, active high */
|
||||
PFSEL |= PF(5); /* select pin as I/O */
|
||||
PFDIR |= PF(5); /* select pin as output */
|
||||
PFDATA &= ~PF(5); /* set pin low */
|
||||
|
||||
/* cs8900 hardware reset */
|
||||
PFDATA |= PF(5);
|
||||
{ int i; for (i = 0; i < 32000; ++i); }
|
||||
PFDATA &= ~PF(5);
|
||||
|
||||
/* INT1 enable (cs8900 IRQ) */
|
||||
PDPOL &= ~PD(1); /* active high signal */
|
||||
PDIQEG &= ~PD(1);
|
||||
PDIRQEN |= PD(1); /* IRQ enabled */
|
||||
|
||||
#ifdef CONFIG_INIT_LCD
|
||||
/* initialize LCD controller */
|
||||
LSSA = (long) screen_bits;
|
||||
LVPW = 0x14;
|
||||
LXMAX = 0x140;
|
||||
LYMAX = 0xef;
|
||||
LRRA = 0;
|
||||
LPXCD = 3;
|
||||
LPICF = 0x08;
|
||||
LPOLCF = 0;
|
||||
LCKCON = 0x80;
|
||||
PCPDEN = 0xff;
|
||||
PCSEL = 0;
|
||||
|
||||
/* Enable LCD controller */
|
||||
PKDIR |= 0x4;
|
||||
PKSEL |= 0x4;
|
||||
PKDATA &= ~0x4;
|
||||
|
||||
/* Enable CCFL backlighting circuit */
|
||||
PBDIR |= 0x20;
|
||||
PBSEL |= 0x20;
|
||||
PBDATA &= ~0x20;
|
||||
|
||||
/* contrast control register */
|
||||
PFDIR |= 0x1;
|
||||
PFSEL &= ~0x1;
|
||||
PWMR = 0x037F;
|
||||
#endif
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* m68328.c - 68328 specific config
|
||||
* m68328.c - 68328/68EZ328/68VZ328 specific config
|
||||
*
|
||||
* Copyright (C) 1993 Hamish Macdonald
|
||||
* Copyright (C) 1999 D. Jeff Dionne
|
||||
* Copyright (C) 2001 Georges Menie, Ken Desmet
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
@@ -20,18 +21,18 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/MC68328.h>
|
||||
#if defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD)
|
||||
|
||||
#if defined(CONFIG_INIT_LCD) && defined(CONFIG_M68VZ328)
|
||||
#include "bootlogo-vz.h"
|
||||
#elif defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD)
|
||||
#include "bootlogo.h"
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int m68328_hwclk(int set, struct rtc_time *t);
|
||||
#include "m68328.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void m68328_reset (void)
|
||||
static void m68328_reset(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
asm volatile ("moveal #0x10c00000, %a0;\n\t"
|
||||
@@ -45,12 +46,19 @@ void m68328_reset (void)
|
||||
|
||||
void __init config_BSP(char *command, int len)
|
||||
{
|
||||
pr_info("68328 support D. Jeff Dionne <jeff@uclinux.org>\n");
|
||||
pr_info("68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
|
||||
pr_info("68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n");
|
||||
mach_sched_init = hw_timer_init;
|
||||
mach_hwclk = m68328_hwclk;
|
||||
mach_reset = m68328_reset;
|
||||
|
||||
mach_hwclk = m68328_hwclk;
|
||||
mach_reset = m68328_reset;
|
||||
#if defined(CONFIG_PILOT) && defined(CONFIG_M68328)
|
||||
mach_sched_init = NULL;
|
||||
#elif defined(CONFIG_UCSIMM)
|
||||
init_ucsimm(command, len);
|
||||
#elif defined(CONFIG_UCDIMM)
|
||||
init_ucsimm(command, len);
|
||||
#elif defined(CONFIG_DRAGEN2)
|
||||
init_dragen2(command, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
5
arch/m68k/68000/m68328.h
Normal file
5
arch/m68k/68000/m68328.h
Normal file
@@ -0,0 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
void init_dragen2(char *command, int size);
|
||||
void init_ucsimm(char *command, int size);
|
||||
struct rtc_time;
|
||||
int m68328_hwclk(int set, struct rtc_time *t);
|
||||
@@ -1,77 +0,0 @@
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* m68EZ328.c - 68EZ328 specific config
|
||||
*
|
||||
* Copyright (C) 1993 Hamish Macdonald
|
||||
* Copyright (C) 1999 D. Jeff Dionne
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/MC68EZ328.h>
|
||||
#ifdef CONFIG_UCSIMM
|
||||
#include <asm/bootstd.h>
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int m68328_hwclk(int set, struct rtc_time *t);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void m68ez328_reset(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
asm volatile (
|
||||
"moveal #0x10c00000, %a0;\n"
|
||||
"moveb #0, 0xFFFFF300;\n"
|
||||
"moveal 0(%a0), %sp;\n"
|
||||
"moveal 4(%a0), %a0;\n"
|
||||
"jmp (%a0);\n"
|
||||
);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
unsigned char *cs8900a_hwaddr;
|
||||
static int errno;
|
||||
|
||||
#ifdef CONFIG_UCSIMM
|
||||
_bsc0(char *, getserialnum)
|
||||
_bsc1(unsigned char *, gethwaddr, int, a)
|
||||
_bsc1(char *, getbenv, char *, a)
|
||||
#endif
|
||||
|
||||
void __init config_BSP(char *command, int len)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
pr_info("68EZ328 DragonBallEZ support (C) 1999 Rt-Control, Inc\n");
|
||||
|
||||
#ifdef CONFIG_UCSIMM
|
||||
pr_info("uCsimm serial string [%s]\n", getserialnum());
|
||||
p = cs8900a_hwaddr = gethwaddr(0);
|
||||
pr_info("uCsimm hwaddr %pM\n", p);
|
||||
|
||||
p = getbenv("APPEND");
|
||||
if (p) strcpy(p,command);
|
||||
else command[0] = 0;
|
||||
#endif
|
||||
|
||||
mach_sched_init = hw_timer_init;
|
||||
mach_hwclk = m68328_hwclk;
|
||||
mach_reset = m68ez328_reset;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
@@ -1,189 +0,0 @@
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* m68VZ328.c - 68VZ328 specific config
|
||||
*
|
||||
* Copyright (C) 1993 Hamish Macdonald
|
||||
* Copyright (C) 1999 D. Jeff Dionne
|
||||
* Copyright (C) 2001 Georges Menie, Ken Desmet
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/MC68VZ328.h>
|
||||
#include <asm/bootstd.h>
|
||||
|
||||
#ifdef CONFIG_INIT_LCD
|
||||
#include "bootlogo-vz.h"
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int m68328_hwclk(int set, struct rtc_time *t);
|
||||
|
||||
/***************************************************************************/
|
||||
/* Init Drangon Engine hardware */
|
||||
/***************************************************************************/
|
||||
#if defined(CONFIG_DRAGEN2)
|
||||
|
||||
static void m68vz328_reset(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
#ifdef CONFIG_INIT_LCD
|
||||
PBDATA |= 0x20; /* disable CCFL light */
|
||||
PKDATA |= 0x4; /* disable LCD controller */
|
||||
LCKCON = 0;
|
||||
#endif
|
||||
|
||||
__asm__ __volatile__(
|
||||
"reset\n\t"
|
||||
"moveal #0x04000000, %a0\n\t"
|
||||
"moveal 0(%a0), %sp\n\t"
|
||||
"moveal 4(%a0), %a0\n\t"
|
||||
"jmp (%a0)"
|
||||
);
|
||||
}
|
||||
|
||||
static void __init init_hardware(char *command, int size)
|
||||
{
|
||||
#ifdef CONFIG_DIRECT_IO_ACCESS
|
||||
SCR = 0x10; /* allow user access to internal registers */
|
||||
#endif
|
||||
|
||||
/* CSGB Init */
|
||||
CSGBB = 0x4000;
|
||||
CSB = 0x1a1;
|
||||
|
||||
/* CS8900 init */
|
||||
/* PK3: hardware sleep function pin, active low */
|
||||
PKSEL |= PK(3); /* select pin as I/O */
|
||||
PKDIR |= PK(3); /* select pin as output */
|
||||
PKDATA |= PK(3); /* set pin high */
|
||||
|
||||
/* PF5: hardware reset function pin, active high */
|
||||
PFSEL |= PF(5); /* select pin as I/O */
|
||||
PFDIR |= PF(5); /* select pin as output */
|
||||
PFDATA &= ~PF(5); /* set pin low */
|
||||
|
||||
/* cs8900 hardware reset */
|
||||
PFDATA |= PF(5);
|
||||
{ int i; for (i = 0; i < 32000; ++i); }
|
||||
PFDATA &= ~PF(5);
|
||||
|
||||
/* INT1 enable (cs8900 IRQ) */
|
||||
PDPOL &= ~PD(1); /* active high signal */
|
||||
PDIQEG &= ~PD(1);
|
||||
PDIRQEN |= PD(1); /* IRQ enabled */
|
||||
|
||||
#ifdef CONFIG_INIT_LCD
|
||||
/* initialize LCD controller */
|
||||
LSSA = (long) screen_bits;
|
||||
LVPW = 0x14;
|
||||
LXMAX = 0x140;
|
||||
LYMAX = 0xef;
|
||||
LRRA = 0;
|
||||
LPXCD = 3;
|
||||
LPICF = 0x08;
|
||||
LPOLCF = 0;
|
||||
LCKCON = 0x80;
|
||||
PCPDEN = 0xff;
|
||||
PCSEL = 0;
|
||||
|
||||
/* Enable LCD controller */
|
||||
PKDIR |= 0x4;
|
||||
PKSEL |= 0x4;
|
||||
PKDATA &= ~0x4;
|
||||
|
||||
/* Enable CCFL backlighting circuit */
|
||||
PBDIR |= 0x20;
|
||||
PBSEL |= 0x20;
|
||||
PBDATA &= ~0x20;
|
||||
|
||||
/* contrast control register */
|
||||
PFDIR |= 0x1;
|
||||
PFSEL &= ~0x1;
|
||||
PWMR = 0x037F;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Init RT-Control uCdimm hardware */
|
||||
/***************************************************************************/
|
||||
#elif defined(CONFIG_UCDIMM)
|
||||
|
||||
static void m68vz328_reset(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
asm volatile (
|
||||
"moveal #0x10c00000, %a0;\n\t"
|
||||
"moveb #0, 0xFFFFF300;\n\t"
|
||||
"moveal 0(%a0), %sp;\n\t"
|
||||
"moveal 4(%a0), %a0;\n\t"
|
||||
"jmp (%a0);\n"
|
||||
);
|
||||
}
|
||||
|
||||
unsigned char *cs8900a_hwaddr;
|
||||
static int errno;
|
||||
|
||||
_bsc0(char *, getserialnum)
|
||||
_bsc1(unsigned char *, gethwaddr, int, a)
|
||||
_bsc1(char *, getbenv, char *, a)
|
||||
|
||||
static void __init init_hardware(char *command, int size)
|
||||
{
|
||||
char *p;
|
||||
|
||||
pr_info("uCdimm serial string [%s]\n", getserialnum());
|
||||
p = cs8900a_hwaddr = gethwaddr(0);
|
||||
pr_info("uCdimm hwaddr %pM\n", p);
|
||||
p = getbenv("APPEND");
|
||||
if (p)
|
||||
strcpy(p, command);
|
||||
else
|
||||
command[0] = 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
#else
|
||||
|
||||
static void m68vz328_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init init_hardware(char *command, int size)
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
#endif
|
||||
/***************************************************************************/
|
||||
|
||||
void __init config_BSP(char *command, int size)
|
||||
{
|
||||
pr_info("68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
|
||||
|
||||
init_hardware(command, size);
|
||||
|
||||
mach_sched_init = hw_timer_init;
|
||||
mach_hwclk = m68328_hwclk;
|
||||
mach_reset = m68vz328_reset;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
38
arch/m68k/68000/ucsimm.c
Normal file
38
arch/m68k/68000/ucsimm.c
Normal file
@@ -0,0 +1,38 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 1993 Hamish Macdonald
|
||||
* Copyright (C) 1999 D. Jeff Dionne
|
||||
* Copyright (C) 2001 Georges Menie, Ken Desmet
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <asm/bootstd.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/MC68VZ328.h>
|
||||
|
||||
|
||||
#include "m68328.h"
|
||||
|
||||
unsigned char *cs8900a_hwaddr;
|
||||
static int errno;
|
||||
|
||||
_bsc0(char *, getserialnum)
|
||||
_bsc1(unsigned char *, gethwaddr, int, a)
|
||||
_bsc1(char *, getbenv, char *, a)
|
||||
|
||||
void __init init_ucsimm(char *command, int size)
|
||||
{
|
||||
char *p;
|
||||
|
||||
pr_info("uCsimm/uCdimm serial string [%s]\n", getserialnum());
|
||||
p = cs8900a_hwaddr = gethwaddr(0);
|
||||
pr_info("uCsimm/uCdimm hwaddr %pM\n", p);
|
||||
p = getbenv("APPEND");
|
||||
if (p)
|
||||
strcpy(p, command);
|
||||
else
|
||||
command[0] = 0;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ endchoice
|
||||
if M68KCLASSIC
|
||||
|
||||
config M68000
|
||||
bool "MC68000"
|
||||
bool
|
||||
depends on !MMU
|
||||
select CPU_HAS_NO_BITFIELDS
|
||||
select CPU_HAS_NO_MULDIV64
|
||||
@@ -103,7 +103,7 @@ config M68060
|
||||
processor, say Y. Otherwise, say N.
|
||||
|
||||
config M68328
|
||||
bool "MC68328"
|
||||
bool
|
||||
depends on !MMU
|
||||
select LEGACY_TIMER_TICK
|
||||
select M68000
|
||||
@@ -111,7 +111,7 @@ config M68328
|
||||
Motorola 68328 processor support.
|
||||
|
||||
config M68EZ328
|
||||
bool "MC68EZ328"
|
||||
bool
|
||||
depends on !MMU
|
||||
select LEGACY_TIMER_TICK
|
||||
select M68000
|
||||
@@ -119,7 +119,7 @@ config M68EZ328
|
||||
Motorola 68EX328 processor support.
|
||||
|
||||
config M68VZ328
|
||||
bool "MC68VZ328"
|
||||
bool
|
||||
depends on !MMU
|
||||
select LEGACY_TIMER_TICK
|
||||
select M68000
|
||||
|
||||
@@ -145,14 +145,13 @@ config SUN3
|
||||
|
||||
If you don't want to compile a kernel exclusively for a Sun 3, say N.
|
||||
|
||||
endif # M68KCLASSIC
|
||||
|
||||
config PILOT
|
||||
bool
|
||||
|
||||
config PILOT3
|
||||
bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
|
||||
depends on M68328
|
||||
depends on !MMU
|
||||
select M68328
|
||||
select PILOT
|
||||
help
|
||||
Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
|
||||
@@ -165,19 +164,22 @@ config XCOPILOT_BUGS
|
||||
|
||||
config UCSIMM
|
||||
bool "uCsimm module support"
|
||||
depends on M68EZ328
|
||||
depends on !MMU
|
||||
select M68EZ328
|
||||
help
|
||||
Support for the Arcturus Networks uCsimm module.
|
||||
|
||||
config UCDIMM
|
||||
bool "uDsimm module support"
|
||||
depends on M68VZ328
|
||||
depends on !MMU
|
||||
select M68VZ328
|
||||
help
|
||||
Support for the Arcturus Networks uDsimm module.
|
||||
|
||||
config DRAGEN2
|
||||
bool "DragenEngine II board support"
|
||||
depends on M68VZ328
|
||||
depends on !MMU
|
||||
select M68VZ328
|
||||
help
|
||||
Support for the DragenEngine II board.
|
||||
|
||||
@@ -200,6 +202,8 @@ config MEMORY_RESERVE
|
||||
help
|
||||
Reserve certain memory regions on 68x328 based boards.
|
||||
|
||||
endif # M68KCLASSIC
|
||||
|
||||
config ARN5206
|
||||
bool "Arnewsh 5206 board support"
|
||||
depends on M5206
|
||||
|
||||
@@ -106,8 +106,16 @@ void __init setup_arch(char **cmdline_p)
|
||||
#ifdef CONFIG_UCDIMM
|
||||
pr_info("uCdimm by Lineo, Inc. <www.lineo.com>\n");
|
||||
#endif
|
||||
#ifdef CONFIG_M68328
|
||||
pr_info("68328 support D. Jeff Dionne <jeff@uclinux.org>\n");
|
||||
pr_info("68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
|
||||
#endif
|
||||
#ifdef CONFIG_M68EZ328
|
||||
pr_info("68EZ328 DragonBallEZ support (C) 1999 Rt-Control, Inc\n");
|
||||
#endif
|
||||
#ifdef CONFIG_M68VZ328
|
||||
pr_info("M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n");
|
||||
pr_info("68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
|
||||
#endif
|
||||
#ifdef CONFIG_COLDFIRE
|
||||
pr_info("COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n");
|
||||
@@ -121,6 +129,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
pr_info("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
|
||||
|
||||
#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
|
||||
pr_info("68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n");
|
||||
pr_info("TRG SuperPilot FLASH card support <info@trgnet.com>\n");
|
||||
#endif
|
||||
#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
|
||||
|
||||
@@ -81,7 +81,7 @@ SECTIONS {
|
||||
__init_end = .;
|
||||
}
|
||||
|
||||
BSS_SECTION(0, 0, 0)
|
||||
BSS_SECTION(4, 0, 4)
|
||||
|
||||
_end = .;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ config SOC_SIFIVE
|
||||
select SERIAL_SIFIVE if TTY
|
||||
select SERIAL_SIFIVE_CONSOLE if TTY
|
||||
select CLK_SIFIVE
|
||||
select CLK_SIFIVE_FU540_PRCI
|
||||
select CLK_SIFIVE_PRCI
|
||||
select SIFIVE_PLIC
|
||||
help
|
||||
This enables support for SiFive SoC platform hardware.
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_clk.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_clk.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
@@ -188,6 +188,14 @@ config COMMON_CLK_CS2000_CP
|
||||
help
|
||||
If you say yes here you get support for the CS2000 clock multiplier.
|
||||
|
||||
config COMMON_CLK_FSL_FLEXSPI
|
||||
tristate "Clock driver for FlexSPI on Layerscape SoCs"
|
||||
depends on ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
default ARCH_LAYERSCAPE && SPI_NXP_FLEXSPI
|
||||
help
|
||||
On Layerscape SoCs there is a special clock for the FlexSPI
|
||||
interface.
|
||||
|
||||
config COMMON_CLK_FSL_SAI
|
||||
bool "Clock driver for BCLK of Freescale SAI cores"
|
||||
depends on ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
@@ -246,7 +254,8 @@ config COMMON_CLK_AXI_CLKGEN
|
||||
|
||||
config CLK_QORIQ
|
||||
bool "Clock driver for Freescale QorIQ platforms"
|
||||
depends on (PPC_E500MC || ARM || ARM64 || COMPILE_TEST) && OF
|
||||
depends on OF
|
||||
depends on PPC_E500MC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
help
|
||||
This adds the clock driver support for Freescale QorIQ platforms
|
||||
using common clock framework.
|
||||
|
||||
@@ -30,6 +30,7 @@ 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
|
||||
obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o
|
||||
obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
|
||||
obj-$(CONFIG_COMMON_CLK_ASPEED) += clk-aspeed.o
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(rm9200_mck_lock);
|
||||
|
||||
struct sck {
|
||||
char *n;
|
||||
char *p;
|
||||
@@ -137,9 +139,20 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "pllbck";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&rm9200_mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&rm9200_mck_characteristics,
|
||||
&rm9200_mck_lock, CLK_SET_RATE_GATE,
|
||||
INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91rm9200_master_layout,
|
||||
&rm9200_mck_characteristics,
|
||||
&rm9200_mck_lock, CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -181,7 +194,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
|
||||
for (i = 0; i < ARRAY_SIZE(at91rm9200_periphck); i++) {
|
||||
hw = at91_clk_register_peripheral(regmap,
|
||||
at91rm9200_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
at91rm9200_periphck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -32,6 +32,8 @@ struct at91sam926x_data {
|
||||
bool has_slck;
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(at91sam9260_mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics sam9260_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 105000000 },
|
||||
.divisors = { 1, 2, 4, 0 },
|
||||
@@ -218,8 +220,8 @@ static const struct sck at91sam9261_systemck[] = {
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "pck3", .p = "prog3", .id = 11 },
|
||||
{ .n = "hclk0", .p = "masterck", .id = 16 },
|
||||
{ .n = "hclk1", .p = "masterck", .id = 17 },
|
||||
{ .n = "hclk0", .p = "masterck_div", .id = 16 },
|
||||
{ .n = "hclk1", .p = "masterck_div", .id = 17 },
|
||||
};
|
||||
|
||||
static const struct pck at91sam9261_periphck[] = {
|
||||
@@ -413,9 +415,21 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "pllbck";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
data->mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
data->mck_characteristics,
|
||||
&at91sam9260_mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91rm9200_master_layout,
|
||||
data->mck_characteristics,
|
||||
&at91sam9260_mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -457,7 +471,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
for (i = 0; i < data->num_pck; i++) {
|
||||
hw = at91_clk_register_peripheral(regmap,
|
||||
data->pck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
data->pck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(at91sam9g45_mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 0, .max = 133333333 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
@@ -40,10 +42,10 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} at91sam9g45_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
};
|
||||
|
||||
struct pck {
|
||||
@@ -148,9 +150,21 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&mck_characteristics,
|
||||
&at91sam9g45_mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91rm9200_master_layout,
|
||||
&mck_characteristics,
|
||||
&at91sam9g45_mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -166,7 +180,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
for (i = 0; i < 2; i++) {
|
||||
char name[6];
|
||||
|
||||
@@ -195,7 +209,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) {
|
||||
hw = at91_clk_register_peripheral(regmap,
|
||||
at91sam9g45_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
at91sam9g45_periphck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(at91sam9n12_mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 0, .max = 133333333 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
@@ -54,12 +56,12 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} at91sam9n12_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck", .id = 3 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
};
|
||||
|
||||
static const struct clk_pcr_layout at91sam9n12_pcr_layout = {
|
||||
@@ -175,9 +177,21 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "pllbck";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics,
|
||||
&at91sam9n12_mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics,
|
||||
&at91sam9n12_mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -191,7 +205,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "pllbck";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
for (i = 0; i < 2; i++) {
|
||||
char name[6];
|
||||
|
||||
@@ -221,7 +235,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&at91sam9n12_pcr_layout,
|
||||
at91sam9n12_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
at91sam9n12_periphck[i].id,
|
||||
&range, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(sam9rl_mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics sam9rl_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 94000000 },
|
||||
.divisors = { 1, 2, 4, 0 },
|
||||
@@ -117,9 +119,20 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&sam9rl_mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&sam9rl_mck_characteristics,
|
||||
&sam9rl_mck_lock, CLK_SET_RATE_GATE,
|
||||
INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91rm9200_master_layout,
|
||||
&sam9rl_mck_characteristics,
|
||||
&sam9rl_mck_lock, CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -129,7 +142,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
for (i = 0; i < 2; i++) {
|
||||
char name[6];
|
||||
|
||||
@@ -158,7 +171,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
|
||||
hw = at91_clk_register_peripheral(regmap,
|
||||
at91sam9rl_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
at91sam9rl_periphck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 0, .max = 133333333 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
@@ -41,7 +43,7 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} at91sam9x5_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
@@ -196,9 +198,19 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -218,7 +230,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
for (i = 0; i < 2; i++) {
|
||||
char name[6];
|
||||
|
||||
@@ -245,7 +257,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
}
|
||||
|
||||
if (has_lcdck) {
|
||||
hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
|
||||
hw = at91_clk_register_system(regmap, "lcdck", "masterck_div", 3);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -256,7 +268,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&at91sam9x5_pcr_layout,
|
||||
at91sam9x5_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
at91sam9x5_periphck[i].id,
|
||||
&range, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
@@ -269,7 +281,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&at91sam9x5_pcr_layout,
|
||||
extra_pcks[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
extra_pcks[i].id,
|
||||
&range, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define MASTER_PRES_MASK 0x7
|
||||
#define MASTER_PRES_MAX MASTER_PRES_MASK
|
||||
#define MASTER_DIV_SHIFT 8
|
||||
#define MASTER_DIV_MASK 0x3
|
||||
#define MASTER_DIV_MASK 0x7
|
||||
|
||||
#define PMC_MCR 0x30
|
||||
#define PMC_MCR_ID_MSK GENMASK(3, 0)
|
||||
@@ -58,119 +58,153 @@ static inline bool clk_master_ready(struct clk_master *master)
|
||||
static int clk_master_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
|
||||
while (!clk_master_ready(master))
|
||||
cpu_relax();
|
||||
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_master_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
unsigned long flags;
|
||||
bool status;
|
||||
|
||||
return clk_master_ready(master);
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
status = clk_master_ready(master);
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
static unsigned long clk_master_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
u8 pres;
|
||||
u8 div;
|
||||
unsigned long rate = parent_rate;
|
||||
unsigned long flags, rate = parent_rate;
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
const struct clk_master_layout *layout = master->layout;
|
||||
const struct clk_master_characteristics *characteristics =
|
||||
master->characteristics;
|
||||
unsigned int mckr;
|
||||
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
regmap_read(master->regmap, master->layout->offset, &mckr);
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
mckr &= layout->mask;
|
||||
|
||||
pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
|
||||
div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
|
||||
|
||||
if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
|
||||
rate /= 3;
|
||||
else
|
||||
rate >>= pres;
|
||||
|
||||
rate /= characteristics->divisors[div];
|
||||
|
||||
if (rate < characteristics->output.min)
|
||||
pr_warn("master clk is underclocked");
|
||||
pr_warn("master clk div is underclocked");
|
||||
else if (rate > characteristics->output.max)
|
||||
pr_warn("master clk is overclocked");
|
||||
pr_warn("master clk div is overclocked");
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static u8 clk_master_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
unsigned int mckr;
|
||||
|
||||
regmap_read(master->regmap, master->layout->offset, &mckr);
|
||||
|
||||
return mckr & AT91_PMC_CSS;
|
||||
}
|
||||
|
||||
static const struct clk_ops master_ops = {
|
||||
static const struct clk_ops master_div_ops = {
|
||||
.prepare = clk_master_prepare,
|
||||
.is_prepared = clk_master_is_prepared,
|
||||
.recalc_rate = clk_master_recalc_rate,
|
||||
.get_parent = clk_master_get_parent,
|
||||
.recalc_rate = clk_master_div_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master(struct regmap *regmap,
|
||||
const char *name, int num_parents,
|
||||
const char **parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics)
|
||||
{
|
||||
struct clk_master *master;
|
||||
struct clk_init_data init;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
if (!name || !num_parents || !parent_names)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
master = kzalloc(sizeof(*master), GFP_KERNEL);
|
||||
if (!master)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &master_ops;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
init.flags = 0;
|
||||
|
||||
master->hw.init = &init;
|
||||
master->layout = layout;
|
||||
master->characteristics = characteristics;
|
||||
master->regmap = regmap;
|
||||
|
||||
hw = &master->hw;
|
||||
ret = clk_hw_register(NULL, &master->hw);
|
||||
if (ret) {
|
||||
kfree(master);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
const struct clk_master_characteristics *characteristics =
|
||||
master->characteristics;
|
||||
unsigned long flags;
|
||||
int div, i;
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
|
||||
div = DIV_ROUND_CLOSEST(parent_rate, rate);
|
||||
if (div > ARRAY_SIZE(characteristics->divisors))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
|
||||
if (!characteristics->divisors[i])
|
||||
break;
|
||||
|
||||
if (div == characteristics->divisors[i]) {
|
||||
div = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(characteristics->divisors))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
regmap_update_bits(master->regmap, master->layout->offset,
|
||||
(MASTER_DIV_MASK << MASTER_DIV_SHIFT),
|
||||
(div << MASTER_DIV_SHIFT));
|
||||
while (!clk_master_ready(master))
|
||||
cpu_relax();
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_master_div_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
const struct clk_master_characteristics *characteristics =
|
||||
master->characteristics;
|
||||
struct clk_hw *parent;
|
||||
unsigned long parent_rate, tmp_rate, best_rate = 0;
|
||||
int i, best_diff = INT_MIN, tmp_diff;
|
||||
|
||||
parent = clk_hw_get_parent(hw);
|
||||
if (!parent)
|
||||
return -EINVAL;
|
||||
|
||||
parent_rate = clk_hw_get_rate(parent);
|
||||
if (!parent_rate)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
|
||||
if (!characteristics->divisors[i])
|
||||
break;
|
||||
|
||||
tmp_rate = DIV_ROUND_CLOSEST_ULL(parent_rate,
|
||||
characteristics->divisors[i]);
|
||||
tmp_diff = abs(tmp_rate - req->rate);
|
||||
|
||||
if (!best_rate || best_diff > tmp_diff) {
|
||||
best_diff = tmp_diff;
|
||||
best_rate = tmp_rate;
|
||||
}
|
||||
|
||||
if (!best_diff)
|
||||
break;
|
||||
}
|
||||
|
||||
req->best_parent_rate = best_rate;
|
||||
req->best_parent_hw = parent;
|
||||
req->rate = best_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops master_div_ops_chg = {
|
||||
.prepare = clk_master_prepare,
|
||||
.is_prepared = clk_master_is_prepared,
|
||||
.recalc_rate = clk_master_div_recalc_rate,
|
||||
.determine_rate = clk_master_div_determine_rate,
|
||||
.set_rate = clk_master_div_set_rate,
|
||||
};
|
||||
|
||||
static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
|
||||
struct clk_hw *parent,
|
||||
unsigned long parent_rate,
|
||||
@@ -195,6 +229,217 @@ static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
|
||||
}
|
||||
}
|
||||
|
||||
static int clk_master_pres_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
struct clk_rate_request req_parent = *req;
|
||||
const struct clk_master_characteristics *characteristics =
|
||||
master->characteristics;
|
||||
struct clk_hw *parent;
|
||||
long best_rate = LONG_MIN, best_diff = LONG_MIN;
|
||||
u32 pres;
|
||||
int i;
|
||||
|
||||
if (master->chg_pid < 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
parent = clk_hw_get_parent_by_index(hw, master->chg_pid);
|
||||
if (!parent)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i <= MASTER_PRES_MAX; i++) {
|
||||
if (characteristics->have_div3_pres && i == MASTER_PRES_MAX)
|
||||
pres = 3;
|
||||
else
|
||||
pres = 1 << i;
|
||||
|
||||
req_parent.rate = req->rate * pres;
|
||||
if (__clk_determine_rate(parent, &req_parent))
|
||||
continue;
|
||||
|
||||
clk_sama7g5_master_best_diff(req, parent, req_parent.rate,
|
||||
&best_diff, &best_rate, pres);
|
||||
if (!best_diff)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
unsigned long flags;
|
||||
unsigned int pres;
|
||||
|
||||
pres = DIV_ROUND_CLOSEST(parent_rate, rate);
|
||||
if (pres > MASTER_PRES_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
else if (pres == 3)
|
||||
pres = MASTER_PRES_MAX;
|
||||
else
|
||||
pres = ffs(pres) - 1;
|
||||
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
regmap_update_bits(master->regmap, master->layout->offset,
|
||||
(MASTER_PRES_MASK << master->layout->pres_shift),
|
||||
(pres << master->layout->pres_shift));
|
||||
|
||||
while (!clk_master_ready(master))
|
||||
cpu_relax();
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
const struct clk_master_characteristics *characteristics =
|
||||
master->characteristics;
|
||||
unsigned long flags;
|
||||
unsigned int val, pres;
|
||||
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
regmap_read(master->regmap, master->layout->offset, &val);
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
|
||||
if (pres == 3 && characteristics->have_div3_pres)
|
||||
pres = 3;
|
||||
else
|
||||
pres = (1 << pres);
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(parent_rate, pres);
|
||||
}
|
||||
|
||||
static u8 clk_master_pres_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
unsigned long flags;
|
||||
unsigned int mckr;
|
||||
|
||||
spin_lock_irqsave(master->lock, flags);
|
||||
regmap_read(master->regmap, master->layout->offset, &mckr);
|
||||
spin_unlock_irqrestore(master->lock, flags);
|
||||
|
||||
return mckr & AT91_PMC_CSS;
|
||||
}
|
||||
|
||||
static const struct clk_ops master_pres_ops = {
|
||||
.prepare = clk_master_prepare,
|
||||
.is_prepared = clk_master_is_prepared,
|
||||
.recalc_rate = clk_master_pres_recalc_rate,
|
||||
.get_parent = clk_master_pres_get_parent,
|
||||
};
|
||||
|
||||
static const struct clk_ops master_pres_ops_chg = {
|
||||
.prepare = clk_master_prepare,
|
||||
.is_prepared = clk_master_is_prepared,
|
||||
.determine_rate = clk_master_pres_determine_rate,
|
||||
.recalc_rate = clk_master_pres_recalc_rate,
|
||||
.get_parent = clk_master_pres_get_parent,
|
||||
.set_rate = clk_master_pres_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
at91_clk_register_master_internal(struct regmap *regmap,
|
||||
const char *name, int num_parents,
|
||||
const char **parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics,
|
||||
const struct clk_ops *ops, spinlock_t *lock, u32 flags,
|
||||
int chg_pid)
|
||||
{
|
||||
struct clk_master *master;
|
||||
struct clk_init_data init;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
if (!name || !num_parents || !parent_names || !lock)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
master = kzalloc(sizeof(*master), GFP_KERNEL);
|
||||
if (!master)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = ops;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
init.flags = flags;
|
||||
|
||||
master->hw.init = &init;
|
||||
master->layout = layout;
|
||||
master->characteristics = characteristics;
|
||||
master->regmap = regmap;
|
||||
master->chg_pid = chg_pid;
|
||||
master->lock = lock;
|
||||
|
||||
hw = &master->hw;
|
||||
ret = clk_hw_register(NULL, &master->hw);
|
||||
if (ret) {
|
||||
kfree(master);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master_pres(struct regmap *regmap,
|
||||
const char *name, int num_parents,
|
||||
const char **parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics,
|
||||
spinlock_t *lock, u32 flags, int chg_pid)
|
||||
{
|
||||
const struct clk_ops *ops;
|
||||
|
||||
if (flags & CLK_SET_RATE_GATE)
|
||||
ops = &master_pres_ops;
|
||||
else
|
||||
ops = &master_pres_ops_chg;
|
||||
|
||||
return at91_clk_register_master_internal(regmap, name, num_parents,
|
||||
parent_names, layout,
|
||||
characteristics, ops,
|
||||
lock, flags, chg_pid);
|
||||
}
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master_div(struct regmap *regmap,
|
||||
const char *name, const char *parent_name,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics,
|
||||
spinlock_t *lock, u32 flags)
|
||||
{
|
||||
const struct clk_ops *ops;
|
||||
|
||||
if (flags & CLK_SET_RATE_GATE)
|
||||
ops = &master_div_ops;
|
||||
else
|
||||
ops = &master_div_ops_chg;
|
||||
|
||||
return at91_clk_register_master_internal(regmap, name, 1,
|
||||
&parent_name, layout,
|
||||
characteristics, ops,
|
||||
lock, flags, -EINVAL);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
|
||||
}
|
||||
|
||||
static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
|
||||
@@ -229,6 +229,57 @@ static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
|
||||
}
|
||||
|
||||
static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
|
||||
struct sam9x60_frac *frac = to_sam9x60_frac(core);
|
||||
struct regmap *regmap = core->regmap;
|
||||
unsigned long irqflags;
|
||||
unsigned int val, cfrac, cmul;
|
||||
long ret;
|
||||
|
||||
ret = sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(core->lock, irqflags);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core->id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
|
||||
cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
|
||||
cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
|
||||
|
||||
if (cmul == frac->mul && cfrac == frac->frac)
|
||||
goto unlock;
|
||||
|
||||
regmap_write(regmap, AT91_PMC_PLL_CTRL1,
|
||||
(frac->mul << core->layout->mul_shift) |
|
||||
(frac->frac << core->layout->frac_shift));
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
|
||||
AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
|
||||
AT91_PMC_PLL_CTRL0_ENLOCK |
|
||||
AT91_PMC_PLL_CTRL0_ENPLL);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
while (!sam9x60_pll_ready(regmap, core->id))
|
||||
cpu_relax();
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(core->lock, irqflags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct clk_ops sam9x60_frac_pll_ops = {
|
||||
.prepare = sam9x60_frac_pll_prepare,
|
||||
.unprepare = sam9x60_frac_pll_unprepare,
|
||||
@@ -238,6 +289,15 @@ static const struct clk_ops sam9x60_frac_pll_ops = {
|
||||
.set_rate = sam9x60_frac_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops sam9x60_frac_pll_ops_chg = {
|
||||
.prepare = sam9x60_frac_pll_prepare,
|
||||
.unprepare = sam9x60_frac_pll_unprepare,
|
||||
.is_prepared = sam9x60_frac_pll_is_prepared,
|
||||
.recalc_rate = sam9x60_frac_pll_recalc_rate,
|
||||
.round_rate = sam9x60_frac_pll_round_rate,
|
||||
.set_rate = sam9x60_frac_pll_set_rate_chg,
|
||||
};
|
||||
|
||||
static int sam9x60_div_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
|
||||
@@ -384,6 +444,44 @@ static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
|
||||
struct sam9x60_div *div = to_sam9x60_div(core);
|
||||
struct regmap *regmap = core->regmap;
|
||||
unsigned long irqflags;
|
||||
unsigned int val, cdiv;
|
||||
|
||||
div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
|
||||
|
||||
spin_lock_irqsave(core->lock, irqflags);
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core->id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
|
||||
cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
|
||||
|
||||
/* Stop if nothing changed. */
|
||||
if (cdiv == div->div)
|
||||
goto unlock;
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
|
||||
core->layout->div_mask,
|
||||
(div->div << core->layout->div_shift));
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
while (!sam9x60_pll_ready(regmap, core->id))
|
||||
cpu_relax();
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(core->lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops sam9x60_div_pll_ops = {
|
||||
.prepare = sam9x60_div_pll_prepare,
|
||||
.unprepare = sam9x60_div_pll_unprepare,
|
||||
@@ -393,17 +491,26 @@ static const struct clk_ops sam9x60_div_pll_ops = {
|
||||
.set_rate = sam9x60_div_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops sam9x60_div_pll_ops_chg = {
|
||||
.prepare = sam9x60_div_pll_prepare,
|
||||
.unprepare = sam9x60_div_pll_unprepare,
|
||||
.is_prepared = sam9x60_div_pll_is_prepared,
|
||||
.recalc_rate = sam9x60_div_pll_recalc_rate,
|
||||
.round_rate = sam9x60_div_pll_round_rate,
|
||||
.set_rate = sam9x60_div_pll_set_rate_chg,
|
||||
};
|
||||
|
||||
struct clk_hw * __init
|
||||
sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char *parent_name,
|
||||
struct clk_hw *parent_hw, u8 id,
|
||||
const struct clk_pll_characteristics *characteristics,
|
||||
const struct clk_pll_layout *layout, bool critical)
|
||||
const struct clk_pll_layout *layout, u32 flags)
|
||||
{
|
||||
struct sam9x60_frac *frac;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
unsigned long parent_rate, flags;
|
||||
unsigned long parent_rate, irqflags;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
@@ -417,10 +524,12 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
init.name = name;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.ops = &sam9x60_frac_pll_ops;
|
||||
init.flags = CLK_SET_RATE_GATE;
|
||||
if (critical)
|
||||
init.flags |= CLK_IS_CRITICAL;
|
||||
if (flags & CLK_SET_RATE_GATE)
|
||||
init.ops = &sam9x60_frac_pll_ops;
|
||||
else
|
||||
init.ops = &sam9x60_frac_pll_ops_chg;
|
||||
|
||||
init.flags = flags;
|
||||
|
||||
frac->core.id = id;
|
||||
frac->core.hw.init = &init;
|
||||
@@ -429,7 +538,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
frac->core.regmap = regmap;
|
||||
frac->core.lock = lock;
|
||||
|
||||
spin_lock_irqsave(frac->core.lock, flags);
|
||||
spin_lock_irqsave(frac->core.lock, irqflags);
|
||||
if (sam9x60_pll_ready(regmap, id)) {
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, id);
|
||||
@@ -457,7 +566,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(frac->core.lock, flags);
|
||||
spin_unlock_irqrestore(frac->core.lock, irqflags);
|
||||
|
||||
hw = &frac->core.hw;
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
@@ -469,7 +578,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
return hw;
|
||||
|
||||
free:
|
||||
spin_unlock_irqrestore(frac->core.lock, flags);
|
||||
spin_unlock_irqrestore(frac->core.lock, irqflags);
|
||||
kfree(frac);
|
||||
return hw;
|
||||
}
|
||||
@@ -478,12 +587,12 @@ struct clk_hw * __init
|
||||
sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char *parent_name, u8 id,
|
||||
const struct clk_pll_characteristics *characteristics,
|
||||
const struct clk_pll_layout *layout, bool critical)
|
||||
const struct clk_pll_layout *layout, u32 flags)
|
||||
{
|
||||
struct sam9x60_div *div;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
unsigned long flags;
|
||||
unsigned long irqflags;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
@@ -497,11 +606,11 @@ sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
init.name = name;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.ops = &sam9x60_div_pll_ops;
|
||||
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT;
|
||||
if (critical)
|
||||
init.flags |= CLK_IS_CRITICAL;
|
||||
if (flags & CLK_SET_RATE_GATE)
|
||||
init.ops = &sam9x60_div_pll_ops;
|
||||
else
|
||||
init.ops = &sam9x60_div_pll_ops_chg;
|
||||
init.flags = flags;
|
||||
|
||||
div->core.id = id;
|
||||
div->core.hw.init = &init;
|
||||
@@ -510,14 +619,14 @@ sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
div->core.regmap = regmap;
|
||||
div->core.lock = lock;
|
||||
|
||||
spin_lock_irqsave(div->core.lock, flags);
|
||||
spin_lock_irqsave(div->core.lock, irqflags);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
|
||||
div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
|
||||
|
||||
spin_unlock_irqrestore(div->core.lock, flags);
|
||||
spin_unlock_irqrestore(div->core.lock, irqflags);
|
||||
|
||||
hw = &div->core.hw;
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#define GCK_INDEX_DT_AUDIO_PLL 5
|
||||
|
||||
static DEFINE_SPINLOCK(mck_lock);
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_AUDIO_PLL
|
||||
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
|
||||
{
|
||||
@@ -388,9 +390,16 @@ of_at91_clk_master_setup(struct device_node *np,
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_master(regmap, name, num_parents,
|
||||
parent_names, layout,
|
||||
characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,
|
||||
parent_names, layout,
|
||||
characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto out_free_characteristics;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, name, "masterck_pres",
|
||||
layout, characteristics,
|
||||
&mck_lock, CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto out_free_characteristics;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ extern const struct clk_master_layout at91sam9x5_master_layout;
|
||||
|
||||
struct clk_master_characteristics {
|
||||
struct clk_range output;
|
||||
u32 divisors[4];
|
||||
u32 divisors[5];
|
||||
u8 have_div3_pres;
|
||||
};
|
||||
|
||||
@@ -155,10 +155,18 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, int num_parents);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master(struct regmap *regmap, const char *name,
|
||||
int num_parents, const char **parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics);
|
||||
at91_clk_register_master_pres(struct regmap *regmap, const char *name,
|
||||
int num_parents, const char **parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics,
|
||||
spinlock_t *lock, u32 flags, int chg_pid);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master_div(struct regmap *regmap, const char *name,
|
||||
const char *parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics,
|
||||
spinlock_t *lock, u32 flags);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_sama7g5_register_master(struct regmap *regmap,
|
||||
@@ -190,14 +198,14 @@ struct clk_hw * __init
|
||||
sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char *parent_name, u8 id,
|
||||
const struct clk_pll_characteristics *characteristics,
|
||||
const struct clk_pll_layout *layout, bool critical);
|
||||
const struct clk_pll_layout *layout, u32 flags);
|
||||
|
||||
struct clk_hw * __init
|
||||
sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char *parent_name,
|
||||
struct clk_hw *parent_hw, u8 id,
|
||||
const struct clk_pll_characteristics *characteristics,
|
||||
const struct clk_pll_layout *layout, bool critical);
|
||||
const struct clk_pll_layout *layout, u32 flags);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_programmable(struct regmap *regmap, const char *name,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(pmc_pll_lock);
|
||||
static DEFINE_SPINLOCK(mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 140000000, .max = 200000000 },
|
||||
@@ -76,11 +77,11 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} sam9x60_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "qspick", .p = "masterck", .id = 19 },
|
||||
{ .n = "qspick", .p = "masterck_div", .id = 19 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@@ -174,7 +175,6 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
struct regmap *regmap;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
bool bypass;
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "td_slck");
|
||||
if (i < 0)
|
||||
@@ -209,10 +209,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
|
||||
bypass);
|
||||
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 0);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
main_osc_hw = hw;
|
||||
@@ -228,13 +225,24 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "pllack_fracck",
|
||||
"mainck", sam9x60_pmc->chws[PMC_MAIN],
|
||||
0, &plla_characteristics,
|
||||
&pll_frac_layout, true);
|
||||
&pll_frac_layout,
|
||||
/*
|
||||
* This feeds pllack_divck which
|
||||
* feeds CPU. It should not be
|
||||
* disabled.
|
||||
*/
|
||||
CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
|
||||
"pllack_fracck", 0, &plla_characteristics,
|
||||
&pll_div_layout, true);
|
||||
&pll_div_layout,
|
||||
/*
|
||||
* This feeds CPU. It should not
|
||||
* be disabled.
|
||||
*/
|
||||
CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -243,13 +251,16 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "upllck_fracck",
|
||||
"main_osc", main_osc_hw, 1,
|
||||
&upll_characteristics,
|
||||
&pll_frac_layout, false);
|
||||
&pll_frac_layout, CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
|
||||
"upllck_fracck", 1, &upll_characteristics,
|
||||
&pll_div_layout, false);
|
||||
&pll_div_layout,
|
||||
CLK_SET_RATE_GATE |
|
||||
CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -258,9 +269,17 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
parent_names[0] = md_slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack_divck";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
|
||||
&sam9x60_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3,
|
||||
parent_names, &sam9x60_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres", &sam9x60_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -276,7 +295,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
parent_names[0] = md_slck_name;
|
||||
parent_names[1] = td_slck_name;
|
||||
parent_names[2] = "mainck";
|
||||
parent_names[3] = "masterck";
|
||||
parent_names[3] = "masterck_div";
|
||||
parent_names[4] = "pllack_divck";
|
||||
parent_names[5] = "upllck_divck";
|
||||
for (i = 0; i < 2; i++) {
|
||||
@@ -308,7 +327,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&sam9x60_pcr_layout,
|
||||
sam9x60_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
sam9x60_periphck[i].id,
|
||||
&range, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 124000000, .max = 166000000 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
@@ -40,14 +42,14 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} sama5d2_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck", .id = 3 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "iscck", .p = "masterck", .id = 18 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "iscck", .p = "masterck_div", .id = 18 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@@ -235,15 +237,25 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
|
||||
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -259,7 +271,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
parent_names[5] = "audiopll_pmcck";
|
||||
for (i = 0; i < 3; i++) {
|
||||
char name[6];
|
||||
@@ -290,7 +302,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&sama5d2_pcr_layout,
|
||||
sama5d2_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
sama5d2_periphck[i].id,
|
||||
&range, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
@@ -317,7 +329,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
parent_names[5] = "audiopll_pmcck";
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
|
||||
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 0, .max = 166000000 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
@@ -40,14 +42,14 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} sama5d3_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck", .id = 3 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@@ -170,9 +172,19 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -192,7 +204,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
for (i = 0; i < 3; i++) {
|
||||
char name[6];
|
||||
|
||||
@@ -222,7 +234,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&sama5d3_pcr_layout,
|
||||
sama5d3_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
sama5d3_periphck[i].id,
|
||||
&sama5d3_periphck[i].r,
|
||||
INT_MIN);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(mck_lock);
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 125000000, .max = 200000000 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
@@ -39,14 +41,14 @@ static const struct {
|
||||
char *p;
|
||||
u8 id;
|
||||
} sama5d4_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck", .id = 3 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@@ -185,15 +187,25 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
|
||||
parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "masterck_div",
|
||||
"masterck_pres",
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics, &mck_lock,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
|
||||
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -215,7 +227,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
parent_names[4] = "masterck_div";
|
||||
for (i = 0; i < 3; i++) {
|
||||
char name[6];
|
||||
|
||||
@@ -245,7 +257,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
&sama5d4_pcr_layout,
|
||||
sama5d4_periphck[i].n,
|
||||
"masterck",
|
||||
"masterck_div",
|
||||
sama5d4_periphck[i].id,
|
||||
&range, INT_MIN);
|
||||
if (IS_ERR(hw))
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
} while (0)
|
||||
|
||||
static DEFINE_SPINLOCK(pmc_pll_lock);
|
||||
static DEFINE_SPINLOCK(pmc_mck0_lock);
|
||||
static DEFINE_SPINLOCK(pmc_mckX_lock);
|
||||
|
||||
/**
|
||||
@@ -89,118 +90,198 @@ static const struct clk_pll_layout pll_layout_divio = {
|
||||
.endiv_shift = 30,
|
||||
};
|
||||
|
||||
/*
|
||||
* CPU PLL output range.
|
||||
* Notice: The upper limit has been setup to 1000000002 due to hardware
|
||||
* block which cannot output exactly 1GHz.
|
||||
*/
|
||||
static const struct clk_range cpu_pll_outputs[] = {
|
||||
{ .min = 2343750, .max = 1000000002 },
|
||||
};
|
||||
|
||||
/* PLL output range. */
|
||||
static const struct clk_range pll_outputs[] = {
|
||||
{ .min = 2343750, .max = 1200000000 },
|
||||
};
|
||||
|
||||
/* CPU PLL characteristics. */
|
||||
static const struct clk_pll_characteristics cpu_pll_characteristics = {
|
||||
.input = { .min = 12000000, .max = 50000000 },
|
||||
.num_output = ARRAY_SIZE(cpu_pll_outputs),
|
||||
.output = cpu_pll_outputs,
|
||||
};
|
||||
|
||||
/* PLL characteristics. */
|
||||
static const struct clk_pll_characteristics pll_characteristics = {
|
||||
.input = { .min = 12000000, .max = 50000000 },
|
||||
.num_output = ARRAY_SIZE(pll_outputs),
|
||||
.output = pll_outputs,
|
||||
};
|
||||
|
||||
/**
|
||||
* PLL clocks description
|
||||
* @n: clock name
|
||||
* @p: clock parent
|
||||
* @l: clock layout
|
||||
* @c: clock characteristics
|
||||
* @t: clock type
|
||||
* @f: true if clock is critical and cannot be disabled
|
||||
* @f: clock flags
|
||||
* @eid: export index in sama7g5->chws[] array
|
||||
*/
|
||||
static const struct {
|
||||
const char *n;
|
||||
const char *p;
|
||||
const struct clk_pll_layout *l;
|
||||
const struct clk_pll_characteristics *c;
|
||||
unsigned long f;
|
||||
u8 t;
|
||||
u8 c;
|
||||
u8 eid;
|
||||
} sama7g5_plls[][PLL_ID_MAX] = {
|
||||
[PLL_ID_CPU] = {
|
||||
{ .n = "cpupll_fracck",
|
||||
.p = "mainck",
|
||||
.l = &pll_layout_frac,
|
||||
.c = &cpu_pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.c = 1, },
|
||||
/*
|
||||
* This feeds cpupll_divpmcck which feeds CPU. It should
|
||||
* not be disabled.
|
||||
*/
|
||||
.f = CLK_IS_CRITICAL, },
|
||||
|
||||
{ .n = "cpupll_divpmcck",
|
||||
.p = "cpupll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.c = &cpu_pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.c = 1, },
|
||||
/* This feeds CPU. It should not be disabled. */
|
||||
.f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
|
||||
.eid = PMC_CPUPLL, },
|
||||
},
|
||||
|
||||
[PLL_ID_SYS] = {
|
||||
{ .n = "syspll_fracck",
|
||||
.p = "mainck",
|
||||
.l = &pll_layout_frac,
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.c = 1, },
|
||||
/*
|
||||
* This feeds syspll_divpmcck which may feed critial parts
|
||||
* of the systems like timers. Therefore it should not be
|
||||
* disabled.
|
||||
*/
|
||||
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
|
||||
|
||||
{ .n = "syspll_divpmcck",
|
||||
.p = "syspll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.c = 1, },
|
||||
/*
|
||||
* This may feed critial parts of the systems like timers.
|
||||
* Therefore it should not be disabled.
|
||||
*/
|
||||
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
|
||||
.eid = PMC_SYSPLL, },
|
||||
},
|
||||
|
||||
[PLL_ID_DDR] = {
|
||||
{ .n = "ddrpll_fracck",
|
||||
.p = "mainck",
|
||||
.l = &pll_layout_frac,
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.c = 1, },
|
||||
/*
|
||||
* This feeds ddrpll_divpmcck which feeds DDR. It should not
|
||||
* be disabled.
|
||||
*/
|
||||
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
|
||||
|
||||
{ .n = "ddrpll_divpmcck",
|
||||
.p = "ddrpll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.c = 1, },
|
||||
/* This feeds DDR. It should not be disabled. */
|
||||
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
|
||||
},
|
||||
|
||||
[PLL_ID_IMG] = {
|
||||
{ .n = "imgpll_fracck",
|
||||
.p = "mainck",
|
||||
.l = &pll_layout_frac,
|
||||
.t = PLL_TYPE_FRAC, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.f = CLK_SET_RATE_GATE, },
|
||||
|
||||
{ .n = "imgpll_divpmcck",
|
||||
.p = "imgpll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.t = PLL_TYPE_DIV, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT, },
|
||||
},
|
||||
|
||||
[PLL_ID_BAUD] = {
|
||||
{ .n = "baudpll_fracck",
|
||||
.p = "mainck",
|
||||
.l = &pll_layout_frac,
|
||||
.t = PLL_TYPE_FRAC, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.f = CLK_SET_RATE_GATE, },
|
||||
|
||||
{ .n = "baudpll_divpmcck",
|
||||
.p = "baudpll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.t = PLL_TYPE_DIV, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT, },
|
||||
},
|
||||
|
||||
[PLL_ID_AUDIO] = {
|
||||
{ .n = "audiopll_fracck",
|
||||
.p = "main_xtal",
|
||||
.l = &pll_layout_frac,
|
||||
.t = PLL_TYPE_FRAC, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.f = CLK_SET_RATE_GATE, },
|
||||
|
||||
{ .n = "audiopll_divpmcck",
|
||||
.p = "audiopll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.eid = PMC_I2S0_MUX, },
|
||||
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT,
|
||||
.eid = PMC_AUDIOPMCPLL, },
|
||||
|
||||
{ .n = "audiopll_diviock",
|
||||
.p = "audiopll_fracck",
|
||||
.l = &pll_layout_divio,
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.eid = PMC_I2S1_MUX, },
|
||||
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT,
|
||||
.eid = PMC_AUDIOIOPLL, },
|
||||
},
|
||||
|
||||
[PLL_ID_ETH] = {
|
||||
{ .n = "ethpll_fracck",
|
||||
.p = "main_xtal",
|
||||
.l = &pll_layout_frac,
|
||||
.t = PLL_TYPE_FRAC, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_FRAC,
|
||||
.f = CLK_SET_RATE_GATE, },
|
||||
|
||||
{ .n = "ethpll_divpmcck",
|
||||
.p = "ethpll_fracck",
|
||||
.l = &pll_layout_divpmc,
|
||||
.t = PLL_TYPE_DIV, },
|
||||
.c = &pll_characteristics,
|
||||
.t = PLL_TYPE_DIV,
|
||||
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT, },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -245,7 +326,7 @@ static const struct {
|
||||
.ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", },
|
||||
.ep_mux_table = { 5, 6, 7, },
|
||||
.ep_count = 3,
|
||||
.ep_chg_id = 6, },
|
||||
.ep_chg_id = 5, },
|
||||
|
||||
{ .n = "mck4",
|
||||
.id = 4,
|
||||
@@ -278,7 +359,7 @@ static const struct {
|
||||
};
|
||||
|
||||
/* Mux table for programmable clocks. */
|
||||
static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, };
|
||||
static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
|
||||
|
||||
/**
|
||||
* Peripheral clock description
|
||||
@@ -401,7 +482,7 @@ static const struct {
|
||||
.pp = { "audiopll_divpmcck", },
|
||||
.pp_mux_table = { 9, },
|
||||
.pp_count = 1,
|
||||
.pp_chg_id = 4, },
|
||||
.pp_chg_id = 3, },
|
||||
|
||||
{ .n = "csi_gclk",
|
||||
.id = 33,
|
||||
@@ -513,7 +594,7 @@ static const struct {
|
||||
.pp = { "ethpll_divpmcck", },
|
||||
.pp_mux_table = { 10, },
|
||||
.pp_count = 1,
|
||||
.pp_chg_id = 4, },
|
||||
.pp_chg_id = 3, },
|
||||
|
||||
{ .n = "gmac1_gclk",
|
||||
.id = 52,
|
||||
@@ -545,7 +626,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "audiopll_divpmcck", },
|
||||
.pp_mux_table = { 5, 9, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "i2smcc1_gclk",
|
||||
.id = 58,
|
||||
@@ -553,7 +634,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "audiopll_divpmcck", },
|
||||
.pp_mux_table = { 5, 9, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "mcan0_gclk",
|
||||
.id = 61,
|
||||
@@ -695,7 +776,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "baudpll_divpmcck", },
|
||||
.pp_mux_table = { 5, 8, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "sdmmc1_gclk",
|
||||
.id = 81,
|
||||
@@ -703,7 +784,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "baudpll_divpmcck", },
|
||||
.pp_mux_table = { 5, 8, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "sdmmc2_gclk",
|
||||
.id = 82,
|
||||
@@ -711,7 +792,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "baudpll_divpmcck", },
|
||||
.pp_mux_table = { 5, 8, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "spdifrx_gclk",
|
||||
.id = 84,
|
||||
@@ -719,7 +800,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "audiopll_divpmcck", },
|
||||
.pp_mux_table = { 5, 9, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "spdiftx_gclk",
|
||||
.id = 85,
|
||||
@@ -727,7 +808,7 @@ static const struct {
|
||||
.pp = { "syspll_divpmcck", "audiopll_divpmcck", },
|
||||
.pp_mux_table = { 5, 9, },
|
||||
.pp_count = 2,
|
||||
.pp_chg_id = 5, },
|
||||
.pp_chg_id = 4, },
|
||||
|
||||
{ .n = "tcb0_ch0_gclk",
|
||||
.id = 88,
|
||||
@@ -758,28 +839,16 @@ static const struct {
|
||||
.pp_chg_id = INT_MIN, },
|
||||
};
|
||||
|
||||
/* PLL output range. */
|
||||
static const struct clk_range pll_outputs[] = {
|
||||
{ .min = 2343750, .max = 1200000000 },
|
||||
};
|
||||
|
||||
/* PLL characteristics. */
|
||||
static const struct clk_pll_characteristics pll_characteristics = {
|
||||
.input = { .min = 12000000, .max = 50000000 },
|
||||
.num_output = ARRAY_SIZE(pll_outputs),
|
||||
.output = pll_outputs,
|
||||
};
|
||||
|
||||
/* MCK0 characteristics. */
|
||||
static const struct clk_master_characteristics mck0_characteristics = {
|
||||
.output = { .min = 140000000, .max = 200000000 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
.output = { .min = 50000000, .max = 200000000 },
|
||||
.divisors = { 1, 2, 4, 3, 5 },
|
||||
.have_div3_pres = 1,
|
||||
};
|
||||
|
||||
/* MCK0 layout. */
|
||||
static const struct clk_master_layout mck0_layout = {
|
||||
.mask = 0x373,
|
||||
.mask = 0x773,
|
||||
.pres_shift = 4,
|
||||
.offset = 0x28,
|
||||
};
|
||||
@@ -835,10 +904,10 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sama7g5_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
|
||||
sama7g5_pmc = pmc_data_allocate(PMC_CPU + 1,
|
||||
nck(sama7g5_systemck),
|
||||
nck(sama7g5_periphck),
|
||||
nck(sama7g5_gck));
|
||||
nck(sama7g5_gck), 8);
|
||||
if (!sama7g5_pmc)
|
||||
return;
|
||||
|
||||
@@ -886,18 +955,18 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
hw = sam9x60_clk_register_frac_pll(regmap,
|
||||
&pmc_pll_lock, sama7g5_plls[i][j].n,
|
||||
sama7g5_plls[i][j].p, parent_hw, i,
|
||||
&pll_characteristics,
|
||||
sama7g5_plls[i][j].c,
|
||||
sama7g5_plls[i][j].l,
|
||||
sama7g5_plls[i][j].c);
|
||||
sama7g5_plls[i][j].f);
|
||||
break;
|
||||
|
||||
case PLL_TYPE_DIV:
|
||||
hw = sam9x60_clk_register_div_pll(regmap,
|
||||
&pmc_pll_lock, sama7g5_plls[i][j].n,
|
||||
sama7g5_plls[i][j].p, i,
|
||||
&pll_characteristics,
|
||||
sama7g5_plls[i][j].c,
|
||||
sama7g5_plls[i][j].l,
|
||||
sama7g5_plls[i][j].c);
|
||||
sama7g5_plls[i][j].f);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -912,12 +981,19 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
}
|
||||
}
|
||||
|
||||
parent_names[0] = md_slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "cpupll_divpmcck";
|
||||
parent_names[3] = "syspll_divpmcck";
|
||||
hw = at91_clk_register_master(regmap, "mck0", 4, parent_names,
|
||||
&mck0_layout, &mck0_characteristics);
|
||||
parent_names[0] = "cpupll_divpmcck";
|
||||
hw = at91_clk_register_master_pres(regmap, "cpuck", 1, parent_names,
|
||||
&mck0_layout, &mck0_characteristics,
|
||||
&pmc_mck0_lock,
|
||||
CLK_SET_RATE_PARENT, 0);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama7g5_pmc->chws[PMC_CPU] = hw;
|
||||
|
||||
hw = at91_clk_register_master_div(regmap, "mck0", "cpuck",
|
||||
&mck0_layout, &mck0_characteristics,
|
||||
&pmc_mck0_lock, 0);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
@@ -926,9 +1002,8 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
parent_names[0] = md_slck_name;
|
||||
parent_names[1] = td_slck_name;
|
||||
parent_names[2] = "mainck";
|
||||
parent_names[3] = "mck0";
|
||||
for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
|
||||
u8 num_parents = 4 + sama7g5_mckx[i].ep_count;
|
||||
u8 num_parents = 3 + sama7g5_mckx[i].ep_count;
|
||||
u32 *mux_table;
|
||||
|
||||
mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
|
||||
@@ -936,10 +1011,10 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
if (!mux_table)
|
||||
goto err_free;
|
||||
|
||||
SAMA7G5_INIT_TABLE(mux_table, 4);
|
||||
SAMA7G5_FILL_TABLE(&mux_table[4], sama7g5_mckx[i].ep_mux_table,
|
||||
SAMA7G5_INIT_TABLE(mux_table, 3);
|
||||
SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table,
|
||||
sama7g5_mckx[i].ep_count);
|
||||
SAMA7G5_FILL_TABLE(&parent_names[4], sama7g5_mckx[i].ep,
|
||||
SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_mckx[i].ep,
|
||||
sama7g5_mckx[i].ep_count);
|
||||
|
||||
hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
|
||||
@@ -962,24 +1037,25 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
parent_names[0] = md_slck_name;
|
||||
parent_names[1] = td_slck_name;
|
||||
parent_names[2] = "mainck";
|
||||
parent_names[3] = "mck0";
|
||||
parent_names[4] = "syspll_divpmcck";
|
||||
parent_names[5] = "ddrpll_divpmcck";
|
||||
parent_names[6] = "imgpll_divpmcck";
|
||||
parent_names[7] = "baudpll_divpmcck";
|
||||
parent_names[8] = "audiopll_divpmcck";
|
||||
parent_names[9] = "ethpll_divpmcck";
|
||||
parent_names[3] = "syspll_divpmcck";
|
||||
parent_names[4] = "ddrpll_divpmcck";
|
||||
parent_names[5] = "imgpll_divpmcck";
|
||||
parent_names[6] = "baudpll_divpmcck";
|
||||
parent_names[7] = "audiopll_divpmcck";
|
||||
parent_names[8] = "ethpll_divpmcck";
|
||||
for (i = 0; i < 8; i++) {
|
||||
char name[6];
|
||||
|
||||
snprintf(name, sizeof(name), "prog%d", i);
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name, parent_names,
|
||||
10, i,
|
||||
9, i,
|
||||
&programmable_layout,
|
||||
sama7g5_prog_mux_table);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama7g5_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
|
||||
@@ -1010,9 +1086,8 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
parent_names[0] = md_slck_name;
|
||||
parent_names[1] = td_slck_name;
|
||||
parent_names[2] = "mainck";
|
||||
parent_names[3] = "mck0";
|
||||
for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
|
||||
u8 num_parents = 4 + sama7g5_gck[i].pp_count;
|
||||
u8 num_parents = 3 + sama7g5_gck[i].pp_count;
|
||||
u32 *mux_table;
|
||||
|
||||
mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
|
||||
@@ -1020,10 +1095,10 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
if (!mux_table)
|
||||
goto err_free;
|
||||
|
||||
SAMA7G5_INIT_TABLE(mux_table, 4);
|
||||
SAMA7G5_FILL_TABLE(&mux_table[4], sama7g5_gck[i].pp_mux_table,
|
||||
SAMA7G5_INIT_TABLE(mux_table, 3);
|
||||
SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table,
|
||||
sama7g5_gck[i].pp_count);
|
||||
SAMA7G5_FILL_TABLE(&parent_names[4], sama7g5_gck[i].pp,
|
||||
SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_gck[i].pp,
|
||||
sama7g5_gck[i].pp_count);
|
||||
|
||||
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
|
||||
@@ -1052,7 +1127,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
|
||||
kfree(alloc_mem);
|
||||
}
|
||||
|
||||
pmc_data_free(sama7g5_pmc);
|
||||
kfree(sama7g5_pmc);
|
||||
}
|
||||
|
||||
/* Some clks are used for a clocksource */
|
||||
|
||||
@@ -25,7 +25,6 @@ static const struct clk_parent_data clk_dvp_parent = {
|
||||
static int clk_dvp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_hw_onecell_data *data;
|
||||
struct resource *res;
|
||||
struct clk_dvp *dvp;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
@@ -42,7 +41,7 @@ static int clk_dvp_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
data = dvp->data;
|
||||
|
||||
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
@@ -108,6 +107,7 @@ static const struct of_device_id clk_dvp_dt_ids[] = {
|
||||
{ .compatible = "brcm,brcm2711-dvp", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clk_dvp_dt_ids);
|
||||
|
||||
static struct platform_driver clk_dvp_driver = {
|
||||
.probe = clk_dvp_probe,
|
||||
|
||||
@@ -46,9 +46,17 @@
|
||||
#define MMCM_CLK_DIV_DIVIDE BIT(11)
|
||||
#define MMCM_CLK_DIV_NOCOUNT BIT(12)
|
||||
|
||||
struct axi_clkgen_limits {
|
||||
unsigned int fpfd_min;
|
||||
unsigned int fpfd_max;
|
||||
unsigned int fvco_min;
|
||||
unsigned int fvco_max;
|
||||
};
|
||||
|
||||
struct axi_clkgen {
|
||||
void __iomem *base;
|
||||
struct clk_hw clk_hw;
|
||||
struct axi_clkgen_limits limits;
|
||||
};
|
||||
|
||||
static uint32_t axi_clkgen_lookup_filter(unsigned int m)
|
||||
@@ -100,12 +108,15 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
|
||||
return 0x1f1f00fa;
|
||||
}
|
||||
|
||||
static const unsigned int fpfd_min = 10000;
|
||||
static const unsigned int fpfd_max = 300000;
|
||||
static const unsigned int fvco_min = 600000;
|
||||
static const unsigned int fvco_max = 1200000;
|
||||
static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = {
|
||||
.fpfd_min = 10000,
|
||||
.fpfd_max = 300000,
|
||||
.fvco_min = 600000,
|
||||
.fvco_max = 1200000,
|
||||
};
|
||||
|
||||
static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
|
||||
static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
|
||||
unsigned long fin, unsigned long fout,
|
||||
unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
|
||||
{
|
||||
unsigned long d, d_min, d_max, _d_min, _d_max;
|
||||
@@ -122,12 +133,12 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
|
||||
*best_m = 0;
|
||||
*best_dout = 0;
|
||||
|
||||
d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
|
||||
d_max = min_t(unsigned long, fin / fpfd_min, 80);
|
||||
d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1);
|
||||
d_max = min_t(unsigned long, fin / limits->fpfd_min, 80);
|
||||
|
||||
again:
|
||||
fvco_min_fract = fvco_min << fract_shift;
|
||||
fvco_max_fract = fvco_max << fract_shift;
|
||||
fvco_min_fract = limits->fvco_min << fract_shift;
|
||||
fvco_max_fract = limits->fvco_max << fract_shift;
|
||||
|
||||
m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
|
||||
m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
|
||||
@@ -319,6 +330,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
|
||||
const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
|
||||
unsigned int d, m, dout;
|
||||
struct axi_clkgen_div_params params;
|
||||
uint32_t power = 0;
|
||||
@@ -328,7 +340,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
|
||||
if (parent_rate == 0 || rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
|
||||
axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout);
|
||||
|
||||
if (d == 0 || dout == 0 || m == 0)
|
||||
return -EINVAL;
|
||||
@@ -368,10 +380,12 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
|
||||
static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
|
||||
const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
|
||||
unsigned int d, m, dout;
|
||||
unsigned long long tmp;
|
||||
|
||||
axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
|
||||
axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout);
|
||||
|
||||
if (d == 0 || dout == 0 || m == 0)
|
||||
return -EINVAL;
|
||||
@@ -482,17 +496,9 @@ static const struct clk_ops axi_clkgen_ops = {
|
||||
.get_parent = axi_clkgen_get_parent,
|
||||
};
|
||||
|
||||
static const struct of_device_id axi_clkgen_ids[] = {
|
||||
{
|
||||
.compatible = "adi,axi-clkgen-2.00.a",
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
|
||||
|
||||
static int axi_clkgen_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *id;
|
||||
const struct axi_clkgen_limits *dflt_limits;
|
||||
struct axi_clkgen *axi_clkgen;
|
||||
struct clk_init_data init;
|
||||
const char *parent_names[2];
|
||||
@@ -501,11 +507,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
return -ENODEV;
|
||||
|
||||
id = of_match_node(axi_clkgen_ids, pdev->dev.of_node);
|
||||
if (!id)
|
||||
dflt_limits = device_get_match_data(&pdev->dev);
|
||||
if (!dflt_limits)
|
||||
return -ENODEV;
|
||||
|
||||
axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
|
||||
@@ -527,6 +530,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&axi_clkgen->limits, dflt_limits, sizeof(axi_clkgen->limits));
|
||||
|
||||
clk_name = pdev->dev.of_node->name;
|
||||
of_property_read_string(pdev->dev.of_node, "clock-output-names",
|
||||
&clk_name);
|
||||
@@ -554,6 +559,15 @@ static int axi_clkgen_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id axi_clkgen_ids[] = {
|
||||
{
|
||||
.compatible = "adi,axi-clkgen-2.00.a",
|
||||
.data = &axi_clkgen_zynq_default_limits,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
|
||||
|
||||
static struct platform_driver axi_clkgen_driver = {
|
||||
.driver = {
|
||||
.name = "adi-axi-clkgen",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -406,3 +407,52 @@ void clk_hw_unregister_composite(struct clk_hw *hw)
|
||||
kfree(composite);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_composite);
|
||||
|
||||
static void devm_clk_hw_release_composite(struct device *dev, void *res)
|
||||
{
|
||||
clk_hw_unregister_composite(*(struct clk_hw **)res);
|
||||
}
|
||||
|
||||
static struct clk_hw *__devm_clk_hw_register_composite(struct device *dev,
|
||||
const char *name, const char * const *parent_names,
|
||||
const struct clk_parent_data *pdata, int num_parents,
|
||||
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
|
||||
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
|
||||
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct clk_hw **ptr, *hw;
|
||||
|
||||
ptr = devres_alloc(devm_clk_hw_release_composite, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hw = __clk_hw_register_composite(dev, name, parent_names, pdata,
|
||||
num_parents, mux_hw, mux_ops, rate_hw,
|
||||
rate_ops, gate_hw, gate_ops, flags);
|
||||
|
||||
if (!IS_ERR(hw)) {
|
||||
*ptr = hw;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
struct clk_hw *devm_clk_hw_register_composite_pdata(struct device *dev,
|
||||
const char *name,
|
||||
const struct clk_parent_data *parent_data,
|
||||
int num_parents,
|
||||
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
|
||||
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
|
||||
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
|
||||
unsigned long flags)
|
||||
{
|
||||
return __devm_clk_hw_register_composite(dev, name, NULL, parent_data,
|
||||
num_parents, mux_hw, mux_ops,
|
||||
rate_hw, rate_ops, gate_hw,
|
||||
gate_ops, flags);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
@@ -578,3 +579,36 @@ void clk_hw_unregister_divider(struct clk_hw *hw)
|
||||
kfree(div);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);
|
||||
|
||||
static void devm_clk_hw_release_divider(struct device *dev, void *res)
|
||||
{
|
||||
clk_hw_unregister_divider(*(struct clk_hw **)res);
|
||||
}
|
||||
|
||||
struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
|
||||
struct device_node *np, const char *name,
|
||||
const char *parent_name, const struct clk_hw *parent_hw,
|
||||
const struct clk_parent_data *parent_data, unsigned long flags,
|
||||
void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
|
||||
const struct clk_div_table *table, spinlock_t *lock)
|
||||
{
|
||||
struct clk_hw **ptr, *hw;
|
||||
|
||||
ptr = devres_alloc(devm_clk_hw_release_divider, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hw = __clk_hw_register_divider(dev, np, name, parent_name, parent_hw,
|
||||
parent_data, flags, reg, shift, width,
|
||||
clk_divider_flags, table, lock);
|
||||
|
||||
if (!IS_ERR(hw)) {
|
||||
*ptr = hw;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_clk_hw_register_divider);
|
||||
|
||||
106
drivers/clk/clk-fsl-flexspi.c
Normal file
106
drivers/clk/clk-fsl-flexspi.c
Normal file
@@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Layerscape FlexSPI clock driver
|
||||
*
|
||||
* Copyright 2020 Michael Walle <michael@walle.cc>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static const struct clk_div_table ls1028a_flexspi_divs[] = {
|
||||
{ .val = 0, .div = 1, },
|
||||
{ .val = 1, .div = 2, },
|
||||
{ .val = 2, .div = 3, },
|
||||
{ .val = 3, .div = 4, },
|
||||
{ .val = 4, .div = 5, },
|
||||
{ .val = 5, .div = 6, },
|
||||
{ .val = 6, .div = 7, },
|
||||
{ .val = 7, .div = 8, },
|
||||
{ .val = 11, .div = 12, },
|
||||
{ .val = 15, .div = 16, },
|
||||
{ .val = 16, .div = 20, },
|
||||
{ .val = 17, .div = 24, },
|
||||
{ .val = 18, .div = 28, },
|
||||
{ .val = 19, .div = 32, },
|
||||
{ .val = 20, .div = 80, },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct clk_div_table lx2160a_flexspi_divs[] = {
|
||||
{ .val = 1, .div = 2, },
|
||||
{ .val = 3, .div = 4, },
|
||||
{ .val = 5, .div = 6, },
|
||||
{ .val = 7, .div = 8, },
|
||||
{ .val = 11, .div = 12, },
|
||||
{ .val = 15, .div = 16, },
|
||||
{ .val = 16, .div = 20, },
|
||||
{ .val = 17, .div = 24, },
|
||||
{ .val = 18, .div = 28, },
|
||||
{ .val = 19, .div = 32, },
|
||||
{ .val = 20, .div = 80, },
|
||||
{}
|
||||
};
|
||||
|
||||
static int fsl_flexspi_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
const char *clk_name = np->name;
|
||||
const char *clk_parent;
|
||||
struct resource *res;
|
||||
void __iomem *reg;
|
||||
struct clk_hw *hw;
|
||||
const struct clk_div_table *divs;
|
||||
|
||||
divs = device_get_match_data(dev);
|
||||
if (!divs)
|
||||
return -ENOENT;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENOENT;
|
||||
|
||||
/*
|
||||
* Can't use devm_ioremap_resource() or devm_of_iomap() because the
|
||||
* resource might already be taken by the parent device.
|
||||
*/
|
||||
reg = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!reg)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_parent = of_clk_get_parent_name(np, 0);
|
||||
if (!clk_parent)
|
||||
return -EINVAL;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &clk_name);
|
||||
|
||||
hw = devm_clk_hw_register_divider_table(dev, clk_name, clk_parent, 0,
|
||||
reg, 0, 5, 0, divs, NULL);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
|
||||
static const struct of_device_id fsl_flexspi_clk_dt_ids[] = {
|
||||
{ .compatible = "fsl,ls1028a-flexspi-clk", .data = &ls1028a_flexspi_divs },
|
||||
{ .compatible = "fsl,lx2160a-flexspi-clk", .data = &lx2160a_flexspi_divs },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fsl_flexspi_clk_dt_ids);
|
||||
|
||||
static struct platform_driver fsl_flexspi_clk_driver = {
|
||||
.driver = {
|
||||
.name = "fsl-flexspi-clk",
|
||||
.of_match_table = fsl_flexspi_clk_dt_ids,
|
||||
},
|
||||
.probe = fsl_flexspi_clk_probe,
|
||||
};
|
||||
module_platform_driver(fsl_flexspi_clk_driver);
|
||||
|
||||
MODULE_DESCRIPTION("FlexSPI clock driver for Layerscape SoCs");
|
||||
MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -58,13 +58,13 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
|
||||
/* set clock direction, we are the BCLK master */
|
||||
writel(CR2_BCD, base + I2S_CR2);
|
||||
|
||||
hw = clk_hw_register_composite_pdata(dev, dev->of_node->name,
|
||||
&pdata, 1, NULL, NULL,
|
||||
&sai_clk->div.hw,
|
||||
&clk_divider_ops,
|
||||
&sai_clk->gate.hw,
|
||||
&clk_gate_ops,
|
||||
CLK_SET_RATE_GATE);
|
||||
hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
|
||||
&pdata, 1, NULL, NULL,
|
||||
&sai_clk->div.hw,
|
||||
&clk_divider_ops,
|
||||
&sai_clk->gate.hw,
|
||||
&clk_gate_ops,
|
||||
CLK_SET_RATE_GATE);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ static struct platform_driver clk_pwm_driver = {
|
||||
.remove = clk_pwm_remove,
|
||||
.driver = {
|
||||
.name = "pwm-clock",
|
||||
.of_match_table = of_match_ptr(clk_pwm_dt_ids),
|
||||
.of_match_table = clk_pwm_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <dt-bindings/clock/fsl,qoriq-clockgen.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
@@ -1368,33 +1369,33 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
|
||||
idx = clkspec->args[1];
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
case QORIQ_CLK_SYSCLK:
|
||||
if (idx != 0)
|
||||
goto bad_args;
|
||||
clk = cg->sysclk;
|
||||
break;
|
||||
case 1:
|
||||
case QORIQ_CLK_CMUX:
|
||||
if (idx >= ARRAY_SIZE(cg->cmux))
|
||||
goto bad_args;
|
||||
clk = cg->cmux[idx];
|
||||
break;
|
||||
case 2:
|
||||
case QORIQ_CLK_HWACCEL:
|
||||
if (idx >= ARRAY_SIZE(cg->hwaccel))
|
||||
goto bad_args;
|
||||
clk = cg->hwaccel[idx];
|
||||
break;
|
||||
case 3:
|
||||
case QORIQ_CLK_FMAN:
|
||||
if (idx >= ARRAY_SIZE(cg->fman))
|
||||
goto bad_args;
|
||||
clk = cg->fman[idx];
|
||||
break;
|
||||
case 4:
|
||||
case QORIQ_CLK_PLATFORM_PLL:
|
||||
pll = &cg->pll[PLATFORM_PLL];
|
||||
if (idx >= ARRAY_SIZE(pll->div))
|
||||
goto bad_args;
|
||||
clk = pll->div[idx].clk;
|
||||
break;
|
||||
case 5:
|
||||
case QORIQ_CLK_CORECLK:
|
||||
if (idx != 0)
|
||||
goto bad_args;
|
||||
clk = cg->coreclk;
|
||||
|
||||
@@ -195,6 +195,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
err_reg:
|
||||
of_node_put(s2mps11_clks[0].clk_np);
|
||||
while (--i >= 0)
|
||||
clkdev_drop(s2mps11_clks[i].lookup);
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ static const struct clk_ops scpi_dvfs_ops = {
|
||||
.set_rate = scpi_dvfs_set_rate,
|
||||
};
|
||||
|
||||
static const struct of_device_id scpi_clk_match[] = {
|
||||
static const struct of_device_id scpi_clk_match[] __maybe_unused = {
|
||||
{ .compatible = "arm,scpi-dvfs-clocks", .data = &scpi_dvfs_ops, },
|
||||
{ .compatible = "arm,scpi-variable-clocks", .data = &scpi_clk_ops, },
|
||||
{}
|
||||
|
||||
@@ -902,6 +902,10 @@ static int _si5351_clkout_set_disable_state(
|
||||
static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num)
|
||||
{
|
||||
u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + num);
|
||||
u8 mask = val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
|
||||
SI5351_PLL_RESET_A;
|
||||
unsigned int v;
|
||||
int err;
|
||||
|
||||
switch (val & SI5351_CLK_INPUT_MASK) {
|
||||
case SI5351_CLK_INPUT_XTAL:
|
||||
@@ -909,9 +913,12 @@ static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num
|
||||
return; /* pll not used, no need to reset */
|
||||
}
|
||||
|
||||
si5351_reg_write(drvdata, SI5351_PLL_RESET,
|
||||
val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
|
||||
SI5351_PLL_RESET_A);
|
||||
si5351_reg_write(drvdata, SI5351_PLL_RESET, mask);
|
||||
|
||||
err = regmap_read_poll_timeout(drvdata->regmap, SI5351_PLL_RESET, v,
|
||||
!(v & mask), 0, 20000);
|
||||
if (err < 0)
|
||||
dev_err(&drvdata->client->dev, "Reset bit didn't clear\n");
|
||||
|
||||
dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n",
|
||||
__func__, clk_hw_get_name(&drvdata->clkout[num].hw),
|
||||
|
||||
@@ -739,8 +739,8 @@ static int vc5_update_power(struct device_node *np_output,
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!of_property_read_u32(np_output,
|
||||
"idt,voltage-microvolts", &value)) {
|
||||
if (!of_property_read_u32(np_output, "idt,voltage-microvolt",
|
||||
&value)) {
|
||||
clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_PWR_MASK;
|
||||
switch (value) {
|
||||
case 1800000:
|
||||
|
||||
@@ -422,7 +422,7 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
|
||||
static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
|
||||
{
|
||||
struct clk_parent_map *entry = &core->parents[index];
|
||||
struct clk_core *parent = ERR_PTR(-ENOENT);
|
||||
struct clk_core *parent;
|
||||
|
||||
if (entry->hw) {
|
||||
parent = entry->hw->core;
|
||||
@@ -2393,6 +2393,8 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
trace_clk_set_rate_range(clk->core, min, max);
|
||||
|
||||
if (min > max) {
|
||||
pr_err("%s: clk %s dev %s con %s: invalid range [%lu, %lu]\n",
|
||||
__func__, clk->core->name, clk->dev_id, clk->con_id,
|
||||
@@ -2460,6 +2462,8 @@ int clk_set_min_rate(struct clk *clk, unsigned long rate)
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
trace_clk_set_min_rate(clk->core, rate);
|
||||
|
||||
return clk_set_rate_range(clk, rate, clk->max_rate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_min_rate);
|
||||
@@ -2476,6 +2480,8 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate)
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
trace_clk_set_max_rate(clk->core, rate);
|
||||
|
||||
return clk_set_rate_range(clk, clk->min_rate, rate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_max_rate);
|
||||
@@ -3010,7 +3016,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
|
||||
else
|
||||
seq_puts(s, "-----");
|
||||
|
||||
seq_printf(s, " %6d\n", clk_core_get_scaled_duty_cycle(c, 100000));
|
||||
seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
|
||||
|
||||
if (c->ops->is_enabled)
|
||||
seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
|
||||
else if (!c->ops->enable)
|
||||
seq_printf(s, " %9c\n", 'Y');
|
||||
else
|
||||
seq_printf(s, " %9c\n", '?');
|
||||
}
|
||||
|
||||
static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
|
||||
@@ -3029,9 +3042,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
|
||||
struct clk_core *c;
|
||||
struct hlist_head **lists = (struct hlist_head **)s->private;
|
||||
|
||||
seq_puts(s, " enable prepare protect duty\n");
|
||||
seq_puts(s, " clock count count count rate accuracy phase cycle\n");
|
||||
seq_puts(s, "---------------------------------------------------------------------------------------------\n");
|
||||
seq_puts(s, " enable prepare protect duty hardware\n");
|
||||
seq_puts(s, " clock count count count rate accuracy phase cycle enable\n");
|
||||
seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
clk_prepare_lock();
|
||||
|
||||
@@ -3750,6 +3763,24 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
|
||||
return clk;
|
||||
}
|
||||
|
||||
/**
|
||||
* clk_hw_get_clk - get clk consumer given an clk_hw
|
||||
* @hw: clk_hw associated with the clk being consumed
|
||||
* @con_id: connection ID string on device
|
||||
*
|
||||
* Returns: new clk consumer
|
||||
* This is the function to be used by providers which need
|
||||
* to get a consumer clk and act on the clock element
|
||||
* Calls to this function must be balanced with calls clk_put()
|
||||
*/
|
||||
struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id)
|
||||
{
|
||||
struct device *dev = hw->core->dev;
|
||||
|
||||
return clk_hw_create_clk(dev, hw, dev_name(dev), con_id);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_hw_get_clk);
|
||||
|
||||
static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
|
||||
{
|
||||
const char *dst;
|
||||
@@ -4151,12 +4182,12 @@ void clk_hw_unregister(struct clk_hw *hw)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister);
|
||||
|
||||
static void devm_clk_release(struct device *dev, void *res)
|
||||
static void devm_clk_unregister_cb(struct device *dev, void *res)
|
||||
{
|
||||
clk_unregister(*(struct clk **)res);
|
||||
}
|
||||
|
||||
static void devm_clk_hw_release(struct device *dev, void *res)
|
||||
static void devm_clk_hw_unregister_cb(struct device *dev, void *res)
|
||||
{
|
||||
clk_hw_unregister(*(struct clk_hw **)res);
|
||||
}
|
||||
@@ -4176,7 +4207,7 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
|
||||
struct clk *clk;
|
||||
struct clk **clkp;
|
||||
|
||||
clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
|
||||
clkp = devres_alloc(devm_clk_unregister_cb, sizeof(*clkp), GFP_KERNEL);
|
||||
if (!clkp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@@ -4206,7 +4237,7 @@ int devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
|
||||
struct clk_hw **hwp;
|
||||
int ret;
|
||||
|
||||
hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL);
|
||||
hwp = devres_alloc(devm_clk_hw_unregister_cb, sizeof(*hwp), GFP_KERNEL);
|
||||
if (!hwp)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -4250,7 +4281,7 @@ static int devm_clk_hw_match(struct device *dev, void *res, void *data)
|
||||
*/
|
||||
void devm_clk_unregister(struct device *dev, struct clk *clk)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
|
||||
WARN_ON(devres_release(dev, devm_clk_unregister_cb, devm_clk_match, clk));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_unregister);
|
||||
|
||||
@@ -4265,11 +4296,54 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
|
||||
*/
|
||||
void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match,
|
||||
WARN_ON(devres_release(dev, devm_clk_hw_unregister_cb, devm_clk_hw_match,
|
||||
hw));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_hw_unregister);
|
||||
|
||||
static void devm_clk_release(struct device *dev, void *res)
|
||||
{
|
||||
clk_put(*(struct clk **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_clk_hw_get_clk - resource managed clk_hw_get_clk()
|
||||
* @dev: device that is registering this clock
|
||||
* @hw: clk_hw associated with the clk being consumed
|
||||
* @con_id: connection ID string on device
|
||||
*
|
||||
* Managed clk_hw_get_clk(). Clocks got with this function are
|
||||
* automatically clk_put() on driver detach. See clk_put()
|
||||
* for more information.
|
||||
*/
|
||||
struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw,
|
||||
const char *con_id)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk **clkp;
|
||||
|
||||
/* This should not happen because it would mean we have drivers
|
||||
* passing around clk_hw pointers instead of having the caller use
|
||||
* proper clk_get() style APIs
|
||||
*/
|
||||
WARN_ON_ONCE(dev != hw->core->dev);
|
||||
|
||||
clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
|
||||
if (!clkp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk = clk_hw_get_clk(hw, con_id);
|
||||
if (!IS_ERR(clk)) {
|
||||
*clkp = clk;
|
||||
devres_add(dev, clkp);
|
||||
} else {
|
||||
devres_free(clkp);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_hw_get_clk);
|
||||
|
||||
/*
|
||||
* clkdev helpers
|
||||
*/
|
||||
@@ -4417,6 +4491,42 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_notifier_unregister);
|
||||
|
||||
struct clk_notifier_devres {
|
||||
struct clk *clk;
|
||||
struct notifier_block *nb;
|
||||
};
|
||||
|
||||
static void devm_clk_notifier_release(struct device *dev, void *res)
|
||||
{
|
||||
struct clk_notifier_devres *devres = res;
|
||||
|
||||
clk_notifier_unregister(devres->clk, devres->nb);
|
||||
}
|
||||
|
||||
int devm_clk_notifier_register(struct device *dev, struct clk *clk,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
struct clk_notifier_devres *devres;
|
||||
int ret;
|
||||
|
||||
devres = devres_alloc(devm_clk_notifier_release,
|
||||
sizeof(*devres), GFP_KERNEL);
|
||||
|
||||
if (!devres)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = clk_notifier_register(clk, nb);
|
||||
if (!ret) {
|
||||
devres->clk = clk;
|
||||
devres->nb = nb;
|
||||
} else {
|
||||
devres_free(devres);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_notifier_register);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static void clk_core_reparent_orphans(void)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ struct clk_gate2 {
|
||||
void __iomem *reg;
|
||||
u8 bit_idx;
|
||||
u8 cgr_val;
|
||||
u8 cgr_mask;
|
||||
u8 flags;
|
||||
spinlock_t *lock;
|
||||
unsigned int *share_count;
|
||||
@@ -37,37 +38,38 @@ struct clk_gate2 {
|
||||
|
||||
#define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw)
|
||||
|
||||
static int clk_gate2_enable(struct clk_hw *hw)
|
||||
static void clk_gate2_do_shared_clks(struct clk_hw *hw, bool enable)
|
||||
{
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
u32 reg;
|
||||
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(gate->cgr_mask << gate->bit_idx);
|
||||
if (enable)
|
||||
reg |= (gate->cgr_val & gate->cgr_mask) << gate->bit_idx;
|
||||
writel(reg, gate->reg);
|
||||
}
|
||||
|
||||
static int clk_gate2_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (gate->share_count && (*gate->share_count)++ > 0)
|
||||
goto out;
|
||||
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
|
||||
ret = clk_gate_ops.enable(hw);
|
||||
} else {
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
reg |= gate->cgr_val << gate->bit_idx;
|
||||
writel(reg, gate->reg);
|
||||
}
|
||||
|
||||
clk_gate2_do_shared_clks(hw, true);
|
||||
out:
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clk_gate2_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
@@ -79,23 +81,17 @@ static void clk_gate2_disable(struct clk_hw *hw)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
|
||||
clk_gate_ops.disable(hw);
|
||||
} else {
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
writel(reg, gate->reg);
|
||||
}
|
||||
|
||||
clk_gate2_do_shared_clks(hw, false);
|
||||
out:
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
|
||||
static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx)
|
||||
static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx,
|
||||
u8 cgr_val, u8 cgr_mask)
|
||||
{
|
||||
u32 val = readl(reg);
|
||||
|
||||
if (((val >> bit_idx) & 1) == 1)
|
||||
if (((val >> bit_idx) & cgr_mask) == cgr_val)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -104,29 +100,28 @@ static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx)
|
||||
static int clk_gate2_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
|
||||
return clk_gate_ops.is_enabled(hw);
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
|
||||
ret = clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx,
|
||||
gate->cgr_val, gate->cgr_mask);
|
||||
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_gate2_disable_unused(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (!gate->share_count || *gate->share_count == 0) {
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
writel(reg, gate->reg);
|
||||
}
|
||||
if (!gate->share_count || *gate->share_count == 0)
|
||||
clk_gate2_do_shared_clks(hw, false);
|
||||
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
@@ -140,7 +135,7 @@ static const struct clk_ops clk_gate2_ops = {
|
||||
|
||||
struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 bit_idx, u8 cgr_val,
|
||||
void __iomem *reg, u8 bit_idx, u8 cgr_val, u8 cgr_mask,
|
||||
u8 clk_gate2_flags, spinlock_t *lock,
|
||||
unsigned int *share_count)
|
||||
{
|
||||
@@ -157,6 +152,7 @@ struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
|
||||
gate->reg = reg;
|
||||
gate->bit_idx = bit_idx;
|
||||
gate->cgr_val = cgr_val;
|
||||
gate->cgr_mask = cgr_mask;
|
||||
gate->flags = clk_gate2_flags;
|
||||
gate->lock = lock;
|
||||
gate->share_count = share_count;
|
||||
|
||||
@@ -653,7 +653,7 @@ static struct platform_driver imx8mm_clk_driver = {
|
||||
* reloading the driver will crash or break devices.
|
||||
*/
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = of_match_ptr(imx8mm_clk_of_match),
|
||||
.of_match_table = imx8mm_clk_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(imx8mm_clk_driver);
|
||||
|
||||
@@ -604,7 +604,7 @@ static struct platform_driver imx8mn_clk_driver = {
|
||||
* reloading the driver will crash or break devices.
|
||||
*/
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = of_match_ptr(imx8mn_clk_of_match),
|
||||
.of_match_table = imx8mn_clk_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(imx8mn_clk_driver);
|
||||
|
||||
@@ -425,7 +425,7 @@ static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1];
|
||||
static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *np;
|
||||
void __iomem *anatop_base, *ccm_base;
|
||||
int i;
|
||||
|
||||
@@ -763,7 +763,7 @@ static struct platform_driver imx8mp_clk_driver = {
|
||||
* reloading the driver will crash or break devices.
|
||||
*/
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = of_match_ptr(imx8mp_clk_of_match),
|
||||
.of_match_table = imx8mp_clk_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(imx8mp_clk_driver);
|
||||
|
||||
@@ -639,7 +639,7 @@ static struct platform_driver imx8mq_clk_driver = {
|
||||
* reloading the driver will crash or break devices.
|
||||
*/
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = of_match_ptr(imx8mq_clk_of_match),
|
||||
.of_match_table = imx8mq_clk_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(imx8mq_clk_driver);
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk-scu.h"
|
||||
@@ -157,6 +159,135 @@ static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = {
|
||||
.num_max = IMX_LSIO_LPCG_CLK_END,
|
||||
};
|
||||
|
||||
#define IMX_LPCG_MAX_CLKS 8
|
||||
|
||||
static struct clk_hw *imx_lpcg_of_clk_src_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
struct clk_hw_onecell_data *hw_data = data;
|
||||
unsigned int idx = clkspec->args[0] / 4;
|
||||
|
||||
if (idx >= hw_data->num) {
|
||||
pr_err("%s: invalid index %u\n", __func__, idx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return hw_data->hws[idx];
|
||||
}
|
||||
|
||||
static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
const char *output_names[IMX_LPCG_MAX_CLKS];
|
||||
const char *parent_names[IMX_LPCG_MAX_CLKS];
|
||||
unsigned int bit_offset[IMX_LPCG_MAX_CLKS];
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
struct clk_hw **clk_hws;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int count;
|
||||
int idx;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (!of_device_is_compatible(np, "fsl,imx8qxp-lpcg"))
|
||||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
count = of_property_count_u32_elems(np, "clock-indices");
|
||||
if (count < 0) {
|
||||
dev_err(&pdev->dev, "failed to count clocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* A trick here is that we set the num of clks to the MAX instead
|
||||
* of the count from clock-indices because one LPCG supports up to
|
||||
* 8 clock outputs which each of them is fixed to 4 bits. Then we can
|
||||
* easily get the clock by clk-indices (bit-offset) / 4.
|
||||
* And the cost is very limited few pointers.
|
||||
*/
|
||||
|
||||
clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws,
|
||||
IMX_LPCG_MAX_CLKS), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_data->num = IMX_LPCG_MAX_CLKS;
|
||||
clk_hws = clk_data->hws;
|
||||
|
||||
ret = of_property_read_u32_array(np, "clock-indices", bit_offset,
|
||||
count);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to read clock-indices\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_clk_parent_fill(np, parent_names, count);
|
||||
if (ret != count) {
|
||||
dev_err(&pdev->dev, "failed to get clock parent names\n");
|
||||
return count;
|
||||
}
|
||||
|
||||
ret = of_property_read_string_array(np, "clock-output-names",
|
||||
output_names, count);
|
||||
if (ret != count) {
|
||||
dev_err(&pdev->dev, "failed to read clock-output-names\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
idx = bit_offset[i] / 4;
|
||||
if (idx > IMX_LPCG_MAX_CLKS) {
|
||||
dev_warn(&pdev->dev, "invalid bit offset of clock %d\n",
|
||||
i);
|
||||
ret = -EINVAL;
|
||||
goto unreg;
|
||||
}
|
||||
|
||||
clk_hws[idx] = imx_clk_lpcg_scu_dev(&pdev->dev, output_names[i],
|
||||
parent_names[i], 0, base,
|
||||
bit_offset[i], false);
|
||||
if (IS_ERR(clk_hws[idx])) {
|
||||
dev_warn(&pdev->dev, "failed to register clock %d\n",
|
||||
idx);
|
||||
ret = PTR_ERR(clk_hws[idx]);
|
||||
goto unreg;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get,
|
||||
clk_data);
|
||||
if (ret)
|
||||
goto unreg;
|
||||
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
unreg:
|
||||
while (--i >= 0) {
|
||||
idx = bit_offset[i] / 4;
|
||||
if (clk_hws[idx])
|
||||
imx_clk_lpcg_scu_unregister(clk_hws[idx]);
|
||||
}
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -167,8 +298,14 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
struct clk_hw **clks;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* try new binding to parse clocks from device tree first */
|
||||
ret = imx_lpcg_parse_clks_from_dt(pdev, np);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
ss_lpcg = of_device_get_match_data(dev);
|
||||
if (!ss_lpcg)
|
||||
return -ENODEV;
|
||||
@@ -219,6 +356,7 @@ static const struct of_device_id imx8qxp_lpcg_match[] = {
|
||||
{ .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
|
||||
{ .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
|
||||
{ .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
|
||||
{ .compatible = "fsl,imx8qxp-lpcg", NULL },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@@ -226,6 +364,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = {
|
||||
.driver = {
|
||||
.name = "imx8qxp-lpcg-clk",
|
||||
.of_match_table = imx8qxp_lpcg_match,
|
||||
.pm = &imx_clk_lpcg_scu_pm_ops,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = imx8qxp_lpcg_clk_probe,
|
||||
|
||||
@@ -22,9 +22,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
|
||||
struct device_node *ccm_node = pdev->dev.of_node;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
struct clk_hw **clks;
|
||||
u32 clk_cells;
|
||||
int ret, i;
|
||||
|
||||
ret = imx_clk_scu_init();
|
||||
ret = imx_clk_scu_init(ccm_node);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -33,6 +34,9 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_property_read_u32(ccm_node, "#clock-cells", &clk_cells))
|
||||
return -EINVAL;
|
||||
|
||||
clk_data->num = IMX_SCU_CLK_END;
|
||||
clks = clk_data->hws;
|
||||
|
||||
@@ -55,78 +59,78 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
|
||||
clks[IMX_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000);
|
||||
|
||||
/* ARM core */
|
||||
clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
|
||||
clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU, clk_cells);
|
||||
|
||||
/* LSIO SS */
|
||||
clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
|
||||
/* ADMA SS */
|
||||
clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
|
||||
/* Connectivity */
|
||||
clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
|
||||
clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
|
||||
clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
|
||||
clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
|
||||
clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
|
||||
clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
|
||||
clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
|
||||
clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS, clk_cells);
|
||||
clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0, clk_cells);
|
||||
clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS, clk_cells);
|
||||
clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0, clk_cells);
|
||||
clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS, clk_cells);
|
||||
clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS, clk_cells);
|
||||
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);
|
||||
clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
|
||||
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);
|
||||
|
||||
/* MIPI-LVDS SS */
|
||||
clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
|
||||
clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
|
||||
clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, clk_cells);
|
||||
clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
|
||||
/* GPU SS */
|
||||
clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
|
||||
clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
|
||||
clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER, clk_cells);
|
||||
clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC, clk_cells);
|
||||
|
||||
for (i = 0; i < clk_data->num; i++) {
|
||||
if (IS_ERR(clks[i]))
|
||||
@@ -134,7 +138,19 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
|
||||
i, PTR_ERR(clks[i]));
|
||||
}
|
||||
|
||||
return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
|
||||
if (clk_cells == 2) {
|
||||
ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks);
|
||||
if (ret)
|
||||
imx_clk_scu_unregister();
|
||||
} else {
|
||||
/*
|
||||
* legacy binding code path doesn't unregister here because
|
||||
* it will be removed later.
|
||||
*/
|
||||
ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id imx8qxp_match[] = {
|
||||
|
||||
@@ -34,6 +34,9 @@ struct clk_lpcg_scu {
|
||||
void __iomem *reg;
|
||||
u8 bit_idx;
|
||||
bool hw_gate;
|
||||
|
||||
/* for state save&restore */
|
||||
u32 state;
|
||||
};
|
||||
|
||||
#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
|
||||
@@ -81,9 +84,9 @@ static const struct clk_ops clk_lpcg_scu_ops = {
|
||||
.disable = clk_lpcg_scu_disable,
|
||||
};
|
||||
|
||||
struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
|
||||
unsigned long flags, void __iomem *reg,
|
||||
u8 bit_idx, bool hw_gate)
|
||||
struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 bit_idx, bool hw_gate)
|
||||
{
|
||||
struct clk_lpcg_scu *clk;
|
||||
struct clk_init_data init;
|
||||
@@ -107,11 +110,53 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
|
||||
clk->hw.init = &init;
|
||||
|
||||
hw = &clk->hw;
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(clk);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (dev)
|
||||
dev_set_drvdata(dev, clk);
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
void imx_clk_lpcg_scu_unregister(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
|
||||
|
||||
clk_hw_unregister(&clk->hw);
|
||||
kfree(clk);
|
||||
}
|
||||
|
||||
static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev)
|
||||
{
|
||||
struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
|
||||
|
||||
clk->state = readl_relaxed(clk->reg);
|
||||
dev_dbg(dev, "save lpcg state 0x%x\n", clk->state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
|
||||
{
|
||||
struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
|
||||
|
||||
/*
|
||||
* FIXME: Sometimes writes don't work unless the CPU issues
|
||||
* them twice
|
||||
*/
|
||||
|
||||
writel(clk->state, clk->reg);
|
||||
writel(clk->state, clk->reg);
|
||||
dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = {
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend,
|
||||
imx_clk_lpcg_scu_resume)
|
||||
};
|
||||
|
||||
@@ -416,7 +416,7 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
|
||||
__func__, name);
|
||||
kfree(pll);
|
||||
return ERR_PTR(-EINVAL);
|
||||
};
|
||||
}
|
||||
|
||||
pll->base = base;
|
||||
pll->hw.init = &init;
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk-scu.h"
|
||||
@@ -16,6 +20,21 @@
|
||||
#define IMX_SIP_SET_CPUFREQ 0x00
|
||||
|
||||
static struct imx_sc_ipc *ccm_ipc_handle;
|
||||
static struct device_node *pd_np;
|
||||
static struct platform_driver imx_clk_scu_driver;
|
||||
|
||||
struct imx_scu_clk_node {
|
||||
const char *name;
|
||||
u32 rsrc;
|
||||
u8 clk_type;
|
||||
const char * const *parents;
|
||||
int num_parents;
|
||||
|
||||
struct clk_hw *hw;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct list_head imx_scu_clks[IMX_SC_R_LAST];
|
||||
|
||||
/*
|
||||
* struct clk_scu - Description of one SCU clock
|
||||
@@ -27,6 +46,10 @@ struct clk_scu {
|
||||
struct clk_hw hw;
|
||||
u16 rsrc_id;
|
||||
u8 clk_type;
|
||||
|
||||
/* for state save&restore */
|
||||
bool is_enabled;
|
||||
u32 rate;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -128,9 +151,28 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
|
||||
return container_of(hw, struct clk_scu, hw);
|
||||
}
|
||||
|
||||
int imx_clk_scu_init(void)
|
||||
int imx_clk_scu_init(struct device_node *np)
|
||||
{
|
||||
return imx_scu_get_handle(&ccm_ipc_handle);
|
||||
u32 clk_cells;
|
||||
int ret, i;
|
||||
|
||||
ret = imx_scu_get_handle(&ccm_ipc_handle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
of_property_read_u32(np, "#clock-cells", &clk_cells);
|
||||
|
||||
if (clk_cells == 2) {
|
||||
for (i = 0; i < IMX_SC_R_LAST; i++)
|
||||
INIT_LIST_HEAD(&imx_scu_clks[i]);
|
||||
|
||||
/* pd_np will be used to attach power domains later */
|
||||
pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd");
|
||||
if (!pd_np)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return platform_driver_register(&imx_clk_scu_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -344,8 +386,9 @@ static const struct clk_ops clk_scu_cpu_ops = {
|
||||
.unprepare = clk_scu_unprepare,
|
||||
};
|
||||
|
||||
struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
|
||||
int num_parents, u32 rsrc_id, u8 clk_type)
|
||||
struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
|
||||
const char * const *parents, int num_parents,
|
||||
u32 rsrc_id, u8 clk_type)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_scu *clk;
|
||||
@@ -379,11 +422,185 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
|
||||
clk->hw.init = &init;
|
||||
|
||||
hw = &clk->hw;
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(clk);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (dev)
|
||||
dev_set_drvdata(dev, clk);
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
unsigned int rsrc = clkspec->args[0];
|
||||
unsigned int idx = clkspec->args[1];
|
||||
struct list_head *scu_clks = data;
|
||||
struct imx_scu_clk_node *clk;
|
||||
|
||||
list_for_each_entry(clk, &scu_clks[rsrc], node) {
|
||||
if (clk->clk_type == idx)
|
||||
return clk->hw;
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static int imx_clk_scu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct imx_scu_clk_node *clk = dev_get_platdata(dev);
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 50);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret) {
|
||||
pm_runtime_disable(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents,
|
||||
clk->rsrc, clk->clk_type);
|
||||
if (IS_ERR(hw)) {
|
||||
pm_runtime_disable(dev);
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
|
||||
clk->hw = hw;
|
||||
list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]);
|
||||
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc,
|
||||
clk->clk_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused imx_clk_scu_suspend(struct device *dev)
|
||||
{
|
||||
struct clk_scu *clk = dev_get_drvdata(dev);
|
||||
|
||||
clk->rate = clk_hw_get_rate(&clk->hw);
|
||||
clk->is_enabled = clk_hw_is_enabled(&clk->hw);
|
||||
|
||||
if (clk->rate)
|
||||
dev_dbg(dev, "save rate %d\n", clk->rate);
|
||||
|
||||
if (clk->is_enabled)
|
||||
dev_dbg(dev, "save enabled state\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused imx_clk_scu_resume(struct device *dev)
|
||||
{
|
||||
struct clk_scu *clk = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (clk->rate) {
|
||||
ret = clk_scu_set_rate(&clk->hw, clk->rate, 0);
|
||||
dev_dbg(dev, "restore rate %d %s\n", clk->rate,
|
||||
!ret ? "success" : "failed");
|
||||
}
|
||||
|
||||
if (clk->is_enabled) {
|
||||
ret = clk_scu_prepare(&clk->hw);
|
||||
dev_dbg(dev, "restore enabled state %s\n",
|
||||
!ret ? "success" : "failed");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops imx_clk_scu_pm_ops = {
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend,
|
||||
imx_clk_scu_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver imx_clk_scu_driver = {
|
||||
.driver = {
|
||||
.name = "imx-scu-clk",
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &imx_clk_scu_pm_ops,
|
||||
},
|
||||
.probe = imx_clk_scu_probe,
|
||||
};
|
||||
|
||||
static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
|
||||
{
|
||||
struct of_phandle_args genpdspec = {
|
||||
.np = pd_np,
|
||||
.args_count = 1,
|
||||
.args[0] = rsrc_id,
|
||||
};
|
||||
|
||||
if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 ||
|
||||
rsrc_id == IMX_SC_R_A72)
|
||||
return 0;
|
||||
|
||||
return of_genpd_add_device(&genpdspec, dev);
|
||||
}
|
||||
|
||||
struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
|
||||
const char * const *parents,
|
||||
int num_parents, u32 rsrc_id, u8 clk_type)
|
||||
{
|
||||
struct imx_scu_clk_node clk = {
|
||||
.name = name,
|
||||
.rsrc = rsrc_id,
|
||||
.clk_type = clk_type,
|
||||
.parents = parents,
|
||||
.num_parents = num_parents,
|
||||
};
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
|
||||
if (!pdev) {
|
||||
pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
|
||||
name, rsrc_id, clk_type);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(pdev, &clk, sizeof(clk));
|
||||
if (ret) {
|
||||
platform_device_put(pdev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
pdev->driver_override = "imx-scu-clk";
|
||||
|
||||
ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id);
|
||||
if (ret)
|
||||
pr_warn("%s: failed to attached the power domain %d\n",
|
||||
name, ret);
|
||||
|
||||
platform_device_add(pdev);
|
||||
|
||||
/* For API backwards compatiblilty, simply return NULL for success */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void imx_clk_scu_unregister(void)
|
||||
{
|
||||
struct imx_scu_clk_node *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IMX_SC_R_LAST; i++) {
|
||||
list_for_each_entry(clk, &imx_scu_clks[i], node) {
|
||||
clk_hw_unregister(clk->hw);
|
||||
kfree(clk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,25 +8,61 @@
|
||||
#define __IMX_CLK_SCU_H
|
||||
|
||||
#include <linux/firmware/imx/sci.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
int imx_clk_scu_init(void);
|
||||
extern struct list_head imx_scu_clks[];
|
||||
extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops;
|
||||
|
||||
struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
|
||||
int num_parents, u32 rsrc_id, u8 clk_type);
|
||||
int imx_clk_scu_init(struct device_node *np);
|
||||
struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
|
||||
void *data);
|
||||
struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
|
||||
const char * const *parents,
|
||||
int num_parents, u32 rsrc_id, u8 clk_type);
|
||||
|
||||
struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
|
||||
const char * const *parents, int num_parents,
|
||||
u32 rsrc_id, u8 clk_type);
|
||||
|
||||
void imx_clk_scu_unregister(void);
|
||||
|
||||
struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 bit_idx, bool hw_gate);
|
||||
void imx_clk_lpcg_scu_unregister(struct clk_hw *hw);
|
||||
|
||||
static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
|
||||
u8 clk_type)
|
||||
u8 clk_type, u8 clk_cells)
|
||||
{
|
||||
return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
|
||||
if (clk_cells == 2)
|
||||
return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type);
|
||||
else
|
||||
return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
|
||||
int num_parents, u32 rsrc_id, u8 clk_type)
|
||||
int num_parents, u32 rsrc_id, u8 clk_type,
|
||||
u8 clk_cells)
|
||||
{
|
||||
return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
|
||||
if (clk_cells == 2)
|
||||
return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type);
|
||||
else
|
||||
return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type);
|
||||
}
|
||||
|
||||
struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
|
||||
unsigned long flags, void __iomem *reg,
|
||||
u8 bit_idx, bool hw_gate);
|
||||
static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 bit_idx, bool hw_gate)
|
||||
{
|
||||
return __imx_clk_lpcg_scu(dev, name, parent_name, flags, reg,
|
||||
bit_idx, hw_gate);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
|
||||
unsigned long flags, void __iomem *reg,
|
||||
u8 bit_idx, bool hw_gate)
|
||||
{
|
||||
return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg,
|
||||
bit_idx, hw_gate);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#define IMX_CLK_GATE2_SINGLE_BIT 1
|
||||
|
||||
extern spinlock_t imx_ccm_lock;
|
||||
|
||||
void imx_check_clocks(struct clk *clks[], unsigned int count);
|
||||
@@ -68,9 +66,9 @@ extern struct imx_pll14xx_clk imx_1443x_dram_pll;
|
||||
to_clk(imx_clk_hw_cpu(name, parent_name, div, mux, pll, step))
|
||||
|
||||
#define clk_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
|
||||
cgr_val, clk_gate_flags, lock, share_count) \
|
||||
cgr_val, cgr_mask, clk_gate_flags, lock, share_count) \
|
||||
to_clk(clk_hw_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
|
||||
cgr_val, clk_gate_flags, lock, share_count))
|
||||
cgr_val, cgr_mask, clk_gate_flags, lock, share_count))
|
||||
|
||||
#define imx_clk_pllv3(type, name, parent_name, base, div_mask) \
|
||||
to_clk(imx_clk_hw_pllv3(type, name, parent_name, base, div_mask))
|
||||
@@ -198,7 +196,7 @@ struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
|
||||
|
||||
struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 bit_idx, u8 cgr_val,
|
||||
void __iomem *reg, u8 bit_idx, u8 cgr_val, u8 cgr_mask,
|
||||
u8 clk_gate_flags, spinlock_t *lock,
|
||||
unsigned int *share_count);
|
||||
|
||||
@@ -351,14 +349,14 @@ static inline struct clk_hw *imx_clk_hw_gate2(const char *name, const char *pare
|
||||
void __iomem *reg, u8 shift)
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
shift, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_gate2_flags(const char *name, const char *parent,
|
||||
void __iomem *reg, u8 shift, unsigned long flags)
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
|
||||
shift, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_gate2_shared(const char *name,
|
||||
@@ -366,7 +364,7 @@ static inline struct clk_hw *imx_clk_hw_gate2_shared(const char *name,
|
||||
unsigned int *share_count)
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
shift, 0x3, 0, &imx_ccm_lock, share_count);
|
||||
shift, 0x3, 0x3, 0, &imx_ccm_lock, share_count);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_gate2_shared2(const char *name,
|
||||
@@ -374,7 +372,7 @@ static inline struct clk_hw *imx_clk_hw_gate2_shared2(const char *name,
|
||||
unsigned int *share_count)
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
|
||||
CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
|
||||
CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0x3, 0,
|
||||
&imx_ccm_lock, share_count);
|
||||
}
|
||||
|
||||
@@ -384,16 +382,15 @@ static inline struct clk_hw *imx_dev_clk_hw_gate_shared(struct device *dev,
|
||||
unsigned int *share_count)
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
|
||||
CLK_OPS_PARENT_ENABLE, reg, shift, 0x3,
|
||||
IMX_CLK_GATE2_SINGLE_BIT,
|
||||
&imx_ccm_lock, share_count);
|
||||
CLK_OPS_PARENT_ENABLE, reg, shift, 0x1,
|
||||
0x1, 0, &imx_ccm_lock, share_count);
|
||||
}
|
||||
|
||||
static inline struct clk *imx_clk_gate2_cgr(const char *name,
|
||||
const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
|
||||
{
|
||||
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
shift, cgr_val, 0, &imx_ccm_lock, NULL);
|
||||
shift, cgr_val, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_gate3(const char *name, const char *parent,
|
||||
@@ -421,7 +418,7 @@ static inline struct clk_hw *imx_clk_hw_gate4(const char *name, const char *pare
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent,
|
||||
CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
reg, shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_gate4_flags(const char *name,
|
||||
@@ -430,7 +427,7 @@ static inline struct clk_hw *imx_clk_hw_gate4_flags(const char *name,
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent,
|
||||
flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
reg, shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
|
||||
}
|
||||
|
||||
#define imx_clk_gate4_flags(name, parent, reg, shift, flags) \
|
||||
|
||||
@@ -392,15 +392,21 @@ static unsigned int
|
||||
ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info,
|
||||
unsigned int div)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i, best_i = 0, best = (unsigned int)-1;
|
||||
|
||||
for (i = 0; i < (1 << clk_info->div.bits)
|
||||
&& clk_info->div.div_table[i]; i++) {
|
||||
if (clk_info->div.div_table[i] >= div)
|
||||
return i;
|
||||
if (clk_info->div.div_table[i] >= div &&
|
||||
clk_info->div.div_table[i] < best) {
|
||||
best = clk_info->div.div_table[i];
|
||||
best_i = i;
|
||||
|
||||
if (div == best)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i - 1;
|
||||
return best_i;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
|
||||
@@ -155,7 +155,7 @@ const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
|
||||
.set_parent = mtk_clk_mux_set_parent_setclr_lock,
|
||||
};
|
||||
|
||||
struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
|
||||
static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
|
||||
struct regmap *regmap,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
|
||||
@@ -77,10 +77,6 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
|
||||
_width, _gate, _upd_ofs, _upd, \
|
||||
CLK_SET_RATE_PARENT)
|
||||
|
||||
struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
|
||||
struct regmap *regmap,
|
||||
spinlock_t *lock);
|
||||
|
||||
int mtk_clk_register_muxes(const struct mtk_mux *muxes,
|
||||
int num, struct device_node *node,
|
||||
spinlock_t *lock,
|
||||
|
||||
@@ -58,7 +58,7 @@ config COMMON_CLK_MESON8B
|
||||
want peripherals and CPU frequency scaling to work.
|
||||
|
||||
config COMMON_CLK_GXBB
|
||||
bool "GXBB and GXL SoC clock controllers support"
|
||||
tristate "GXBB and GXL SoC clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
@@ -74,7 +74,7 @@ config COMMON_CLK_GXBB
|
||||
Say Y if you want peripherals and CPU frequency scaling to work.
|
||||
|
||||
config COMMON_CLK_AXG
|
||||
bool "AXG SoC clock controllers support"
|
||||
tristate "AXG SoC clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
@@ -100,7 +100,7 @@ config COMMON_CLK_AXG_AUDIO
|
||||
aka axg, Say Y if you want audio subsystem to work.
|
||||
|
||||
config COMMON_CLK_G12A
|
||||
bool "G12 and SM1 SoC clock controllers support"
|
||||
tristate "G12 and SM1 SoC clock controllers support"
|
||||
depends on ARM64
|
||||
default y
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
@@ -110,6 +110,7 @@ config COMMON_CLK_G12A
|
||||
select COMMON_CLK_MESON_AO_CLKC
|
||||
select COMMON_CLK_MESON_EE_CLKC
|
||||
select COMMON_CLK_MESON_CPU_DYNDIV
|
||||
select COMMON_CLK_MESON_VID_PLL_DIV
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include "meson-aoclk.h"
|
||||
#include "axg-aoclk.h"
|
||||
|
||||
@@ -326,6 +327,7 @@ static const struct of_device_id axg_aoclkc_match_table[] = {
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axg_aoclkc_match_table);
|
||||
|
||||
static struct platform_driver axg_aoclkc_driver = {
|
||||
.probe = meson_aoclkc_probe,
|
||||
@@ -335,4 +337,5 @@ static struct platform_driver axg_aoclkc_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(axg_aoclkc_driver);
|
||||
module_platform_driver(axg_aoclkc_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "clk-regmap.h"
|
||||
#include "clk-pll.h"
|
||||
@@ -1026,6 +1027,743 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
|
||||
},
|
||||
};
|
||||
|
||||
/* VPU Clock */
|
||||
|
||||
static const struct clk_hw *axg_vpu_parent_hws[] = {
|
||||
&axg_fclk_div4.hw,
|
||||
&axg_fclk_div3.hw,
|
||||
&axg_fclk_div5.hw,
|
||||
&axg_fclk_div7.hw,
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu_0_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_0_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_vpu_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
|
||||
/* We need a specific parent for VPU clock source, let it be set in DT */
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu_0_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_0_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vpu_0_sel.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu_0 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vpu_0",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vpu_0_div.hw },
|
||||
.num_parents = 1,
|
||||
/*
|
||||
* We want to avoid CCF to disable the VPU clock if
|
||||
* display has been set by Bootloader
|
||||
*/
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu_1_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 25,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_1_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_vpu_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
|
||||
/* We need a specific parent for VPU clock source, let it be set in DT */
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu_1_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_1_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vpu_1_sel.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu_1 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vpu_1",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vpu_1_div.hw },
|
||||
.num_parents = 1,
|
||||
/*
|
||||
* We want to avoid CCF to disable the VPU clock if
|
||||
* display has been set by Bootloader
|
||||
*/
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vpu = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VPU_CLK_CNTL,
|
||||
.mask = 1,
|
||||
.shift = 31,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vpu_0.hw,
|
||||
&axg_vpu_1.hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
/* VAPB Clock */
|
||||
|
||||
static struct clk_regmap axg_vapb_0_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_0_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_vpu_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb_0_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_0_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vapb_0_sel.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb_0 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vapb_0",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vapb_0_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb_1_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 25,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_1_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_vpu_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb_1_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_1_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vapb_1_sel.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb_1 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vapb_1",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vapb_1_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.mask = 1,
|
||||
.shift = 31,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vapb_0.hw,
|
||||
&axg_vapb_1.hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vapb = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VAPBCLK_CNTL,
|
||||
.bit_idx = 30,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vapb",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vapb_sel.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
/* Video Clocks */
|
||||
|
||||
static const struct clk_hw *axg_vclk_parent_hws[] = {
|
||||
&axg_gp0_pll.hw,
|
||||
&axg_fclk_div4.hw,
|
||||
&axg_fclk_div3.hw,
|
||||
&axg_fclk_div5.hw,
|
||||
&axg_fclk_div2.hw,
|
||||
&axg_fclk_div7.hw,
|
||||
&axg_mpll1.hw,
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_vclk_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_vclk_parent_hws),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_vclk_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_vclk_parent_hws),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_input = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_DIV,
|
||||
.bit_idx = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_input",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk_sel.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_input = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_DIV,
|
||||
.bit_idx = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_input",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2_sel.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VID_CLK_DIV,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk_input.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VIID_CLK_DIV,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk2_input.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 19,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk_div.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 19,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2_div.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_div1 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 0,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div1",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_div2_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 1,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div2_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_div4_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 2,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div4_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_div6_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 3,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div6_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk_div12_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 4,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div12_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_div1 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 0,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div1",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_div2_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 1,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div2_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_div4_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 2,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div4_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_div6_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 3,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div6_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vclk2_div12_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 4,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div12_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk_div2 = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div2",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk_div2_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk_div4 = {
|
||||
.mult = 1,
|
||||
.div = 4,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div4",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk_div4_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk_div6 = {
|
||||
.mult = 1,
|
||||
.div = 6,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div6",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk_div6_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk_div12 = {
|
||||
.mult = 1,
|
||||
.div = 12,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div12",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk_div12_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk2_div2 = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div2",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk2_div2_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk2_div4 = {
|
||||
.mult = 1,
|
||||
.div = 4,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div4",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk2_div4_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk2_div6 = {
|
||||
.mult = 1,
|
||||
.div = 6,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div6",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk2_div6_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor axg_vclk2_div12 = {
|
||||
.mult = 1,
|
||||
.div = 12,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div12",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vclk2_div12_en.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
|
||||
static const struct clk_hw *axg_cts_parent_hws[] = {
|
||||
&axg_vclk_div1.hw,
|
||||
&axg_vclk_div2.hw,
|
||||
&axg_vclk_div4.hw,
|
||||
&axg_vclk_div6.hw,
|
||||
&axg_vclk_div12.hw,
|
||||
&axg_vclk2_div1.hw,
|
||||
&axg_vclk2_div2.hw,
|
||||
&axg_vclk2_div4.hw,
|
||||
&axg_vclk2_div6.hw,
|
||||
&axg_vclk2_div12.hw,
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_cts_encl_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VIID_CLK_DIV,
|
||||
.mask = 0xf,
|
||||
.shift = 12,
|
||||
.table = mux_table_cts_sel,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_encl_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = axg_cts_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(axg_cts_parent_hws),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_cts_encl = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL2,
|
||||
.bit_idx = 3,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "cts_encl",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_cts_encl_sel.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
/* MIPI DSI Host Clock */
|
||||
|
||||
static u32 mux_table_axg_vdin_meas[] = { 0, 1, 2, 3, 6, 7 };
|
||||
static const struct clk_parent_data axg_vdin_meas_parent_data[] = {
|
||||
{ .fw_name = "xtal", },
|
||||
{ .hw = &axg_fclk_div4.hw },
|
||||
{ .hw = &axg_fclk_div3.hw },
|
||||
{ .hw = &axg_fclk_div5.hw },
|
||||
{ .hw = &axg_fclk_div2.hw },
|
||||
{ .hw = &axg_fclk_div7.hw },
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vdin_meas_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VDIN_MEAS_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 21,
|
||||
.flags = CLK_MUX_ROUND_CLOSEST,
|
||||
.table = mux_table_axg_vdin_meas,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdin_meas_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_data = axg_vdin_meas_parent_data,
|
||||
.num_parents = ARRAY_SIZE(axg_vdin_meas_parent_data),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vdin_meas_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VDIN_MEAS_CLK_CNTL,
|
||||
.shift = 12,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdin_meas_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vdin_meas_sel.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap axg_vdin_meas = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VDIN_MEAS_CLK_CNTL,
|
||||
.bit_idx = 20,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vdin_meas",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&axg_vdin_meas_div.hw },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 13, 14, };
|
||||
static const struct clk_parent_data gen_clk_parent_data[] = {
|
||||
@@ -1246,6 +1984,52 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
|
||||
[CLKID_HIFI_PLL_DCO] = &axg_hifi_pll_dco.hw,
|
||||
[CLKID_PCIE_PLL_DCO] = &axg_pcie_pll_dco.hw,
|
||||
[CLKID_PCIE_PLL_OD] = &axg_pcie_pll_od.hw,
|
||||
[CLKID_VPU_0_DIV] = &axg_vpu_0_div.hw,
|
||||
[CLKID_VPU_0_SEL] = &axg_vpu_0_sel.hw,
|
||||
[CLKID_VPU_0] = &axg_vpu_0.hw,
|
||||
[CLKID_VPU_1_DIV] = &axg_vpu_1_div.hw,
|
||||
[CLKID_VPU_1_SEL] = &axg_vpu_1_sel.hw,
|
||||
[CLKID_VPU_1] = &axg_vpu_1.hw,
|
||||
[CLKID_VPU] = &axg_vpu.hw,
|
||||
[CLKID_VAPB_0_DIV] = &axg_vapb_0_div.hw,
|
||||
[CLKID_VAPB_0_SEL] = &axg_vapb_0_sel.hw,
|
||||
[CLKID_VAPB_0] = &axg_vapb_0.hw,
|
||||
[CLKID_VAPB_1_DIV] = &axg_vapb_1_div.hw,
|
||||
[CLKID_VAPB_1_SEL] = &axg_vapb_1_sel.hw,
|
||||
[CLKID_VAPB_1] = &axg_vapb_1.hw,
|
||||
[CLKID_VAPB_SEL] = &axg_vapb_sel.hw,
|
||||
[CLKID_VAPB] = &axg_vapb.hw,
|
||||
[CLKID_VCLK] = &axg_vclk.hw,
|
||||
[CLKID_VCLK2] = &axg_vclk2.hw,
|
||||
[CLKID_VCLK_SEL] = &axg_vclk_sel.hw,
|
||||
[CLKID_VCLK2_SEL] = &axg_vclk2_sel.hw,
|
||||
[CLKID_VCLK_INPUT] = &axg_vclk_input.hw,
|
||||
[CLKID_VCLK2_INPUT] = &axg_vclk2_input.hw,
|
||||
[CLKID_VCLK_DIV] = &axg_vclk_div.hw,
|
||||
[CLKID_VCLK2_DIV] = &axg_vclk2_div.hw,
|
||||
[CLKID_VCLK_DIV2_EN] = &axg_vclk_div2_en.hw,
|
||||
[CLKID_VCLK_DIV4_EN] = &axg_vclk_div4_en.hw,
|
||||
[CLKID_VCLK_DIV6_EN] = &axg_vclk_div6_en.hw,
|
||||
[CLKID_VCLK_DIV12_EN] = &axg_vclk_div12_en.hw,
|
||||
[CLKID_VCLK2_DIV2_EN] = &axg_vclk2_div2_en.hw,
|
||||
[CLKID_VCLK2_DIV4_EN] = &axg_vclk2_div4_en.hw,
|
||||
[CLKID_VCLK2_DIV6_EN] = &axg_vclk2_div6_en.hw,
|
||||
[CLKID_VCLK2_DIV12_EN] = &axg_vclk2_div12_en.hw,
|
||||
[CLKID_VCLK_DIV1] = &axg_vclk_div1.hw,
|
||||
[CLKID_VCLK_DIV2] = &axg_vclk_div2.hw,
|
||||
[CLKID_VCLK_DIV4] = &axg_vclk_div4.hw,
|
||||
[CLKID_VCLK_DIV6] = &axg_vclk_div6.hw,
|
||||
[CLKID_VCLK_DIV12] = &axg_vclk_div12.hw,
|
||||
[CLKID_VCLK2_DIV1] = &axg_vclk2_div1.hw,
|
||||
[CLKID_VCLK2_DIV2] = &axg_vclk2_div2.hw,
|
||||
[CLKID_VCLK2_DIV4] = &axg_vclk2_div4.hw,
|
||||
[CLKID_VCLK2_DIV6] = &axg_vclk2_div6.hw,
|
||||
[CLKID_VCLK2_DIV12] = &axg_vclk2_div12.hw,
|
||||
[CLKID_CTS_ENCL_SEL] = &axg_cts_encl_sel.hw,
|
||||
[CLKID_CTS_ENCL] = &axg_cts_encl.hw,
|
||||
[CLKID_VDIN_MEAS_SEL] = &axg_vdin_meas_sel.hw,
|
||||
[CLKID_VDIN_MEAS_DIV] = &axg_vdin_meas_div.hw,
|
||||
[CLKID_VDIN_MEAS] = &axg_vdin_meas.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
@@ -1341,6 +2125,42 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
|
||||
&axg_hifi_pll_dco,
|
||||
&axg_pcie_pll_dco,
|
||||
&axg_pcie_pll_od,
|
||||
&axg_vpu_0_div,
|
||||
&axg_vpu_0_sel,
|
||||
&axg_vpu_0,
|
||||
&axg_vpu_1_div,
|
||||
&axg_vpu_1_sel,
|
||||
&axg_vpu_1,
|
||||
&axg_vpu,
|
||||
&axg_vapb_0_div,
|
||||
&axg_vapb_0_sel,
|
||||
&axg_vapb_0,
|
||||
&axg_vapb_1_div,
|
||||
&axg_vapb_1_sel,
|
||||
&axg_vapb_1,
|
||||
&axg_vapb_sel,
|
||||
&axg_vapb,
|
||||
&axg_vclk,
|
||||
&axg_vclk2,
|
||||
&axg_vclk_sel,
|
||||
&axg_vclk2_sel,
|
||||
&axg_vclk_input,
|
||||
&axg_vclk2_input,
|
||||
&axg_vclk_div,
|
||||
&axg_vclk2_div,
|
||||
&axg_vclk_div2_en,
|
||||
&axg_vclk_div4_en,
|
||||
&axg_vclk_div6_en,
|
||||
&axg_vclk_div12_en,
|
||||
&axg_vclk2_div2_en,
|
||||
&axg_vclk2_div4_en,
|
||||
&axg_vclk2_div6_en,
|
||||
&axg_vclk2_div12_en,
|
||||
&axg_cts_encl_sel,
|
||||
&axg_cts_encl,
|
||||
&axg_vdin_meas_sel,
|
||||
&axg_vdin_meas_div,
|
||||
&axg_vdin_meas,
|
||||
};
|
||||
|
||||
static const struct meson_eeclkc_data axg_clkc_data = {
|
||||
@@ -1354,6 +2174,7 @@ static const struct of_device_id clkc_match_table[] = {
|
||||
{ .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clkc_match_table);
|
||||
|
||||
static struct platform_driver axg_driver = {
|
||||
.probe = meson_eeclkc_probe,
|
||||
@@ -1363,4 +2184,5 @@ static struct platform_driver axg_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(axg_driver);
|
||||
module_platform_driver(axg_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -139,8 +139,29 @@
|
||||
#define CLKID_HIFI_PLL_DCO 88
|
||||
#define CLKID_PCIE_PLL_DCO 89
|
||||
#define CLKID_PCIE_PLL_OD 90
|
||||
#define CLKID_VPU_0_DIV 91
|
||||
#define CLKID_VPU_1_DIV 94
|
||||
#define CLKID_VAPB_0_DIV 98
|
||||
#define CLKID_VAPB_1_DIV 101
|
||||
#define CLKID_VCLK_SEL 108
|
||||
#define CLKID_VCLK2_SEL 109
|
||||
#define CLKID_VCLK_INPUT 110
|
||||
#define CLKID_VCLK2_INPUT 111
|
||||
#define CLKID_VCLK_DIV 112
|
||||
#define CLKID_VCLK2_DIV 113
|
||||
#define CLKID_VCLK_DIV2_EN 114
|
||||
#define CLKID_VCLK_DIV4_EN 115
|
||||
#define CLKID_VCLK_DIV6_EN 116
|
||||
#define CLKID_VCLK_DIV12_EN 117
|
||||
#define CLKID_VCLK2_DIV2_EN 118
|
||||
#define CLKID_VCLK2_DIV4_EN 119
|
||||
#define CLKID_VCLK2_DIV6_EN 120
|
||||
#define CLKID_VCLK2_DIV12_EN 121
|
||||
#define CLKID_CTS_ENCL_SEL 132
|
||||
#define CLKID_VDIN_MEAS_SEL 134
|
||||
#define CLKID_VDIN_MEAS_DIV 135
|
||||
|
||||
#define NR_CLKS 91
|
||||
#define NR_CLKS 137
|
||||
|
||||
/* include the CLKIDs that have been made part of the DT binding */
|
||||
#include <dt-bindings/clock/axg-clkc.h>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include "meson-aoclk.h"
|
||||
#include "g12a-aoclk.h"
|
||||
|
||||
@@ -461,6 +462,7 @@ static const struct of_device_id g12a_aoclkc_match_table[] = {
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, g12a_aoclkc_match_table);
|
||||
|
||||
static struct platform_driver g12a_aoclkc_driver = {
|
||||
.probe = meson_aoclkc_probe,
|
||||
@@ -470,4 +472,5 @@ static struct platform_driver g12a_aoclkc_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(g12a_aoclkc_driver);
|
||||
module_platform_driver(g12a_aoclkc_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "clk-mpll.h"
|
||||
#include "clk-pll.h"
|
||||
@@ -3657,6 +3658,68 @@ static struct clk_regmap g12a_hdmi_tx = {
|
||||
},
|
||||
};
|
||||
|
||||
/* MIPI DSI Host Clocks */
|
||||
|
||||
static const struct clk_hw *g12a_mipi_dsi_pxclk_parent_hws[] = {
|
||||
&g12a_vid_pll.hw,
|
||||
&g12a_gp0_pll.hw,
|
||||
&g12a_hifi_pll.hw,
|
||||
&g12a_mpll1.hw,
|
||||
&g12a_fclk_div2.hw,
|
||||
&g12a_fclk_div2p5.hw,
|
||||
&g12a_fclk_div3.hw,
|
||||
&g12a_fclk_div7.hw,
|
||||
};
|
||||
|
||||
static struct clk_regmap g12a_mipi_dsi_pxclk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_MIPIDSI_PHY_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 12,
|
||||
.flags = CLK_MUX_ROUND_CLOSEST,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mipi_dsi_pxclk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_hws = g12a_mipi_dsi_pxclk_parent_hws,
|
||||
.num_parents = ARRAY_SIZE(g12a_mipi_dsi_pxclk_parent_hws),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_MIPIDSI_PHY_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mipi_dsi_pxclk_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&g12a_mipi_dsi_pxclk_sel.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap g12a_mipi_dsi_pxclk = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_MIPIDSI_PHY_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "mipi_dsi_pxclk",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&g12a_mipi_dsi_pxclk_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
/* HDMI Clocks */
|
||||
|
||||
static const struct clk_parent_data g12a_hdmi_parent_data[] = {
|
||||
@@ -4402,6 +4465,9 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = {
|
||||
[CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw,
|
||||
[CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw,
|
||||
[CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
@@ -4657,6 +4723,9 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = {
|
||||
[CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw,
|
||||
[CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw,
|
||||
[CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
@@ -4903,6 +4972,9 @@ static struct clk_hw_onecell_data sm1_hw_onecell_data = {
|
||||
[CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel.hw,
|
||||
[CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div.hw,
|
||||
[CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div.hw,
|
||||
[CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
@@ -5150,16 +5222,20 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
|
||||
&sm1_nna_core_clk_sel,
|
||||
&sm1_nna_core_clk_div,
|
||||
&sm1_nna_core_clk,
|
||||
&g12a_mipi_dsi_pxclk_sel,
|
||||
&g12a_mipi_dsi_pxclk_div,
|
||||
&g12a_mipi_dsi_pxclk,
|
||||
};
|
||||
|
||||
static const struct reg_sequence g12a_init_regs[] = {
|
||||
{ .reg = HHI_MPLL_CNTL0, .def = 0x00000543 },
|
||||
};
|
||||
|
||||
static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
|
||||
#define DVFS_CON_ID "dvfs"
|
||||
|
||||
static int meson_g12a_dvfs_setup_common(struct device *dev,
|
||||
struct clk_hw **hws)
|
||||
{
|
||||
const char *notifier_clk_name;
|
||||
struct clk *notifier_clk;
|
||||
struct clk_hw *xtal;
|
||||
int ret;
|
||||
@@ -5168,21 +5244,22 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
|
||||
|
||||
/* Setup clock notifier for cpu_clk_postmux0 */
|
||||
g12a_cpu_clk_postmux0_nb_data.xtal = xtal;
|
||||
notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk,
|
||||
&g12a_cpu_clk_postmux0_nb_data.nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_postmux0.hw,
|
||||
DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_cpu_clk_postmux0_nb_data.nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpu_clk_postmux0 notifier\n");
|
||||
dev_err(dev, "failed to register the cpu_clk_postmux0 notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup clock notifier for cpu_clk_dyn mux */
|
||||
notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_dyn.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_dyn.hw,
|
||||
DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_cpu_clk_mux_nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpu_clk_dyn notifier\n");
|
||||
dev_err(dev, "failed to register the cpu_clk_dyn notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5192,33 +5269,34 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
|
||||
static int meson_g12b_dvfs_setup(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_hw **hws = g12b_hw_onecell_data.hws;
|
||||
const char *notifier_clk_name;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk *notifier_clk;
|
||||
struct clk_hw *xtal;
|
||||
int ret;
|
||||
|
||||
ret = meson_g12a_dvfs_setup_common(pdev, hws);
|
||||
ret = meson_g12a_dvfs_setup_common(dev, hws);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0);
|
||||
|
||||
/* Setup clock notifier for cpu_clk mux */
|
||||
notifier_clk_name = clk_hw_get_name(&g12b_cpu_clk.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpu_clk.hw,
|
||||
DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_cpu_clk_mux_nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n");
|
||||
dev_err(dev, "failed to register the cpu_clk notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup clock notifier for sys1_pll */
|
||||
notifier_clk_name = clk_hw_get_name(&g12b_sys1_pll.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk,
|
||||
&g12b_cpu_clk_sys1_pll_nb_data.nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12b_sys1_pll.hw,
|
||||
DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12b_cpu_clk_sys1_pll_nb_data.nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the sys1_pll notifier\n");
|
||||
dev_err(dev, "failed to register the sys1_pll notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5226,40 +5304,39 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev)
|
||||
|
||||
/* Setup clock notifier for cpub_clk_postmux0 */
|
||||
g12b_cpub_clk_postmux0_nb_data.xtal = xtal;
|
||||
notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_postmux0.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk,
|
||||
&g12b_cpub_clk_postmux0_nb_data.nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_postmux0.hw,
|
||||
DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12b_cpub_clk_postmux0_nb_data.nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpub_clk_postmux0 notifier\n");
|
||||
dev_err(dev, "failed to register the cpub_clk_postmux0 notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup clock notifier for cpub_clk_dyn mux */
|
||||
notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_dyn.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_dyn.hw, "dvfs");
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_cpu_clk_mux_nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpub_clk_dyn notifier\n");
|
||||
dev_err(dev, "failed to register the cpub_clk_dyn notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup clock notifier for cpub_clk mux */
|
||||
notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk.hw, DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_cpu_clk_mux_nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpub_clk notifier\n");
|
||||
dev_err(dev, "failed to register the cpub_clk notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup clock notifier for sys_pll */
|
||||
notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk,
|
||||
&g12b_cpub_clk_sys_pll_nb_data.nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12b_cpub_clk_sys_pll_nb_data.nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the sys_pll notifier\n");
|
||||
dev_err(dev, "failed to register the sys_pll notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5269,29 +5346,29 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev)
|
||||
static int meson_g12a_dvfs_setup(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_hw **hws = g12a_hw_onecell_data.hws;
|
||||
const char *notifier_clk_name;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk *notifier_clk;
|
||||
int ret;
|
||||
|
||||
ret = meson_g12a_dvfs_setup_common(pdev, hws);
|
||||
ret = meson_g12a_dvfs_setup_common(dev, hws);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Setup clock notifier for cpu_clk mux */
|
||||
notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk.hw, DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_cpu_clk_mux_nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n");
|
||||
dev_err(dev, "failed to register the cpu_clk notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup clock notifier for sys_pll */
|
||||
notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb);
|
||||
notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID);
|
||||
ret = devm_clk_notifier_register(dev, notifier_clk,
|
||||
&g12a_sys_pll_nb_data.nb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register the sys_pll notifier\n");
|
||||
dev_err(dev, "failed to register the sys_pll notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5370,6 +5447,7 @@ static const struct of_device_id clkc_match_table[] = {
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clkc_match_table);
|
||||
|
||||
static struct platform_driver g12a_driver = {
|
||||
.probe = meson_g12a_probe,
|
||||
@@ -5379,4 +5457,5 @@ static struct platform_driver g12a_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(g12a_driver);
|
||||
module_platform_driver(g12a_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -264,8 +264,9 @@
|
||||
#define CLKID_NNA_AXI_CLK_DIV 263
|
||||
#define CLKID_NNA_CORE_CLK_SEL 265
|
||||
#define CLKID_NNA_CORE_CLK_DIV 266
|
||||
#define CLKID_MIPI_DSI_PXCLK_DIV 268
|
||||
|
||||
#define NR_CLKS 268
|
||||
#define NR_CLKS 271
|
||||
|
||||
/* include the CLKIDs that have been made part of the DT binding */
|
||||
#include <dt-bindings/clock/g12a-clkc.h>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include "meson-aoclk.h"
|
||||
#include "gxbb-aoclk.h"
|
||||
|
||||
@@ -287,6 +288,7 @@ static const struct of_device_id gxbb_aoclkc_match_table[] = {
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
|
||||
|
||||
static struct platform_driver gxbb_aoclkc_driver = {
|
||||
.probe = meson_aoclkc_probe,
|
||||
@@ -295,4 +297,5 @@ static struct platform_driver gxbb_aoclkc_driver = {
|
||||
.of_match_table = gxbb_aoclkc_match_table,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(gxbb_aoclkc_driver);
|
||||
module_platform_driver(gxbb_aoclkc_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "gxbb.h"
|
||||
#include "clk-regmap.h"
|
||||
@@ -3519,6 +3520,7 @@ static const struct of_device_id clkc_match_table[] = {
|
||||
{ .compatible = "amlogic,gxl-clkc", .data = &gxl_clkc_data },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clkc_match_table);
|
||||
|
||||
static struct platform_driver gxbb_driver = {
|
||||
.probe = meson_eeclkc_probe,
|
||||
@@ -3528,4 +3530,5 @@ static struct platform_driver gxbb_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(gxbb_driver);
|
||||
module_platform_driver(gxbb_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include "meson-aoclk.h"
|
||||
|
||||
@@ -84,3 +86,5 @@ int meson_aoclkc_probe(struct platform_device *pdev)
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
(void *) data->hw_data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(meson_aoclkc_probe);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "clk-regmap.h"
|
||||
#include "meson-eeclk.h"
|
||||
@@ -54,3 +55,5 @@ int meson_eeclkc_probe(struct platform_device *pdev)
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
data->hw_onecell_data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(meson_eeclkc_probe);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define NB_GPIO1_LATCH 0xC
|
||||
#define XTAL_MODE BIT(31)
|
||||
#define NB_GPIO1_LATCH 0x8
|
||||
#define XTAL_MODE BIT(9)
|
||||
|
||||
static int armada_3700_xtal_clock_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ config QCOM_CLK_APCC_MSM8996
|
||||
help
|
||||
Support for the CPU clock controller on msm8996 devices.
|
||||
Say Y if you want to support CPU clock scaling using CPUfreq
|
||||
drivers for dyanmic power management.
|
||||
drivers for dynamic power management.
|
||||
|
||||
config QCOM_CLK_RPM
|
||||
tristate "RPM based Clock Controller"
|
||||
@@ -290,6 +290,15 @@ config QCS_GCC_404
|
||||
Say Y if you want to use multimedia devices or peripheral
|
||||
devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc.
|
||||
|
||||
config SC_CAMCC_7180
|
||||
tristate "SC7180 Camera Clock Controller"
|
||||
select SC_GCC_7180
|
||||
help
|
||||
Support for the camera clock controller on Qualcomm Technologies, Inc
|
||||
SC7180 devices.
|
||||
Say Y if you want to support camera devices and functionality such as
|
||||
capturing pictures.
|
||||
|
||||
config SC_DISPCC_7180
|
||||
tristate "SC7180 Display Clock Controller"
|
||||
select SC_GCC_7180
|
||||
@@ -413,6 +422,14 @@ config SDM_LPASSCC_845
|
||||
Say Y if you want to use the LPASS branch clocks of the LPASS clock
|
||||
controller to reset the LPASS subsystem.
|
||||
|
||||
config SDX_GCC_55
|
||||
tristate "SDX55 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on SDX55 devices.
|
||||
Say Y if you want to use peripheral devices such as UART,
|
||||
SPI, I2C, USB, SD/UFS, PCIe etc.
|
||||
|
||||
config SM_DISPCC_8250
|
||||
tristate "SM8150 and SM8250 Display Clock Controller"
|
||||
depends on SM_GCC_8150 || SM_GCC_8250
|
||||
@@ -502,4 +519,10 @@ config KRAITCC
|
||||
Support for the Krait CPU clocks on Qualcomm devices.
|
||||
Say Y if you want to support CPU frequency scaling.
|
||||
|
||||
config CLK_GFM_LPASS_SM8250
|
||||
tristate "SM8250 GFM LPASS Clocks"
|
||||
help
|
||||
Support for the Glitch Free Mux (GFM) Low power audio
|
||||
subsystem (LPASS) clocks found on SM8250 SoCs.
|
||||
|
||||
endif
|
||||
|
||||
@@ -19,6 +19,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
|
||||
# Keep alphabetically sorted by config
|
||||
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
|
||||
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
|
||||
obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
|
||||
obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
|
||||
obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
|
||||
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
|
||||
@@ -51,6 +52,7 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
|
||||
obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
|
||||
obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o
|
||||
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_GPUCC_7180) += gpucc-sc7180.o
|
||||
@@ -64,6 +66,7 @@ obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
|
||||
obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o
|
||||
obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
|
||||
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
|
||||
obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o
|
||||
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
|
||||
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
|
||||
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
|
||||
|
||||
1732
drivers/clk/qcom/camcc-sc7180.c
Normal file
1732
drivers/clk/qcom/camcc-sc7180.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -116,6 +116,16 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
|
||||
[PLL_OFF_OPMODE] = 0x38,
|
||||
[PLL_OFF_ALPHA_VAL] = 0x40,
|
||||
},
|
||||
[CLK_ALPHA_PLL_TYPE_AGERA] = {
|
||||
[PLL_OFF_L_VAL] = 0x04,
|
||||
[PLL_OFF_ALPHA_VAL] = 0x08,
|
||||
[PLL_OFF_USER_CTL] = 0x0c,
|
||||
[PLL_OFF_CONFIG_CTL] = 0x10,
|
||||
[PLL_OFF_CONFIG_CTL_U] = 0x14,
|
||||
[PLL_OFF_TEST_CTL] = 0x18,
|
||||
[PLL_OFF_TEST_CTL_U] = 0x1c,
|
||||
[PLL_OFF_STATUS] = 0x2c,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
||||
|
||||
@@ -207,6 +217,13 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
|
||||
#define wait_for_pll_update_ack_clear(pll) \
|
||||
wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 1, "update_ack_clear")
|
||||
|
||||
static void clk_alpha_pll_write_config(struct regmap *regmap, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
if (val)
|
||||
regmap_write(regmap, reg, val);
|
||||
}
|
||||
|
||||
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config)
|
||||
{
|
||||
@@ -1004,33 +1021,19 @@ void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
{
|
||||
u32 val, mask;
|
||||
|
||||
if (config->l)
|
||||
regmap_write(regmap, PLL_L_VAL(pll), config->l);
|
||||
|
||||
if (config->alpha)
|
||||
regmap_write(regmap, PLL_FRAC(pll), config->alpha);
|
||||
|
||||
if (config->config_ctl_val)
|
||||
regmap_write(regmap, PLL_CONFIG_CTL(pll),
|
||||
clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
|
||||
clk_alpha_pll_write_config(regmap, PLL_FRAC(pll), config->alpha);
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),
|
||||
config->config_ctl_val);
|
||||
|
||||
if (config->config_ctl_hi_val)
|
||||
regmap_write(regmap, PLL_CONFIG_CTL_U(pll),
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),
|
||||
config->config_ctl_hi_val);
|
||||
|
||||
if (config->user_ctl_val)
|
||||
regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val);
|
||||
|
||||
if (config->user_ctl_hi_val)
|
||||
regmap_write(regmap, PLL_USER_CTL_U(pll),
|
||||
clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
|
||||
config->user_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),
|
||||
config->user_ctl_hi_val);
|
||||
|
||||
if (config->test_ctl_val)
|
||||
regmap_write(regmap, PLL_TEST_CTL(pll),
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
|
||||
config->test_ctl_val);
|
||||
|
||||
if (config->test_ctl_hi_val)
|
||||
regmap_write(regmap, PLL_TEST_CTL_U(pll),
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
|
||||
config->test_ctl_hi_val);
|
||||
|
||||
if (config->post_div_mask) {
|
||||
@@ -1145,25 +1148,38 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw,
|
||||
return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Due to limited number of bits for fractional rate programming, the
|
||||
* rounded up rate could be marginally higher than the requested rate.
|
||||
*/
|
||||
static int alpha_pll_check_rate_margin(struct clk_hw *hw,
|
||||
unsigned long rrate, unsigned long rate)
|
||||
{
|
||||
unsigned long rate_margin = rate + PLL_RATE_MARGIN;
|
||||
|
||||
if (rrate > rate_margin || rrate < rate) {
|
||||
pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n",
|
||||
clk_hw_get_name(hw), rrate, rate, rate_margin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l, alpha_width = pll_alpha_width(pll);
|
||||
unsigned long rrate;
|
||||
int ret;
|
||||
u64 a;
|
||||
unsigned long rrate, max = rate + PLL_RATE_MARGIN;
|
||||
|
||||
rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
|
||||
|
||||
/*
|
||||
* Due to limited number of bits for fractional rate programming, the
|
||||
* rounded up rate could be marginally higher than the requested rate.
|
||||
*/
|
||||
if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) {
|
||||
pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n",
|
||||
clk_hw_get_name(hw), rrate, rate, max);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = alpha_pll_check_rate_margin(hw, rrate, rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
|
||||
regmap_write(pll->clkr.regmap, PLL_FRAC(pll), a);
|
||||
@@ -1206,12 +1222,10 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw)
|
||||
|
||||
rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw),
|
||||
&cal_l, &a, alpha_width);
|
||||
/*
|
||||
* Due to a limited number of bits for fractional rate programming, the
|
||||
* rounded up rate could be marginally higher than the requested rate.
|
||||
*/
|
||||
if (rrate > (cal_freq + PLL_RATE_MARGIN) || rrate < cal_freq)
|
||||
return -EINVAL;
|
||||
|
||||
ret = alpha_pll_check_rate_margin(hw, rrate, cal_freq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Setup PLL for calibration frequency */
|
||||
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l);
|
||||
@@ -1388,49 +1402,27 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops);
|
||||
void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config)
|
||||
{
|
||||
if (config->l)
|
||||
regmap_write(regmap, PLL_L_VAL(pll), config->l);
|
||||
|
||||
clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
|
||||
regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL);
|
||||
|
||||
if (config->alpha)
|
||||
regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);
|
||||
|
||||
if (config->config_ctl_val)
|
||||
regmap_write(regmap, PLL_CONFIG_CTL(pll),
|
||||
config->config_ctl_val);
|
||||
|
||||
if (config->config_ctl_hi_val)
|
||||
regmap_write(regmap, PLL_CONFIG_CTL_U(pll),
|
||||
config->config_ctl_hi_val);
|
||||
|
||||
if (config->config_ctl_hi1_val)
|
||||
regmap_write(regmap, PLL_CONFIG_CTL_U1(pll),
|
||||
config->config_ctl_hi1_val);
|
||||
|
||||
if (config->user_ctl_val)
|
||||
regmap_write(regmap, PLL_USER_CTL(pll),
|
||||
config->user_ctl_val);
|
||||
|
||||
if (config->user_ctl_hi_val)
|
||||
regmap_write(regmap, PLL_USER_CTL_U(pll),
|
||||
config->user_ctl_hi_val);
|
||||
|
||||
if (config->user_ctl_hi1_val)
|
||||
regmap_write(regmap, PLL_USER_CTL_U1(pll),
|
||||
config->user_ctl_hi1_val);
|
||||
|
||||
if (config->test_ctl_val)
|
||||
regmap_write(regmap, PLL_TEST_CTL(pll),
|
||||
config->test_ctl_val);
|
||||
|
||||
if (config->test_ctl_hi_val)
|
||||
regmap_write(regmap, PLL_TEST_CTL_U(pll),
|
||||
config->test_ctl_hi_val);
|
||||
|
||||
if (config->test_ctl_hi1_val)
|
||||
regmap_write(regmap, PLL_TEST_CTL_U1(pll),
|
||||
config->test_ctl_hi1_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),
|
||||
config->config_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),
|
||||
config->config_ctl_hi_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll),
|
||||
config->config_ctl_hi1_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
|
||||
config->user_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),
|
||||
config->user_ctl_hi_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll),
|
||||
config->user_ctl_hi1_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
|
||||
config->test_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
|
||||
config->test_ctl_hi_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll),
|
||||
config->test_ctl_hi1_val);
|
||||
|
||||
regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS,
|
||||
PLL_UPDATE_BYPASS);
|
||||
@@ -1490,14 +1482,9 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
|
||||
|
||||
/*
|
||||
* Due to a limited number of bits for fractional rate programming, the
|
||||
* rounded up rate could be marginally higher than the requested rate.
|
||||
*/
|
||||
if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) {
|
||||
pr_err("Call set rate on the PLL with rounded rates!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = alpha_pll_check_rate_margin(hw, rrate, rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
|
||||
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
|
||||
@@ -1561,3 +1548,55 @@ const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = {
|
||||
.set_rate = clk_alpha_pll_postdiv_fabia_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops);
|
||||
|
||||
void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config)
|
||||
{
|
||||
clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
|
||||
clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
|
||||
clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
|
||||
config->user_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),
|
||||
config->config_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),
|
||||
config->config_ctl_hi_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
|
||||
config->test_ctl_val);
|
||||
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
|
||||
config->test_ctl_hi_val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_agera_pll_configure);
|
||||
|
||||
static int clk_alpha_pll_agera_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l, alpha_width = pll_alpha_width(pll);
|
||||
int ret;
|
||||
unsigned long rrate;
|
||||
u64 a;
|
||||
|
||||
rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
|
||||
ret = alpha_pll_check_rate_margin(hw, rrate, rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* change L_VAL without having to go through the power on sequence */
|
||||
regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
|
||||
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
|
||||
|
||||
if (clk_hw_is_enabled(hw))
|
||||
return wait_for_pll_enable_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_agera_ops = {
|
||||
.enable = clk_alpha_pll_enable,
|
||||
.disable = clk_alpha_pll_disable,
|
||||
.is_enabled = clk_alpha_pll_is_enabled,
|
||||
.recalc_rate = alpha_pll_fabia_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_round_rate,
|
||||
.set_rate = clk_alpha_pll_agera_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
|
||||
|
||||
@@ -15,6 +15,7 @@ enum {
|
||||
CLK_ALPHA_PLL_TYPE_FABIA,
|
||||
CLK_ALPHA_PLL_TYPE_TRION,
|
||||
CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
|
||||
CLK_ALPHA_PLL_TYPE_AGERA,
|
||||
CLK_ALPHA_PLL_TYPE_MAX,
|
||||
};
|
||||
|
||||
@@ -141,6 +142,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_lucid_ops;
|
||||
#define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops
|
||||
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_agera_ops;
|
||||
|
||||
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config);
|
||||
@@ -148,6 +150,8 @@ void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config);
|
||||
void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config);
|
||||
void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config);
|
||||
#define clk_lucid_pll_configure(pll, regmap, config) \
|
||||
clk_trion_pll_configure(pll, regmap, config)
|
||||
|
||||
|
||||
@@ -349,6 +349,7 @@ 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_BCM(sdm845, ipa, "IP0");
|
||||
DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0");
|
||||
|
||||
static struct clk_hw *sdm845_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
|
||||
@@ -364,6 +365,7 @@ static struct clk_hw *sdm845_rpmh_clocks[] = {
|
||||
[RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
|
||||
[RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
|
||||
[RPMH_IPA_CLK] = &sdm845_ipa.hw,
|
||||
[RPMH_CE_CLK] = &sdm845_ce.hw,
|
||||
};
|
||||
|
||||
static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
|
||||
@@ -371,6 +373,25 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
|
||||
.num_clks = ARRAY_SIZE(sdm845_rpmh_clocks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
|
||||
DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
|
||||
DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0");
|
||||
|
||||
static struct clk_hw *sdx55_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
|
||||
[RPMH_RF_CLK1] = &sdx55_rf_clk1.hw,
|
||||
[RPMH_RF_CLK1_A] = &sdx55_rf_clk1_ao.hw,
|
||||
[RPMH_RF_CLK2] = &sdx55_rf_clk2.hw,
|
||||
[RPMH_RF_CLK2_A] = &sdx55_rf_clk2_ao.hw,
|
||||
[RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
|
||||
};
|
||||
|
||||
static const struct clk_rpmh_desc clk_rpmh_sdx55 = {
|
||||
.clks = sdx55_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sdx55_rpmh_clocks),
|
||||
};
|
||||
|
||||
static struct clk_hw *sm8150_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
|
||||
@@ -432,6 +453,39 @@ static const struct clk_rpmh_desc clk_rpmh_sm8250 = {
|
||||
.num_clks = ARRAY_SIZE(sm8250_rpmh_clocks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_RPMH_VRM(sm8350, div_clk1, div_clk1_ao, "divclka1", 2);
|
||||
DEFINE_CLK_RPMH_VRM(sm8350, rf_clk4, rf_clk4_ao, "rfclka4", 1);
|
||||
DEFINE_CLK_RPMH_VRM(sm8350, rf_clk5, rf_clk5_ao, "rfclka5", 1);
|
||||
DEFINE_CLK_RPMH_BCM(sm8350, pka, "PKA0");
|
||||
DEFINE_CLK_RPMH_BCM(sm8350, hwkm, "HK0");
|
||||
|
||||
static struct clk_hw *sm8350_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
|
||||
[RPMH_DIV_CLK1] = &sm8350_div_clk1.hw,
|
||||
[RPMH_DIV_CLK1_A] = &sm8350_div_clk1_ao.hw,
|
||||
[RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw,
|
||||
[RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_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_RF_CLK5] = &sm8350_rf_clk5.hw,
|
||||
[RPMH_RF_CLK5_A] = &sm8350_rf_clk5_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_sm8350 = {
|
||||
.clks = sm8350_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sm8350_rpmh_clocks),
|
||||
};
|
||||
|
||||
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
@@ -517,8 +571,10 @@ 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,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},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);
|
||||
|
||||
@@ -963,6 +963,7 @@ static struct gdsc mdss_gdsc = {
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = HW_CTRL,
|
||||
.supply = "mmcx",
|
||||
};
|
||||
|
||||
static struct clk_regmap *disp_cc_sm8250_clocks[] = {
|
||||
|
||||
@@ -642,7 +642,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
|
||||
.name = "gcc_sdcc1_ice_core_clk_src",
|
||||
.parent_data = gcc_parent_data_0,
|
||||
.num_parents = 4,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_floor_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -651,6 +651,7 @@ static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
|
||||
F(9600000, P_BI_TCXO, 2, 0, 0),
|
||||
F(19200000, P_BI_TCXO, 1, 0, 0),
|
||||
F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
|
||||
F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
|
||||
F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
|
||||
F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0),
|
||||
{ }
|
||||
@@ -666,7 +667,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
|
||||
.name = "gcc_sdcc2_apps_clk_src",
|
||||
.parent_data = gcc_parent_data_5,
|
||||
.num_parents = 5,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_floor_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
1659
drivers/clk/qcom/gcc-sdx55.c
Normal file
1659
drivers/clk/qcom/gcc-sdx55.c
Normal file
File diff suppressed because it is too large
Load Diff
320
drivers/clk/qcom/lpass-gfm-sm8250.c
Normal file
320
drivers/clk/qcom/lpass-gfm-sm8250.c
Normal file
@@ -0,0 +1,320 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* LPASS Audio CC and Always ON CC Glitch Free Mux clock driver
|
||||
*
|
||||
* Copyright (c) 2020 Linaro Ltd.
|
||||
* Author: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <dt-bindings/clock/qcom,sm8250-lpass-audiocc.h>
|
||||
#include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
|
||||
|
||||
struct lpass_gfm {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
struct clk_gfm {
|
||||
unsigned int mux_reg;
|
||||
unsigned int mux_mask;
|
||||
struct clk_hw hw;
|
||||
struct lpass_gfm *priv;
|
||||
void __iomem *gfm_mux;
|
||||
};
|
||||
|
||||
#define GFM_MASK BIT(1)
|
||||
#define to_clk_gfm(_hw) container_of(_hw, struct clk_gfm, hw)
|
||||
|
||||
static u8 clk_gfm_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gfm *clk = to_clk_gfm(hw);
|
||||
|
||||
return readl(clk->gfm_mux) & GFM_MASK;
|
||||
}
|
||||
|
||||
static int clk_gfm_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct clk_gfm *clk = to_clk_gfm(hw);
|
||||
unsigned int val;
|
||||
|
||||
val = readl(clk->gfm_mux);
|
||||
|
||||
if (index)
|
||||
val |= GFM_MASK;
|
||||
else
|
||||
val &= ~GFM_MASK;
|
||||
|
||||
writel(val, clk->gfm_mux);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_gfm_ops = {
|
||||
.get_parent = clk_gfm_get_parent,
|
||||
.set_parent = clk_gfm_set_parent,
|
||||
.determine_rate = __clk_mux_determine_rate,
|
||||
};
|
||||
|
||||
static struct clk_gfm lpass_gfm_va_mclk = {
|
||||
.mux_reg = 0x20000,
|
||||
.mux_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "VA_MCLK",
|
||||
.ops = &clk_gfm_ops,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
.num_parents = 2,
|
||||
.parent_data = (const struct clk_parent_data[]){
|
||||
{
|
||||
.index = 0,
|
||||
.fw_name = "LPASS_CLK_ID_TX_CORE_MCLK",
|
||||
}, {
|
||||
.index = 1,
|
||||
.fw_name = "LPASS_CLK_ID_VA_CORE_MCLK",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gfm lpass_gfm_tx_npl = {
|
||||
.mux_reg = 0x20000,
|
||||
.mux_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "TX_NPL",
|
||||
.ops = &clk_gfm_ops,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
.parent_data = (const struct clk_parent_data[]){
|
||||
{
|
||||
.index = 0,
|
||||
.fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK",
|
||||
}, {
|
||||
.index = 1,
|
||||
.fw_name = "LPASS_CLK_ID_VA_CORE_2X_MCLK",
|
||||
},
|
||||
},
|
||||
.num_parents = 2,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gfm lpass_gfm_wsa_mclk = {
|
||||
.mux_reg = 0x220d8,
|
||||
.mux_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "WSA_MCLK",
|
||||
.ops = &clk_gfm_ops,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
.parent_data = (const struct clk_parent_data[]){
|
||||
{
|
||||
.index = 0,
|
||||
.fw_name = "LPASS_CLK_ID_TX_CORE_MCLK",
|
||||
}, {
|
||||
.index = 1,
|
||||
.fw_name = "LPASS_CLK_ID_WSA_CORE_MCLK",
|
||||
},
|
||||
},
|
||||
.num_parents = 2,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gfm lpass_gfm_wsa_npl = {
|
||||
.mux_reg = 0x220d8,
|
||||
.mux_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "WSA_NPL",
|
||||
.ops = &clk_gfm_ops,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
.parent_data = (const struct clk_parent_data[]){
|
||||
{
|
||||
.index = 0,
|
||||
.fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK",
|
||||
}, {
|
||||
.index = 1,
|
||||
.fw_name = "LPASS_CLK_ID_WSA_CORE_NPL_MCLK",
|
||||
},
|
||||
},
|
||||
.num_parents = 2,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gfm lpass_gfm_rx_mclk_mclk2 = {
|
||||
.mux_reg = 0x240d8,
|
||||
.mux_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "RX_MCLK_MCLK2",
|
||||
.ops = &clk_gfm_ops,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
.parent_data = (const struct clk_parent_data[]){
|
||||
{
|
||||
.index = 0,
|
||||
.fw_name = "LPASS_CLK_ID_TX_CORE_MCLK",
|
||||
}, {
|
||||
.index = 1,
|
||||
.fw_name = "LPASS_CLK_ID_RX_CORE_MCLK",
|
||||
},
|
||||
},
|
||||
.num_parents = 2,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gfm lpass_gfm_rx_npl = {
|
||||
.mux_reg = 0x240d8,
|
||||
.mux_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "RX_NPL",
|
||||
.ops = &clk_gfm_ops,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
|
||||
.parent_data = (const struct clk_parent_data[]){
|
||||
{
|
||||
.index = 0,
|
||||
.fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK",
|
||||
}, {
|
||||
.index = 1,
|
||||
.fw_name = "LPASS_CLK_ID_RX_CORE_NPL_MCLK",
|
||||
},
|
||||
},
|
||||
.num_parents = 2,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gfm *aoncc_gfm_clks[] = {
|
||||
[LPASS_CDC_VA_MCLK] = &lpass_gfm_va_mclk,
|
||||
[LPASS_CDC_TX_NPL] = &lpass_gfm_tx_npl,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data aoncc_hw_onecell_data = {
|
||||
.hws = {
|
||||
[LPASS_CDC_VA_MCLK] = &lpass_gfm_va_mclk.hw,
|
||||
[LPASS_CDC_TX_NPL] = &lpass_gfm_tx_npl.hw,
|
||||
},
|
||||
.num = ARRAY_SIZE(aoncc_gfm_clks),
|
||||
};
|
||||
|
||||
static struct clk_gfm *audiocc_gfm_clks[] = {
|
||||
[LPASS_CDC_WSA_NPL] = &lpass_gfm_wsa_npl,
|
||||
[LPASS_CDC_WSA_MCLK] = &lpass_gfm_wsa_mclk,
|
||||
[LPASS_CDC_RX_NPL] = &lpass_gfm_rx_npl,
|
||||
[LPASS_CDC_RX_MCLK_MCLK2] = &lpass_gfm_rx_mclk_mclk2,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data audiocc_hw_onecell_data = {
|
||||
.hws = {
|
||||
[LPASS_CDC_WSA_NPL] = &lpass_gfm_wsa_npl.hw,
|
||||
[LPASS_CDC_WSA_MCLK] = &lpass_gfm_wsa_mclk.hw,
|
||||
[LPASS_CDC_RX_NPL] = &lpass_gfm_rx_npl.hw,
|
||||
[LPASS_CDC_RX_MCLK_MCLK2] = &lpass_gfm_rx_mclk_mclk2.hw,
|
||||
},
|
||||
.num = ARRAY_SIZE(audiocc_gfm_clks),
|
||||
};
|
||||
|
||||
struct lpass_gfm_data {
|
||||
struct clk_hw_onecell_data *onecell_data;
|
||||
struct clk_gfm **gfm_clks;
|
||||
};
|
||||
|
||||
static struct lpass_gfm_data audiocc_data = {
|
||||
.onecell_data = &audiocc_hw_onecell_data,
|
||||
.gfm_clks = audiocc_gfm_clks,
|
||||
};
|
||||
|
||||
static struct lpass_gfm_data aoncc_data = {
|
||||
.onecell_data = &aoncc_hw_onecell_data,
|
||||
.gfm_clks = aoncc_gfm_clks,
|
||||
};
|
||||
|
||||
static int lpass_gfm_clk_driver_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct lpass_gfm_data *data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk_gfm *gfm;
|
||||
struct lpass_gfm *cc;
|
||||
int err, i;
|
||||
|
||||
data = of_device_get_match_data(dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL);
|
||||
if (!cc)
|
||||
return -ENOMEM;
|
||||
|
||||
cc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(cc->base))
|
||||
return PTR_ERR(cc->base);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
err = pm_clk_create(dev);
|
||||
if (err)
|
||||
goto pm_clk_err;
|
||||
|
||||
err = of_pm_clk_add_clks(dev);
|
||||
if (err < 0) {
|
||||
dev_dbg(dev, "Failed to get lpass core voting clocks\n");
|
||||
goto clk_reg_err;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->onecell_data->num; i++) {
|
||||
if (!data->gfm_clks[i])
|
||||
continue;
|
||||
|
||||
gfm = data->gfm_clks[i];
|
||||
gfm->priv = cc;
|
||||
gfm->gfm_mux = cc->base;
|
||||
gfm->gfm_mux = gfm->gfm_mux + data->gfm_clks[i]->mux_reg;
|
||||
|
||||
err = devm_clk_hw_register(dev, &data->gfm_clks[i]->hw);
|
||||
if (err)
|
||||
goto clk_reg_err;
|
||||
|
||||
}
|
||||
|
||||
err = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
data->onecell_data);
|
||||
if (err)
|
||||
goto clk_reg_err;
|
||||
|
||||
return 0;
|
||||
|
||||
clk_reg_err:
|
||||
pm_clk_destroy(dev);
|
||||
pm_clk_err:
|
||||
pm_runtime_disable(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct of_device_id lpass_gfm_clk_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,sm8250-lpass-aoncc",
|
||||
.data = &aoncc_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,sm8250-lpass-audiocc",
|
||||
.data = &audiocc_data,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lpass_gfm_clk_match_table);
|
||||
|
||||
static const struct dev_pm_ops lpass_gfm_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver lpass_gfm_clk_driver = {
|
||||
.probe = lpass_gfm_clk_driver_probe,
|
||||
.driver = {
|
||||
.name = "lpass-gfm-clk",
|
||||
.of_match_table = lpass_gfm_clk_match_table,
|
||||
.pm = &lpass_gfm_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(lpass_gfm_clk_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -356,12 +356,52 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = {
|
||||
.num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs),
|
||||
};
|
||||
|
||||
static void lpass_pm_runtime_disable(void *data)
|
||||
{
|
||||
pm_runtime_disable(data);
|
||||
}
|
||||
|
||||
static void lpass_pm_clk_destroy(void *data)
|
||||
{
|
||||
pm_clk_destroy(data);
|
||||
}
|
||||
|
||||
static int lpass_create_pm_clks(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pm_clk_create(&pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_clk_destroy, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pm_clk_add(&pdev->dev, "iface");
|
||||
if (ret < 0)
|
||||
dev_err(&pdev->dev, "failed to acquire iface clock\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct qcom_cc_desc *desc;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
ret = lpass_create_pm_clks(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lpass_core_cc_sc7180_regmap_config.name = "lpass_audio_cc";
|
||||
desc = &lpass_audio_hm_sc7180_desc;
|
||||
ret = qcom_cc_probe_by_index(pdev, 1, desc);
|
||||
@@ -386,12 +426,22 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
|
||||
clk_fabia_pll_configure(&lpass_lpaaudio_dig_pll, regmap,
|
||||
&lpass_lpaaudio_dig_pll_config);
|
||||
|
||||
return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap);
|
||||
ret = qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap);
|
||||
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpass_hm_core_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct qcom_cc_desc *desc;
|
||||
int ret;
|
||||
|
||||
ret = lpass_create_pm_clks(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core";
|
||||
desc = &lpass_core_hm_sc7180_desc;
|
||||
@@ -399,61 +449,28 @@ static int lpass_hm_core_probe(struct platform_device *pdev)
|
||||
return qcom_cc_probe_by_index(pdev, 0, desc);
|
||||
}
|
||||
|
||||
static const struct of_device_id lpass_core_cc_sc7180_match_table[] = {
|
||||
static const struct of_device_id lpass_hm_sc7180_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,sc7180-lpasshm",
|
||||
.data = lpass_hm_core_probe,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lpass_hm_sc7180_match_table);
|
||||
|
||||
static const struct of_device_id lpass_core_cc_sc7180_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,sc7180-lpasscorecc",
|
||||
.data = lpass_core_cc_sc7180_probe,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table);
|
||||
|
||||
static int lpass_core_sc7180_probe(struct platform_device *pdev)
|
||||
{
|
||||
int (*clk_probe)(struct platform_device *p);
|
||||
int ret;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
ret = pm_clk_create(&pdev->dev);
|
||||
if (ret)
|
||||
goto disable_pm_runtime;
|
||||
|
||||
ret = pm_clk_add(&pdev->dev, "iface");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to acquire iface clock\n");
|
||||
goto destroy_pm_clk;
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
clk_probe = of_device_get_match_data(&pdev->dev);
|
||||
if (!clk_probe)
|
||||
goto destroy_pm_clk;
|
||||
|
||||
ret = clk_probe(pdev);
|
||||
if (ret)
|
||||
goto destroy_pm_clk;
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_pm_clk:
|
||||
pm_clk_destroy(&pdev->dev);
|
||||
|
||||
disable_pm_runtime:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops lpass_core_cc_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver lpass_core_cc_sc7180_driver = {
|
||||
.probe = lpass_core_sc7180_probe,
|
||||
.probe = lpass_core_cc_sc7180_probe,
|
||||
.driver = {
|
||||
.name = "lpass_core_cc-sc7180",
|
||||
.of_match_table = lpass_core_cc_sc7180_match_table,
|
||||
@@ -461,17 +478,43 @@ static struct platform_driver lpass_core_cc_sc7180_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init lpass_core_cc_sc7180_init(void)
|
||||
{
|
||||
return platform_driver_register(&lpass_core_cc_sc7180_driver);
|
||||
}
|
||||
subsys_initcall(lpass_core_cc_sc7180_init);
|
||||
static const struct dev_pm_ops lpass_hm_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
|
||||
};
|
||||
|
||||
static void __exit lpass_core_cc_sc7180_exit(void)
|
||||
static struct platform_driver lpass_hm_sc7180_driver = {
|
||||
.probe = lpass_hm_core_probe,
|
||||
.driver = {
|
||||
.name = "lpass_hm-sc7180",
|
||||
.of_match_table = lpass_hm_sc7180_match_table,
|
||||
.pm = &lpass_hm_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init lpass_sc7180_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&lpass_core_cc_sc7180_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_register(&lpass_hm_sc7180_driver);
|
||||
if (ret) {
|
||||
platform_driver_unregister(&lpass_core_cc_sc7180_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(lpass_sc7180_init);
|
||||
|
||||
static void __exit lpass_sc7180_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lpass_hm_sc7180_driver);
|
||||
platform_driver_unregister(&lpass_core_cc_sc7180_driver);
|
||||
}
|
||||
module_exit(lpass_core_cc_sc7180_exit);
|
||||
module_exit(lpass_sc7180_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7180 Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -121,7 +121,7 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
|
||||
(phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
|
||||
|
||||
parent_name = phy_no ? "dsi1pck" : "dsi0pck";
|
||||
mult = __raw_readl(dsi_reg);
|
||||
mult = readl(dsi_reg);
|
||||
if (!(mult & 0x8000))
|
||||
mult = 1;
|
||||
else
|
||||
|
||||
@@ -41,6 +41,7 @@ enum clk_ids {
|
||||
CLK_S2,
|
||||
CLK_S3,
|
||||
CLK_SDSRC,
|
||||
CLK_RPCSRC,
|
||||
CLK_RINT,
|
||||
|
||||
/* Module Clocks */
|
||||
@@ -67,6 +68,12 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
|
||||
DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
|
||||
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
|
||||
|
||||
DEF_BASE("rpc", R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC,
|
||||
CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
|
||||
R8A774A1_CLK_RPC),
|
||||
|
||||
DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
|
||||
|
||||
@@ -200,6 +207,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
|
||||
DEF_MOD("can-fd", 914, R8A774A1_CLK_S3D2),
|
||||
DEF_MOD("can-if1", 915, R8A774A1_CLK_S3D4),
|
||||
DEF_MOD("can-if0", 916, R8A774A1_CLK_S3D4),
|
||||
DEF_MOD("rpc-if", 917, R8A774A1_CLK_RPCD2),
|
||||
DEF_MOD("i2c6", 918, R8A774A1_CLK_S0D6),
|
||||
DEF_MOD("i2c5", 919, R8A774A1_CLK_S0D6),
|
||||
DEF_MOD("i2c-dvfs", 926, R8A774A1_CLK_CP),
|
||||
|
||||
@@ -40,6 +40,7 @@ enum clk_ids {
|
||||
CLK_S2,
|
||||
CLK_S3,
|
||||
CLK_SDSRC,
|
||||
CLK_RPCSRC,
|
||||
CLK_RINT,
|
||||
|
||||
/* Module Clocks */
|
||||
@@ -65,6 +66,12 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = {
|
||||
DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
|
||||
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
|
||||
|
||||
DEF_BASE("rpc", R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC,
|
||||
CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
|
||||
R8A774B1_CLK_RPC),
|
||||
|
||||
DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
|
||||
|
||||
@@ -196,6 +203,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = {
|
||||
DEF_MOD("can-fd", 914, R8A774B1_CLK_S3D2),
|
||||
DEF_MOD("can-if1", 915, R8A774B1_CLK_S3D4),
|
||||
DEF_MOD("can-if0", 916, R8A774B1_CLK_S3D4),
|
||||
DEF_MOD("rpc-if", 917, R8A774B1_CLK_RPCD2),
|
||||
DEF_MOD("i2c6", 918, R8A774B1_CLK_S0D6),
|
||||
DEF_MOD("i2c5", 919, R8A774B1_CLK_S0D6),
|
||||
DEF_MOD("i2c-dvfs", 926, R8A774B1_CLK_CP),
|
||||
|
||||
@@ -44,6 +44,7 @@ enum clk_ids {
|
||||
CLK_S2,
|
||||
CLK_S3,
|
||||
CLK_SDSRC,
|
||||
CLK_RPCSRC,
|
||||
CLK_RINT,
|
||||
CLK_OCO,
|
||||
|
||||
@@ -74,6 +75,13 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1),
|
||||
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1),
|
||||
|
||||
DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1),
|
||||
|
||||
DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC,
|
||||
CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
|
||||
R8A774C0_CLK_RPC),
|
||||
|
||||
DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
|
||||
|
||||
DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000),
|
||||
@@ -199,6 +207,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
|
||||
DEF_MOD("can-fd", 914, R8A774C0_CLK_S3D2),
|
||||
DEF_MOD("can-if1", 915, R8A774C0_CLK_S3D4),
|
||||
DEF_MOD("can-if0", 916, R8A774C0_CLK_S3D4),
|
||||
DEF_MOD("rpc-if", 917, R8A774C0_CLK_RPCD2),
|
||||
DEF_MOD("i2c6", 918, R8A774C0_CLK_S3D2),
|
||||
DEF_MOD("i2c5", 919, R8A774C0_CLK_S3D2),
|
||||
DEF_MOD("i2c-dvfs", 926, R8A774C0_CLK_CP),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user