mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge fb3b0673b7 ("Merge tag 'mailbox-v5.17' of git://git.linaro.org/landing-teams/working/fujitsu/integration") into android-mainline
Steps on the way to 5.17-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ideab24121c5f822810b2cc3e5daaa4bea519c8bd
This commit is contained in:
@@ -216,7 +216,6 @@ ForEachMacros:
|
||||
- 'for_each_migratetype_order'
|
||||
- 'for_each_msi_entry'
|
||||
- 'for_each_msi_entry_safe'
|
||||
- 'for_each_msi_vector'
|
||||
- 'for_each_net'
|
||||
- 'for_each_net_continue_reverse'
|
||||
- 'for_each_netdev'
|
||||
|
||||
@@ -612,8 +612,8 @@
|
||||
clocksource.max_cswd_read_retries= [KNL]
|
||||
Number of clocksource_watchdog() retries due to
|
||||
external delays before the clock will be marked
|
||||
unstable. Defaults to three retries, that is,
|
||||
four attempts to read the clock under test.
|
||||
unstable. Defaults to two retries, that is,
|
||||
three attempts to read the clock under test.
|
||||
|
||||
clocksource.verify_n_cpus= [KNL]
|
||||
Limit the number of CPUs checked for clocksources
|
||||
|
||||
@@ -14,6 +14,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-apmixedsys"
|
||||
- "mediatek,mt7623-apmixedsys", "mediatek,mt2701-apmixedsys"
|
||||
- "mediatek,mt7629-apmixedsys"
|
||||
- "mediatek,mt7986-apmixedsys"
|
||||
- "mediatek,mt8135-apmixedsys"
|
||||
- "mediatek,mt8167-apmixedsys", "syscon"
|
||||
- "mediatek,mt8173-apmixedsys"
|
||||
|
||||
@@ -10,6 +10,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-ethsys", "syscon"
|
||||
- "mediatek,mt7623-ethsys", "mediatek,mt2701-ethsys", "syscon"
|
||||
- "mediatek,mt7629-ethsys", "syscon"
|
||||
- "mediatek,mt7986-ethsys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
- #reset-cells: Must be 1
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-infracfg", "syscon"
|
||||
- "mediatek,mt7623-infracfg", "mediatek,mt2701-infracfg", "syscon"
|
||||
- "mediatek,mt7629-infracfg", "syscon"
|
||||
- "mediatek,mt7986-infracfg", "syscon"
|
||||
- "mediatek,mt8135-infracfg", "syscon"
|
||||
- "mediatek,mt8167-infracfg", "syscon"
|
||||
- "mediatek,mt8173-infracfg", "syscon"
|
||||
|
||||
@@ -8,6 +8,8 @@ Required Properties:
|
||||
- compatible: Should be:
|
||||
- "mediatek,mt7622-sgmiisys", "syscon"
|
||||
- "mediatek,mt7629-sgmiisys", "syscon"
|
||||
- "mediatek,mt7986-sgmiisys_0", "syscon"
|
||||
- "mediatek,mt7986-sgmiisys_1", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
The SGMIISYS controller uses the common clk binding from
|
||||
|
||||
@@ -14,6 +14,7 @@ Required Properties:
|
||||
- "mediatek,mt7622-topckgen"
|
||||
- "mediatek,mt7623-topckgen", "mediatek,mt2701-topckgen"
|
||||
- "mediatek,mt7629-topckgen"
|
||||
- "mediatek,mt7986-topckgen", "syscon"
|
||||
- "mediatek,mt8135-topckgen"
|
||||
- "mediatek,mt8167-topckgen", "syscon"
|
||||
- "mediatek,mt8173-topckgen"
|
||||
|
||||
@@ -34,6 +34,8 @@ properties:
|
||||
- allwinner,sun8i-v3-ccu
|
||||
- allwinner,sun8i-v3s-ccu
|
||||
- allwinner,sun9i-a80-ccu
|
||||
- allwinner,sun20i-d1-ccu
|
||||
- allwinner,sun20i-d1-r-ccu
|
||||
- allwinner,sun50i-a64-ccu
|
||||
- allwinner,sun50i-a64-r-ccu
|
||||
- allwinner,sun50i-a100-ccu
|
||||
@@ -79,6 +81,7 @@ if:
|
||||
enum:
|
||||
- allwinner,sun8i-a83t-r-ccu
|
||||
- allwinner,sun8i-h3-r-ccu
|
||||
- allwinner,sun20i-d1-r-ccu
|
||||
- allwinner,sun50i-a64-r-ccu
|
||||
- allwinner,sun50i-a100-r-ccu
|
||||
- allwinner,sun50i-h6-r-ccu
|
||||
@@ -99,6 +102,7 @@ else:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun20i-d1-ccu
|
||||
- allwinner,sun50i-a100-ccu
|
||||
- allwinner,sun50i-h6-ccu
|
||||
- allwinner,sun50i-h616-ccu
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/microchip,lan966x-gck.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip LAN966X Generic Clock Controller
|
||||
|
||||
maintainers:
|
||||
- Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
|
||||
|
||||
description: |
|
||||
The LAN966X Generic clock controller contains 3 PLLs - cpu_clk,
|
||||
ddr_clk and sys_clk. This clock controller generates and supplies
|
||||
clock to various peripherals within the SoC.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,lan966x-gck
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Generic clock registers
|
||||
- description: Optional gate clock registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: CPU clock source
|
||||
- description: DDR clock source
|
||||
- description: System clock source
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: cpu
|
||||
- const: ddr
|
||||
- const: sys
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clks: clock-controller@e00c00a8 {
|
||||
compatible = "microchip,lan966x-gck";
|
||||
#clock-cells = <1>;
|
||||
clocks = <&cpu_clk>, <&ddr_clk>, <&sys_clk>;
|
||||
clock-names = "cpu", "ddr", "sys";
|
||||
reg = <0xe00c00a8 0x38>;
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,97 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8976.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Global Clock & Reset Controller Binding for MSM8976
|
||||
|
||||
maintainers:
|
||||
- Stephen Boyd <sboyd@kernel.org>
|
||||
- Taniya Das <tdas@codeaurora.org>
|
||||
|
||||
description: |
|
||||
Qualcomm global clock control module which supports the clocks, resets and
|
||||
power domains on MSM8976.
|
||||
|
||||
See also:
|
||||
- dt-bindings/clock/qcom,gcc-msm8976.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,gcc-msm8976
|
||||
- qcom,gcc-msm8976-v1.1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO source
|
||||
- description: Always-on XO source
|
||||
- description: Pixel clock from DSI PHY0
|
||||
- description: Byte clock from DSI PHY0
|
||||
- description: Pixel clock from DSI PHY1
|
||||
- description: Byte clock from DSI PHY1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
- const: xo_a
|
||||
- const: dsi0pll
|
||||
- const: dsi0pllbyte
|
||||
- const: dsi1pll
|
||||
- const: dsi1pllbyte
|
||||
|
||||
vdd_gfx-supply:
|
||||
description:
|
||||
Phandle to voltage regulator providing power to the GX domain.
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- vdd_gfx-supply
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
- '#power-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@1800000 {
|
||||
compatible = "qcom,gcc-msm8976";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
reg = <0x1800000 0x80000>;
|
||||
|
||||
clocks = <&xo_board>,
|
||||
<&xo_board>,
|
||||
<&dsi0_phy 1>,
|
||||
<&dsi0_phy 0>,
|
||||
<&dsi1_phy 1>,
|
||||
<&dsi1_phy 0>;
|
||||
|
||||
clock-names = "xo",
|
||||
"xo_a",
|
||||
"dsi0pll",
|
||||
"dsi0pllbyte",
|
||||
"dsi1pll",
|
||||
"dsi1pllbyte";
|
||||
|
||||
vdd_gfx-supply = <&pm8004_s5>;
|
||||
};
|
||||
...
|
||||
@@ -22,10 +22,12 @@ properties:
|
||||
- qcom,sc8180x-rpmh-clk
|
||||
- qcom,sdm845-rpmh-clk
|
||||
- qcom,sdx55-rpmh-clk
|
||||
- qcom,sdx65-rpmh-clk
|
||||
- qcom,sm6350-rpmh-clk
|
||||
- qcom,sm8150-rpmh-clk
|
||||
- qcom,sm8250-rpmh-clk
|
||||
- qcom,sm8350-rpmh-clk
|
||||
- qcom,sm8450-rpmh-clk
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
@@ -48,6 +48,7 @@ properties:
|
||||
- renesas,r8a77990-cpg-mssr # R-Car E3
|
||||
- renesas,r8a77995-cpg-mssr # R-Car D3
|
||||
- renesas,r8a779a0-cpg-mssr # R-Car V3U
|
||||
- renesas,r8a779f0-cpg-mssr # R-Car S4-8
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/samsung,exynos7885-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung Exynos7885 SoC clock controller
|
||||
|
||||
maintainers:
|
||||
- Dávid Virág <virag.david003@gmail.com>
|
||||
- Chanwoo Choi <cw00.choi@samsung.com>
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
- Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
- Tomasz Figa <tomasz.figa@gmail.com>
|
||||
|
||||
description: |
|
||||
Exynos7885 clock controller is comprised of several CMU units, generating
|
||||
clocks for different domains. Those CMU units are modeled as separate device
|
||||
tree nodes, and might depend on each other. The root clock in that root tree
|
||||
is an external clock: OSCCLK (26 MHz). This external clock must be defined
|
||||
as a fixed-rate clock in dts.
|
||||
|
||||
CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
|
||||
dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All clocks available for usage
|
||||
in clock consumer nodes are defined as preprocessor macros in
|
||||
'dt-bindings/clock/exynos7885.h' header.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- samsung,exynos7885-cmu-top
|
||||
- samsung,exynos7885-cmu-core
|
||||
- samsung,exynos7885-cmu-peri
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 10
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 10
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7885-cmu-top
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7885-cmu-core
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_CORE bus clock (from CMU_TOP)
|
||||
- description: CCI clock (from CMU_TOP)
|
||||
- description: G3D clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_core_bus
|
||||
- const: dout_core_cci
|
||||
- const: dout_core_g3d
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7885-cmu-peri
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_PERI bus clock (from CMU_TOP)
|
||||
- description: SPI0 clock (from CMU_TOP)
|
||||
- description: SPI1 clock (from CMU_TOP)
|
||||
- description: UART0 clock (from CMU_TOP)
|
||||
- description: UART1 clock (from CMU_TOP)
|
||||
- description: UART2 clock (from CMU_TOP)
|
||||
- description: USI0 clock (from CMU_TOP)
|
||||
- description: USI1 clock (from CMU_TOP)
|
||||
- description: USI2 clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_peri_bus
|
||||
- const: dout_peri_spi0
|
||||
- const: dout_peri_spi1
|
||||
- const: dout_peri_uart0
|
||||
- const: dout_peri_uart1
|
||||
- const: dout_peri_uart2
|
||||
- const: dout_peri_usi0
|
||||
- const: dout_peri_usi1
|
||||
- const: dout_peri_usi2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Clock controller node for CMU_PERI
|
||||
- |
|
||||
#include <dt-bindings/clock/exynos7885.h>
|
||||
|
||||
cmu_peri: clock-controller@10010000 {
|
||||
compatible = "samsung,exynos7885-cmu-peri";
|
||||
reg = <0x10010000 0x8000>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&oscclk>,
|
||||
<&cmu_top CLK_DOUT_PERI_BUS>,
|
||||
<&cmu_top CLK_DOUT_PERI_SPI0>,
|
||||
<&cmu_top CLK_DOUT_PERI_SPI1>,
|
||||
<&cmu_top CLK_DOUT_PERI_UART0>,
|
||||
<&cmu_top CLK_DOUT_PERI_UART1>,
|
||||
<&cmu_top CLK_DOUT_PERI_UART2>,
|
||||
<&cmu_top CLK_DOUT_PERI_USI0>,
|
||||
<&cmu_top CLK_DOUT_PERI_USI1>,
|
||||
<&cmu_top CLK_DOUT_PERI_USI2>;
|
||||
clock-names = "oscclk",
|
||||
"dout_peri_bus",
|
||||
"dout_peri_spi0",
|
||||
"dout_peri_spi1",
|
||||
"dout_peri_uart0",
|
||||
"dout_peri_uart1",
|
||||
"dout_peri_uart2",
|
||||
"dout_peri_usi0",
|
||||
"dout_peri_usi1",
|
||||
"dout_peri_usi2";
|
||||
};
|
||||
|
||||
...
|
||||
@@ -32,6 +32,8 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- samsung,exynos850-cmu-top
|
||||
- samsung,exynos850-cmu-apm
|
||||
- samsung,exynos850-cmu-cmgp
|
||||
- samsung,exynos850-cmu-core
|
||||
- samsung,exynos850-cmu-dpu
|
||||
- samsung,exynos850-cmu-hsi
|
||||
@@ -68,6 +70,42 @@ allOf:
|
||||
items:
|
||||
- const: oscclk
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos850-cmu-apm
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_APM bus clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_clkcmu_apm_bus
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos850-cmu-cmgp
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: CMU_CMGP bus clock (from CMU_APM)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: gout_clkcmu_cmgp_bus
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/toshiba,tmpv770x-pipllct.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Toshiba Visconti5 TMPV770X PLL Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
|
||||
description:
|
||||
Toshia Visconti5 PLL controller which supports the PLLs on TMPV770X.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: toshiba,tmpv7708-pipllct
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
description: External reference clock (OSC2)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
osc2_clk: osc2-clk {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <20000000>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pipllct: clock-controller@24220000 {
|
||||
compatible = "toshiba,tmpv7708-pipllct";
|
||||
reg = <0 0x24220000 0 0x820>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc2_clk>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/toshiba,tmpv770x-pismu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Toshiba Visconti5 TMPV770x SMU controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
|
||||
description:
|
||||
Toshia Visconti5 SMU (System Management Unit) which supports the clock
|
||||
and resets on TMPV770x.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: toshiba,tmpv7708-pismu
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- "#reset-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pismu: syscon@24200000 {
|
||||
compatible = "toshiba,tmpv7708-pismu", "syscon";
|
||||
reg = <0 0x24200000 0 0x2140>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
||||
159
Documentation/devicetree/bindings/leds/leds-mt6360.yaml
Normal file
159
Documentation/devicetree/bindings/leds/leds-mt6360.yaml
Normal file
@@ -0,0 +1,159 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/leds-mt6360.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: LED driver for MT6360 PMIC from MediaTek Integrated.
|
||||
|
||||
maintainers:
|
||||
- Gene Chen <gene_chen@richtek.com>
|
||||
|
||||
description: |
|
||||
This module is part of the MT6360 MFD device.
|
||||
see Documentation/devicetree/bindings/mfd/mt6360.yaml
|
||||
Add MT6360 LED driver include 2-channel Flash LED with torch/strobe mode,
|
||||
and 4-channel RGB LED support Register/Flash/Breath Mode
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6360-led
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^(multi-)?led@[0-5]$":
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
description:
|
||||
Properties for a single LED.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: Index of the LED.
|
||||
enum:
|
||||
- 0 # LED output ISINK1
|
||||
- 1 # LED output ISINK2
|
||||
- 2 # LED output ISINK3
|
||||
- 3 # LED output ISINKML
|
||||
- 4 # LED output FLASH1
|
||||
- 5 # LED output FLASH2
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
led-controller {
|
||||
compatible = "mediatek,mt6360-led";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
multi-led@0 {
|
||||
reg = <0>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
led-max-microamp = <24000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
led@0 {
|
||||
reg = <0>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
led-max-microamp = <150000>;
|
||||
};
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function-enumerator = <1>;
|
||||
led-max-microamp = <200000>;
|
||||
flash-max-microamp = <500000>;
|
||||
flash-max-timeout-us = <1024000>;
|
||||
};
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function-enumerator = <2>;
|
||||
led-max-microamp = <200000>;
|
||||
flash-max-microamp = <500000>;
|
||||
flash-max-timeout-us = <1024000>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
|
||||
led-controller {
|
||||
compatible = "mediatek,mt6360-led";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@0 {
|
||||
reg = <0>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
led-max-microamp = <24000>;
|
||||
};
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
led-max-microamp = <24000>;
|
||||
};
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
led-max-microamp = <24000>;
|
||||
};
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
led-max-microamp = <150000>;
|
||||
};
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function-enumerator = <1>;
|
||||
led-max-microamp = <200000>;
|
||||
flash-max-microamp = <500000>;
|
||||
flash-max-timeout-us = <1024000>;
|
||||
};
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function-enumerator = <2>;
|
||||
led-max-microamp = <200000>;
|
||||
flash-max-microamp = <500000>;
|
||||
flash-max-timeout-us = <1024000>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -27,14 +27,20 @@ properties:
|
||||
for example for the display controller, the system management
|
||||
controller and the NVMe coprocessor.
|
||||
items:
|
||||
- const: apple,t8103-asc-mailbox
|
||||
- enum:
|
||||
- apple,t8103-asc-mailbox
|
||||
- apple,t6000-asc-mailbox
|
||||
- const: apple,asc-mailbox-v4
|
||||
|
||||
- description:
|
||||
M3 mailboxes are an older variant with a slightly different MMIO
|
||||
interface still found on the M1. It is used for the Thunderbolt
|
||||
co-processors.
|
||||
items:
|
||||
- const: apple,t8103-m3-mailbox
|
||||
- enum:
|
||||
- apple,t8103-m3-mailbox
|
||||
- apple,t6000-m3-mailbox
|
||||
- const: apple,m3-mailbox-v2
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -71,7 +77,7 @@ additionalProperties: false
|
||||
examples:
|
||||
- |
|
||||
mailbox@77408000 {
|
||||
compatible = "apple,t8103-asc-mailbox";
|
||||
compatible = "apple,t8103-asc-mailbox", "apple,asc-mailbox-v4";
|
||||
reg = <0x77408000 0x4000>;
|
||||
interrupts = <1 583 4>, <1 584 4>, <1 585 4>, <1 586 4>;
|
||||
interrupt-names = "send-empty", "send-not-empty",
|
||||
|
||||
@@ -25,6 +25,9 @@ properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
timer-width:
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description: |
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/timer/mstar,msc313e-timer.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mstar MSC313e Timer Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Daniel Palmer <daniel@0x0f.com>
|
||||
- Romain Perier <romain.perier@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mstar,msc313e-timer
|
||||
- sstar,ssd20xd-timer
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
timer@6040 {
|
||||
compatible = "mstar,msc313e-timer";
|
||||
reg = <0x6040 0x40>;
|
||||
clocks = <&xtal_div2>;
|
||||
interrupts-extended = <&intc_fiq GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
...
|
||||
@@ -19,7 +19,11 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx7ulp-tpm
|
||||
oneOf:
|
||||
- const: fsl,imx7ulp-tpm
|
||||
- items:
|
||||
- const: fsl,imx8ulp-tpm
|
||||
- const: fsl,imx7ulp-tpm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -21,9 +21,10 @@ properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r7s72100-ostm # RZ/A1H
|
||||
- renesas,r7s9210-ostm # RZ/A2M
|
||||
- const: renesas,ostm # Generic
|
||||
- renesas,r7s72100-ostm # RZ/A1H
|
||||
- renesas,r7s9210-ostm # RZ/A2M
|
||||
- renesas,r9a07g044-ostm # RZ/G2{L,LC}
|
||||
- const: renesas,ostm # Generic
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -37,6 +38,9 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -44,6 +48,16 @@ required:
|
||||
- clocks
|
||||
- power-domains
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,r9a07g044-ostm
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
||||
@@ -18,7 +18,6 @@ properties:
|
||||
- enum:
|
||||
- rockchip,rv1108-timer
|
||||
- rockchip,rk3036-timer
|
||||
- rockchip,rk3066-timer
|
||||
- rockchip,rk3188-timer
|
||||
- rockchip,rk3228-timer
|
||||
- rockchip,rk3229-timer
|
||||
|
||||
@@ -13,7 +13,7 @@ PCI Support Library
|
||||
.. kernel-doc:: drivers/pci/search.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/msi.c
|
||||
.. kernel-doc:: drivers/pci/msi/msi.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/bus.c
|
||||
|
||||
13
MAINTAINERS
13
MAINTAINERS
@@ -2304,6 +2304,7 @@ F: Documentation/devicetree/bindings/gpio/mstar,msc313-gpio.yaml
|
||||
F: arch/arm/boot/dts/mstar-*
|
||||
F: arch/arm/mach-mstar/
|
||||
F: drivers/clk/mstar/
|
||||
F: drivers/clocksource/timer-msc313e.c
|
||||
F: drivers/gpio/gpio-msc313.c
|
||||
F: drivers/rtc/rtc-msc313.c
|
||||
F: drivers/watchdog/msc313e_wdt.c
|
||||
@@ -2807,12 +2808,15 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwamatsu/linux-visconti.git
|
||||
F: Documentation/devicetree/bindings/arm/toshiba.yaml
|
||||
F: Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pipllct.yaml
|
||||
F: Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pismu.yaml
|
||||
F: Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
|
||||
F: Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
|
||||
F: Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml
|
||||
F: Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
|
||||
F: arch/arm64/boot/dts/toshiba/
|
||||
F: drivers/clk/visconti/
|
||||
F: drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
|
||||
F: drivers/gpio/gpio-visconti.c
|
||||
F: drivers/pci/controller/dwc/pcie-visconti.c
|
||||
@@ -15875,6 +15879,15 @@ F: Documentation/admin-guide/media/qcom_camss.rst
|
||||
F: Documentation/devicetree/bindings/media/*camss*
|
||||
F: drivers/media/platform/qcom/camss/
|
||||
|
||||
QUALCOMM CLOCK DRIVERS
|
||||
M: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
|
||||
F: Documentation/devicetree/bindings/clock/qcom,*
|
||||
F: drivers/clk/qcom/
|
||||
F: include/dt-bindings/clock/qcom,*
|
||||
|
||||
QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER
|
||||
M: Niklas Cassel <nks@flawful.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "omap34xx.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/*
|
||||
* Default secure signed bootloader (Nokia X-Loader) does not enable L3 firewall
|
||||
@@ -630,63 +631,92 @@
|
||||
};
|
||||
|
||||
lp5523: lp5523@32 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "national,lp5523";
|
||||
reg = <0x32>;
|
||||
clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */
|
||||
enable-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */
|
||||
enable-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */
|
||||
|
||||
chan0 {
|
||||
led@0 {
|
||||
reg = <0>;
|
||||
chan-name = "lp5523:kb1";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
};
|
||||
|
||||
chan1 {
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
chan-name = "lp5523:kb2";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
};
|
||||
|
||||
chan2 {
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
chan-name = "lp5523:kb3";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
};
|
||||
|
||||
chan3 {
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
chan-name = "lp5523:kb4";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
};
|
||||
|
||||
chan4 {
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
chan-name = "lp5523:b";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
};
|
||||
|
||||
chan5 {
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
chan-name = "lp5523:g";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
};
|
||||
|
||||
chan6 {
|
||||
led@6 {
|
||||
reg = <6>;
|
||||
chan-name = "lp5523:r";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
};
|
||||
|
||||
chan7 {
|
||||
led@7 {
|
||||
reg = <7>;
|
||||
chan-name = "lp5523:kb5";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
};
|
||||
|
||||
chan8 {
|
||||
led@8 {
|
||||
reg = <8>;
|
||||
chan-name = "lp5523:kb6";
|
||||
led-cur = /bits/ 8 <50>;
|
||||
max-cur = /bits/ 8 <100>;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
||||
u64 search_mask;
|
||||
int index;
|
||||
|
||||
if (desc->pci.msi_attrib.is_msix)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Read the MSI config to figure out how many IRQs this device
|
||||
* wants. Most devices only want 1, which will give
|
||||
@@ -182,35 +185,6 @@ msi_irq_allocated:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* MSI-X is not supported.
|
||||
*/
|
||||
if (type == PCI_CAP_ID_MSIX)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* If an architecture wants to support multiple MSI, it needs to
|
||||
* override arch_setup_msi_irqs()
|
||||
*/
|
||||
if (type == PCI_CAP_ID_MSI && nvec > 1)
|
||||
return 1;
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
ret = arch_setup_msi_irq(dev, entry);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0)
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a device no longer needs its MSI interrupts. All
|
||||
* MSI interrupts for the device are freed.
|
||||
|
||||
@@ -366,30 +366,5 @@
|
||||
0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
|
||||
0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
|
||||
};
|
||||
|
||||
MSI: ppc4xx-msi@C10000000 {
|
||||
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
|
||||
reg = < 0xC 0x10000000 0x100
|
||||
0xC 0x10000000 0x100>;
|
||||
sdr-base = <0x36C>;
|
||||
msi-data = <0x00004440>;
|
||||
msi-mask = <0x0000ffe0>;
|
||||
interrupts =<0 1 2 3 4 5 6 7>;
|
||||
interrupt-parent = <&MSI>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
msi-available-ranges = <0x0 0x100>;
|
||||
interrupt-map = <
|
||||
0 &UIC3 0x18 1
|
||||
1 &UIC3 0x19 1
|
||||
2 &UIC3 0x1A 1
|
||||
3 &UIC3 0x1B 1
|
||||
4 &UIC3 0x1C 1
|
||||
5 &UIC3 0x1D 1
|
||||
6 &UIC3 0x1E 1
|
||||
7 &UIC3 0x1F 1
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -544,23 +544,5 @@
|
||||
0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */
|
||||
0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>;
|
||||
};
|
||||
|
||||
MSI: ppc4xx-msi@C10000000 {
|
||||
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
|
||||
reg = < 0xC 0x10000000 0x100>;
|
||||
sdr-base = <0x36C>;
|
||||
msi-data = <0x00000000>;
|
||||
msi-mask = <0x44440000>;
|
||||
interrupt-count = <3>;
|
||||
interrupts = <0 1 2 3>;
|
||||
interrupt-parent = <&UIC3>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = <0 &UIC3 0x18 1
|
||||
1 &UIC3 0x19 1
|
||||
2 &UIC3 0x1A 1
|
||||
3 &UIC3 0x1B 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -442,24 +442,6 @@
|
||||
0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
|
||||
};
|
||||
|
||||
MSI: ppc4xx-msi@400300000 {
|
||||
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
|
||||
reg = < 0x4 0x00300000 0x100>;
|
||||
sdr-base = <0x3B0>;
|
||||
msi-data = <0x00000000>;
|
||||
msi-mask = <0x44440000>;
|
||||
interrupt-count = <3>;
|
||||
interrupts =<0 1 2 3>;
|
||||
interrupt-parent = <&UIC0>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = <0 &UIC0 0xC 1
|
||||
1 &UIC0 0x0D 1
|
||||
2 &UIC0 0x0E 1
|
||||
3 &UIC0 0x0F 1>;
|
||||
};
|
||||
|
||||
I2O: i2o@400100000 {
|
||||
compatible = "ibm,i2o-440spe";
|
||||
reg = <0x00000004 0x00100000 0x100>;
|
||||
|
||||
@@ -403,33 +403,5 @@
|
||||
0x0 0x0 0x0 0x3 &UIC2 0xd 0x4 /* swizzled int C */
|
||||
0x0 0x0 0x0 0x4 &UIC2 0xe 0x4 /* swizzled int D */>;
|
||||
};
|
||||
|
||||
MSI: ppc4xx-msi@C10000000 {
|
||||
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
|
||||
reg = <0xEF620000 0x100>;
|
||||
sdr-base = <0x4B0>;
|
||||
msi-data = <0x00000000>;
|
||||
msi-mask = <0x44440000>;
|
||||
interrupt-count = <12>;
|
||||
interrupts = <0 1 2 3 4 5 6 7 8 9 0xA 0xB 0xC 0xD>;
|
||||
interrupt-parent = <&UIC2>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = <0 &UIC2 0x10 1
|
||||
1 &UIC2 0x11 1
|
||||
2 &UIC2 0x12 1
|
||||
2 &UIC2 0x13 1
|
||||
2 &UIC2 0x14 1
|
||||
2 &UIC2 0x15 1
|
||||
2 &UIC2 0x16 1
|
||||
2 &UIC2 0x17 1
|
||||
2 &UIC2 0x18 1
|
||||
2 &UIC2 0x19 1
|
||||
2 &UIC2 0x1A 1
|
||||
2 &UIC2 0x1B 1
|
||||
2 &UIC2 0x1C 1
|
||||
3 &UIC2 0x1D 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -358,25 +358,6 @@
|
||||
0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
|
||||
};
|
||||
|
||||
MSI: ppc4xx-msi@400300000 {
|
||||
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
|
||||
reg = < 0x4 0x00300000 0x100
|
||||
0x4 0x00300000 0x100>;
|
||||
sdr-base = <0x3B0>;
|
||||
msi-data = <0x00000000>;
|
||||
msi-mask = <0x44440000>;
|
||||
interrupt-count = <3>;
|
||||
interrupts =<0 1 2 3>;
|
||||
interrupt-parent = <&UIC0>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = <0 &UIC0 0xC 1
|
||||
1 &UIC0 0x0D 1
|
||||
2 &UIC0 0x0E 1
|
||||
3 &UIC0 0x0F 1>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ config KILAUEA
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select FORCE_PCI
|
||||
select PCI_MSI
|
||||
select PPC4xx_MSI
|
||||
help
|
||||
This option enables support for the AMCC PPC405EX evaluation board.
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ config BLUESTONE
|
||||
select APM821xx
|
||||
select FORCE_PCI
|
||||
select PCI_MSI
|
||||
select PPC4xx_MSI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select IBM_EMAC_RGMII if IBM_EMAC
|
||||
help
|
||||
@@ -73,7 +72,6 @@ config KATMAI
|
||||
select FORCE_PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select PCI_MSI
|
||||
select PPC4xx_MSI
|
||||
help
|
||||
This option enables support for the AMCC PPC440SPe evaluation board.
|
||||
|
||||
@@ -115,7 +113,6 @@ config CANYONLANDS
|
||||
select FORCE_PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select PCI_MSI
|
||||
select PPC4xx_MSI
|
||||
select IBM_EMAC_RGMII if IBM_EMAC
|
||||
select IBM_EMAC_ZMII if IBM_EMAC
|
||||
help
|
||||
@@ -141,7 +138,6 @@ config REDWOOD
|
||||
select FORCE_PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select PCI_MSI
|
||||
select PPC4xx_MSI
|
||||
help
|
||||
This option enables support for the AMCC PPC460SX Redwood board.
|
||||
|
||||
|
||||
@@ -3,6 +3,5 @@ obj-y += uic.o machine_check.o
|
||||
obj-$(CONFIG_4xx_SOC) += soc.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
obj-$(CONFIG_PPC4xx_HSTA_MSI) += hsta_msi.o
|
||||
obj-$(CONFIG_PPC4xx_MSI) += msi.o
|
||||
obj-$(CONFIG_PPC4xx_CPM) += cpm.o
|
||||
obj-$(CONFIG_PPC4xx_GPIO) += gpio.o
|
||||
|
||||
@@ -47,7 +47,7 @@ static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
msi_for_each_desc(entry, &dev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
|
||||
if (irq < 0) {
|
||||
pr_debug("%s: Failed to allocate msi interrupt\n",
|
||||
@@ -105,10 +105,7 @@ static void hsta_teardown_msi_irqs(struct pci_dev *dev)
|
||||
struct msi_desc *entry;
|
||||
int irq;
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
if (!entry->irq)
|
||||
continue;
|
||||
|
||||
msi_for_each_desc(entry, &dev->dev, MSI_DESC_ASSOCIATED) {
|
||||
irq = hsta_find_hwirq_offset(entry->irq);
|
||||
|
||||
/* entry->irq should always be in irq_map */
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Adding PCI-E MSI support for PPC4XX SoCs.
|
||||
*
|
||||
* Copyright (c) 2010, Applied Micro Circuits Corporation
|
||||
* Authors: Tirumala R Marri <tmarri@apm.com>
|
||||
* Feng Kan <fkan@apm.com>
|
||||
*/
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
#include <asm/dcr.h>
|
||||
#include <asm/dcr-regs.h>
|
||||
#include <asm/msi_bitmap.h>
|
||||
|
||||
#define PEIH_TERMADH 0x00
|
||||
#define PEIH_TERMADL 0x08
|
||||
#define PEIH_MSIED 0x10
|
||||
#define PEIH_MSIMK 0x18
|
||||
#define PEIH_MSIASS 0x20
|
||||
#define PEIH_FLUSH0 0x30
|
||||
#define PEIH_FLUSH1 0x38
|
||||
#define PEIH_CNTRST 0x48
|
||||
|
||||
static int msi_irqs;
|
||||
|
||||
struct ppc4xx_msi {
|
||||
u32 msi_addr_lo;
|
||||
u32 msi_addr_hi;
|
||||
void __iomem *msi_regs;
|
||||
int *msi_virqs;
|
||||
struct msi_bitmap bitmap;
|
||||
struct device_node *msi_dev;
|
||||
};
|
||||
|
||||
static struct ppc4xx_msi ppc4xx_msi;
|
||||
|
||||
static int ppc4xx_msi_init_allocator(struct platform_device *dev,
|
||||
struct ppc4xx_msi *msi_data)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs,
|
||||
dev->dev.of_node);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
|
||||
if (err < 0) {
|
||||
msi_bitmap_free(&msi_data->bitmap);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
{
|
||||
int int_no = -ENOMEM;
|
||||
unsigned int virq;
|
||||
struct msi_msg msg;
|
||||
struct msi_desc *entry;
|
||||
struct ppc4xx_msi *msi_data = &ppc4xx_msi;
|
||||
|
||||
dev_dbg(&dev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
|
||||
__func__, nvec, type);
|
||||
if (type == PCI_CAP_ID_MSIX)
|
||||
pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
|
||||
|
||||
msi_data->msi_virqs = kmalloc_array(msi_irqs, sizeof(int), GFP_KERNEL);
|
||||
if (!msi_data->msi_virqs)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
|
||||
if (int_no >= 0)
|
||||
break;
|
||||
if (int_no < 0) {
|
||||
pr_debug("%s: fail allocating msi interrupt\n",
|
||||
__func__);
|
||||
}
|
||||
virq = irq_of_parse_and_map(msi_data->msi_dev, int_no);
|
||||
if (!virq) {
|
||||
dev_err(&dev->dev, "%s: fail mapping irq\n", __func__);
|
||||
msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1);
|
||||
return -ENOSPC;
|
||||
}
|
||||
dev_dbg(&dev->dev, "%s: virq = %d\n", __func__, virq);
|
||||
|
||||
/* Setup msi address space */
|
||||
msg.address_hi = msi_data->msi_addr_hi;
|
||||
msg.address_lo = msi_data->msi_addr_lo;
|
||||
|
||||
irq_set_msi_desc(virq, entry);
|
||||
msg.data = int_no;
|
||||
pci_write_msi_msg(virq, &msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
struct ppc4xx_msi *msi_data = &ppc4xx_msi;
|
||||
irq_hw_number_t hwirq;
|
||||
|
||||
dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
if (!entry->irq)
|
||||
continue;
|
||||
hwirq = virq_to_hw(entry->irq);
|
||||
irq_set_msi_desc(entry->irq, NULL);
|
||||
irq_dispose_mapping(entry->irq);
|
||||
msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
|
||||
struct resource res, struct ppc4xx_msi *msi)
|
||||
{
|
||||
const u32 *msi_data;
|
||||
const u32 *msi_mask;
|
||||
const u32 *sdr_addr;
|
||||
dma_addr_t msi_phys;
|
||||
void *msi_virt;
|
||||
int err;
|
||||
|
||||
sdr_addr = of_get_property(dev->dev.of_node, "sdr-base", NULL);
|
||||
if (!sdr_addr)
|
||||
return -EINVAL;
|
||||
|
||||
msi_data = of_get_property(dev->dev.of_node, "msi-data", NULL);
|
||||
if (!msi_data)
|
||||
return -EINVAL;
|
||||
|
||||
msi_mask = of_get_property(dev->dev.of_node, "msi-mask", NULL);
|
||||
if (!msi_mask)
|
||||
return -EINVAL;
|
||||
|
||||
msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
|
||||
if (!msi->msi_dev)
|
||||
return -ENODEV;
|
||||
|
||||
msi->msi_regs = of_iomap(msi->msi_dev, 0);
|
||||
if (!msi->msi_regs) {
|
||||
dev_err(&dev->dev, "of_iomap failed\n");
|
||||
err = -ENOMEM;
|
||||
goto node_put;
|
||||
}
|
||||
dev_dbg(&dev->dev, "PCIE-MSI: msi register mapped 0x%x 0x%x\n",
|
||||
(u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
|
||||
|
||||
msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
|
||||
if (!msi_virt) {
|
||||
err = -ENOMEM;
|
||||
goto iounmap;
|
||||
}
|
||||
msi->msi_addr_hi = upper_32_bits(msi_phys);
|
||||
msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff);
|
||||
dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n",
|
||||
msi->msi_addr_hi, msi->msi_addr_lo);
|
||||
|
||||
mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */
|
||||
mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */
|
||||
|
||||
/* Progam the Interrupt handler Termination addr registers */
|
||||
out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
|
||||
out_be32(msi->msi_regs + PEIH_TERMADL, msi->msi_addr_lo);
|
||||
|
||||
/* Program MSI Expected data and Mask bits */
|
||||
out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
|
||||
out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
|
||||
|
||||
dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys);
|
||||
|
||||
return 0;
|
||||
|
||||
iounmap:
|
||||
iounmap(msi->msi_regs);
|
||||
node_put:
|
||||
of_node_put(msi->msi_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ppc4xx_of_msi_remove(struct platform_device *dev)
|
||||
{
|
||||
struct ppc4xx_msi *msi = dev->dev.platform_data;
|
||||
int i;
|
||||
int virq;
|
||||
|
||||
for (i = 0; i < msi_irqs; i++) {
|
||||
virq = msi->msi_virqs[i];
|
||||
if (virq)
|
||||
irq_dispose_mapping(virq);
|
||||
}
|
||||
|
||||
if (msi->bitmap.bitmap)
|
||||
msi_bitmap_free(&msi->bitmap);
|
||||
iounmap(msi->msi_regs);
|
||||
of_node_put(msi->msi_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ppc4xx_msi_probe(struct platform_device *dev)
|
||||
{
|
||||
struct ppc4xx_msi *msi;
|
||||
struct resource res;
|
||||
int err = 0;
|
||||
struct pci_controller *phb;
|
||||
|
||||
dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
|
||||
|
||||
msi = devm_kzalloc(&dev->dev, sizeof(*msi), GFP_KERNEL);
|
||||
if (!msi)
|
||||
return -ENOMEM;
|
||||
dev->dev.platform_data = msi;
|
||||
|
||||
/* Get MSI ranges */
|
||||
err = of_address_to_resource(dev->dev.of_node, 0, &res);
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "%pOF resource error!\n", dev->dev.of_node);
|
||||
return err;
|
||||
}
|
||||
|
||||
msi_irqs = of_irq_count(dev->dev.of_node);
|
||||
if (!msi_irqs)
|
||||
return -ENODEV;
|
||||
|
||||
err = ppc4xx_setup_pcieh_hw(dev, res, msi);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ppc4xx_msi_init_allocator(dev, msi);
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "Error allocating MSI bitmap\n");
|
||||
goto error_out;
|
||||
}
|
||||
ppc4xx_msi = *msi;
|
||||
|
||||
list_for_each_entry(phb, &hose_list, list_node) {
|
||||
phb->controller_ops.setup_msi_irqs = ppc4xx_setup_msi_irqs;
|
||||
phb->controller_ops.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
ppc4xx_of_msi_remove(dev);
|
||||
return err;
|
||||
}
|
||||
static const struct of_device_id ppc4xx_msi_ids[] = {
|
||||
{
|
||||
.compatible = "amcc,ppc4xx-msi",
|
||||
},
|
||||
{}
|
||||
};
|
||||
static struct platform_driver ppc4xx_msi_driver = {
|
||||
.probe = ppc4xx_msi_probe,
|
||||
.remove = ppc4xx_of_msi_remove,
|
||||
.driver = {
|
||||
.name = "ppc4xx-msi",
|
||||
.of_match_table = ppc4xx_msi_ids,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static __init int ppc4xx_msi_init(void)
|
||||
{
|
||||
return platform_driver_register(&ppc4xx_msi_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(ppc4xx_msi_init);
|
||||
@@ -199,7 +199,6 @@ out_error:
|
||||
static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct msi_desc *entry;
|
||||
int len;
|
||||
const u32 *prop;
|
||||
|
||||
@@ -209,10 +208,8 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
entry = first_pci_msi_entry(dev);
|
||||
|
||||
for (; dn; dn = of_get_next_parent(dn)) {
|
||||
if (entry->msi_attrib.is_64) {
|
||||
if (!dev->no_64bit_msi) {
|
||||
prop = of_get_property(dn, "msi-address-64", &len);
|
||||
if (prop)
|
||||
break;
|
||||
@@ -265,7 +262,7 @@ static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
msi_for_each_desc(entry, &dev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
virq = irq_create_direct_mapping(msic->irq_domain);
|
||||
if (!virq) {
|
||||
dev_warn(&dev->dev,
|
||||
@@ -288,10 +285,7 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
|
||||
|
||||
dev_dbg(&dev->dev, "axon_msi: tearing down msi irqs\n");
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
if (!entry->irq)
|
||||
continue;
|
||||
|
||||
msi_for_each_desc(entry, &dev->dev, MSI_DESC_ASSOCIATED) {
|
||||
irq_set_msi_desc(entry->irq, NULL);
|
||||
irq_dispose_mapping(entry->irq);
|
||||
}
|
||||
|
||||
@@ -62,17 +62,12 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
|
||||
|
||||
pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev);
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
if (!entry->irq)
|
||||
continue;
|
||||
|
||||
msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) {
|
||||
hwirq = virq_to_hw(entry->irq);
|
||||
irq_set_msi_desc(entry->irq, NULL);
|
||||
irq_dispose_mapping(entry->irq);
|
||||
msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, ALLOC_CHUNK);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
@@ -90,7 +85,7 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
msg.address_hi = 0;
|
||||
msg.address_lo = PASEMI_MSI_ADDR;
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
/* Allocate 16 interrupts for now, since that's the grouping for
|
||||
* affinity. This can be changed later if it turns out 32 is too
|
||||
* few MSIs for someone, but restrictions will apply to how the
|
||||
|
||||
@@ -2154,10 +2154,10 @@ static void pnv_msi_compose_msg(struct irq_data *d, struct msi_msg *msg)
|
||||
int rc;
|
||||
|
||||
rc = __pnv_pci_ioda_msi_setup(phb, pdev, d->hwirq,
|
||||
entry->msi_attrib.is_64, msg);
|
||||
entry->pci.msi_attrib.is_64, msg);
|
||||
if (rc)
|
||||
dev_err(&pdev->dev, "Failed to setup %s-bit MSI #%ld : %d\n",
|
||||
entry->msi_attrib.is_64 ? "64" : "32", d->hwirq, rc);
|
||||
entry->pci.msi_attrib.is_64 ? "64" : "32", d->hwirq, rc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -321,27 +321,6 @@ out:
|
||||
return request;
|
||||
}
|
||||
|
||||
static int check_msix_entries(struct pci_dev *pdev)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
int expected;
|
||||
|
||||
/* There's no way for us to express to firmware that we want
|
||||
* a discontiguous, or non-zero based, range of MSI-X entries.
|
||||
* So we must reject such requests. */
|
||||
|
||||
expected = 0;
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
if (entry->msi_attrib.entry_nr != expected) {
|
||||
pr_debug("rtas_msi: bad MSI-X entries.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
expected++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev)
|
||||
{
|
||||
u32 addr_hi, addr_lo;
|
||||
@@ -380,9 +359,6 @@ static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
|
||||
if (quota && quota < nvec)
|
||||
return quota;
|
||||
|
||||
if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Firmware currently refuse any non power of two allocation
|
||||
* so we round up if the quota will allow it.
|
||||
@@ -448,8 +424,7 @@ static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev
|
||||
int nvec, msi_alloc_info_t *arg)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct msi_desc *desc = first_pci_msi_entry(pdev);
|
||||
int type = desc->msi_attrib.is_msix ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI;
|
||||
int type = pdev->msix_enabled ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI;
|
||||
|
||||
return rtas_prepare_msi_irqs(pdev, nvec, type, arg);
|
||||
}
|
||||
@@ -530,9 +505,16 @@ static struct irq_chip pseries_pci_msi_irq_chip = {
|
||||
.irq_write_msi_msg = pseries_msi_write_msg,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Set MSI_FLAG_MSIX_CONTIGUOUS as there is no way to express to
|
||||
* firmware to request a discontiguous or non-zero based range of
|
||||
* MSI-X entries. Core code will reject such setup attempts.
|
||||
*/
|
||||
static struct msi_domain_info pseries_msi_domain_info = {
|
||||
.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
||||
MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
|
||||
MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX |
|
||||
MSI_FLAG_MSIX_CONTIGUOUS),
|
||||
.ops = &pseries_pci_msi_domain_ops,
|
||||
.chip = &pseries_pci_msi_irq_chip,
|
||||
};
|
||||
@@ -580,7 +562,7 @@ static int pseries_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
|
||||
int hwirq;
|
||||
int i, ret;
|
||||
|
||||
hwirq = rtas_query_irq_number(pci_get_pdn(pdev), desc->msi_attrib.entry_nr);
|
||||
hwirq = rtas_query_irq_number(pci_get_pdn(pdev), desc->msi_index);
|
||||
if (hwirq < 0) {
|
||||
dev_err(&pdev->dev, "Failed to query HW IRQ: %d\n", hwirq);
|
||||
return hwirq;
|
||||
|
||||
@@ -12,17 +12,11 @@ config PPC4xx_HSTA_MSI
|
||||
depends on PCI_MSI
|
||||
depends on PCI && 4xx
|
||||
|
||||
config PPC4xx_MSI
|
||||
bool
|
||||
depends on PCI_MSI
|
||||
depends on PCI && 4xx
|
||||
|
||||
config PPC_MSI_BITMAP
|
||||
bool
|
||||
depends on PCI_MSI
|
||||
default y if MPIC
|
||||
default y if FSL_PCI
|
||||
default y if PPC4xx_MSI
|
||||
default y if PPC_POWERNV
|
||||
|
||||
source "arch/powerpc/sysdev/xics/Kconfig"
|
||||
|
||||
@@ -125,17 +125,13 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
|
||||
struct fsl_msi *msi_data;
|
||||
irq_hw_number_t hwirq;
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
if (!entry->irq)
|
||||
continue;
|
||||
msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) {
|
||||
hwirq = virq_to_hw(entry->irq);
|
||||
msi_data = irq_get_chip_data(entry->irq);
|
||||
irq_set_msi_desc(entry->irq, NULL);
|
||||
irq_dispose_mapping(entry->irq);
|
||||
msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
|
||||
@@ -215,7 +211,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
}
|
||||
}
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
/*
|
||||
* Loop over all the MSI devices until we find one that has an
|
||||
* available interrupt.
|
||||
|
||||
@@ -104,17 +104,12 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
|
||||
struct msi_desc *entry;
|
||||
irq_hw_number_t hwirq;
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
if (!entry->irq)
|
||||
continue;
|
||||
|
||||
msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) {
|
||||
hwirq = virq_to_hw(entry->irq);
|
||||
irq_set_msi_desc(entry->irq, NULL);
|
||||
irq_dispose_mapping(entry->irq);
|
||||
msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
@@ -136,7 +131,7 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
|
||||
if (hwirq < 0) {
|
||||
pr_debug("u3msi: failed allocating hwirq\n");
|
||||
|
||||
@@ -303,7 +303,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
|
||||
/* Request MSI interrupts */
|
||||
hwirq = bit;
|
||||
for_each_pci_msi_entry(msi, pdev) {
|
||||
msi_for_each_desc(msi, &pdev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
rc = -EIO;
|
||||
if (hwirq - bit >= msi_vecs)
|
||||
break;
|
||||
@@ -362,9 +362,7 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
|
||||
return;
|
||||
|
||||
/* Release MSI interrupts */
|
||||
for_each_pci_msi_entry(msi, pdev) {
|
||||
if (!msi->irq)
|
||||
continue;
|
||||
msi_for_each_desc(msi, &pdev->dev, MSI_DESC_ASSOCIATED) {
|
||||
irq_set_msi_desc(msi->irq, NULL);
|
||||
irq_free_desc(msi->irq);
|
||||
msi->msg.address_lo = 0;
|
||||
@@ -387,13 +385,13 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
|
||||
airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->msi_nr_irqs);
|
||||
}
|
||||
|
||||
void arch_restore_msi_irqs(struct pci_dev *pdev)
|
||||
bool arch_restore_msi_irqs(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
|
||||
if (!zdev->irqs_registered)
|
||||
zpci_set_irq(zdev);
|
||||
default_restore_msi_irqs(pdev);
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct airq_struct zpci_airq = {
|
||||
|
||||
@@ -146,13 +146,13 @@ static int sparc64_setup_msi_irq(unsigned int *irq_p,
|
||||
msiqid = pick_msiq(pbm);
|
||||
|
||||
err = ops->msi_setup(pbm, msiqid, msi,
|
||||
(entry->msi_attrib.is_64 ? 1 : 0));
|
||||
(entry->pci.msi_attrib.is_64 ? 1 : 0));
|
||||
if (err)
|
||||
goto out_msi_free;
|
||||
|
||||
pbm->msi_irq_table[msi - pbm->msi_first] = *irq_p;
|
||||
|
||||
if (entry->msi_attrib.is_64) {
|
||||
if (entry->pci.msi_attrib.is_64) {
|
||||
msg.address_hi = pbm->msi64_start >> 32;
|
||||
msg.address_lo = pbm->msi64_start & 0xffffffff;
|
||||
} else {
|
||||
|
||||
@@ -253,64 +253,43 @@ static int hv_unmap_msi_interrupt(struct pci_dev *dev, struct hv_interrupt_entry
|
||||
return hv_unmap_interrupt(hv_build_pci_dev_id(dev).as_uint64, old_entry);
|
||||
}
|
||||
|
||||
static void hv_teardown_msi_irq_common(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
|
||||
static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
|
||||
{
|
||||
u64 status;
|
||||
struct hv_interrupt_entry old_entry;
|
||||
struct irq_desc *desc;
|
||||
struct irq_data *data;
|
||||
struct msi_msg msg;
|
||||
u64 status;
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
if (!desc) {
|
||||
pr_debug("%s: no irq desc\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
data = &desc->irq_data;
|
||||
if (!data) {
|
||||
pr_debug("%s: no irq data\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data->chip_data) {
|
||||
if (!irqd->chip_data) {
|
||||
pr_debug("%s: no chip data\n!", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
old_entry = *(struct hv_interrupt_entry *)data->chip_data;
|
||||
old_entry = *(struct hv_interrupt_entry *)irqd->chip_data;
|
||||
entry_to_msi_msg(&old_entry, &msg);
|
||||
|
||||
kfree(data->chip_data);
|
||||
data->chip_data = NULL;
|
||||
kfree(irqd->chip_data);
|
||||
irqd->chip_data = NULL;
|
||||
|
||||
status = hv_unmap_msi_interrupt(dev, &old_entry);
|
||||
|
||||
if (status != HV_STATUS_SUCCESS) {
|
||||
if (status != HV_STATUS_SUCCESS)
|
||||
pr_err("%s: hypercall failed, status %lld\n", __func__, status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void hv_msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
|
||||
static void hv_msi_free_irq(struct irq_domain *domain,
|
||||
struct msi_domain_info *info, unsigned int virq)
|
||||
{
|
||||
int i;
|
||||
struct msi_desc *entry;
|
||||
struct pci_dev *pdev;
|
||||
struct irq_data *irqd = irq_get_irq_data(virq);
|
||||
struct msi_desc *desc;
|
||||
|
||||
if (WARN_ON_ONCE(!dev_is_pci(dev)))
|
||||
if (!irqd)
|
||||
return;
|
||||
|
||||
pdev = to_pci_dev(dev);
|
||||
desc = irq_data_get_msi_desc(irqd);
|
||||
if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev)))
|
||||
return;
|
||||
|
||||
for_each_pci_msi_entry(entry, pdev) {
|
||||
if (entry->irq) {
|
||||
for (i = 0; i < entry->nvec_used; i++) {
|
||||
hv_teardown_msi_irq_common(pdev, entry, entry->irq + i);
|
||||
irq_domain_free_irqs(entry->irq + i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -329,7 +308,7 @@ static struct irq_chip hv_pci_msi_controller = {
|
||||
};
|
||||
|
||||
static struct msi_domain_ops pci_msi_domain_ops = {
|
||||
.domain_free_irqs = hv_msi_domain_free_irqs,
|
||||
.msi_free = hv_msi_free_irq,
|
||||
.msi_prepare = pci_msi_prepare,
|
||||
};
|
||||
|
||||
|
||||
@@ -289,12 +289,6 @@ struct x86_platform_ops {
|
||||
struct x86_hyper_runtime hyper;
|
||||
};
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
struct x86_msi_ops {
|
||||
void (*restore_msi_irqs)(struct pci_dev *dev);
|
||||
};
|
||||
|
||||
struct x86_apic_ops {
|
||||
unsigned int (*io_apic_read) (unsigned int apic, unsigned int reg);
|
||||
void (*restore)(void);
|
||||
|
||||
@@ -57,6 +57,14 @@ static inline bool __init xen_x2apic_para_available(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
#ifdef CONFIG_XEN_PV_DOM0
|
||||
bool xen_initdom_restore_msi(struct pci_dev *dev);
|
||||
#else
|
||||
static inline bool xen_initdom_restore_msi(struct pci_dev *dev) { return true; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
void xen_arch_register_cpu(int num);
|
||||
void xen_arch_unregister_cpu(int num);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/irq_remapping.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
struct irq_domain *x86_pci_msi_default_domain __ro_after_init;
|
||||
|
||||
@@ -159,11 +160,8 @@ static struct irq_chip pci_msi_controller = {
|
||||
int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
|
||||
msi_alloc_info_t *arg)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct msi_desc *desc = first_pci_msi_entry(pdev);
|
||||
|
||||
init_irq_alloc_info(arg, NULL);
|
||||
if (desc->msi_attrib.is_msix) {
|
||||
if (to_pci_dev(dev)->msix_enabled) {
|
||||
arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX;
|
||||
} else {
|
||||
arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI;
|
||||
@@ -345,3 +343,8 @@ void dmar_free_hwirq(int irq)
|
||||
irq_domain_free_irqs(irq, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool arch_restore_msi_irqs(struct pci_dev *dev)
|
||||
{
|
||||
return xen_initdom_restore_msi(dev);
|
||||
}
|
||||
|
||||
@@ -145,18 +145,6 @@ struct x86_platform_ops x86_platform __ro_after_init = {
|
||||
|
||||
EXPORT_SYMBOL_GPL(x86_platform);
|
||||
|
||||
#if defined(CONFIG_PCI_MSI)
|
||||
struct x86_msi_ops x86_msi __ro_after_init = {
|
||||
.restore_msi_irqs = default_restore_msi_irqs,
|
||||
};
|
||||
|
||||
/* MSI arch specific hooks */
|
||||
void arch_restore_msi_irqs(struct pci_dev *dev)
|
||||
{
|
||||
x86_msi.restore_msi_irqs(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct x86_apic_ops x86_apic_ops __ro_after_init = {
|
||||
.io_apic_read = native_io_apic_read,
|
||||
.restore = native_restore_boot_irq_mode,
|
||||
|
||||
@@ -184,7 +184,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
if (ret)
|
||||
goto error;
|
||||
i = 0;
|
||||
for_each_pci_msi_entry(msidesc, dev) {
|
||||
msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
|
||||
(type == PCI_CAP_ID_MSI) ? nvec : 1,
|
||||
(type == PCI_CAP_ID_MSIX) ?
|
||||
@@ -235,7 +235,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
if (type == PCI_CAP_ID_MSI && nvec > 1)
|
||||
return 1;
|
||||
|
||||
for_each_pci_msi_entry(msidesc, dev) {
|
||||
msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
pirq = xen_allocate_pirq_msi(dev, msidesc);
|
||||
if (pirq < 0) {
|
||||
irq = -ENODEV;
|
||||
@@ -270,7 +270,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
int ret = 0;
|
||||
struct msi_desc *msidesc;
|
||||
|
||||
for_each_pci_msi_entry(msidesc, dev) {
|
||||
msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_NOTASSOCIATED) {
|
||||
struct physdev_map_pirq map_irq;
|
||||
domid_t domid;
|
||||
|
||||
@@ -306,7 +306,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
return -EINVAL;
|
||||
|
||||
map_irq.table_base = pci_resource_start(dev, bir);
|
||||
map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
|
||||
map_irq.entry_nr = msidesc->msi_index;
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
@@ -351,10 +351,13 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
|
||||
bool xen_initdom_restore_msi(struct pci_dev *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!xen_initial_domain())
|
||||
return true;
|
||||
|
||||
if (pci_seg_supported) {
|
||||
struct physdev_pci_device restore_ext;
|
||||
|
||||
@@ -375,10 +378,10 @@ static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
|
||||
ret = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore);
|
||||
WARN(ret && ret != -ENOSYS, "restore_msi -> %d\n", ret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else /* CONFIG_XEN_PV_DOM0 */
|
||||
#define xen_initdom_setup_msi_irqs NULL
|
||||
#define xen_initdom_restore_msi_irqs NULL
|
||||
#endif /* !CONFIG_XEN_PV_DOM0 */
|
||||
|
||||
static void xen_teardown_msi_irqs(struct pci_dev *dev)
|
||||
@@ -386,19 +389,15 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
|
||||
struct msi_desc *msidesc;
|
||||
int i;
|
||||
|
||||
for_each_pci_msi_entry(msidesc, dev) {
|
||||
if (msidesc->irq) {
|
||||
for (i = 0; i < msidesc->nvec_used; i++)
|
||||
xen_destroy_irq(msidesc->irq + i);
|
||||
}
|
||||
msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_ASSOCIATED) {
|
||||
for (i = 0; i < msidesc->nvec_used; i++)
|
||||
xen_destroy_irq(msidesc->irq + i);
|
||||
}
|
||||
}
|
||||
|
||||
static void xen_pv_teardown_msi_irqs(struct pci_dev *dev)
|
||||
{
|
||||
struct msi_desc *msidesc = first_pci_msi_entry(dev);
|
||||
|
||||
if (msidesc->msi_attrib.is_msix)
|
||||
if (dev->msix_enabled)
|
||||
xen_pci_frontend_disable_msix(dev);
|
||||
else
|
||||
xen_pci_frontend_disable_msi(dev);
|
||||
@@ -414,10 +413,7 @@ static int xen_msi_domain_alloc_irqs(struct irq_domain *domain,
|
||||
if (WARN_ON_ONCE(!dev_is_pci(dev)))
|
||||
return -EINVAL;
|
||||
|
||||
if (first_msi_entry(dev)->msi_attrib.is_msix)
|
||||
type = PCI_CAP_ID_MSIX;
|
||||
else
|
||||
type = PCI_CAP_ID_MSI;
|
||||
type = to_pci_dev(dev)->msix_enabled ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI;
|
||||
|
||||
return xen_msi_ops.setup_msi_irqs(to_pci_dev(dev), nvec, type);
|
||||
}
|
||||
@@ -466,12 +462,10 @@ static __init struct irq_domain *xen_create_pci_msi_domain(void)
|
||||
static __init void xen_setup_pci_msi(void)
|
||||
{
|
||||
if (xen_pv_domain()) {
|
||||
if (xen_initial_domain()) {
|
||||
if (xen_initial_domain())
|
||||
xen_msi_ops.setup_msi_irqs = xen_initdom_setup_msi_irqs;
|
||||
x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs;
|
||||
} else {
|
||||
else
|
||||
xen_msi_ops.setup_msi_irqs = xen_setup_msi_irqs;
|
||||
}
|
||||
xen_msi_ops.teardown_msi_irqs = xen_pv_teardown_msi_irqs;
|
||||
pci_msi_ignore_mask = 1;
|
||||
} else if (xen_hvm_domain()) {
|
||||
|
||||
@@ -87,8 +87,15 @@ static int fch_misc_setup(struct apd_private_data *pdata)
|
||||
if (ret < 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (!acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, &obj))
|
||||
clk_data->is_rv = obj->integer.value;
|
||||
if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {
|
||||
clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,
|
||||
GFP_KERNEL);
|
||||
|
||||
strcpy(clk_data->name, obj->string.pointer);
|
||||
} else {
|
||||
/* Set default name to mclk if entry missing in firmware */
|
||||
clk_data->name = "mclk";
|
||||
}
|
||||
|
||||
list_for_each_entry(rentry, &resource_list, node) {
|
||||
clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,
|
||||
|
||||
@@ -2872,10 +2872,6 @@ void device_initialize(struct device *dev)
|
||||
INIT_LIST_HEAD(&dev->devres_head);
|
||||
device_pm_init(dev);
|
||||
set_dev_node(dev, NUMA_NO_NODE);
|
||||
#ifdef CONFIG_GENERIC_MSI_IRQ
|
||||
raw_spin_lock_init(&dev->msi_lock);
|
||||
INIT_LIST_HEAD(&dev->msi_list);
|
||||
#endif
|
||||
INIT_LIST_HEAD(&dev->links.consumers);
|
||||
INIT_LIST_HEAD(&dev->links.suppliers);
|
||||
INIT_LIST_HEAD(&dev->links.defer_sync);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
struct platform_msi_priv_data {
|
||||
struct device *dev;
|
||||
void *host_data;
|
||||
const struct attribute_group **msi_irq_groups;
|
||||
msi_alloc_info_t arg;
|
||||
irq_write_msi_msg_t write_msg;
|
||||
int devid;
|
||||
@@ -39,11 +38,9 @@ static DEFINE_IDA(platform_msi_devid_ida);
|
||||
*/
|
||||
static irq_hw_number_t platform_msi_calc_hwirq(struct msi_desc *desc)
|
||||
{
|
||||
u32 devid;
|
||||
u32 devid = desc->dev->msi.data->platform_data->devid;
|
||||
|
||||
devid = desc->platform.msi_priv_data->devid;
|
||||
|
||||
return (devid << (32 - DEV_ID_SHIFT)) | desc->platform.msi_index;
|
||||
return (devid << (32 - DEV_ID_SHIFT)) | desc->msi_index;
|
||||
}
|
||||
|
||||
static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
|
||||
@@ -86,11 +83,8 @@ static void platform_msi_update_dom_ops(struct msi_domain_info *info)
|
||||
static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
|
||||
{
|
||||
struct msi_desc *desc = irq_data_get_msi_desc(data);
|
||||
struct platform_msi_priv_data *priv_data;
|
||||
|
||||
priv_data = desc->platform.msi_priv_data;
|
||||
|
||||
priv_data->write_msg(desc, msg);
|
||||
desc->dev->msi.data->platform_data->write_msg(desc, msg);
|
||||
}
|
||||
|
||||
static void platform_msi_update_chip_ops(struct msi_domain_info *info)
|
||||
@@ -113,62 +107,6 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
|
||||
info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
|
||||
}
|
||||
|
||||
static void platform_msi_free_descs(struct device *dev, int base, int nvec)
|
||||
{
|
||||
struct msi_desc *desc, *tmp;
|
||||
|
||||
list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
|
||||
if (desc->platform.msi_index >= base &&
|
||||
desc->platform.msi_index < (base + nvec)) {
|
||||
list_del(&desc->list);
|
||||
free_msi_entry(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int platform_msi_alloc_descs_with_irq(struct device *dev, int virq,
|
||||
int nvec,
|
||||
struct platform_msi_priv_data *data)
|
||||
|
||||
{
|
||||
struct msi_desc *desc;
|
||||
int i, base = 0;
|
||||
|
||||
if (!list_empty(dev_to_msi_list(dev))) {
|
||||
desc = list_last_entry(dev_to_msi_list(dev),
|
||||
struct msi_desc, list);
|
||||
base = desc->platform.msi_index + 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < nvec; i++) {
|
||||
desc = alloc_msi_entry(dev, 1, NULL);
|
||||
if (!desc)
|
||||
break;
|
||||
|
||||
desc->platform.msi_priv_data = data;
|
||||
desc->platform.msi_index = base + i;
|
||||
desc->irq = virq ? virq + i : 0;
|
||||
|
||||
list_add_tail(&desc->list, dev_to_msi_list(dev));
|
||||
}
|
||||
|
||||
if (i != nvec) {
|
||||
/* Clean up the mess */
|
||||
platform_msi_free_descs(dev, base, nvec);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int platform_msi_alloc_descs(struct device *dev, int nvec,
|
||||
struct platform_msi_priv_data *data)
|
||||
|
||||
{
|
||||
return platform_msi_alloc_descs_with_irq(dev, 0, nvec, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* platform_msi_create_irq_domain - Create a platform MSI interrupt domain
|
||||
* @fwnode: Optional fwnode of the interrupt controller
|
||||
@@ -191,6 +129,8 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
|
||||
platform_msi_update_dom_ops(info);
|
||||
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
|
||||
platform_msi_update_chip_ops(info);
|
||||
info->flags |= MSI_FLAG_DEV_SYSFS | MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS |
|
||||
MSI_FLAG_FREE_MSI_DESCS;
|
||||
|
||||
domain = msi_create_irq_domain(fwnode, info, parent);
|
||||
if (domain)
|
||||
@@ -199,49 +139,57 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
|
||||
return domain;
|
||||
}
|
||||
|
||||
static struct platform_msi_priv_data *
|
||||
platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
|
||||
irq_write_msi_msg_t write_msi_msg)
|
||||
static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
|
||||
irq_write_msi_msg_t write_msi_msg)
|
||||
{
|
||||
struct platform_msi_priv_data *datap;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Limit the number of interrupts to 2048 per device. Should we
|
||||
* need to bump this up, DEV_ID_SHIFT should be adjusted
|
||||
* accordingly (which would impact the max number of MSI
|
||||
* capable devices).
|
||||
*/
|
||||
if (!dev->msi_domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (!dev->msi.domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
|
||||
if (dev->msi.domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
|
||||
dev_err(dev, "Incompatible msi_domain, giving up\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Already had a helping of MSI? Greed... */
|
||||
if (!list_empty(dev_to_msi_list(dev)))
|
||||
return ERR_PTR(-EBUSY);
|
||||
err = msi_setup_device_data(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Already initialized? */
|
||||
if (dev->msi.data->platform_data)
|
||||
return -EBUSY;
|
||||
|
||||
datap = kzalloc(sizeof(*datap), GFP_KERNEL);
|
||||
if (!datap)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return -ENOMEM;
|
||||
|
||||
datap->devid = ida_simple_get(&platform_msi_devid_ida,
|
||||
0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
|
||||
if (datap->devid < 0) {
|
||||
int err = datap->devid;
|
||||
err = datap->devid;
|
||||
kfree(datap);
|
||||
return ERR_PTR(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
datap->write_msg = write_msi_msg;
|
||||
datap->dev = dev;
|
||||
|
||||
return datap;
|
||||
dev->msi.data->platform_data = datap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void platform_msi_free_priv_data(struct platform_msi_priv_data *data)
|
||||
static void platform_msi_free_priv_data(struct device *dev)
|
||||
{
|
||||
struct platform_msi_priv_data *data = dev->msi.data->platform_data;
|
||||
|
||||
dev->msi.data->platform_data = NULL;
|
||||
ida_simple_remove(&platform_msi_devid_ida, data->devid);
|
||||
kfree(data);
|
||||
}
|
||||
@@ -258,35 +206,15 @@ static void platform_msi_free_priv_data(struct platform_msi_priv_data *data)
|
||||
int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
|
||||
irq_write_msi_msg_t write_msi_msg)
|
||||
{
|
||||
struct platform_msi_priv_data *priv_data;
|
||||
int err;
|
||||
|
||||
priv_data = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
|
||||
if (IS_ERR(priv_data))
|
||||
return PTR_ERR(priv_data);
|
||||
|
||||
err = platform_msi_alloc_descs(dev, nvec, priv_data);
|
||||
err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
|
||||
if (err)
|
||||
goto out_free_priv_data;
|
||||
return err;
|
||||
|
||||
err = msi_domain_alloc_irqs(dev->msi_domain, dev, nvec);
|
||||
err = msi_domain_alloc_irqs(dev->msi.domain, dev, nvec);
|
||||
if (err)
|
||||
goto out_free_desc;
|
||||
|
||||
priv_data->msi_irq_groups = msi_populate_sysfs(dev);
|
||||
if (IS_ERR(priv_data->msi_irq_groups)) {
|
||||
err = PTR_ERR(priv_data->msi_irq_groups);
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_irqs:
|
||||
msi_domain_free_irqs(dev->msi_domain, dev);
|
||||
out_free_desc:
|
||||
platform_msi_free_descs(dev, 0, nvec);
|
||||
out_free_priv_data:
|
||||
platform_msi_free_priv_data(priv_data);
|
||||
platform_msi_free_priv_data(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -298,16 +226,8 @@ EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);
|
||||
*/
|
||||
void platform_msi_domain_free_irqs(struct device *dev)
|
||||
{
|
||||
if (!list_empty(dev_to_msi_list(dev))) {
|
||||
struct msi_desc *desc;
|
||||
|
||||
desc = first_msi_entry(dev);
|
||||
msi_destroy_sysfs(dev, desc->platform.msi_priv_data->msi_irq_groups);
|
||||
platform_msi_free_priv_data(desc->platform.msi_priv_data);
|
||||
}
|
||||
|
||||
msi_domain_free_irqs(dev->msi_domain, dev);
|
||||
platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
|
||||
msi_domain_free_irqs(dev->msi.domain, dev);
|
||||
platform_msi_free_priv_data(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
|
||||
|
||||
@@ -316,17 +236,20 @@ EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
|
||||
* a platform-msi domain
|
||||
* @domain: The platform-msi domain
|
||||
*
|
||||
* Returns the private data provided when calling
|
||||
* platform_msi_create_device_domain.
|
||||
* Return: The private data provided when calling
|
||||
* platform_msi_create_device_domain().
|
||||
*/
|
||||
void *platform_msi_get_host_data(struct irq_domain *domain)
|
||||
{
|
||||
struct platform_msi_priv_data *data = domain->host_data;
|
||||
|
||||
return data->host_data;
|
||||
}
|
||||
|
||||
static struct lock_class_key platform_device_msi_lock_class;
|
||||
|
||||
/**
|
||||
* __platform_msi_create_device_domain - Create a platform-msi domain
|
||||
* __platform_msi_create_device_domain - Create a platform-msi device domain
|
||||
*
|
||||
* @dev: The device generating the MSIs
|
||||
* @nvec: The number of MSIs that need to be allocated
|
||||
@@ -335,7 +258,11 @@ void *platform_msi_get_host_data(struct irq_domain *domain)
|
||||
* @ops: The hierarchy domain operations to use
|
||||
* @host_data: Private data associated to this domain
|
||||
*
|
||||
* Returns an irqdomain for @nvec interrupts
|
||||
* Return: An irqdomain for @nvec interrupts on success, NULL in case of error.
|
||||
*
|
||||
* This is for interrupt domains which stack on a platform-msi domain
|
||||
* created by platform_msi_create_irq_domain(). @dev->msi.domain points to
|
||||
* that platform-msi domain which is the parent for the new domain.
|
||||
*/
|
||||
struct irq_domain *
|
||||
__platform_msi_create_device_domain(struct device *dev,
|
||||
@@ -349,12 +276,20 @@ __platform_msi_create_device_domain(struct device *dev,
|
||||
struct irq_domain *domain;
|
||||
int err;
|
||||
|
||||
data = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
|
||||
if (IS_ERR(data))
|
||||
err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
|
||||
if (err)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Use a separate lock class for the MSI descriptor mutex on
|
||||
* platform MSI device domains because the descriptor mutex nests
|
||||
* into the domain mutex. See alloc/free below.
|
||||
*/
|
||||
lockdep_set_class(&dev->msi.data->mutex, &platform_device_msi_lock_class);
|
||||
|
||||
data = dev->msi.data->platform_data;
|
||||
data->host_data = host_data;
|
||||
domain = irq_domain_create_hierarchy(dev->msi_domain, 0,
|
||||
domain = irq_domain_create_hierarchy(dev->msi.domain, 0,
|
||||
is_tree ? 0 : nvec,
|
||||
dev->fwnode, ops, data);
|
||||
if (!domain)
|
||||
@@ -370,61 +305,46 @@ __platform_msi_create_device_domain(struct device *dev,
|
||||
free_domain:
|
||||
irq_domain_remove(domain);
|
||||
free_priv:
|
||||
platform_msi_free_priv_data(data);
|
||||
platform_msi_free_priv_data(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* platform_msi_domain_free - Free interrupts associated with a platform-msi
|
||||
* domain
|
||||
* platform_msi_device_domain_free - Free interrupts associated with a platform-msi
|
||||
* device domain
|
||||
*
|
||||
* @domain: The platform-msi domain
|
||||
* @domain: The platform-msi device domain
|
||||
* @virq: The base irq from which to perform the free operation
|
||||
* @nvec: How many interrupts to free from @virq
|
||||
* @nr_irqs: How many interrupts to free from @virq
|
||||
*/
|
||||
void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nvec)
|
||||
void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs)
|
||||
{
|
||||
struct platform_msi_priv_data *data = domain->host_data;
|
||||
struct msi_desc *desc, *tmp;
|
||||
for_each_msi_entry_safe(desc, tmp, data->dev) {
|
||||
if (WARN_ON(!desc->irq || desc->nvec_used != 1))
|
||||
return;
|
||||
if (!(desc->irq >= virq && desc->irq < (virq + nvec)))
|
||||
continue;
|
||||
|
||||
irq_domain_free_irqs_common(domain, desc->irq, 1);
|
||||
list_del(&desc->list);
|
||||
free_msi_entry(desc);
|
||||
}
|
||||
msi_lock_descs(data->dev);
|
||||
irq_domain_free_irqs_common(domain, virq, nr_irqs);
|
||||
msi_free_msi_descs_range(data->dev, MSI_DESC_ALL, virq, virq + nr_irqs - 1);
|
||||
msi_unlock_descs(data->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* platform_msi_domain_alloc - Allocate interrupts associated with
|
||||
* a platform-msi domain
|
||||
* platform_msi_device_domain_alloc - Allocate interrupts associated with
|
||||
* a platform-msi device domain
|
||||
*
|
||||
* @domain: The platform-msi domain
|
||||
* @domain: The platform-msi device domain
|
||||
* @virq: The base irq from which to perform the allocate operation
|
||||
* @nr_irqs: How many interrupts to free from @virq
|
||||
* @nr_irqs: How many interrupts to allocate from @virq
|
||||
*
|
||||
* Return 0 on success, or an error code on failure. Must be called
|
||||
* with irq_domain_mutex held (which can only be done as part of a
|
||||
* top-level interrupt allocation).
|
||||
*/
|
||||
int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs)
|
||||
int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs)
|
||||
{
|
||||
struct platform_msi_priv_data *data = domain->host_data;
|
||||
int err;
|
||||
struct device *dev = data->dev;
|
||||
|
||||
err = platform_msi_alloc_descs_with_irq(data->dev, virq, nr_irqs, data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = msi_domain_populate_irqs(domain->parent, data->dev,
|
||||
virq, nr_irqs, &data->arg);
|
||||
if (err)
|
||||
platform_msi_domain_free(domain, virq, nr_irqs);
|
||||
|
||||
return err;
|
||||
return msi_domain_populate_irqs(domain->parent, dev, virq, nr_irqs, &data->arg);
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ static void msg_conf(void *priv, int errno)
|
||||
schedule_work(&iu->work);
|
||||
}
|
||||
|
||||
static int send_usr_msg(struct rtrs_clt *rtrs, int dir,
|
||||
static int send_usr_msg(struct rtrs_clt_sess *rtrs, int dir,
|
||||
struct rnbd_iu *iu, struct kvec *vec,
|
||||
size_t len, struct scatterlist *sg, unsigned int sg_len,
|
||||
void (*conf)(struct work_struct *work),
|
||||
@@ -1010,7 +1010,7 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
|
||||
struct request *rq,
|
||||
struct rnbd_iu *iu)
|
||||
{
|
||||
struct rtrs_clt *rtrs = dev->sess->rtrs;
|
||||
struct rtrs_clt_sess *rtrs = dev->sess->rtrs;
|
||||
struct rtrs_permit *permit = iu->permit;
|
||||
struct rnbd_msg_io msg;
|
||||
struct rtrs_clt_req_ops req_ops;
|
||||
|
||||
@@ -75,7 +75,7 @@ struct rnbd_cpu_qlist {
|
||||
|
||||
struct rnbd_clt_session {
|
||||
struct list_head list;
|
||||
struct rtrs_clt *rtrs;
|
||||
struct rtrs_clt_sess *rtrs;
|
||||
wait_queue_head_t rtrs_waitq;
|
||||
bool rtrs_ready;
|
||||
struct rnbd_cpu_qlist __percpu
|
||||
|
||||
@@ -263,15 +263,15 @@ out:
|
||||
kfree(srv_sess);
|
||||
}
|
||||
|
||||
static int create_sess(struct rtrs_srv *rtrs)
|
||||
static int create_sess(struct rtrs_srv_sess *rtrs)
|
||||
{
|
||||
struct rnbd_srv_session *srv_sess;
|
||||
char sessname[NAME_MAX];
|
||||
char pathname[NAME_MAX];
|
||||
int err;
|
||||
|
||||
err = rtrs_srv_get_sess_name(rtrs, sessname, sizeof(sessname));
|
||||
err = rtrs_srv_get_path_name(rtrs, pathname, sizeof(pathname));
|
||||
if (err) {
|
||||
pr_err("rtrs_srv_get_sess_name(%s): %d\n", sessname, err);
|
||||
pr_err("rtrs_srv_get_path_name(%s): %d\n", pathname, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -284,8 +284,8 @@ static int create_sess(struct rtrs_srv *rtrs)
|
||||
offsetof(struct rnbd_dev_blk_io, bio),
|
||||
BIOSET_NEED_BVECS);
|
||||
if (err) {
|
||||
pr_err("Allocating srv_session for session %s failed\n",
|
||||
sessname);
|
||||
pr_err("Allocating srv_session for path %s failed\n",
|
||||
pathname);
|
||||
kfree(srv_sess);
|
||||
return err;
|
||||
}
|
||||
@@ -298,14 +298,14 @@ static int create_sess(struct rtrs_srv *rtrs)
|
||||
mutex_unlock(&sess_lock);
|
||||
|
||||
srv_sess->rtrs = rtrs;
|
||||
strscpy(srv_sess->sessname, sessname, sizeof(srv_sess->sessname));
|
||||
strscpy(srv_sess->sessname, pathname, sizeof(srv_sess->sessname));
|
||||
|
||||
rtrs_srv_set_sess_priv(rtrs, srv_sess);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rnbd_srv_link_ev(struct rtrs_srv *rtrs,
|
||||
static int rnbd_srv_link_ev(struct rtrs_srv_sess *rtrs,
|
||||
enum rtrs_srv_link_ev ev, void *priv)
|
||||
{
|
||||
struct rnbd_srv_session *srv_sess = priv;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
struct rnbd_srv_session {
|
||||
/* Entry inside global sess_list */
|
||||
struct list_head list;
|
||||
struct rtrs_srv *rtrs;
|
||||
struct rtrs_srv_sess *rtrs;
|
||||
char sessname[NAME_MAX];
|
||||
int queue_depth;
|
||||
struct bio_set sess_bio_set;
|
||||
|
||||
@@ -400,7 +400,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
|
||||
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
|
||||
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
|
||||
struct fsl_mc_io *mc_io = mc_dev->mc_io;
|
||||
struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
|
||||
int irq = mc_dev->irqs[0]->virq;
|
||||
|
||||
dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
|
||||
irq_num, smp_processor_id());
|
||||
@@ -409,7 +409,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
mutex_lock(&mc_bus->scan_mutex);
|
||||
if (!msi_desc || msi_desc->irq != (u32)irq_num)
|
||||
if (irq != (u32)irq_num)
|
||||
goto out;
|
||||
|
||||
status = 0;
|
||||
@@ -521,7 +521,7 @@ static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
|
||||
* function that programs the MSI physically in the device
|
||||
*/
|
||||
error = devm_request_threaded_irq(&mc_dev->dev,
|
||||
irq->msi_desc->irq,
|
||||
irq->virq,
|
||||
dprc_irq0_handler,
|
||||
dprc_irq0_handler_thread,
|
||||
IRQF_NO_SUSPEND | IRQF_ONESHOT,
|
||||
@@ -771,7 +771,7 @@ static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
|
||||
|
||||
(void)disable_dprc_irq(mc_dev);
|
||||
|
||||
devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
|
||||
devm_free_irq(&mc_dev->dev, irq->virq, &mc_dev->dev);
|
||||
|
||||
fsl_mc_free_irqs(mc_dev);
|
||||
}
|
||||
|
||||
@@ -350,7 +350,6 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
|
||||
unsigned int irq_count)
|
||||
{
|
||||
unsigned int i;
|
||||
struct msi_desc *msi_desc;
|
||||
struct fsl_mc_device_irq *irq_resources;
|
||||
struct fsl_mc_device_irq *mc_dev_irq;
|
||||
int error;
|
||||
@@ -388,16 +387,12 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
|
||||
mc_dev_irq->resource.type = res_pool->type;
|
||||
mc_dev_irq->resource.data = mc_dev_irq;
|
||||
mc_dev_irq->resource.parent_pool = res_pool;
|
||||
mc_dev_irq->virq = msi_get_virq(&mc_bus_dev->dev, i);
|
||||
mc_dev_irq->resource.id = mc_dev_irq->virq;
|
||||
INIT_LIST_HEAD(&mc_dev_irq->resource.node);
|
||||
list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
|
||||
}
|
||||
|
||||
for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
|
||||
mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
|
||||
mc_dev_irq->msi_desc = msi_desc;
|
||||
mc_dev_irq->resource.id = msi_desc->irq;
|
||||
}
|
||||
|
||||
res_pool->max_count = irq_count;
|
||||
res_pool->free_count = irq_count;
|
||||
mc_bus->irq_resources = irq_resources;
|
||||
|
||||
@@ -29,7 +29,7 @@ static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
|
||||
* Make the base hwirq value for ICID*10000 so it is readable
|
||||
* as a decimal value in /proc/interrupts.
|
||||
*/
|
||||
return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
|
||||
return (irq_hw_number_t)(desc->msi_index + (dev->icid * 10000));
|
||||
}
|
||||
|
||||
static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
|
||||
@@ -58,11 +58,11 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
|
||||
}
|
||||
|
||||
static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
|
||||
struct fsl_mc_device_irq *mc_dev_irq)
|
||||
struct fsl_mc_device_irq *mc_dev_irq,
|
||||
struct msi_desc *msi_desc)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
|
||||
struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
|
||||
struct dprc_irq_cfg irq_cfg;
|
||||
|
||||
/*
|
||||
@@ -122,14 +122,14 @@ static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
|
||||
struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
|
||||
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
|
||||
struct fsl_mc_device_irq *mc_dev_irq =
|
||||
&mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
|
||||
&mc_bus->irq_resources[msi_desc->msi_index];
|
||||
|
||||
msi_desc->msg = *msg;
|
||||
|
||||
/*
|
||||
* Program the MSI (paddr, value) pair in the device:
|
||||
*/
|
||||
__fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
|
||||
__fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq, msi_desc);
|
||||
}
|
||||
|
||||
static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
|
||||
@@ -170,6 +170,7 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
|
||||
fsl_mc_msi_update_dom_ops(info);
|
||||
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
|
||||
fsl_mc_msi_update_chip_ops(info);
|
||||
info->flags |= MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | MSI_FLAG_FREE_MSI_DESCS;
|
||||
|
||||
domain = msi_create_irq_domain(fwnode, info, parent);
|
||||
if (domain)
|
||||
@@ -210,61 +211,21 @@ struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
|
||||
return msi_domain;
|
||||
}
|
||||
|
||||
static void fsl_mc_msi_free_descs(struct device *dev)
|
||||
{
|
||||
struct msi_desc *desc, *tmp;
|
||||
|
||||
list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
|
||||
list_del(&desc->list);
|
||||
free_msi_entry(desc);
|
||||
}
|
||||
}
|
||||
|
||||
static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
|
||||
|
||||
{
|
||||
unsigned int i;
|
||||
int error;
|
||||
struct msi_desc *msi_desc;
|
||||
|
||||
for (i = 0; i < irq_count; i++) {
|
||||
msi_desc = alloc_msi_entry(dev, 1, NULL);
|
||||
if (!msi_desc) {
|
||||
dev_err(dev, "Failed to allocate msi entry\n");
|
||||
error = -ENOMEM;
|
||||
goto cleanup_msi_descs;
|
||||
}
|
||||
|
||||
msi_desc->fsl_mc.msi_index = i;
|
||||
INIT_LIST_HEAD(&msi_desc->list);
|
||||
list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_msi_descs:
|
||||
fsl_mc_msi_free_descs(dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
|
||||
unsigned int irq_count)
|
||||
int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count)
|
||||
{
|
||||
struct irq_domain *msi_domain;
|
||||
int error;
|
||||
|
||||
if (!list_empty(dev_to_msi_list(dev)))
|
||||
msi_domain = dev_get_msi_domain(dev);
|
||||
if (!msi_domain)
|
||||
return -EINVAL;
|
||||
|
||||
error = fsl_mc_msi_alloc_descs(dev, irq_count);
|
||||
if (error < 0)
|
||||
error = msi_setup_device_data(dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
msi_domain = dev_get_msi_domain(dev);
|
||||
if (!msi_domain) {
|
||||
error = -EINVAL;
|
||||
goto cleanup_msi_descs;
|
||||
}
|
||||
if (msi_first_desc(dev, MSI_DESC_ALL))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* NOTE: Calling this function will trigger the invocation of the
|
||||
@@ -272,15 +233,8 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
|
||||
*/
|
||||
error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
|
||||
|
||||
if (error) {
|
||||
if (error)
|
||||
dev_err(dev, "Failed to allocate IRQs\n");
|
||||
goto cleanup_msi_descs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_msi_descs:
|
||||
fsl_mc_msi_free_descs(dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -293,9 +247,4 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev)
|
||||
return;
|
||||
|
||||
msi_domain_free_irqs(msi_domain, dev);
|
||||
|
||||
if (list_empty(dev_to_msi_list(dev)))
|
||||
return;
|
||||
|
||||
fsl_mc_msi_free_descs(dev);
|
||||
}
|
||||
|
||||
@@ -169,6 +169,14 @@ config COMMON_CLK_CDCE706
|
||||
help
|
||||
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
|
||||
|
||||
config COMMON_CLK_TPS68470
|
||||
tristate "Clock Driver for TI TPS68470 PMIC"
|
||||
depends on I2C
|
||||
depends on INTEL_SKL_INT3472 || COMPILE_TEST
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports the clocks provided by the TPS68470 PMIC.
|
||||
|
||||
config COMMON_CLK_CDCE925
|
||||
tristate "Clock driver for TI CDCE913/925/937/949 devices"
|
||||
depends on I2C
|
||||
@@ -221,6 +229,13 @@ config COMMON_CLK_GEMINI
|
||||
This driver supports the SoC clocks on the Cortina Systems Gemini
|
||||
platform, also known as SL3516 or CS3516.
|
||||
|
||||
config COMMON_CLK_LAN966X
|
||||
bool "Generic Clock Controller driver for LAN966X SoC"
|
||||
help
|
||||
This driver provides support for Generic Clock Controller(GCK) on
|
||||
LAN966X SoC. GCK generates and supplies clock to various peripherals
|
||||
within the SoC.
|
||||
|
||||
config COMMON_CLK_ASPEED
|
||||
bool "Clock driver for Aspeed BMC SoCs"
|
||||
depends on ARCH_ASPEED || COMPILE_TEST
|
||||
@@ -339,16 +354,6 @@ config COMMON_CLK_STM32MP157
|
||||
help
|
||||
Support for stm32mp157 SoC family clocks
|
||||
|
||||
config COMMON_CLK_STM32MP157_SCMI
|
||||
bool "stm32mp157 Clock driver with Trusted Firmware"
|
||||
depends on COMMON_CLK_STM32MP157
|
||||
select COMMON_CLK_SCMI
|
||||
select ARM_SCMI_PROTOCOL
|
||||
default y
|
||||
help
|
||||
Support for stm32mp157 SoC family clocks with Trusted Firmware using
|
||||
SCMI protocol.
|
||||
|
||||
config COMMON_CLK_STM32F
|
||||
def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746)
|
||||
help
|
||||
@@ -418,6 +423,7 @@ source "drivers/clk/sunxi-ng/Kconfig"
|
||||
source "drivers/clk/tegra/Kconfig"
|
||||
source "drivers/clk/ti/Kconfig"
|
||||
source "drivers/clk/uniphier/Kconfig"
|
||||
source "drivers/clk/visconti/Kconfig"
|
||||
source "drivers/clk/x86/Kconfig"
|
||||
source "drivers/clk/xilinx/Kconfig"
|
||||
source "drivers/clk/zynqmp/Kconfig"
|
||||
|
||||
@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
|
||||
obj-$(CONFIG_COMMON_CLK_K210) += clk-k210.o
|
||||
obj-$(CONFIG_LMK04832) += clk-lmk04832.o
|
||||
obj-$(CONFIG_COMMON_CLK_LAN966X) += clk-lan966x.o
|
||||
obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o
|
||||
@@ -63,6 +64,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
|
||||
obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
|
||||
obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
|
||||
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
|
||||
obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o
|
||||
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
|
||||
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
|
||||
obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o
|
||||
@@ -111,12 +113,13 @@ obj-y += sprd/
|
||||
obj-$(CONFIG_ARCH_STI) += st/
|
||||
obj-$(CONFIG_SOC_STARFIVE) += starfive/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/
|
||||
obj-y += sunxi-ng/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-y += ti/
|
||||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||
obj-y += versatile/
|
||||
obj-$(CONFIG_COMMON_CLK_VISCONTI) += visconti/
|
||||
ifeq ($(CONFIG_COMMON_CLK), y)
|
||||
obj-$(CONFIG_X86) += x86/
|
||||
endif
|
||||
|
||||
@@ -522,14 +522,6 @@ static struct clk_hw *bm1880_clk_register_pll(struct bm1880_pll_hw_clock *pll_cl
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void bm1880_clk_unregister_pll(struct clk_hw *hw)
|
||||
{
|
||||
struct bm1880_pll_hw_clock *pll_hw = to_bm1880_pll_clk(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(pll_hw);
|
||||
}
|
||||
|
||||
static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,
|
||||
int num_clks,
|
||||
struct bm1880_clock_data *data)
|
||||
@@ -555,7 +547,7 @@ static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,
|
||||
|
||||
err_clk:
|
||||
while (i--)
|
||||
bm1880_clk_unregister_pll(data->hw_data.hws[clks[i].pll.id]);
|
||||
clk_hw_unregister(data->hw_data.hws[clks[i].pll.id]);
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
@@ -695,14 +687,6 @@ static struct clk_hw *bm1880_clk_register_div(struct bm1880_div_hw_clock *div_cl
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void bm1880_clk_unregister_div(struct clk_hw *hw)
|
||||
{
|
||||
struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(div_hw);
|
||||
}
|
||||
|
||||
static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,
|
||||
int num_clks,
|
||||
struct bm1880_clock_data *data)
|
||||
@@ -729,7 +713,7 @@ static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,
|
||||
|
||||
err_clk:
|
||||
while (i--)
|
||||
bm1880_clk_unregister_div(data->hw_data.hws[clks[i].div.id]);
|
||||
clk_hw_unregister(data->hw_data.hws[clks[i].div.id]);
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
@@ -222,3 +223,37 @@ void clk_hw_unregister_gate(struct clk_hw *hw)
|
||||
kfree(gate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_gate);
|
||||
|
||||
static void devm_clk_hw_release_gate(struct device *dev, void *res)
|
||||
{
|
||||
clk_hw_unregister_gate(*(struct clk_hw **)res);
|
||||
}
|
||||
|
||||
struct clk_hw *__devm_clk_hw_register_gate(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 bit_idx,
|
||||
u8 clk_gate_flags, spinlock_t *lock)
|
||||
{
|
||||
struct clk_hw **ptr, *hw;
|
||||
|
||||
ptr = devres_alloc(devm_clk_hw_release_gate, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hw = __clk_hw_register_gate(dev, np, name, parent_name, parent_hw,
|
||||
parent_data, flags, reg, bit_idx,
|
||||
clk_gate_flags, lock);
|
||||
|
||||
if (!IS_ERR(hw)) {
|
||||
*ptr = hw;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_clk_hw_register_gate);
|
||||
|
||||
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(gemini_clk_lock);
|
||||
#define PCI_DLL_TAP_SEL_MASK 0x1f
|
||||
|
||||
/**
|
||||
* struct gemini_data_data - Gemini gated clocks
|
||||
* struct gemini_gate_data - Gemini gated clocks
|
||||
* @bit_idx: the bit used to gate this clock in the clock register
|
||||
* @name: the clock name
|
||||
* @parent_name: the name of the parent clock
|
||||
|
||||
293
drivers/clk/clk-lan966x.c
Normal file
293
drivers/clk/clk-lan966x.c
Normal file
@@ -0,0 +1,293 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Microchip LAN966x SoC Clock driver.
|
||||
*
|
||||
* Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
|
||||
*
|
||||
* Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/microchip,lan966x.h>
|
||||
|
||||
#define GCK_ENA BIT(0)
|
||||
#define GCK_SRC_SEL GENMASK(9, 8)
|
||||
#define GCK_PRESCALER GENMASK(23, 16)
|
||||
|
||||
#define DIV_MAX 255
|
||||
|
||||
static const char *clk_names[N_CLOCKS] = {
|
||||
"qspi0", "qspi1", "qspi2", "sdmmc0",
|
||||
"pi", "mcan0", "mcan1", "flexcom0",
|
||||
"flexcom1", "flexcom2", "flexcom3",
|
||||
"flexcom4", "timer1", "usb_refclk",
|
||||
};
|
||||
|
||||
struct lan966x_gck {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
};
|
||||
#define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw)
|
||||
|
||||
static const struct clk_parent_data lan966x_gck_pdata[] = {
|
||||
{ .fw_name = "cpu", },
|
||||
{ .fw_name = "ddr", },
|
||||
{ .fw_name = "sys", },
|
||||
};
|
||||
|
||||
static struct clk_init_data init = {
|
||||
.parent_data = lan966x_gck_pdata,
|
||||
.num_parents = ARRAY_SIZE(lan966x_gck_pdata),
|
||||
};
|
||||
|
||||
struct clk_gate_soc_desc {
|
||||
const char *name;
|
||||
int bit_idx;
|
||||
};
|
||||
|
||||
static const struct clk_gate_soc_desc clk_gate_desc[] = {
|
||||
{ "uhphs", 11 },
|
||||
{ "udphs", 10 },
|
||||
{ "mcramc", 9 },
|
||||
{ "hmatrix", 8 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(clk_gate_lock);
|
||||
static void __iomem *base;
|
||||
|
||||
static int lan966x_gck_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
val |= GCK_ENA;
|
||||
writel(val, gck->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lan966x_gck_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
val &= ~GCK_ENA;
|
||||
writel(val, gck->reg);
|
||||
}
|
||||
|
||||
static int lan966x_gck_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 div, val = readl(gck->reg);
|
||||
|
||||
if (rate == 0 || parent_rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set Prescalar */
|
||||
div = parent_rate / rate;
|
||||
val &= ~GCK_PRESCALER;
|
||||
val |= FIELD_PREP(GCK_PRESCALER, (div - 1));
|
||||
writel(val, gck->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long lan966x_gck_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
unsigned int div;
|
||||
|
||||
if (rate == 0 || *parent_rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (rate >= *parent_rate)
|
||||
return *parent_rate;
|
||||
|
||||
div = DIV_ROUND_CLOSEST(*parent_rate, rate);
|
||||
|
||||
return *parent_rate / div;
|
||||
}
|
||||
|
||||
static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 div, val = readl(gck->reg);
|
||||
|
||||
div = FIELD_GET(GCK_PRESCALER, val);
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static int lan966x_gck_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_hw *parent;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
|
||||
parent = clk_hw_get_parent_by_index(hw, i);
|
||||
if (!parent)
|
||||
continue;
|
||||
|
||||
/* Allowed prescaler divider range is 0-255 */
|
||||
if (clk_hw_get_rate(parent) / req->rate <= DIV_MAX) {
|
||||
req->best_parent_hw = parent;
|
||||
req->best_parent_rate = clk_hw_get_rate(parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static u8 lan966x_gck_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
return FIELD_GET(GCK_SRC_SEL, val);
|
||||
}
|
||||
|
||||
static int lan966x_gck_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct lan966x_gck *gck = to_lan966x_gck(hw);
|
||||
u32 val = readl(gck->reg);
|
||||
|
||||
val &= ~GCK_SRC_SEL;
|
||||
val |= FIELD_PREP(GCK_SRC_SEL, index);
|
||||
writel(val, gck->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops lan966x_gck_ops = {
|
||||
.enable = lan966x_gck_enable,
|
||||
.disable = lan966x_gck_disable,
|
||||
.set_rate = lan966x_gck_set_rate,
|
||||
.round_rate = lan966x_gck_round_rate,
|
||||
.recalc_rate = lan966x_gck_recalc_rate,
|
||||
.determine_rate = lan966x_gck_determine_rate,
|
||||
.set_parent = lan966x_gck_set_parent,
|
||||
.get_parent = lan966x_gck_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
|
||||
{
|
||||
struct lan966x_gck *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
priv->reg = base + (i * 4);
|
||||
priv->hw.init = &init;
|
||||
ret = devm_clk_hw_register(dev, &priv->hw);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return &priv->hw;
|
||||
};
|
||||
|
||||
static int lan966x_gate_clk_register(struct device *dev,
|
||||
struct clk_hw_onecell_data *hw_data,
|
||||
void __iomem *gate_base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = GCK_GATE_UHPHS; i < N_CLOCKS; ++i) {
|
||||
int idx = i - GCK_GATE_UHPHS;
|
||||
|
||||
hw_data->hws[i] =
|
||||
devm_clk_hw_register_gate(dev, clk_gate_desc[idx].name,
|
||||
"lan966x", 0, base,
|
||||
clk_gate_desc[idx].bit_idx,
|
||||
0, &clk_gate_lock);
|
||||
|
||||
if (IS_ERR(hw_data->hws[i]))
|
||||
return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
|
||||
"failed to register %s clock\n",
|
||||
clk_gate_desc[idx].name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lan966x_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_hw_onecell_data *hw_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *gate_base;
|
||||
struct resource *res;
|
||||
int i, ret;
|
||||
|
||||
hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, N_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
if (!hw_data)
|
||||
return -ENOMEM;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
init.ops = &lan966x_gck_ops;
|
||||
|
||||
hw_data->num = GCK_GATE_UHPHS;
|
||||
|
||||
for (i = 0; i < GCK_GATE_UHPHS; i++) {
|
||||
init.name = clk_names[i];
|
||||
hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
|
||||
if (IS_ERR(hw_data->hws[i])) {
|
||||
dev_err(dev, "failed to register %s clock\n",
|
||||
init.name);
|
||||
return PTR_ERR(hw_data->hws[i]);
|
||||
}
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (res) {
|
||||
gate_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(gate_base))
|
||||
return PTR_ERR(gate_base);
|
||||
|
||||
hw_data->num = N_CLOCKS;
|
||||
|
||||
ret = lan966x_gate_clk_register(dev, hw_data, gate_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id lan966x_clk_dt_ids[] = {
|
||||
{ .compatible = "microchip,lan966x-gck", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);
|
||||
|
||||
static struct platform_driver lan966x_clk_driver = {
|
||||
.probe = lan966x_clk_probe,
|
||||
.driver = {
|
||||
.name = "lan966x-clk",
|
||||
.of_match_table = lan966x_clk_dt_ids,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(lan966x_clk_driver);
|
||||
|
||||
MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>");
|
||||
MODULE_DESCRIPTION("LAN966X clock driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
};
|
||||
|
||||
static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
|
||||
@@ -211,7 +210,6 @@ static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
};
|
||||
|
||||
static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
|
||||
@@ -286,7 +284,6 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
};
|
||||
|
||||
static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
|
||||
@@ -364,7 +361,6 @@ static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
|
||||
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
|
||||
{ STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" },
|
||||
};
|
||||
|
||||
|
||||
@@ -2253,8 +2253,6 @@ static int stm32_rcc_reset_init(struct device *dev, void __iomem *base,
|
||||
const struct stm32_rcc_match_data *data = match->data;
|
||||
struct stm32_reset_data *reset_data = NULL;
|
||||
|
||||
data = match->data;
|
||||
|
||||
reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
|
||||
if (!reset_data)
|
||||
return -ENOMEM;
|
||||
|
||||
261
drivers/clk/clk-tps68470.c
Normal file
261
drivers/clk/clk-tps68470.c
Normal file
@@ -0,0 +1,261 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Clock driver for TPS68470 PMIC
|
||||
*
|
||||
* Copyright (c) 2021 Red Hat Inc.
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Hans de Goede <hdegoede@redhat.com>
|
||||
* Zaikuo Wang <zaikuo.wang@intel.com>
|
||||
* Tianshu Qiu <tian.shu.qiu@intel.com>
|
||||
* Jian Xu Zheng <jian.xu.zheng@intel.com>
|
||||
* Yuning Pu <yuning.pu@intel.com>
|
||||
* Antti Laakso <antti.laakso@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/tps68470.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/tps68470.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define TPS68470_CLK_NAME "tps68470-clk"
|
||||
|
||||
#define to_tps68470_clkdata(clkd) \
|
||||
container_of(clkd, struct tps68470_clkdata, clkout_hw)
|
||||
|
||||
static struct tps68470_clkout_freqs {
|
||||
unsigned long freq;
|
||||
unsigned int xtaldiv;
|
||||
unsigned int plldiv;
|
||||
unsigned int postdiv;
|
||||
unsigned int buckdiv;
|
||||
unsigned int boostdiv;
|
||||
} clk_freqs[] = {
|
||||
/*
|
||||
* The PLL is used to multiply the crystal oscillator
|
||||
* frequency range of 3 MHz to 27 MHz by a programmable
|
||||
* factor of F = (M/N)*(1/P) such that the output
|
||||
* available at the HCLK_A or HCLK_B pins are in the range
|
||||
* of 4 MHz to 64 MHz in increments of 0.1 MHz.
|
||||
*
|
||||
* hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv)
|
||||
*
|
||||
* PLL_REF_CLK should be as close as possible to 100kHz
|
||||
* PLL_REF_CLK = input clk / XTALDIV[7:0] + 30)
|
||||
*
|
||||
* PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320))
|
||||
*
|
||||
* BOOST should be as close as possible to 2Mhz
|
||||
* BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) *
|
||||
*
|
||||
* BUCK should be as close as possible to 5.2Mhz
|
||||
* BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5)
|
||||
*
|
||||
* osc_in xtaldiv plldiv postdiv hclk_#
|
||||
* 20Mhz 170 32 1 19.2Mhz
|
||||
* 20Mhz 170 40 1 20Mhz
|
||||
* 20Mhz 170 80 1 24Mhz
|
||||
*/
|
||||
{ 19200000, 170, 32, 1, 2, 3 },
|
||||
{ 20000000, 170, 40, 1, 3, 4 },
|
||||
{ 24000000, 170, 80, 1, 4, 8 },
|
||||
};
|
||||
|
||||
struct tps68470_clkdata {
|
||||
struct clk_hw clkout_hw;
|
||||
struct regmap *regmap;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
||||
static int tps68470_clk_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
int val;
|
||||
|
||||
if (regmap_read(clkdata->regmap, TPS68470_REG_PLLCTL, &val))
|
||||
return 0;
|
||||
|
||||
return val & TPS68470_PLL_EN_MASK;
|
||||
}
|
||||
|
||||
static int tps68470_clk_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1,
|
||||
(TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_A_SHIFT) |
|
||||
(TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_B_SHIFT));
|
||||
|
||||
regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL,
|
||||
TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK);
|
||||
|
||||
/*
|
||||
* The PLLCTL reg lock bit is set by the PMIC after approx. 4ms and
|
||||
* does not indicate a true lock, so just wait 4 ms.
|
||||
*/
|
||||
usleep_range(4000, 5000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tps68470_clk_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
|
||||
/* Disable clock first ... */
|
||||
regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, 0);
|
||||
|
||||
/* ... and then tri-state the clock outputs. */
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, 0);
|
||||
}
|
||||
|
||||
static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
|
||||
return clkdata->rate;
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns the index of the clk_freqs[] cfg with the closest rate for
|
||||
* use in tps68470_clk_round_rate(). tps68470_clk_set_rate() checks that
|
||||
* the rate of the returned cfg is an exact match.
|
||||
*/
|
||||
static unsigned int tps68470_clk_cfg_lookup(unsigned long rate)
|
||||
{
|
||||
long diff, best_diff = LONG_MAX;
|
||||
unsigned int i, best_idx = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) {
|
||||
diff = clk_freqs[i].freq - rate;
|
||||
if (diff == 0)
|
||||
return i;
|
||||
|
||||
diff = abs(diff);
|
||||
if (diff < best_diff) {
|
||||
best_diff = diff;
|
||||
best_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
return best_idx;
|
||||
}
|
||||
|
||||
static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
unsigned int idx = tps68470_clk_cfg_lookup(rate);
|
||||
|
||||
return clk_freqs[idx].freq;
|
||||
}
|
||||
|
||||
static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
|
||||
unsigned int idx = tps68470_clk_cfg_lookup(rate);
|
||||
|
||||
if (rate != clk_freqs[idx].freq)
|
||||
return -EINVAL;
|
||||
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, clk_freqs[idx].boostdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, clk_freqs[idx].buckdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, clk_freqs[idx].xtaldiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, clk_freqs[idx].plldiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, clk_freqs[idx].postdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV2, clk_freqs[idx].postdiv);
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA);
|
||||
|
||||
regmap_write(clkdata->regmap, TPS68470_REG_PLLCTL,
|
||||
TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT |
|
||||
TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT);
|
||||
|
||||
clkdata->rate = rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops tps68470_clk_ops = {
|
||||
.is_prepared = tps68470_clk_is_prepared,
|
||||
.prepare = tps68470_clk_prepare,
|
||||
.unprepare = tps68470_clk_unprepare,
|
||||
.recalc_rate = tps68470_clk_recalc_rate,
|
||||
.round_rate = tps68470_clk_round_rate,
|
||||
.set_rate = tps68470_clk_set_rate,
|
||||
};
|
||||
|
||||
static int tps68470_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct clk_init_data tps68470_clk_initdata = {
|
||||
.name = TPS68470_CLK_NAME,
|
||||
.ops = &tps68470_clk_ops,
|
||||
/* Changing the dividers when the PLL is on is not allowed */
|
||||
.flags = CLK_SET_RATE_GATE,
|
||||
};
|
||||
struct tps68470_clkdata *tps68470_clkdata;
|
||||
int ret;
|
||||
|
||||
tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata),
|
||||
GFP_KERNEL);
|
||||
if (!tps68470_clkdata)
|
||||
return -ENOMEM;
|
||||
|
||||
tps68470_clkdata->regmap = dev_get_drvdata(pdev->dev.parent);
|
||||
tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata;
|
||||
|
||||
/* Set initial rate */
|
||||
tps68470_clk_set_rate(&tps68470_clkdata->clkout_hw, clk_freqs[0].freq, 0);
|
||||
|
||||
ret = devm_clk_hw_register(&pdev->dev, &tps68470_clkdata->clkout_hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_clk_hw_register_clkdev(&pdev->dev, &tps68470_clkdata->clkout_hw,
|
||||
TPS68470_CLK_NAME, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pdata) {
|
||||
ret = devm_clk_hw_register_clkdev(&pdev->dev,
|
||||
&tps68470_clkdata->clkout_hw,
|
||||
pdata->consumer_con_id,
|
||||
pdata->consumer_dev_name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver tps68470_clk_driver = {
|
||||
.driver = {
|
||||
.name = TPS68470_CLK_NAME,
|
||||
},
|
||||
.probe = tps68470_clk_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers
|
||||
* registering before the drivers for the camera-sensors which use them bind.
|
||||
* subsys_initcall() ensures this when the drivers are builtin.
|
||||
*/
|
||||
static int __init tps68470_clk_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps68470_clk_driver);
|
||||
}
|
||||
subsys_initcall(tps68470_clk_init);
|
||||
|
||||
static void __exit tps68470_clk_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps68470_clk_driver);
|
||||
}
|
||||
module_exit(tps68470_clk_exit);
|
||||
|
||||
MODULE_ALIAS("platform:tps68470-clk");
|
||||
MODULE_DESCRIPTION("clock driver for TPS68470 pmic");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -426,19 +426,20 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
|
||||
|
||||
if (entry->hw) {
|
||||
parent = entry->hw->core;
|
||||
/*
|
||||
* We have a direct reference but it isn't registered yet?
|
||||
* Orphan it and let clk_reparent() update the orphan status
|
||||
* when the parent is registered.
|
||||
*/
|
||||
if (!parent)
|
||||
parent = ERR_PTR(-EPROBE_DEFER);
|
||||
} else {
|
||||
parent = clk_core_get(core, index);
|
||||
if (PTR_ERR(parent) == -ENOENT && entry->name)
|
||||
parent = clk_core_lookup(entry->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a direct reference but it isn't registered yet?
|
||||
* Orphan it and let clk_reparent() update the orphan status
|
||||
* when the parent is registered.
|
||||
*/
|
||||
if (!parent)
|
||||
parent = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
/* Only cache it if it's not an error */
|
||||
if (!IS_ERR(parent))
|
||||
entry->core = parent;
|
||||
@@ -3044,7 +3045,9 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
|
||||
{
|
||||
struct clk_core *child;
|
||||
|
||||
clk_pm_runtime_get(c);
|
||||
clk_summary_show_one(s, c, level);
|
||||
clk_pm_runtime_put(c);
|
||||
|
||||
hlist_for_each_entry(child, &c->children, child_node)
|
||||
clk_summary_show_subtree(s, child, level + 1);
|
||||
@@ -3296,6 +3299,42 @@ static int current_parent_show(struct seq_file *s, void *data)
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(current_parent);
|
||||
|
||||
#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
|
||||
static ssize_t current_parent_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
struct clk_core *core = s->private;
|
||||
struct clk_core *parent;
|
||||
u8 idx;
|
||||
int err;
|
||||
|
||||
err = kstrtou8_from_user(ubuf, count, 0, &idx);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
parent = clk_core_get_parent_by_index(core, idx);
|
||||
if (!parent)
|
||||
return -ENOENT;
|
||||
|
||||
clk_prepare_lock();
|
||||
err = clk_core_set_parent_nolock(core, parent);
|
||||
clk_prepare_unlock();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations current_parent_rw_fops = {
|
||||
.open = current_parent_open,
|
||||
.write = current_parent_write,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int clk_duty_cycle_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct clk_core *core = s->private;
|
||||
@@ -3361,8 +3400,12 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
|
||||
#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
|
||||
debugfs_create_file("clk_prepare_enable", 0644, root, core,
|
||||
&clk_prepare_enable_fops);
|
||||
#endif
|
||||
|
||||
if (core->num_parents > 1)
|
||||
debugfs_create_file("clk_parent", 0644, root, core,
|
||||
¤t_parent_rw_fops);
|
||||
else
|
||||
#endif
|
||||
if (core->num_parents > 0)
|
||||
debugfs_create_file("clk_parent", 0444, root, core,
|
||||
¤t_parent_fops);
|
||||
@@ -3422,6 +3465,24 @@ static int __init clk_debug_init(void)
|
||||
{
|
||||
struct clk_core *core;
|
||||
|
||||
#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
|
||||
pr_warn("\n");
|
||||
pr_warn("********************************************************************\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** WRITEABLE clk DebugFS SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** This means that this kernel is built to expose clk operations **\n");
|
||||
pr_warn("** such as parent or rate setting, enabling, disabling, etc. **\n");
|
||||
pr_warn("** to userspace, which may compromise security on your system. **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** If you see this message and you are not debugging the **\n");
|
||||
pr_warn("** kernel, report this immediately to your vendor! **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("********************************************************************\n");
|
||||
#endif
|
||||
|
||||
rootdir = debugfs_create_dir("clk", NULL);
|
||||
|
||||
debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
|
||||
@@ -3493,9 +3554,6 @@ static int __clk_core_init(struct clk_core *core)
|
||||
unsigned long rate;
|
||||
int phase;
|
||||
|
||||
if (!core)
|
||||
return -EINVAL;
|
||||
|
||||
clk_prepare_lock();
|
||||
|
||||
/*
|
||||
|
||||
@@ -277,9 +277,9 @@ static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audi
|
||||
|
||||
static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
|
||||
|
||||
static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
|
||||
"sys_pll1_200m", "audio_pll2_out", "vpu_pll",
|
||||
"sys_pll1_80m", };
|
||||
static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy",
|
||||
"sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m",
|
||||
"dummy", "sys_pll1_80m", };
|
||||
static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
|
||||
"sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
|
||||
"video_pll1_out", "osc_32k", };
|
||||
|
||||
@@ -700,7 +700,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
|
||||
hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", ccm_base + 0x4620, 0);
|
||||
hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0);
|
||||
hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "ipg_root", ccm_base + 0x4650, 0);
|
||||
hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "audio_ahb", ccm_base + 0x4650, 0);
|
||||
|
||||
hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core",
|
||||
hws[IMX8MP_CLK_A53_CORE]->clk,
|
||||
|
||||
@@ -559,6 +559,7 @@ static struct platform_driver imx8ulp_clk_driver = {
|
||||
.probe = imx8ulp_clk_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = imx8ulp_clk_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -8,20 +8,19 @@
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
/**
|
||||
* pll v1
|
||||
*
|
||||
* @clk_hw clock source
|
||||
* @parent the parent clock name
|
||||
* @base base address of pll registers
|
||||
*
|
||||
* PLL clock version 1, found on i.MX1/21/25/27/31/35
|
||||
*/
|
||||
|
||||
#define MFN_BITS (10)
|
||||
#define MFN_SIGN (BIT(MFN_BITS - 1))
|
||||
#define MFN_MASK (MFN_SIGN - 1)
|
||||
|
||||
/**
|
||||
* struct clk_pllv1 - IMX PLLv1 clock descriptor
|
||||
*
|
||||
* @hw: clock source
|
||||
* @base: base address of pll registers
|
||||
* @type: type of IMX_PLLV1
|
||||
*
|
||||
* PLL clock version 1, found on i.MX1/21/25/27/31/35
|
||||
*/
|
||||
struct clk_pllv1 {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
|
||||
@@ -247,7 +247,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
div = rate / parent_rate;
|
||||
temp64 = (u64) (rate - div * parent_rate);
|
||||
temp64 *= mfd;
|
||||
do_div(temp64, parent_rate);
|
||||
temp64 = div64_ul(temp64, parent_rate);
|
||||
mfn = temp64;
|
||||
|
||||
temp64 = (u64)parent_rate;
|
||||
@@ -277,7 +277,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
div = rate / parent_rate;
|
||||
temp64 = (u64) (rate - div * parent_rate);
|
||||
temp64 *= mfd;
|
||||
do_div(temp64, parent_rate);
|
||||
temp64 = div64_ul(temp64, parent_rate);
|
||||
mfn = temp64;
|
||||
|
||||
val = readl_relaxed(pll->base);
|
||||
@@ -334,7 +334,7 @@ static struct clk_pllv3_vf610_mf clk_pllv3_vf610_rate_to_mf(
|
||||
/* rate = parent_rate * (mfi + mfn/mfd) */
|
||||
temp64 = rate - parent_rate * mf.mfi;
|
||||
temp64 *= mf.mfd;
|
||||
do_div(temp64, parent_rate);
|
||||
temp64 = div64_ul(temp64, parent_rate);
|
||||
mf.mfn = temp64;
|
||||
}
|
||||
|
||||
|
||||
@@ -313,6 +313,16 @@ static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = {
|
||||
.parents = { JZ4760_CLK_H2CLK, },
|
||||
.gate = { CGU_REG_CLKGR0, 21 },
|
||||
},
|
||||
[JZ4760_CLK_MDMA] = {
|
||||
"mdma", CGU_CLK_GATE,
|
||||
.parents = { JZ4760_CLK_HCLK, },
|
||||
.gate = { CGU_REG_CLKGR0, 25 },
|
||||
},
|
||||
[JZ4760_CLK_BDMA] = {
|
||||
"bdma", CGU_CLK_GATE,
|
||||
.parents = { JZ4760_CLK_HCLK, },
|
||||
.gate = { CGU_REG_CLKGR1, 0 },
|
||||
},
|
||||
[JZ4760_CLK_I2C0] = {
|
||||
"i2c0", CGU_CLK_GATE,
|
||||
.parents = { JZ4760_CLK_EXT, },
|
||||
|
||||
@@ -329,6 +329,11 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
|
||||
.parents = { JZ4770_CLK_H2CLK, },
|
||||
.gate = { CGU_REG_CLKGR0, 21 },
|
||||
},
|
||||
[JZ4770_CLK_BDMA] = {
|
||||
"bdma", CGU_CLK_GATE,
|
||||
.parents = { JZ4770_CLK_H2CLK, },
|
||||
.gate = { CGU_REG_CLKGR1, 0 },
|
||||
},
|
||||
[JZ4770_CLK_I2C0] = {
|
||||
"i2c0", CGU_CLK_GATE,
|
||||
.parents = { JZ4770_CLK_EXT, },
|
||||
|
||||
@@ -344,6 +344,23 @@ config COMMON_CLK_MT7629_HIFSYS
|
||||
This driver supports MediaTek MT7629 HIFSYS clocks providing
|
||||
to PCI-E and USB.
|
||||
|
||||
config COMMON_CLK_MT7986
|
||||
bool "Clock driver for MediaTek MT7986"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK
|
||||
help
|
||||
This driver supports MediaTek MT7986 basic clocks and clocks
|
||||
required for various peripherals found on MediaTek.
|
||||
|
||||
config COMMON_CLK_MT7986_ETHSYS
|
||||
bool "Clock driver for MediaTek MT7986 ETHSYS"
|
||||
depends on COMMON_CLK_MT7986
|
||||
default COMMON_CLK_MT7986
|
||||
help
|
||||
This driver adds support for clocks for Ethernet and SGMII
|
||||
required on MediaTek MT7986 SoC.
|
||||
|
||||
config COMMON_CLK_MT8135
|
||||
bool "Clock driver for MediaTek MT8135"
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
|
||||
@@ -46,6 +46,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o
|
||||
|
||||
@@ -16,28 +16,24 @@
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
|
||||
static u32 mtk_get_clockgating(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 val;
|
||||
|
||||
regmap_read(cg->regmap, cg->sta_ofs, &val);
|
||||
|
||||
val &= BIT(cg->bit);
|
||||
return val & BIT(cg->bit);
|
||||
}
|
||||
|
||||
return val == 0;
|
||||
static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
|
||||
{
|
||||
return mtk_get_clockgating(hw) == 0;
|
||||
}
|
||||
|
||||
static int mtk_cg_bit_is_set(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 val;
|
||||
|
||||
regmap_read(cg->regmap, cg->sta_ofs, &val);
|
||||
|
||||
val &= BIT(cg->bit);
|
||||
|
||||
return val != 0;
|
||||
return mtk_get_clockgating(hw) != 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_set_bit(struct clk_hw *hw)
|
||||
@@ -57,17 +53,15 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
|
||||
static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 cgbit = BIT(cg->bit);
|
||||
|
||||
regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
|
||||
regmap_set_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 cgbit = BIT(cg->bit);
|
||||
|
||||
regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
|
||||
regmap_clear_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static int mtk_cg_enable(struct clk_hw *hw)
|
||||
|
||||
100
drivers/clk/mediatek/clk-mt7986-apmixed.c
Normal file
100
drivers/clk/mediatek/clk-mt7986-apmixed.c
Normal file
@@ -0,0 +1,100 @@
|
||||
// SPDX-License-Identifier: GPL-1.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#define MT7986_PLL_FMAX (2500UL * MHZ)
|
||||
#define CON0_MT7986_RST_BAR BIT(27)
|
||||
|
||||
#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
|
||||
_div_table, _parent_name) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, .flags = _flags, \
|
||||
.rst_bar_mask = CON0_MT7986_RST_BAR, .fmax = MT7986_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, .div_table = _div_table, \
|
||||
.parent_name = _parent_name, \
|
||||
}
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
|
||||
_pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \
|
||||
PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \
|
||||
"clkxtal")
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, 0, 32,
|
||||
0x0200, 4, 0, 0x0204, 0),
|
||||
PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32,
|
||||
0x0210, 4, 0, 0x0214, 0),
|
||||
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32,
|
||||
0x0220, 4, 0, 0x0224, 0),
|
||||
PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x00000001, 0, 32,
|
||||
0x0230, 4, 0, 0x0234, 0),
|
||||
PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x00000001, 0,
|
||||
32, 0x0240, 4, 0, 0x0244, 0),
|
||||
PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x00000001, 0, 32,
|
||||
0x0250, 4, 0, 0x0254, 0),
|
||||
PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, 0x0260,
|
||||
4, 0, 0x0264, 0),
|
||||
PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32,
|
||||
0x0278, 4, 0, 0x027c, 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7986_apmixed[] = {
|
||||
{ .compatible = "mediatek,mt7986-apmixedsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt7986_apmixed_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r) {
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
goto free_apmixed_data;
|
||||
}
|
||||
return r;
|
||||
|
||||
free_apmixed_data:
|
||||
mtk_free_clk_data(clk_data);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt7986_apmixed_drv = {
|
||||
.probe = clk_mt7986_apmixed_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7986-apmixed",
|
||||
.of_match_table = of_match_clk_mt7986_apmixed,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_mt7986_apmixed_drv);
|
||||
132
drivers/clk/mediatek/clk-mt7986-eth.c
Normal file
132
drivers/clk/mediatek/clk-mt7986-eth.c
Normal file
@@ -0,0 +1,132 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs sgmii0_cg_regs = {
|
||||
.set_ofs = 0xe4,
|
||||
.clr_ofs = 0xe4,
|
||||
.sta_ofs = 0xe4,
|
||||
};
|
||||
|
||||
#define GATE_SGMII0(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &sgmii0_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate sgmii0_clks[] __initconst = {
|
||||
GATE_SGMII0(CLK_SGMII0_TX250M_EN, "sgmii0_tx250m_en", "top_xtal", 2),
|
||||
GATE_SGMII0(CLK_SGMII0_RX250M_EN, "sgmii0_rx250m_en", "top_xtal", 3),
|
||||
GATE_SGMII0(CLK_SGMII0_CDR_REF, "sgmii0_cdr_ref", "top_xtal", 4),
|
||||
GATE_SGMII0(CLK_SGMII0_CDR_FB, "sgmii0_cdr_fb", "top_xtal", 5),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs sgmii1_cg_regs = {
|
||||
.set_ofs = 0xe4,
|
||||
.clr_ofs = 0xe4,
|
||||
.sta_ofs = 0xe4,
|
||||
};
|
||||
|
||||
#define GATE_SGMII1(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &sgmii1_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate sgmii1_clks[] __initconst = {
|
||||
GATE_SGMII1(CLK_SGMII1_TX250M_EN, "sgmii1_tx250m_en", "top_xtal", 2),
|
||||
GATE_SGMII1(CLK_SGMII1_RX250M_EN, "sgmii1_rx250m_en", "top_xtal", 3),
|
||||
GATE_SGMII1(CLK_SGMII1_CDR_REF, "sgmii1_cdr_ref", "top_xtal", 4),
|
||||
GATE_SGMII1(CLK_SGMII1_CDR_FB, "sgmii1_cdr_fb", "top_xtal", 5),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs eth_cg_regs = {
|
||||
.set_ofs = 0x30,
|
||||
.clr_ofs = 0x30,
|
||||
.sta_ofs = 0x30,
|
||||
};
|
||||
|
||||
#define GATE_ETH(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = ð_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate eth_clks[] __initconst = {
|
||||
GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x_sel", 6),
|
||||
GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m_sel", 7),
|
||||
GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m_sel", 8),
|
||||
GATE_ETH(CLK_ETH_WOCPU1_EN, "eth_wocpu1_en", "netsys_mcu_sel", 14),
|
||||
GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_mcu_sel", 15),
|
||||
};
|
||||
|
||||
static void __init mtk_sgmiisys_0_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks));
|
||||
|
||||
mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7986-sgmiisys_0",
|
||||
mtk_sgmiisys_0_init);
|
||||
|
||||
static void __init mtk_sgmiisys_1_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks));
|
||||
|
||||
mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7986-sgmiisys_1",
|
||||
mtk_sgmiisys_1_init);
|
||||
|
||||
static void __init mtk_ethsys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks));
|
||||
|
||||
mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys_ck", mtk_ethsys_init);
|
||||
224
drivers/clk/mediatek/clk-mt7986-infracfg.c
Normal file
224
drivers/clk/mediatek/clk-mt7986-infracfg.c
Normal file
@@ -0,0 +1,224 @@
|
||||
// SPDX-License-Identifier: GPL-1.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7986_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_factor infra_divs[] = {
|
||||
FACTOR(CLK_INFRA_SYSAXI_D2, "infra_sysaxi_d2", "sysaxi_sel", 1, 2),
|
||||
};
|
||||
|
||||
static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel",
|
||||
"uart_sel" };
|
||||
|
||||
static const char *const infra_spi_parents[] __initconst = { "i2c_sel",
|
||||
"spi_sel" };
|
||||
|
||||
static const char *const infra_pwm_bsel_parents[] __initconst = {
|
||||
"top_rtc_32p7k", "csw_f26m_sel", "infra_sysaxi_d2", "pwm_sel"
|
||||
};
|
||||
|
||||
static const char *const infra_pcie_parents[] __initconst = {
|
||||
"top_rtc_32p7k", "csw_f26m_sel", "top_xtal", "pextp_tl_ck_sel"
|
||||
};
|
||||
|
||||
static const struct mtk_mux infra_muxes[] = {
|
||||
/* MODULE_CLK_SEL_0 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel",
|
||||
infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel",
|
||||
infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel",
|
||||
infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel",
|
||||
infra_spi_parents, 0x0018, 0x0010, 0x0014, 4, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel",
|
||||
infra_spi_parents, 0x0018, 0x0010, 0x0014, 5, 1,
|
||||
-1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel",
|
||||
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 9,
|
||||
2, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel",
|
||||
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 11,
|
||||
2, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel",
|
||||
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13,
|
||||
2, -1, -1, -1),
|
||||
/* MODULE_CLK_SEL_1 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel",
|
||||
infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2,
|
||||
-1, -1, -1),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra0_cg_regs = {
|
||||
.set_ofs = 0x40,
|
||||
.clr_ofs = 0x44,
|
||||
.sta_ofs = 0x48,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra1_cg_regs = {
|
||||
.set_ofs = 0x50,
|
||||
.clr_ofs = 0x54,
|
||||
.sta_ofs = 0x58,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra2_cg_regs = {
|
||||
.set_ofs = 0x60,
|
||||
.clr_ofs = 0x64,
|
||||
.sta_ofs = 0x68,
|
||||
};
|
||||
|
||||
#define GATE_INFRA0(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra0_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA1(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra1_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA2(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra2_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] = {
|
||||
/* INFRA0 */
|
||||
GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_sysaxi_d2", 0),
|
||||
GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_sysaxi_d2", 1),
|
||||
GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2),
|
||||
GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3),
|
||||
GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4),
|
||||
GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi_sel", 6),
|
||||
GATE_INFRA0(CLK_INFRA_EIP97_CK, "infra_eip97", "eip_b_sel", 7),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi_sel", 8),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l_sel", 10),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys_sel", 11),
|
||||
GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner_sel", 13),
|
||||
GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel",
|
||||
14),
|
||||
GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_sysaxi_d2", 15),
|
||||
GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_sysaxi_d2", 16),
|
||||
GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_sysaxi_d2", 24),
|
||||
GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25),
|
||||
GATE_INFRA0(CLK_INFRA_TRNG_CK, "infra_trng", "sysaxi_sel", 26),
|
||||
/* INFRA1 */
|
||||
GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0),
|
||||
GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_sel", 1),
|
||||
GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2),
|
||||
GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3),
|
||||
GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4),
|
||||
GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x_sel", 8),
|
||||
GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_sel", 9),
|
||||
GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_sysaxi_d2",
|
||||
10),
|
||||
GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11),
|
||||
GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12),
|
||||
GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_sysaxi_d2",
|
||||
13),
|
||||
GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_sysaxi_d2",
|
||||
14),
|
||||
GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "top_rtc_32k", 15),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_416m_sel", 16),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_250m_sel",
|
||||
17),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi_sel",
|
||||
18),
|
||||
GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2",
|
||||
19),
|
||||
GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "csw_f26m_sel", 20),
|
||||
GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21),
|
||||
GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23),
|
||||
/* INFRA2 */
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi_sel", 0),
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "infra_sysaxi_d2",
|
||||
1),
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys_sel", 2),
|
||||
GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_sel", 3),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl_ck_sel", 12),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "top_xtal",
|
||||
13),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m_sel", 14),
|
||||
GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi_sel", 15),
|
||||
};
|
||||
|
||||
static int clk_mt7986_infracfg_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) +
|
||||
ARRAY_SIZE(infra_clks);
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(nr);
|
||||
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
|
||||
mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node,
|
||||
&mt7986_clk_lock, clk_data);
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r) {
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
goto free_infracfg_data;
|
||||
}
|
||||
return r;
|
||||
|
||||
free_infracfg_data:
|
||||
mtk_free_clk_data(clk_data);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7986_infracfg[] = {
|
||||
{ .compatible = "mediatek,mt7986-infracfg", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt7986_infracfg_drv = {
|
||||
.probe = clk_mt7986_infracfg_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7986-infracfg",
|
||||
.of_match_table = of_match_clk_mt7986_infracfg,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_mt7986_infracfg_drv);
|
||||
342
drivers/clk/mediatek/clk-mt7986-topckgen.c
Normal file
342
drivers/clk/mediatek/clk-mt7986-topckgen.c
Normal file
@@ -0,0 +1,342 @@
|
||||
// SPDX-License-Identifier: GPL-1.0
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7986-clk.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7986_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_clk top_fixed_clks[] = {
|
||||
FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000),
|
||||
FIXED_CLK(CLK_TOP_JTAG, "top_jtag", "clkxtal", 50000000),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_factor top_divs[] = {
|
||||
/* XTAL */
|
||||
FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2),
|
||||
FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250),
|
||||
FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220),
|
||||
/* MPLL */
|
||||
FACTOR(CLK_TOP_MPLL_D2, "top_mpll_d2", "mpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MPLL_D4, "top_mpll_d4", "mpll", 1, 4),
|
||||
FACTOR(CLK_TOP_MPLL_D8, "top_mpll_d8", "mpll", 1, 8),
|
||||
FACTOR(CLK_TOP_MPLL_D8_D2, "top_mpll_d8_d2", "mpll", 1, 16),
|
||||
FACTOR(CLK_TOP_MPLL_D3_D2, "top_mpll_d3_d2", "mpll", 1, 6),
|
||||
/* MMPLL */
|
||||
FACTOR(CLK_TOP_MMPLL_D2, "top_mmpll_d2", "mmpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MMPLL_D4, "top_mmpll_d4", "mmpll", 1, 4),
|
||||
FACTOR(CLK_TOP_MMPLL_D8, "top_mmpll_d8", "mmpll", 1, 8),
|
||||
FACTOR(CLK_TOP_MMPLL_D8_D2, "top_mmpll_d8_d2", "mmpll", 1, 16),
|
||||
FACTOR(CLK_TOP_MMPLL_D3_D8, "top_mmpll_d3_d8", "mmpll", 1, 24),
|
||||
FACTOR(CLK_TOP_MMPLL_U2PHY, "top_mmpll_u2phy", "mmpll", 1, 30),
|
||||
/* APLL2 */
|
||||
FACTOR(CLK_TOP_APLL2_D4, "top_apll2_d4", "apll2", 1, 4),
|
||||
/* NET1PLL */
|
||||
FACTOR(CLK_TOP_NET1PLL_D4, "top_net1pll_d4", "net1pll", 1, 4),
|
||||
FACTOR(CLK_TOP_NET1PLL_D5, "top_net1pll_d5", "net1pll", 1, 5),
|
||||
FACTOR(CLK_TOP_NET1PLL_D5_D2, "top_net1pll_d5_d2", "net1pll", 1, 10),
|
||||
FACTOR(CLK_TOP_NET1PLL_D5_D4, "top_net1pll_d5_d4", "net1pll", 1, 20),
|
||||
FACTOR(CLK_TOP_NET1PLL_D8_D2, "top_net1pll_d8_d2", "net1pll", 1, 16),
|
||||
FACTOR(CLK_TOP_NET1PLL_D8_D4, "top_net1pll_d8_d4", "net1pll", 1, 32),
|
||||
/* NET2PLL */
|
||||
FACTOR(CLK_TOP_NET2PLL_D4, "top_net2pll_d4", "net2pll", 1, 4),
|
||||
FACTOR(CLK_TOP_NET2PLL_D4_D2, "top_net2pll_d4_d2", "net2pll", 1, 8),
|
||||
FACTOR(CLK_TOP_NET2PLL_D3_D2, "top_net2pll_d3_d2", "net2pll", 1, 2),
|
||||
/* WEDMCUPLL */
|
||||
FACTOR(CLK_TOP_WEDMCUPLL_D5_D2, "top_wedmcupll_d5_d2", "wedmcupll", 1,
|
||||
10),
|
||||
};
|
||||
|
||||
static const char *const nfi1x_parents[] __initconst = { "top_xtal",
|
||||
"top_mmpll_d8",
|
||||
"top_net1pll_d8_d2",
|
||||
"top_net2pll_d3_d2",
|
||||
"top_mpll_d4",
|
||||
"top_mmpll_d8_d2",
|
||||
"top_wedmcupll_d5_d2",
|
||||
"top_mpll_d8" };
|
||||
|
||||
static const char *const spinfi_parents[] __initconst = {
|
||||
"top_xtal_d2", "top_xtal", "top_net1pll_d5_d4",
|
||||
"top_mpll_d4", "top_mmpll_d8_d2", "top_wedmcupll_d5_d2",
|
||||
"top_mmpll_d3_d8", "top_mpll_d8"
|
||||
};
|
||||
|
||||
static const char *const spi_parents[] __initconst = {
|
||||
"top_xtal", "top_mpll_d2", "top_mmpll_d8",
|
||||
"top_net1pll_d8_d2", "top_net2pll_d3_d2", "top_net1pll_d5_d4",
|
||||
"top_mpll_d4", "top_wedmcupll_d5_d2"
|
||||
};
|
||||
|
||||
static const char *const uart_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d8",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const pwm_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d8_d2", "top_net1pll_d5_d4", "top_mpll_d4"
|
||||
};
|
||||
|
||||
static const char *const i2c_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d4", "top_mpll_d4", "top_net1pll_d8_d4"
|
||||
};
|
||||
|
||||
static const char *const pextp_tl_ck_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d4", "top_net2pll_d4_d2", "top_rtc_32k"
|
||||
};
|
||||
|
||||
static const char *const emmc_250m_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d2"
|
||||
};
|
||||
|
||||
static const char *const emmc_416m_parents[] __initconst = { "top_xtal",
|
||||
"mpll" };
|
||||
|
||||
static const char *const f_26m_adc_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const dramc_md32_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d2" };
|
||||
|
||||
static const char *const sysaxi_parents[] __initconst = { "top_xtal",
|
||||
"top_net1pll_d8_d2",
|
||||
"top_net2pll_d4" };
|
||||
|
||||
static const char *const sysapb_parents[] __initconst = { "top_xtal",
|
||||
"top_mpll_d3_d2",
|
||||
"top_net2pll_d4_d2" };
|
||||
|
||||
static const char *const arm_db_main_parents[] __initconst = {
|
||||
"top_xtal", "top_net2pll_d3_d2"
|
||||
};
|
||||
|
||||
static const char *const arm_db_jtsel_parents[] __initconst = { "top_jtag",
|
||||
"top_xtal" };
|
||||
|
||||
static const char *const netsys_parents[] __initconst = { "top_xtal",
|
||||
"top_mmpll_d4" };
|
||||
|
||||
static const char *const netsys_500m_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5"
|
||||
};
|
||||
|
||||
static const char *const netsys_mcu_parents[] __initconst = {
|
||||
"top_xtal", "wedmcupll", "top_mmpll_d2", "top_net1pll_d4",
|
||||
"top_net1pll_d5"
|
||||
};
|
||||
|
||||
static const char *const netsys_2x_parents[] __initconst = {
|
||||
"top_xtal", "net2pll", "wedmcupll", "top_mmpll_d2"
|
||||
};
|
||||
|
||||
static const char *const sgm_325m_parents[] __initconst = { "top_xtal",
|
||||
"sgmpll" };
|
||||
|
||||
static const char *const sgm_reg_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d8_d4"
|
||||
};
|
||||
|
||||
static const char *const a1sys_parents[] __initconst = { "top_xtal",
|
||||
"top_apll2_d4" };
|
||||
|
||||
static const char *const conn_mcusys_parents[] __initconst = { "top_xtal",
|
||||
"top_mmpll_d2" };
|
||||
|
||||
static const char *const eip_b_parents[] __initconst = { "top_xtal",
|
||||
"net2pll" };
|
||||
|
||||
static const char *const aud_l_parents[] __initconst = { "top_xtal", "apll2",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const a_tuner_parents[] __initconst = { "top_xtal",
|
||||
"top_apll2_d4",
|
||||
"top_mpll_d8_d2" };
|
||||
|
||||
static const char *const u2u3_sys_parents[] __initconst = {
|
||||
"top_xtal", "top_net1pll_d5_d4"
|
||||
};
|
||||
|
||||
static const char *const da_u2_refsel_parents[] __initconst = {
|
||||
"top_xtal", "top_mmpll_u2phy"
|
||||
};
|
||||
|
||||
static const struct mtk_mux top_muxes[] = {
|
||||
/* CLK_CFG_0 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents,
|
||||
0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents,
|
||||
0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000,
|
||||
0x004, 0x008, 16, 3, 23, 0x1C0, 2),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents,
|
||||
0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3),
|
||||
/* CLK_CFG_1 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010,
|
||||
0x014, 0x018, 0, 2, 7, 0x1C0, 4),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010,
|
||||
0x014, 0x018, 8, 2, 15, 0x1C0, 5),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010,
|
||||
0x014, 0x018, 16, 2, 23, 0x1C0, 6),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel",
|
||||
pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2,
|
||||
31, 0x1C0, 7),
|
||||
/* CLK_CFG_2 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
|
||||
emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7,
|
||||
0x1C0, 8),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel",
|
||||
emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15,
|
||||
0x1C0, 9),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel",
|
||||
f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23,
|
||||
0x1C0, 10),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents,
|
||||
0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11),
|
||||
/* CLK_CFG_3 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel",
|
||||
dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7,
|
||||
0x1C0, 12),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents,
|
||||
0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents,
|
||||
0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel",
|
||||
arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1,
|
||||
31, 0x1C0, 15),
|
||||
/* CLK_CFG_4 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_JTSEL, "arm_db_jtsel",
|
||||
arm_db_jtsel_parents, 0x040, 0x044, 0x048, 0, 1, 7,
|
||||
0x1C0, 16),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents,
|
||||
0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel",
|
||||
netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1,
|
||||
23, 0x1C0, 18),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel",
|
||||
netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31,
|
||||
0x1C0, 19),
|
||||
/* CLK_CFG_5 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel",
|
||||
netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7,
|
||||
0x1C0, 20),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel",
|
||||
sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15,
|
||||
0x1C0, 21),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel",
|
||||
sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23,
|
||||
0x1C0, 22),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents,
|
||||
0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23),
|
||||
/* CLK_CFG_6 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel",
|
||||
conn_mcusys_parents, 0x060, 0x064, 0x068, 0, 1, 7,
|
||||
0x1C0, 24),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents,
|
||||
0x060, 0x064, 0x068, 8, 1, 15, 0x1C0, 25),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_PHY_SEL, "pcie_phy_sel",
|
||||
f_26m_adc_parents, 0x060, 0x064, 0x068, 16, 1, 23,
|
||||
0x1C0, 26),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel",
|
||||
f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31,
|
||||
0x1C0, 27),
|
||||
/* CLK_CFG_7 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel",
|
||||
f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7,
|
||||
0x1C0, 28),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents,
|
||||
0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel",
|
||||
a_tuner_parents, 0x070, 0x074, 0x078, 16, 2, 23,
|
||||
0x1C0, 30),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents,
|
||||
0x070, 0x074, 0x078, 24, 1, 31, 0x1C4, 0),
|
||||
/* CLK_CFG_8 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel",
|
||||
u2u3_sys_parents, 0x080, 0x084, 0x088, 0, 1, 7,
|
||||
0x1C4, 1),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel",
|
||||
u2u3_sys_parents, 0x080, 0x084, 0x088, 8, 1, 15,
|
||||
0x1C4, 2),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_REFSEL, "da_u2_refsel",
|
||||
da_u2_refsel_parents, 0x080, 0x084, 0x088, 16, 1,
|
||||
23, 0x1C4, 3),
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel",
|
||||
da_u2_refsel_parents, 0x080, 0x084, 0x088, 24, 1,
|
||||
31, 0x1C4, 4),
|
||||
/* CLK_CFG_9 */
|
||||
MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel",
|
||||
sgm_reg_parents, 0x090, 0x094, 0x098, 0, 1, 7,
|
||||
0x1C4, 5),
|
||||
};
|
||||
|
||||
static int clk_mt7986_topckgen_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) +
|
||||
ARRAY_SIZE(top_muxes);
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(nr);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
|
||||
clk_data);
|
||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
|
||||
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
|
||||
&mt7986_clk_lock, clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAXI_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAPB_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_MD32_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_F26M_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_SGM_REG_SEL]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r) {
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
goto free_topckgen_data;
|
||||
}
|
||||
return r;
|
||||
|
||||
free_topckgen_data:
|
||||
mtk_free_clk_data(clk_data);
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7986_topckgen[] = {
|
||||
{ .compatible = "mediatek,mt7986-topckgen", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt7986_topckgen_drv = {
|
||||
.probe = clk_mt7986_topckgen_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7986-topckgen",
|
||||
.of_match_table = of_match_clk_mt7986_topckgen,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_mt7986_topckgen_drv);
|
||||
@@ -713,6 +713,35 @@ static struct clk_regmap gxbb_mpll_prediv = {
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_mpll0_div = {
|
||||
.data = &(struct meson_clk_mpll_data){
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL,
|
||||
.shift = 25,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.lock = &meson_clk_lock,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0_div",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&gxbb_mpll_prediv.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxl_mpll0_div = {
|
||||
.data = &(struct meson_clk_mpll_data){
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
@@ -749,7 +778,16 @@ static struct clk_regmap gxbb_mpll0 = {
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw },
|
||||
.parent_data = &(const struct clk_parent_data) {
|
||||
/*
|
||||
* Note:
|
||||
* GXL and GXBB have different SDM_EN registers. We
|
||||
* fallback to the global naming string mechanism so
|
||||
* mpll0_div picks up the appropriate one.
|
||||
*/
|
||||
.name = "mpll0_div",
|
||||
.index = -1,
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
@@ -3044,7 +3082,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
|
||||
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
|
||||
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
|
||||
[CLKID_VAPB] = &gxbb_vapb.hw,
|
||||
[CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw,
|
||||
[CLKID_MPLL0_DIV] = &gxl_mpll0_div.hw,
|
||||
[CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
|
||||
[CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
|
||||
[CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
|
||||
@@ -3439,7 +3477,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = {
|
||||
&gxbb_mpll0,
|
||||
&gxbb_mpll1,
|
||||
&gxbb_mpll2,
|
||||
&gxbb_mpll0_div,
|
||||
&gxl_mpll0_div,
|
||||
&gxbb_mpll1_div,
|
||||
&gxbb_mpll2_div,
|
||||
&gxbb_cts_amclk_div,
|
||||
|
||||
@@ -265,6 +265,14 @@ config MSM_MMCC_8974
|
||||
Say Y if you want to support multimedia devices such as display,
|
||||
graphics, video encode/decode, camera, etc.
|
||||
|
||||
config MSM_GCC_8976
|
||||
tristate "MSM8956/76 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on msm8956/76 devices.
|
||||
Say Y if you want to use peripheral devices such as UART, SPI,
|
||||
i2c, USB, SD/eMMC, SATA, PCIe, etc.
|
||||
|
||||
config MSM_MMCC_8994
|
||||
tristate "MSM8994 Multimedia Clock Controller"
|
||||
select MSM_GCC_8994
|
||||
@@ -564,6 +572,14 @@ config SM_CAMCC_8250
|
||||
Support for the camera clock controller on SM8250 devices.
|
||||
Say Y if you want to support camera devices and camera functionality.
|
||||
|
||||
config SDX_GCC_65
|
||||
tristate "SDX65 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on SDX65 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
|
||||
@@ -618,6 +634,14 @@ config SM_GCC_8350
|
||||
Say Y if you want to use peripheral devices such as UART,
|
||||
SPI, I2C, USB, SD/UFS, PCIe etc.
|
||||
|
||||
config SM_GCC_8450
|
||||
tristate "SM8450 Global Clock Controller"
|
||||
select QCOM_GDSC
|
||||
help
|
||||
Support for the global clock controller on SM8450 devices.
|
||||
Say Y if you want to use peripheral devices such as UART,
|
||||
SPI, I2C, USB, SD/UFS, PCIe etc.
|
||||
|
||||
config SM_GPUCC_8150
|
||||
tristate "SM8150 Graphics Clock Controller"
|
||||
select SM_GCC_8150
|
||||
|
||||
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_GCC_8939) += gcc-msm8939.o
|
||||
obj-$(CONFIG_MSM_GCC_8953) += gcc-msm8953.o
|
||||
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
|
||||
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
|
||||
obj-$(CONFIG_MSM_GCC_8976) += gcc-msm8976.o
|
||||
obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
|
||||
obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
|
||||
obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
|
||||
@@ -83,6 +84,7 @@ 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_CAMCC_8250) += camcc-sm8250.o
|
||||
obj-$(CONFIG_SDX_GCC_65) += gcc-sdx65.o
|
||||
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
|
||||
obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o
|
||||
obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o
|
||||
@@ -90,6 +92,7 @@ obj-$(CONFIG_SM_GCC_6350) += gcc-sm6350.o
|
||||
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
|
||||
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
|
||||
obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o
|
||||
obj-$(CONFIG_SM_GCC_8450) += gcc-sm8450.o
|
||||
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
|
||||
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
|
||||
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -139,6 +140,20 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
|
||||
[PLL_OFF_OPMODE] = 0x28,
|
||||
[PLL_OFF_STATUS] = 0x38,
|
||||
},
|
||||
[CLK_ALPHA_PLL_TYPE_LUCID_EVO] = {
|
||||
[PLL_OFF_OPMODE] = 0x04,
|
||||
[PLL_OFF_STATUS] = 0x0c,
|
||||
[PLL_OFF_L_VAL] = 0x10,
|
||||
[PLL_OFF_ALPHA_VAL] = 0x14,
|
||||
[PLL_OFF_USER_CTL] = 0x18,
|
||||
[PLL_OFF_USER_CTL_U] = 0x1c,
|
||||
[PLL_OFF_CONFIG_CTL] = 0x20,
|
||||
[PLL_OFF_CONFIG_CTL_U] = 0x24,
|
||||
[PLL_OFF_CONFIG_CTL_U1] = 0x28,
|
||||
[PLL_OFF_TEST_CTL] = 0x2c,
|
||||
[PLL_OFF_TEST_CTL_U] = 0x30,
|
||||
[PLL_OFF_TEST_CTL_U1] = 0x34,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
||||
|
||||
@@ -175,6 +190,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
||||
#define LUCID_5LPE_PLL_LATCH_INPUT BIT(14)
|
||||
#define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21)
|
||||
|
||||
/* LUCID EVO PLL specific settings and offsets */
|
||||
#define LUCID_EVO_ENABLE_VOTE_RUN BIT(25)
|
||||
#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)
|
||||
|
||||
/* ZONDA PLL specific */
|
||||
#define ZONDA_PLL_OUT_MASK 0xf
|
||||
#define ZONDA_STAY_IN_CFA BIT(16)
|
||||
@@ -204,7 +223,7 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (count = 100; count > 0; count--) {
|
||||
for (count = 200; count > 0; count--) {
|
||||
ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1750,24 +1769,32 @@ static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
LUCID_5LPE_ALPHA_PLL_ACK_LATCH);
|
||||
}
|
||||
|
||||
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
static int __clk_lucid_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate,
|
||||
unsigned long enable_vote_run)
|
||||
{
|
||||
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
|
||||
int i, val = 0, div, ret;
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
int i, val, div, ret;
|
||||
u32 mask;
|
||||
|
||||
/*
|
||||
* If the PLL is in FSM mode, then treat set_rate callback as a
|
||||
* no-operation.
|
||||
*/
|
||||
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
|
||||
ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & LUCID_5LPE_ENABLE_VOTE_RUN)
|
||||
if (val & enable_vote_run)
|
||||
return 0;
|
||||
|
||||
if (!pll->post_div_table) {
|
||||
pr_err("Missing the post_div_table for the %s PLL\n",
|
||||
clk_hw_get_name(&pll->clkr.hw));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||
for (i = 0; i < pll->num_post_div; i++) {
|
||||
if (pll->post_div_table[i].div == div) {
|
||||
@@ -1781,6 +1808,12 @@ static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long
|
||||
mask, val << pll->post_div_shift);
|
||||
}
|
||||
|
||||
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_5LPE_ENABLE_VOTE_RUN);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
|
||||
.prepare = alpha_pll_lucid_5lpe_prepare,
|
||||
.enable = alpha_pll_lucid_5lpe_enable,
|
||||
@@ -1960,3 +1993,124 @@ const struct clk_ops clk_alpha_pll_zonda_ops = {
|
||||
.set_rate = clk_zonda_pll_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL(clk_alpha_pll_zonda_ops);
|
||||
|
||||
static int alpha_pll_lucid_evo_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If in FSM mode, just vote for it */
|
||||
if (val & LUCID_EVO_ENABLE_VOTE_RUN) {
|
||||
ret = clk_enable_regmap(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
return wait_for_pll_enable_lock(pll);
|
||||
}
|
||||
|
||||
/* Check if PLL is already enabled */
|
||||
ret = trion_pll_is_enabled(pll, regmap);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else if (ret) {
|
||||
pr_warn("%s PLL is already enabled\n", clk_hw_get_name(&pll->clkr.hw));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set operation mode to RUN */
|
||||
regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);
|
||||
|
||||
ret = wait_for_pll_enable_lock(pll);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable the PLL outputs */
|
||||
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable the global PLL outputs */
|
||||
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Ensure that the write above goes through before returning. */
|
||||
mb();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void alpha_pll_lucid_evo_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* If in FSM mode, just unvote it */
|
||||
if (val & LUCID_EVO_ENABLE_VOTE_RUN) {
|
||||
clk_disable_regmap(hw);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable the global PLL output */
|
||||
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* Disable the PLL outputs */
|
||||
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* Place the PLL mode in STANDBY */
|
||||
regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
|
||||
}
|
||||
|
||||
static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 l, frac;
|
||||
|
||||
regmap_read(regmap, PLL_L_VAL(pll), &l);
|
||||
l &= LUCID_EVO_PLL_L_VAL_MASK;
|
||||
regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);
|
||||
|
||||
return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll));
|
||||
}
|
||||
|
||||
static int clk_lucid_evo_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_EVO_ENABLE_VOTE_RUN);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops = {
|
||||
.enable = alpha_pll_lucid_evo_enable,
|
||||
.disable = alpha_pll_lucid_evo_disable,
|
||||
.is_enabled = clk_trion_pll_is_enabled,
|
||||
.recalc_rate = alpha_pll_lucid_evo_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_round_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_evo_ops);
|
||||
|
||||
const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops = {
|
||||
.recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_postdiv_fabia_round_rate,
|
||||
.set_rate = clk_lucid_evo_pll_postdiv_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_evo_ops);
|
||||
|
||||
@@ -17,6 +17,7 @@ enum {
|
||||
CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
|
||||
CLK_ALPHA_PLL_TYPE_AGERA,
|
||||
CLK_ALPHA_PLL_TYPE_ZONDA,
|
||||
CLK_ALPHA_PLL_TYPE_LUCID_EVO,
|
||||
CLK_ALPHA_PLL_TYPE_MAX,
|
||||
};
|
||||
|
||||
@@ -151,6 +152,8 @@ extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
|
||||
|
||||
extern const struct clk_ops clk_alpha_pll_zonda_ops;
|
||||
#define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops
|
||||
extern const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops;
|
||||
|
||||
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
|
||||
const struct alpha_pll_config *config);
|
||||
|
||||
@@ -515,6 +515,32 @@ static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
|
||||
/* Resource name must match resource id present in cmd-db */
|
||||
DEFINE_CLK_RPMH_ARC(sc7280, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 4);
|
||||
|
||||
DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
|
||||
DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 4);
|
||||
|
||||
static struct clk_hw *sm8450_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
|
||||
[RPMH_LN_BB_CLK1] = &sm8450_ln_bb_clk1.hw,
|
||||
[RPMH_LN_BB_CLK1_A] = &sm8450_ln_bb_clk1_ao.hw,
|
||||
[RPMH_LN_BB_CLK2] = &sm8450_ln_bb_clk2.hw,
|
||||
[RPMH_LN_BB_CLK2_A] = &sm8450_ln_bb_clk2_ao.hw,
|
||||
[RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
|
||||
[RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
|
||||
[RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
|
||||
[RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
|
||||
[RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
|
||||
[RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
|
||||
[RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
|
||||
[RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
|
||||
[RPMH_IPA_CLK] = &sdm845_ipa.hw,
|
||||
};
|
||||
|
||||
static const struct clk_rpmh_desc clk_rpmh_sm8450 = {
|
||||
.clks = sm8450_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sm8450_rpmh_clocks),
|
||||
};
|
||||
|
||||
static struct clk_hw *sc7280_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
|
||||
@@ -556,6 +582,30 @@ static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
|
||||
.num_clks = ARRAY_SIZE(sm6350_rpmh_clocks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_RPMH_VRM(sdx65, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
|
||||
|
||||
static struct clk_hw *sdx65_rpmh_clocks[] = {
|
||||
[RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
|
||||
[RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
|
||||
[RPMH_LN_BB_CLK1] = &sdx65_ln_bb_clk1.hw,
|
||||
[RPMH_LN_BB_CLK1_A] = &sdx65_ln_bb_clk1_ao.hw,
|
||||
[RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
|
||||
[RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
|
||||
[RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
|
||||
[RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
|
||||
[RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
|
||||
[RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
|
||||
[RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
|
||||
[RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
|
||||
[RPMH_IPA_CLK] = &sdm845_ipa.hw,
|
||||
[RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
|
||||
};
|
||||
|
||||
static const struct clk_rpmh_desc clk_rpmh_sdx65 = {
|
||||
.clks = sdx65_rpmh_clocks,
|
||||
.num_clks = ARRAY_SIZE(sdx65_rpmh_clocks),
|
||||
};
|
||||
|
||||
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
@@ -643,10 +693,12 @@ static const struct of_device_id clk_rpmh_match_table[] = {
|
||||
{ .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
|
||||
{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
|
||||
{ .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
|
||||
{ .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65},
|
||||
{ .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
|
||||
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
|
||||
{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
|
||||
{ .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
|
||||
{ .compatible = "qcom,sm8450-rpmh-clk", .data = &clk_rpmh_sm8450},
|
||||
{ .compatible = "qcom,sc7280-rpmh-clk", .data = &clk_rpmh_sc7280},
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <linux/soc/qcom/smd-rpm.h>
|
||||
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/mfd/qcom-rpm.h>
|
||||
|
||||
#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
|
||||
#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
|
||||
@@ -151,12 +150,6 @@ struct clk_smd_rpm_req {
|
||||
__le32 value;
|
||||
};
|
||||
|
||||
struct rpm_cc {
|
||||
struct qcom_rpm *rpm;
|
||||
struct clk_smd_rpm **clks;
|
||||
size_t num_clks;
|
||||
};
|
||||
|
||||
struct rpm_smd_clk_desc {
|
||||
struct clk_smd_rpm **clks;
|
||||
size_t num_clks;
|
||||
@@ -196,10 +189,6 @@ static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,
|
||||
.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
|
||||
};
|
||||
|
||||
/* Buffered clock needs a binary value */
|
||||
if (r->rpm_res_type == QCOM_SMD_RPM_CLK_BUF_A)
|
||||
req.value = cpu_to_le32(!!req.value);
|
||||
|
||||
return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
r->rpm_res_type, r->rpm_clk_id, &req,
|
||||
sizeof(req));
|
||||
@@ -214,10 +203,6 @@ static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,
|
||||
.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
|
||||
};
|
||||
|
||||
/* Buffered clock needs a binary value */
|
||||
if (r->rpm_res_type == QCOM_SMD_RPM_CLK_BUF_A)
|
||||
req.value = cpu_to_le32(!!req.value);
|
||||
|
||||
return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
|
||||
r->rpm_res_type, r->rpm_clk_id, &req,
|
||||
sizeof(req));
|
||||
@@ -1159,20 +1144,19 @@ MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
|
||||
static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
struct rpm_cc *rcc = data;
|
||||
const struct rpm_smd_clk_desc *desc = data;
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx >= rcc->num_clks) {
|
||||
if (idx >= desc->num_clks) {
|
||||
pr_err("%s: invalid index %u\n", __func__, idx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
|
||||
return desc->clks[idx] ? &desc->clks[idx]->hw : ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
static int rpm_smd_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rpm_cc *rcc;
|
||||
int ret;
|
||||
size_t num_clks, i;
|
||||
struct qcom_smd_rpm *rpm;
|
||||
@@ -1192,13 +1176,6 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
|
||||
rpm_smd_clks = desc->clks;
|
||||
num_clks = desc->num_clks;
|
||||
|
||||
rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
|
||||
if (!rcc)
|
||||
return -ENOMEM;
|
||||
|
||||
rcc->clks = rpm_smd_clks;
|
||||
rcc->num_clks = num_clks;
|
||||
|
||||
for (i = 0; i < num_clks; i++) {
|
||||
if (!rpm_smd_clks[i])
|
||||
continue;
|
||||
@@ -1224,7 +1201,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get,
|
||||
rcc);
|
||||
(void *)desc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
||||
4155
drivers/clk/qcom/gcc-msm8976.c
Normal file
4155
drivers/clk/qcom/gcc-msm8976.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
@@ -2917,7 +2917,7 @@ static struct clk_branch gcc_cfg_noc_lpass_clk = {
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_cfg_noc_lpass_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
.ops = &clk_branch2_aon_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
1611
drivers/clk/qcom/gcc-sdx65.c
Normal file
1611
drivers/clk/qcom/gcc-sdx65.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2020-2021, Linaro Limited
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
3304
drivers/clk/qcom/gcc-sm8450.c
Normal file
3304
drivers/clk/qcom/gcc-sm8450.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user