mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
ARM: SoC drivers for 6.5
Nothing surprising in the SoC specific drivers, with the usual updates: * Added or improved SoC driver support for Tegra234, Exynos4121, RK3588, as well as multiple Mediatek and Qualcomm chips * SCMI firmware gains support for multiple SMC/HVC transport and version 3.2 of the protocol * Cleanups amd minor changes for the reset controller, memory controller, firmware and sram drivers * Minor changes to amd/xilinx, samsung, tegra, nxp, ti, qualcomm, amlogic and renesas SoC specific drivers -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmSdmbIACgkQYKtH/8kJ UicewQ/6Aq8j5pBFYBimZoyQ0bi9z+prGrHoDDYLew2vKjtOXJl5z7ZnM3J1oyPt Zvis3IaGkHJCuuqotPdsquZrzHq8slzXzwkHPfHORJBC4gV0V/vMS8w32tO5FfTq ULrMyWnbsU7Udeywc2xuEpAoC9+bXX9brnCpa3H41peIGZKM+0g7EE6FASt3YaOk O+ZMSGqF8QbCqSQrUH3GudFlFMy/VxIvwuUsbLt8aNkRACunQZXVgUdArvLV49nX SElFN7hOVRoVDv0rgYMxlwElymrta/kMyjLba8GU1GIhzyDGozVqIJQAnsQ3f6CC yyzaJm27zzJH0mx9jx4W+JLBdjqDL4ctE2WyllRVIpTGYMHiMQtutHNwtNupIuD5 j9j/fIVQWZqOdWXnA6V/CHYN1MZBRTH3KQcnLlYPC01dWKThPDnrHGfwOkfsrwtN zuERJJ+gd5b8KW4dmy1ueDOSB8162LxbS7iHxpOBGySmqVOYj3XUqACZhKRfXfIQ BVj9punCE/gO2fMb9IZByjeOzgtV+PBRmPxoglyaGkT4fVfL06kEbpKFYbXXq9b/ aAS/U84gGr8ebWsOXszwDnBzTZRzjMVv/T9KDTTJuWbBEPNyCR7fUG0cZ50rSKnJ 2cTPe3a0sS6LaBt71qfExCIfxG+cJ2c3N1U5/jb2C49Aob45obs= =zvLr -----END PGP SIGNATURE----- Merge tag 'soc-drivers-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc Pull ARM SoC driver updates from Arnd Bergmann: "Nothing surprising in the SoC specific drivers, with the usual updates: - Added or improved SoC driver support for Tegra234, Exynos4121, RK3588, as well as multiple Mediatek and Qualcomm chips - SCMI firmware gains support for multiple SMC/HVC transport and version 3.2 of the protocol - Cleanups amd minor changes for the reset controller, memory controller, firmware and sram drivers - Minor changes to amd/xilinx, samsung, tegra, nxp, ti, qualcomm, amlogic and renesas SoC specific drivers" * tag 'soc-drivers-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (118 commits) dt-bindings: interrupt-controller: Convert Amlogic Meson GPIO interrupt controller binding MAINTAINERS: add PHY-related files to Amlogic SoC file list drivers: meson: secure-pwrc: always enable DMA domain tee: optee: Use kmemdup() to replace kmalloc + memcpy soc: qcom: geni-se: Do not bother about enable/disable of interrupts in secondary sequencer dt-bindings: sram: qcom,imem: document qdu1000 soc: qcom: icc-bwmon: Fix MSM8998 count unit dt-bindings: soc: qcom,rpmh-rsc: Require power-domains soc: qcom: socinfo: Add Soc ID for IPQ5300 dt-bindings: arm: qcom,ids: add SoC ID for IPQ5300 soc: qcom: Fix a IS_ERR() vs NULL bug in probe soc: qcom: socinfo: Add support for new fields in revision 19 soc: qcom: socinfo: Add support for new fields in revision 18 dt-bindings: firmware: scm: Add compatible for SDX75 soc: qcom: mdt_loader: Fix split image detection dt-bindings: memory-controllers: drop unneeded quotes soc: rockchip: dtpm: use C99 array init syntax firmware: tegra: bpmp: Add support for DRAM MRQ GSCs soc/tegra: pmc: Use devm_clk_notifier_register() soc/tegra: pmc: Simplify debugfs initialization ...
This commit is contained in:
commit
e4c8d01865
@ -34,6 +34,10 @@ properties:
|
||||
- description: SCMI compliant firmware with ARM SMC/HVC transport
|
||||
items:
|
||||
- const: arm,scmi-smc
|
||||
- description: SCMI compliant firmware with ARM SMC/HVC transport
|
||||
with shmem address(4KB-page, offset) as parameters
|
||||
items:
|
||||
- const: arm,scmi-smc-param
|
||||
- description: SCMI compliant firmware with SCMI Virtio transport.
|
||||
The virtio transport only supports a single device.
|
||||
items:
|
||||
@ -299,7 +303,9 @@ else:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: arm,scmi-smc
|
||||
enum:
|
||||
- arm,scmi-smc
|
||||
- arm,scmi-smc-param
|
||||
then:
|
||||
required:
|
||||
- arm,smc-id
|
||||
|
@ -51,6 +51,7 @@ properties:
|
||||
- qcom,scm-sdm845
|
||||
- qcom,scm-sdx55
|
||||
- qcom,scm-sdx65
|
||||
- qcom,scm-sdx75
|
||||
- qcom,scm-sm6115
|
||||
- qcom,scm-sm6125
|
||||
- qcom,scm-sm6350
|
||||
|
@ -1,38 +0,0 @@
|
||||
Amlogic meson GPIO interrupt controller
|
||||
|
||||
Meson SoCs contains an interrupt controller which is able to watch the SoC
|
||||
pads and generate an interrupt on edge or level. The controller is essentially
|
||||
a 256 pads to 8 GIC interrupt multiplexer, with a filter block to select edge
|
||||
or level and polarity. It does not expose all 256 mux inputs because the
|
||||
documentation shows that the upper part is not mapped to any pad. The actual
|
||||
number of interrupt exposed depends on the SoC.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : must have "amlogic,meson8-gpio-intc" and either
|
||||
"amlogic,meson8-gpio-intc" for meson8 SoCs (S802) or
|
||||
"amlogic,meson8b-gpio-intc" for meson8b SoCs (S805) or
|
||||
"amlogic,meson-gxbb-gpio-intc" for GXBB SoCs (S905) or
|
||||
"amlogic,meson-gxl-gpio-intc" for GXL SoCs (S905X, S912)
|
||||
"amlogic,meson-axg-gpio-intc" for AXG SoCs (A113D, A113X)
|
||||
"amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2)
|
||||
"amlogic,meson-sm1-gpio-intc" for SM1 SoCs (S905D3, S905X3, S905Y3)
|
||||
"amlogic,meson-a1-gpio-intc" for A1 SoCs (A113L)
|
||||
"amlogic,meson-s4-gpio-intc" for S4 SoCs (S802X2, S905Y4, S805X2G, S905W2)
|
||||
- reg : Specifies base physical address and size of the registers.
|
||||
- interrupt-controller : Identifies the node as an interrupt controller.
|
||||
- #interrupt-cells : Specifies the number of cells needed to encode an
|
||||
interrupt source. The value must be 2.
|
||||
- meson,channel-interrupts: Array with the 8 upstream hwirq numbers. These
|
||||
are the hwirqs used on the parent interrupt controller.
|
||||
|
||||
Example:
|
||||
|
||||
gpio_interrupt: interrupt-controller@9880 {
|
||||
compatible = "amlogic,meson-gxbb-gpio-intc",
|
||||
"amlogic,meson-gpio-intc";
|
||||
reg = <0x0 0x9880 0x0 0x10>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
meson,channel-interrupts = <64 65 66 67 68 69 70 71>;
|
||||
};
|
@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interrupt-controller/amlogic,meson-gpio-intc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic Meson GPIO interrupt controller
|
||||
|
||||
maintainers:
|
||||
- Heiner Kallweit <hkallweit1@gmail.com>
|
||||
|
||||
description: |
|
||||
Meson SoCs contains an interrupt controller which is able to watch the SoC
|
||||
pads and generate an interrupt on edge or level. The controller is essentially
|
||||
a 256 pads to 8 or 12 GIC interrupt multiplexer, with a filter block to select
|
||||
edge or level and polarity. It does not expose all 256 mux inputs because the
|
||||
documentation shows that the upper part is not mapped to any pad. The actual
|
||||
number of interrupts exposed depends on the SoC.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/interrupt-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: amlogic,meson-gpio-intc
|
||||
- items:
|
||||
- enum:
|
||||
- amlogic,meson8-gpio-intc
|
||||
- amlogic,meson8b-gpio-intc
|
||||
- amlogic,meson-gxbb-gpio-intc
|
||||
- amlogic,meson-gxl-gpio-intc
|
||||
- amlogic,meson-axg-gpio-intc
|
||||
- amlogic,meson-g12a-gpio-intc
|
||||
- amlogic,meson-sm1-gpio-intc
|
||||
- amlogic,meson-a1-gpio-intc
|
||||
- amlogic,meson-s4-gpio-intc
|
||||
- const: amlogic,meson-gpio-intc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
amlogic,channel-interrupts:
|
||||
description: Array with the upstream hwirq numbers
|
||||
minItems: 8
|
||||
maxItems: 12
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupt-controller
|
||||
- "#interrupt-cells"
|
||||
- amlogic,channel-interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
interrupt-controller@9880 {
|
||||
compatible = "amlogic,meson-gxbb-gpio-intc",
|
||||
"amlogic,meson-gpio-intc";
|
||||
reg = <0x9880 0x10>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>;
|
||||
};
|
@ -1,78 +0,0 @@
|
||||
* Samsung Multi Format Codec (MFC)
|
||||
|
||||
Multi Format Codec (MFC) is the IP present in Samsung SoCs which
|
||||
supports high resolution decoding and encoding functionalities.
|
||||
The MFC device driver is a v4l2 driver which can encode/decode
|
||||
video raw/elementary streams and has support for all popular
|
||||
video codecs.
|
||||
|
||||
Required properties:
|
||||
- compatible : value should be either one among the following
|
||||
(a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs
|
||||
(b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
|
||||
(c) "samsung,exynos3250-mfc", "samsung,mfc-v7" for MFC v7
|
||||
present in Exynos3250 SoC
|
||||
(d) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
|
||||
(e) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC
|
||||
(f) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC
|
||||
(g) "samsung,mfc-v10" for MFC v10 present in Exynos7880 SoC
|
||||
|
||||
- reg : Physical base address of the IP registers and length of memory
|
||||
mapped region.
|
||||
|
||||
- interrupts : MFC interrupt number to the CPU.
|
||||
- clocks : from common clock binding: handle to mfc clock.
|
||||
- clock-names : from common clock binding: must contain "mfc",
|
||||
corresponding to entry in the clocks property.
|
||||
|
||||
Optional properties:
|
||||
- power-domains : power-domain property defined with a phandle
|
||||
to respective power domain.
|
||||
- memory-region : from reserved memory binding: phandles to two reserved
|
||||
memory regions, first is for "left" mfc memory bus interfaces,
|
||||
second if for the "right" mfc memory bus, used when no SYSMMU
|
||||
support is available; used only by MFC v5 present in Exynos4 SoCs
|
||||
|
||||
Obsolete properties:
|
||||
- samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region
|
||||
property instead
|
||||
|
||||
|
||||
Example:
|
||||
SoC specific DT entry:
|
||||
|
||||
mfc: codec@13400000 {
|
||||
compatible = "samsung,mfc-v5";
|
||||
reg = <0x13400000 0x10000>;
|
||||
interrupts = <0 94 0>;
|
||||
power-domains = <&pd_mfc>;
|
||||
clocks = <&clock 273>;
|
||||
clock-names = "mfc";
|
||||
};
|
||||
|
||||
Reserved memory specific DT entry for given board (see reserved memory binding
|
||||
for more information):
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
mfc_left: region@51000000 {
|
||||
compatible = "shared-dma-pool";
|
||||
no-map;
|
||||
reg = <0x51000000 0x800000>;
|
||||
};
|
||||
|
||||
mfc_right: region@43000000 {
|
||||
compatible = "shared-dma-pool";
|
||||
no-map;
|
||||
reg = <0x43000000 0x800000>;
|
||||
};
|
||||
};
|
||||
|
||||
Board specific DT entry:
|
||||
|
||||
codec@13400000 {
|
||||
memory-region = <&mfc_left>, <&mfc_right>;
|
||||
};
|
184
Documentation/devicetree/bindings/media/samsung,s5p-mfc.yaml
Normal file
184
Documentation/devicetree/bindings/media/samsung,s5p-mfc.yaml
Normal file
@ -0,0 +1,184 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/samsung,s5p-mfc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung Exynos Multi Format Codec (MFC)
|
||||
|
||||
maintainers:
|
||||
- Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
- Aakarsh Jain <aakarsh.jain@samsung.com>
|
||||
|
||||
description:
|
||||
Multi Format Codec (MFC) is the IP present in Samsung SoCs which
|
||||
supports high resolution decoding and encoding functionalities.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- samsung,exynos5433-mfc # Exynos5433
|
||||
- samsung,mfc-v5 # Exynos4
|
||||
- samsung,mfc-v6 # Exynos5
|
||||
- samsung,mfc-v7 # Exynos5420
|
||||
- samsung,mfc-v8 # Exynos5800
|
||||
- samsung,mfc-v10 # Exynos7880
|
||||
- items:
|
||||
- enum:
|
||||
- samsung,exynos3250-mfc # Exynos3250
|
||||
- const: samsung,mfc-v7 # Fall back for Exynos3250
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
iommus:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
iommu-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
memory-region:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,exynos3250-mfc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: mfc
|
||||
- const: sclk_mfc
|
||||
iommus:
|
||||
maxItems: 1
|
||||
iommus-names: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,exynos5433-mfc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: aclk
|
||||
- const: aclk_xiu
|
||||
iommus:
|
||||
maxItems: 2
|
||||
iommus-names:
|
||||
items:
|
||||
- const: left
|
||||
- const: right
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,mfc-v5
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: mfc
|
||||
- const: sclk_mfc
|
||||
iommus:
|
||||
maxItems: 2
|
||||
iommus-names:
|
||||
items:
|
||||
- const: left
|
||||
- const: right
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,mfc-v6
|
||||
- samsung,mfc-v8
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
items:
|
||||
- const: mfc
|
||||
iommus:
|
||||
maxItems: 2
|
||||
iommus-names:
|
||||
items:
|
||||
- const: left
|
||||
- const: right
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,mfc-v7
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
iommus:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/exynos4.h>
|
||||
#include <dt-bindings/clock/exynos-audss-clk.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
codec@13400000 {
|
||||
compatible = "samsung,mfc-v5";
|
||||
reg = <0x13400000 0x10000>;
|
||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
power-domains = <&pd_mfc>;
|
||||
clocks = <&clock CLK_MFC>, <&clock CLK_SCLK_MFC>;
|
||||
clock-names = "mfc", "sclk_mfc";
|
||||
iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
|
||||
iommu-names = "left", "right";
|
||||
};
|
@ -165,7 +165,7 @@ patternProperties:
|
||||
const: 0
|
||||
|
||||
lpddr2:
|
||||
$ref: "ddr/jedec,lpddr2.yaml#"
|
||||
$ref: ddr/jedec,lpddr2.yaml#
|
||||
type: object
|
||||
|
||||
patternProperties:
|
||||
|
@ -129,7 +129,7 @@ patternProperties:
|
||||
The child device node represents the device connected to the GPMC
|
||||
bus. The device can be a NAND chip, SRAM device, NOR device
|
||||
or an ASIC.
|
||||
$ref: "ti,gpmc-child.yaml"
|
||||
$ref: ti,gpmc-child.yaml
|
||||
|
||||
|
||||
required:
|
||||
|
@ -24,6 +24,10 @@ properties:
|
||||
- enum:
|
||||
- mediatek,mt7623-mipi-tx
|
||||
- const: mediatek,mt2701-mipi-tx
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt6795-mipi-tx
|
||||
- const: mediatek,mt8173-mipi-tx
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8365-mipi-tx
|
||||
|
@ -22,7 +22,9 @@ properties:
|
||||
- mediatek,mt8173-disp-pwm
|
||||
- mediatek,mt8183-disp-pwm
|
||||
- items:
|
||||
- const: mediatek,mt8167-disp-pwm
|
||||
- enum:
|
||||
- mediatek,mt6795-disp-pwm
|
||||
- mediatek,mt8167-disp-pwm
|
||||
- const: mediatek,mt8173-disp-pwm
|
||||
- items:
|
||||
- enum:
|
||||
|
@ -1,32 +0,0 @@
|
||||
Oxford Semiconductor OXNAS SoC Family RESET Controller
|
||||
================================================
|
||||
|
||||
Please also refer to reset.txt in this directory for common reset
|
||||
controller binding usage.
|
||||
|
||||
Required properties:
|
||||
- compatible: For OX810SE, should be "oxsemi,ox810se-reset"
|
||||
For OX820, should be "oxsemi,ox820-reset"
|
||||
- #reset-cells: 1, see below
|
||||
|
||||
Parent node should have the following properties :
|
||||
- compatible: For OX810SE, should be :
|
||||
"oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
|
||||
For OX820, should be :
|
||||
"oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd"
|
||||
|
||||
Reset indices are in dt-bindings include files :
|
||||
- For OX810SE: include/dt-bindings/reset/oxsemi,ox810se.h
|
||||
- For OX820: include/dt-bindings/reset/oxsemi,ox820.h
|
||||
|
||||
example:
|
||||
|
||||
sys: sys-ctrl@000000 {
|
||||
compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
|
||||
reg = <0x000000 0x100000>;
|
||||
|
||||
reset: reset-controller {
|
||||
compatible = "oxsemi,ox810se-reset";
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
@ -33,6 +33,7 @@ properties:
|
||||
- mediatek,mt2701-pwrap
|
||||
- mediatek,mt6765-pwrap
|
||||
- mediatek,mt6779-pwrap
|
||||
- mediatek,mt6795-pwrap
|
||||
- mediatek,mt6797-pwrap
|
||||
- mediatek,mt6873-pwrap
|
||||
- mediatek,mt7622-pwrap
|
||||
|
@ -26,6 +26,7 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,qdu1000-aoss-qmp
|
||||
- qcom,sa8775p-aoss-qmp
|
||||
- qcom,sc7180-aoss-qmp
|
||||
- qcom,sc7280-aoss-qmp
|
||||
- qcom,sc8180x-aoss-qmp
|
||||
|
@ -55,9 +55,10 @@ additionalProperties: false
|
||||
examples:
|
||||
- |
|
||||
eud@88e0000 {
|
||||
compatible = "qcom,sc7280-eud","qcom,eud";
|
||||
compatible = "qcom,sc7280-eud", "qcom,eud";
|
||||
reg = <0x88e0000 0x2000>,
|
||||
<0x88e2000 0x1000>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -67,6 +68,7 @@ examples:
|
||||
remote-endpoint = <&usb2_role_switch>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
eud_con: endpoint {
|
||||
|
@ -0,0 +1,69 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/qcom/qcom,rpm-master-stats.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. (QTI) RPM Master Stats
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konrad.dybcio@linaro.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm RPM (Resource Power Manager) architecture includes a concept
|
||||
of "RPM Masters". They can be thought of as "the local gang leaders", usually
|
||||
spanning a single subsystem (e.g. APSS, ADSP, CDSP). All of the RPM decisions
|
||||
(particularly around entering hardware-driven low power modes: XO shutdown
|
||||
and total system-wide power collapse) are first made at Master-level, and
|
||||
only then aggregated for the entire system.
|
||||
|
||||
The Master Stats provide a few useful bits that can be used to assess whether
|
||||
our device has entered the desired low-power mode, how long it took to do so,
|
||||
the duration of that residence, how long it took to come back online,
|
||||
how many times a given sleep state was entered and which cores are actively
|
||||
voting for staying awake.
|
||||
|
||||
This scheme has been used on various SoCs in the 2013-2023 era, with some
|
||||
newer or higher-end designs providing this information through an SMEM query.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,rpm-master-stats
|
||||
|
||||
qcom,rpm-msg-ram:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: Phandle to an RPM MSG RAM slice containing the master stats
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
|
||||
qcom,master-names:
|
||||
$ref: /schemas/types.yaml#/definitions/string-array
|
||||
description:
|
||||
The name of the RPM Master which owns the MSG RAM slice where this
|
||||
instance of Master Stats resides
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- qcom,rpm-msg-ram
|
||||
- qcom,master-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
stats {
|
||||
compatible = "qcom,rpm-master-stats";
|
||||
qcom,rpm-msg-ram = <&apss_master_stats>,
|
||||
<&mpss_master_stats>,
|
||||
<&adsp_master_stats>,
|
||||
<&cdsp_master_stats>,
|
||||
<&tz_master_stats>;
|
||||
qcom,master-names = "APSS",
|
||||
"MPSS",
|
||||
"ADSP",
|
||||
"CDSP",
|
||||
"TZ";
|
||||
};
|
||||
...
|
@ -124,6 +124,7 @@ required:
|
||||
- qcom,tcs-offset
|
||||
- reg
|
||||
- reg-names
|
||||
- power-domains
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@ -179,6 +180,7 @@ examples:
|
||||
<SLEEP_TCS 1>,
|
||||
<WAKE_TCS 1>,
|
||||
<CONTROL_TCS 0>;
|
||||
power-domains = <&CLUSTER_PD>;
|
||||
};
|
||||
|
||||
- |
|
||||
|
@ -81,6 +81,7 @@ if:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,rpm-apq8084
|
||||
- qcom,rpm-msm8226
|
||||
- qcom,rpm-msm8916
|
||||
- qcom,rpm-msm8936
|
||||
- qcom,rpm-msm8974
|
||||
|
@ -24,6 +24,7 @@ properties:
|
||||
- rockchip,rk3588-bigcore1-grf
|
||||
- rockchip,rk3588-ioc
|
||||
- rockchip,rk3588-php-grf
|
||||
- rockchip,rk3588-pipe-phy-grf
|
||||
- rockchip,rk3588-sys-grf
|
||||
- rockchip,rk3588-pcie3-phy-grf
|
||||
- rockchip,rk3588-pcie3-pipe-grf
|
||||
@ -52,6 +53,7 @@ properties:
|
||||
- rockchip,rk3399-pmugrf
|
||||
- rockchip,rk3568-grf
|
||||
- rockchip,rk3568-pmugrf
|
||||
- rockchip,rk3588-usb2phy-grf
|
||||
- rockchip,rv1108-grf
|
||||
- rockchip,rv1108-pmugrf
|
||||
- rockchip,rv1126-grf
|
||||
@ -199,6 +201,7 @@ allOf:
|
||||
- rockchip,rk3308-usb2phy-grf
|
||||
- rockchip,rk3328-usb2phy-grf
|
||||
- rockchip,rk3399-grf
|
||||
- rockchip,rk3588-usb2phy-grf
|
||||
- rockchip,rv1108-grf
|
||||
|
||||
then:
|
||||
|
@ -17,6 +17,7 @@ select:
|
||||
enum:
|
||||
- samsung,exynos3250-pmu
|
||||
- samsung,exynos4210-pmu
|
||||
- samsung,exynos4212-pmu
|
||||
- samsung,exynos4412-pmu
|
||||
- samsung,exynos5250-pmu
|
||||
- samsung,exynos5260-pmu
|
||||
@ -36,6 +37,7 @@ properties:
|
||||
- enum:
|
||||
- samsung,exynos3250-pmu
|
||||
- samsung,exynos4210-pmu
|
||||
- samsung,exynos4212-pmu
|
||||
- samsung,exynos4412-pmu
|
||||
- samsung,exynos5250-pmu
|
||||
- samsung,exynos5260-pmu
|
||||
@ -50,6 +52,7 @@ properties:
|
||||
- enum:
|
||||
- samsung,exynos3250-pmu
|
||||
- samsung,exynos4210-pmu
|
||||
- samsung,exynos4212-pmu
|
||||
- samsung,exynos4412-pmu
|
||||
- samsung,exynos5250-pmu
|
||||
- samsung,exynos5420-pmu
|
||||
@ -125,6 +128,7 @@ allOf:
|
||||
enum:
|
||||
- samsung,exynos3250-pmu
|
||||
- samsung,exynos4210-pmu
|
||||
- samsung,exynos4212-pmu
|
||||
- samsung,exynos4412-pmu
|
||||
- samsung,exynos5250-pmu
|
||||
- samsung,exynos5410-pmu
|
||||
@ -143,6 +147,7 @@ allOf:
|
||||
enum:
|
||||
- samsung,exynos3250-pmu
|
||||
- samsung,exynos4210-pmu
|
||||
- samsung,exynos4212-pmu
|
||||
- samsung,exynos4412-pmu
|
||||
- samsung,exynos5250-pmu
|
||||
- samsung,exynos5420-pmu
|
||||
|
@ -18,9 +18,14 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt6873-spmi
|
||||
- mediatek,mt8195-spmi
|
||||
oneOf:
|
||||
- enum:
|
||||
- mediatek,mt6873-spmi
|
||||
- mediatek,mt8195-spmi
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8186-spmi
|
||||
- const: mediatek,mt8195-spmi
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
@ -18,8 +18,10 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,apq8064-imem
|
||||
- qcom,msm8226-imem
|
||||
- qcom,msm8974-imem
|
||||
- qcom,qcs404-imem
|
||||
- qcom,qdu1000-imem
|
||||
- qcom,sc7180-imem
|
||||
- qcom,sc7280-imem
|
||||
- qcom,sdm630-imem
|
||||
|
@ -94,6 +94,7 @@ patternProperties:
|
||||
- samsung,exynos4210-sysram
|
||||
- samsung,exynos4210-sysram-ns
|
||||
- socionext,milbeaut-smp-sram
|
||||
- stericsson,u8500-esram
|
||||
|
||||
reg:
|
||||
description:
|
||||
|
20
MAINTAINERS
20
MAINTAINERS
@ -1906,10 +1906,12 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: linux-amlogic@lists.infradead.org
|
||||
S: Maintained
|
||||
W: http://linux-meson.com/
|
||||
F: Documentation/devicetree/bindings/phy/amlogic*
|
||||
F: arch/arm/boot/dts/amlogic/
|
||||
F: arch/arm/mach-meson/
|
||||
F: arch/arm64/boot/dts/amlogic/
|
||||
F: drivers/mmc/host/meson*
|
||||
F: drivers/phy/amlogic/
|
||||
F: drivers/pinctrl/meson/
|
||||
F: drivers/rtc/rtc-meson*
|
||||
F: drivers/soc/amlogic/
|
||||
@ -2574,7 +2576,7 @@ F: arch/arm64/boot/dts/qcom/sdm845-cheza*
|
||||
ARM/QUALCOMM SUPPORT
|
||||
M: Andy Gross <agross@kernel.org>
|
||||
M: Bjorn Andersson <andersson@kernel.org>
|
||||
R: Konrad Dybcio <konrad.dybcio@linaro.org>
|
||||
M: Konrad Dybcio <konrad.dybcio@linaro.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
|
||||
@ -7107,7 +7109,6 @@ F: Documentation/gpu/xen-front.rst
|
||||
F: drivers/gpu/drm/xen/
|
||||
|
||||
DRM DRIVERS FOR XILINX
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
@ -23267,7 +23268,7 @@ F: Documentation/devicetree/bindings/iio/adc/xlnx,zynqmp-ams.yaml
|
||||
F: drivers/iio/adc/xilinx-ams.c
|
||||
|
||||
XILINX AXI ETHERNET DRIVER
|
||||
M: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
|
||||
M: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
|
||||
F: drivers/net/ethernet/xilinx/xilinx_axienet*
|
||||
@ -23287,8 +23288,8 @@ F: drivers/soc/xilinx/xlnx_event_manager.c
|
||||
F: include/linux/firmware/xlnx-event-manager.h
|
||||
|
||||
XILINX GPIO DRIVER
|
||||
M: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
|
||||
R: Srinivas Neeli <srinivas.neeli@xilinx.com>
|
||||
M: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
|
||||
R: Srinivas Neeli <srinivas.neeli@amd.com>
|
||||
R: Michal Simek <michal.simek@amd.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
|
||||
@ -23303,8 +23304,8 @@ F: drivers/pwm/pwm-xilinx.c
|
||||
F: include/clocksource/timer-xilinx.h
|
||||
|
||||
XILINX SD-FEC IP CORES
|
||||
M: Derek Kiernan <derek.kiernan@xilinx.com>
|
||||
M: Dragan Cvetic <dragan.cvetic@xilinx.com>
|
||||
M: Derek Kiernan <derek.kiernan@amd.com>
|
||||
M: Dragan Cvetic <dragan.cvetic@amd.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.txt
|
||||
F: Documentation/misc-devices/xilinx_sdfec.rst
|
||||
@ -23320,7 +23321,6 @@ S: Maintained
|
||||
F: drivers/tty/serial/uartlite.c
|
||||
|
||||
XILINX VIDEO IP CORES
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Supported
|
||||
@ -23349,7 +23349,6 @@ F: include/linux/dma/amd_xdma.h
|
||||
F: include/linux/platform_data/amd_xdma.h
|
||||
|
||||
XILINX ZYNQMP DPDMA DRIVER
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dmaengine@vger.kernel.org
|
||||
S: Supported
|
||||
@ -23365,7 +23364,6 @@ F: Documentation/devicetree/bindings/memory-controllers/xlnx,zynqmp-ocmc-1.0.yam
|
||||
F: drivers/edac/zynqmp_edac.c
|
||||
|
||||
XILINX ZYNQMP PSGTR PHY DRIVER
|
||||
M: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
@ -23374,7 +23372,7 @@ F: Documentation/devicetree/bindings/phy/xlnx,zynqmp-psgtr.yaml
|
||||
F: drivers/phy/xilinx/phy-zynqmp.c
|
||||
|
||||
XILINX ZYNQMP SHA3 DRIVER
|
||||
M: Harsha <harsha.harsha@xilinx.com>
|
||||
M: Harsha <harsha.harsha@amd.com>
|
||||
S: Maintained
|
||||
F: drivers/crypto/xilinx/zynqmp-sha.c
|
||||
|
||||
|
@ -97,7 +97,6 @@ config SOC_AT91SAM9
|
||||
depends on ARCH_MULTI_V5
|
||||
select ATMEL_AIC_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select CPU_ARM926T
|
||||
select HAVE_AT91_SMD
|
||||
select HAVE_AT91_USB_CLK
|
||||
@ -131,7 +130,6 @@ config SOC_SAM9X60
|
||||
depends on ARCH_MULTI_V5
|
||||
select ATMEL_AIC5_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select CPU_ARM926T
|
||||
select HAVE_AT91_USB_CLK
|
||||
select HAVE_AT91_GENERATED_CLK
|
||||
@ -213,7 +211,6 @@ config SOC_SAMA5
|
||||
bool
|
||||
select ATMEL_AIC5_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select MEMORY
|
||||
select SOC_SAM_V7
|
||||
select SRAM if PM
|
||||
@ -234,7 +231,6 @@ config SOC_SAMA7
|
||||
bool
|
||||
select ARM_GIC
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select MEMORY
|
||||
select SOC_SAM_V7
|
||||
select SRAM if PM
|
||||
|
@ -835,15 +835,14 @@ EXPORT_SYMBOL_GPL(dprc_cleanup);
|
||||
* It tears down the interrupts that were configured for the DPRC device.
|
||||
* It destroys the interrupt pool associated with this MC bus.
|
||||
*/
|
||||
static int dprc_remove(struct fsl_mc_device *mc_dev)
|
||||
static void dprc_remove(struct fsl_mc_device *mc_dev)
|
||||
{
|
||||
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
|
||||
|
||||
if (!is_fsl_mc_bus_dprc(mc_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!mc_bus->irq_resources)
|
||||
return -EINVAL;
|
||||
if (!mc_bus->irq_resources) {
|
||||
dev_err(&mc_dev->dev, "No irq resources, so unbinding the device failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev_get_msi_domain(&mc_dev->dev))
|
||||
dprc_teardown_irq(mc_dev);
|
||||
@ -853,7 +852,6 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
|
||||
dprc_cleanup(mc_dev);
|
||||
|
||||
dev_info(&mc_dev->dev, "DPRC device unbound from driver");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fsl_mc_device_id match_id_table[] = {
|
||||
|
@ -103,26 +103,32 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
|
||||
struct fsl_mc_resource *resource;
|
||||
int error = -EINVAL;
|
||||
|
||||
if (!fsl_mc_is_allocatable(mc_dev))
|
||||
goto out;
|
||||
|
||||
resource = mc_dev->resource;
|
||||
if (!resource || resource->data != mc_dev)
|
||||
goto out;
|
||||
|
||||
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
|
||||
mc_bus = to_fsl_mc_bus(mc_bus_dev);
|
||||
res_pool = resource->parent_pool;
|
||||
if (res_pool != &mc_bus->resource_pools[resource->type])
|
||||
|
||||
resource = mc_dev->resource;
|
||||
if (!resource || resource->data != mc_dev) {
|
||||
dev_err(&mc_bus_dev->dev, "resource mismatch\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
res_pool = resource->parent_pool;
|
||||
if (res_pool != &mc_bus->resource_pools[resource->type]) {
|
||||
dev_err(&mc_bus_dev->dev, "pool mismatch\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&res_pool->mutex);
|
||||
|
||||
if (res_pool->max_count <= 0)
|
||||
if (res_pool->max_count <= 0) {
|
||||
dev_err(&mc_bus_dev->dev, "max_count underflow\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
if (res_pool->free_count <= 0 ||
|
||||
res_pool->free_count > res_pool->max_count)
|
||||
res_pool->free_count > res_pool->max_count) {
|
||||
dev_err(&mc_bus_dev->dev, "free_count mismatch\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device is currently allocated, its resource is not
|
||||
@ -557,12 +563,9 @@ static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
|
||||
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
|
||||
struct fsl_mc_resource_pool *res_pool =
|
||||
&mc_bus->resource_pools[pool_type];
|
||||
int free_count = 0;
|
||||
|
||||
list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
|
||||
free_count++;
|
||||
list_for_each_entry_safe(resource, next, &res_pool->free_list, node)
|
||||
devm_kfree(&mc_bus_dev->dev, resource);
|
||||
}
|
||||
}
|
||||
|
||||
void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
|
||||
@ -609,22 +612,18 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
|
||||
* fsl_mc_allocator_remove - callback invoked when an allocatable device is
|
||||
* being removed from the system
|
||||
*/
|
||||
static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
|
||||
static void fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!fsl_mc_is_allocatable(mc_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (mc_dev->resource) {
|
||||
error = fsl_mc_resource_pool_remove_device(mc_dev);
|
||||
if (error < 0)
|
||||
return error;
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(&mc_dev->dev,
|
||||
"Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fsl_mc_device_id match_id_table[] = {
|
||||
|
@ -454,13 +454,8 @@ static int fsl_mc_driver_remove(struct device *dev)
|
||||
{
|
||||
struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
|
||||
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
|
||||
int error;
|
||||
|
||||
error = mc_drv->remove(mc_dev);
|
||||
if (error < 0) {
|
||||
dev_err(dev, "%s failed: %d\n", __func__, error);
|
||||
return error;
|
||||
}
|
||||
mc_drv->remove(mc_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1791,7 +1791,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
|
||||
if (!ddata->module_va)
|
||||
return -EIO;
|
||||
|
||||
/* DISP_CONTROL */
|
||||
/* DISP_CONTROL, shut down lcd and digit on disable if enabled */
|
||||
val = sysc_read(ddata, dispc_offset + 0x40);
|
||||
lcd_en = val & lcd_en_mask;
|
||||
digit_en = val & digit_en_mask;
|
||||
@ -1803,7 +1803,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
|
||||
else
|
||||
irq_mask |= BIT(2) | BIT(3); /* EVSYNC bits */
|
||||
}
|
||||
if (disable & (lcd_en | digit_en))
|
||||
if (disable && (lcd_en || digit_en))
|
||||
sysc_write(ddata, dispc_offset + 0x40,
|
||||
val & ~(lcd_en_mask | digit_en_mask));
|
||||
|
||||
|
@ -29,20 +29,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
|
||||
#define MSM_ID_SMEM 137
|
||||
|
||||
enum _msm_id {
|
||||
MSM8996V3 = 0xF6ul,
|
||||
APQ8096V3 = 0x123ul,
|
||||
MSM8996SG = 0x131ul,
|
||||
APQ8096SG = 0x138ul,
|
||||
};
|
||||
|
||||
enum _msm8996_version {
|
||||
MSM8996_V3,
|
||||
MSM8996_SG,
|
||||
NUM_OF_MSM8996_VERSIONS,
|
||||
};
|
||||
#include <dt-bindings/arm/qcom,ids.h>
|
||||
|
||||
struct qcom_cpufreq_drv;
|
||||
|
||||
@ -140,60 +127,32 @@ static void get_krait_bin_format_b(struct device *cpu_dev,
|
||||
dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver);
|
||||
}
|
||||
|
||||
static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
|
||||
{
|
||||
size_t len;
|
||||
u32 *msm_id;
|
||||
enum _msm8996_version version;
|
||||
|
||||
msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
|
||||
if (IS_ERR(msm_id))
|
||||
return NUM_OF_MSM8996_VERSIONS;
|
||||
|
||||
/* The first 4 bytes are format, next to them is the actual msm-id */
|
||||
msm_id++;
|
||||
|
||||
switch ((enum _msm_id)*msm_id) {
|
||||
case MSM8996V3:
|
||||
case APQ8096V3:
|
||||
version = MSM8996_V3;
|
||||
break;
|
||||
case MSM8996SG:
|
||||
case APQ8096SG:
|
||||
version = MSM8996_SG;
|
||||
break;
|
||||
default:
|
||||
version = NUM_OF_MSM8996_VERSIONS;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
|
||||
struct nvmem_cell *speedbin_nvmem,
|
||||
char **pvs_name,
|
||||
struct qcom_cpufreq_drv *drv)
|
||||
{
|
||||
size_t len;
|
||||
u32 msm_id;
|
||||
u8 *speedbin;
|
||||
enum _msm8996_version msm8996_version;
|
||||
int ret;
|
||||
*pvs_name = NULL;
|
||||
|
||||
msm8996_version = qcom_cpufreq_get_msm_id();
|
||||
if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
|
||||
dev_err(cpu_dev, "Not Snapdragon 820/821!");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = qcom_smem_get_soc_id(&msm_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
|
||||
if (IS_ERR(speedbin))
|
||||
return PTR_ERR(speedbin);
|
||||
|
||||
switch (msm8996_version) {
|
||||
case MSM8996_V3:
|
||||
switch (msm_id) {
|
||||
case QCOM_ID_MSM8996:
|
||||
case QCOM_ID_APQ8096:
|
||||
drv->versions = 1 << (unsigned int)(*speedbin);
|
||||
break;
|
||||
case MSM8996_SG:
|
||||
case QCOM_ID_MSM8996SG:
|
||||
case QCOM_ID_APQ8096SG:
|
||||
drv->versions = 1 << ((unsigned int)(*speedbin) + 4);
|
||||
break;
|
||||
default:
|
||||
|
@ -5402,7 +5402,7 @@ err_dma_mask:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev)
|
||||
static void __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev)
|
||||
{
|
||||
struct device *dev;
|
||||
struct dpaa2_caam_priv *priv;
|
||||
@ -5443,8 +5443,6 @@ static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev)
|
||||
free_percpu(priv->ppriv);
|
||||
fsl_mc_portal_free(priv->mc_io);
|
||||
kmem_cache_destroy(qi_cache);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req)
|
||||
|
@ -765,7 +765,7 @@ err_mcportal:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev)
|
||||
static void dpaa2_qdma_remove(struct fsl_mc_device *ls_dev)
|
||||
{
|
||||
struct dpaa2_qdma_engine *dpaa2_qdma;
|
||||
struct dpaa2_qdma_priv *priv;
|
||||
@ -787,8 +787,6 @@ static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev)
|
||||
dma_async_device_unregister(&dpaa2_qdma->dma_dev);
|
||||
kfree(priv);
|
||||
kfree(dpaa2_qdma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev)
|
||||
|
@ -2914,6 +2914,7 @@ static const struct of_device_id scmi_of_match[] = {
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
|
||||
{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
|
||||
{ .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
|
||||
{ .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
|
||||
|
@ -108,6 +108,8 @@ struct scmi_powercap_meas_changed_notify_payld {
|
||||
};
|
||||
|
||||
struct scmi_powercap_state {
|
||||
bool enabled;
|
||||
u32 last_pcap;
|
||||
bool meas_notif_enabled;
|
||||
u64 thresholds;
|
||||
#define THRESH_LOW(p, id) \
|
||||
@ -313,24 +315,33 @@ static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
|
||||
u32 domain_id, u32 *power_cap)
|
||||
static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
|
||||
const struct scmi_powercap_info *dom,
|
||||
u32 *power_cap)
|
||||
{
|
||||
struct scmi_powercap_info *dom;
|
||||
struct powercap_info *pi = ph->get_priv(ph);
|
||||
|
||||
if (!power_cap || domain_id >= pi->num_domains)
|
||||
return -EINVAL;
|
||||
|
||||
dom = pi->powercaps + domain_id;
|
||||
if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) {
|
||||
*power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr);
|
||||
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET,
|
||||
domain_id, *power_cap, 0);
|
||||
dom->id, *power_cap, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return scmi_powercap_xfer_cap_get(ph, domain_id, power_cap);
|
||||
return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap);
|
||||
}
|
||||
|
||||
static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
|
||||
u32 domain_id, u32 *power_cap)
|
||||
{
|
||||
const struct scmi_powercap_info *dom;
|
||||
|
||||
if (!power_cap)
|
||||
return -EINVAL;
|
||||
|
||||
dom = scmi_powercap_dom_info_get(ph, domain_id);
|
||||
if (!dom)
|
||||
return -EINVAL;
|
||||
|
||||
return __scmi_powercap_cap_get(ph, dom, power_cap);
|
||||
}
|
||||
|
||||
static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
|
||||
@ -375,17 +386,20 @@ static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
|
||||
u32 domain_id, u32 power_cap,
|
||||
bool ignore_dresp)
|
||||
static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
|
||||
struct powercap_info *pi, u32 domain_id,
|
||||
u32 power_cap, bool ignore_dresp)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
const struct scmi_powercap_info *pc;
|
||||
|
||||
pc = scmi_powercap_dom_info_get(ph, domain_id);
|
||||
if (!pc || !pc->powercap_cap_config || !power_cap ||
|
||||
power_cap < pc->min_power_cap ||
|
||||
power_cap > pc->max_power_cap)
|
||||
return -EINVAL;
|
||||
if (!pc || !pc->powercap_cap_config)
|
||||
return ret;
|
||||
|
||||
if (power_cap &&
|
||||
(power_cap < pc->min_power_cap || power_cap > pc->max_power_cap))
|
||||
return ret;
|
||||
|
||||
if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) {
|
||||
struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP];
|
||||
@ -394,10 +408,41 @@ static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
|
||||
ph->hops->fastchannel_db_ring(fci->set_db);
|
||||
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET,
|
||||
domain_id, power_cap, 0);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = scmi_powercap_xfer_cap_set(ph, pc, power_cap,
|
||||
ignore_dresp);
|
||||
}
|
||||
|
||||
/* Save the last explicitly set non-zero powercap value */
|
||||
if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap)
|
||||
pi->states[domain_id].last_pcap = power_cap;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
|
||||
u32 domain_id, u32 power_cap,
|
||||
bool ignore_dresp)
|
||||
{
|
||||
struct powercap_info *pi = ph->get_priv(ph);
|
||||
|
||||
/*
|
||||
* Disallow zero as a possible explicitly requested powercap:
|
||||
* there are enable/disable operations for this.
|
||||
*/
|
||||
if (!power_cap)
|
||||
return -EINVAL;
|
||||
|
||||
/* Just log the last set request if acting on a disabled domain */
|
||||
if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 &&
|
||||
!pi->states[domain_id].enabled) {
|
||||
pi->states[domain_id].last_pcap = power_cap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return scmi_powercap_xfer_cap_set(ph, pc, power_cap, ignore_dresp);
|
||||
return __scmi_powercap_cap_set(ph, pi, domain_id,
|
||||
power_cap, ignore_dresp);
|
||||
}
|
||||
|
||||
static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
|
||||
@ -564,11 +609,78 @@ scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph,
|
||||
u32 domain_id, bool enable)
|
||||
{
|
||||
int ret;
|
||||
u32 power_cap;
|
||||
struct powercap_info *pi = ph->get_priv(ph);
|
||||
|
||||
if (PROTOCOL_REV_MAJOR(pi->version) < 0x2)
|
||||
return -EINVAL;
|
||||
|
||||
if (enable == pi->states[domain_id].enabled)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
/* Cannot enable with a zero powercap. */
|
||||
if (!pi->states[domain_id].last_pcap)
|
||||
return -EINVAL;
|
||||
|
||||
ret = __scmi_powercap_cap_set(ph, pi, domain_id,
|
||||
pi->states[domain_id].last_pcap,
|
||||
true);
|
||||
} else {
|
||||
ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Update our internal state to reflect final platform state: the SCMI
|
||||
* server could have ignored a disable request and kept enforcing some
|
||||
* powercap limit requested by other agents.
|
||||
*/
|
||||
ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
|
||||
if (!ret)
|
||||
pi->states[domain_id].enabled = !!power_cap;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph,
|
||||
u32 domain_id, bool *enable)
|
||||
{
|
||||
int ret;
|
||||
u32 power_cap;
|
||||
struct powercap_info *pi = ph->get_priv(ph);
|
||||
|
||||
*enable = true;
|
||||
if (PROTOCOL_REV_MAJOR(pi->version) < 0x2)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Report always real platform state; platform could have ignored
|
||||
* a previous disable request. Default true on any error.
|
||||
*/
|
||||
ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
|
||||
if (!ret)
|
||||
*enable = !!power_cap;
|
||||
|
||||
/* Update internal state with current real platform state */
|
||||
pi->states[domain_id].enabled = *enable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct scmi_powercap_proto_ops powercap_proto_ops = {
|
||||
.num_domains_get = scmi_powercap_num_domains_get,
|
||||
.info_get = scmi_powercap_dom_info_get,
|
||||
.cap_get = scmi_powercap_cap_get,
|
||||
.cap_set = scmi_powercap_cap_set,
|
||||
.cap_enable_set = scmi_powercap_cap_enable_set,
|
||||
.cap_enable_get = scmi_powercap_cap_enable_get,
|
||||
.pai_get = scmi_powercap_pai_get,
|
||||
.pai_set = scmi_powercap_pai_set,
|
||||
.measurements_get = scmi_powercap_measurements_get,
|
||||
@ -829,6 +941,11 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
|
||||
if (!pinfo->powercaps)
|
||||
return -ENOMEM;
|
||||
|
||||
pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
|
||||
sizeof(*pinfo->states), GFP_KERNEL);
|
||||
if (!pinfo->states)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Note that any failure in retrieving any domain attribute leads to
|
||||
* the whole Powercap protocol initialization failure: this way the
|
||||
@ -843,15 +960,21 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
|
||||
if (pinfo->powercaps[domain].fastchannels)
|
||||
scmi_powercap_domain_init_fc(ph, domain,
|
||||
&pinfo->powercaps[domain].fc_info);
|
||||
|
||||
/* Grab initial state when disable is supported. */
|
||||
if (PROTOCOL_REV_MAJOR(version) >= 0x2) {
|
||||
ret = __scmi_powercap_cap_get(ph,
|
||||
&pinfo->powercaps[domain],
|
||||
&pinfo->states[domain].last_pcap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pinfo->states[domain].enabled =
|
||||
!!pinfo->states[domain].last_pcap;
|
||||
}
|
||||
}
|
||||
|
||||
pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
|
||||
sizeof(*pinfo->states), GFP_KERNEL);
|
||||
if (!pinfo->states)
|
||||
return -ENOMEM;
|
||||
|
||||
pinfo->version = version;
|
||||
|
||||
return ph->set_priv(ph, pinfo);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,23 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* The shmem address is split into 4K page and offset.
|
||||
* This is to make sure the parameters fit in 32bit arguments of the
|
||||
* smc/hvc call to keep it uniform across smc32/smc64 conventions.
|
||||
* This however limits the shmem address to 44 bit.
|
||||
*
|
||||
* These optional parameters can be used to distinguish among multiple
|
||||
* scmi instances that are using the same smc-id.
|
||||
* The page parameter is passed in r1/x1/w1 register and the offset parameter
|
||||
* is passed in r2/x2/w2 register.
|
||||
*/
|
||||
|
||||
#define SHMEM_SIZE (SZ_4K)
|
||||
#define SHMEM_SHIFT 12
|
||||
#define SHMEM_PAGE(x) (_UL((x) >> SHMEM_SHIFT))
|
||||
#define SHMEM_OFFSET(x) ((x) & (SHMEM_SIZE - 1))
|
||||
|
||||
/**
|
||||
* struct scmi_smc - Structure representing a SCMI smc transport
|
||||
*
|
||||
@ -30,6 +47,8 @@
|
||||
* @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
|
||||
* Used when operating in atomic mode.
|
||||
* @func_id: smc/hvc call function id
|
||||
* @param_page: 4K page number of the shmem channel
|
||||
* @param_offset: Offset within the 4K page of the shmem channel
|
||||
*/
|
||||
|
||||
struct scmi_smc {
|
||||
@ -40,6 +59,8 @@ struct scmi_smc {
|
||||
#define INFLIGHT_NONE MSG_TOKEN_MAX
|
||||
atomic_t inflight;
|
||||
u32 func_id;
|
||||
u32 param_page;
|
||||
u32 param_offset;
|
||||
};
|
||||
|
||||
static irqreturn_t smc_msg_done_isr(int irq, void *data)
|
||||
@ -137,6 +158,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param")) {
|
||||
scmi_info->param_page = SHMEM_PAGE(res.start);
|
||||
scmi_info->param_offset = SHMEM_OFFSET(res.start);
|
||||
}
|
||||
/*
|
||||
* If there is an interrupt named "a2p", then the service and
|
||||
* completion of a message is signaled by an interrupt rather than by
|
||||
@ -179,6 +204,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
|
||||
{
|
||||
struct scmi_smc *scmi_info = cinfo->transport_info;
|
||||
struct arm_smccc_res res;
|
||||
unsigned long page = scmi_info->param_page;
|
||||
unsigned long offset = scmi_info->param_offset;
|
||||
|
||||
/*
|
||||
* Channel will be released only once response has been
|
||||
@ -188,7 +215,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
|
||||
|
||||
shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
|
||||
|
||||
arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
arm_smccc_1_1_invoke(scmi_info->func_id, page, offset, 0, 0, 0, 0, 0,
|
||||
&res);
|
||||
|
||||
/* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
|
||||
if (res.a0) {
|
||||
|
@ -4,7 +4,9 @@
|
||||
*/
|
||||
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <soc/tegra/bpmp.h>
|
||||
@ -18,7 +20,10 @@ struct tegra186_bpmp {
|
||||
|
||||
struct {
|
||||
struct gen_pool *pool;
|
||||
void __iomem *virt;
|
||||
union {
|
||||
void __iomem *sram;
|
||||
void *dram;
|
||||
};
|
||||
dma_addr_t phys;
|
||||
} tx, rx;
|
||||
|
||||
@ -118,8 +123,13 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
|
||||
queue_size = tegra_ivc_total_queue_size(message_size);
|
||||
offset = queue_size * index;
|
||||
|
||||
iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset);
|
||||
iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + offset);
|
||||
if (priv->rx.pool) {
|
||||
iosys_map_set_vaddr_iomem(&rx, priv->rx.sram + offset);
|
||||
iosys_map_set_vaddr_iomem(&tx, priv->tx.sram + offset);
|
||||
} else {
|
||||
iosys_map_set_vaddr(&rx, priv->rx.dram + offset);
|
||||
iosys_map_set_vaddr(&tx, priv->tx.dram + offset);
|
||||
}
|
||||
|
||||
err = tegra_ivc_init(channel->ivc, NULL, &rx, priv->rx.phys + offset, &tx,
|
||||
priv->tx.phys + offset, 1, message_size, tegra186_bpmp_ivc_notify,
|
||||
@ -158,18 +168,72 @@ static void mbox_handle_rx(struct mbox_client *client, void *data)
|
||||
tegra_bpmp_handle_rx(bpmp);
|
||||
}
|
||||
|
||||
static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
static void tegra186_bpmp_teardown_channels(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
struct tegra186_bpmp *priv;
|
||||
struct tegra186_bpmp *priv = bpmp->priv;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < bpmp->threaded.count; i++) {
|
||||
if (!bpmp->threaded_channels[i].bpmp)
|
||||
continue;
|
||||
|
||||
tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
|
||||
}
|
||||
|
||||
tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
|
||||
tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
|
||||
|
||||
if (priv->tx.pool) {
|
||||
gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.sram, 4096);
|
||||
gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.sram, 4096);
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra186_bpmp_dram_init(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
struct tegra186_bpmp *priv = bpmp->priv;
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
size_t size;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
np = of_parse_phandle(bpmp->dev->of_node, "memory-region", 0);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
bpmp->priv = priv;
|
||||
priv->parent = bpmp;
|
||||
err = of_address_to_resource(np, 0, &res);
|
||||
if (err < 0) {
|
||||
dev_warn(bpmp->dev, "failed to parse memory region: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
size = resource_size(&res);
|
||||
|
||||
if (size < SZ_8K) {
|
||||
dev_warn(bpmp->dev, "DRAM region must be larger than 8 KiB\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->tx.phys = res.start;
|
||||
priv->rx.phys = res.start + SZ_4K;
|
||||
|
||||
priv->tx.dram = devm_memremap(bpmp->dev, priv->tx.phys, size,
|
||||
MEMREMAP_WC);
|
||||
if (IS_ERR(priv->tx.dram)) {
|
||||
err = PTR_ERR(priv->tx.dram);
|
||||
dev_warn(bpmp->dev, "failed to map DRAM region: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
priv->rx.dram = priv->tx.dram + SZ_4K;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_bpmp_sram_init(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
struct tegra186_bpmp *priv = bpmp->priv;
|
||||
int err;
|
||||
|
||||
priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
|
||||
if (!priv->tx.pool) {
|
||||
@ -177,8 +241,9 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
priv->tx.virt = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
|
||||
if (!priv->tx.virt) {
|
||||
priv->tx.sram = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096,
|
||||
&priv->tx.phys);
|
||||
if (!priv->tx.sram) {
|
||||
dev_err(bpmp->dev, "failed to allocate from TX pool\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -190,22 +255,45 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
goto free_tx;
|
||||
}
|
||||
|
||||
priv->rx.virt = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
|
||||
if (!priv->rx.virt) {
|
||||
priv->rx.sram = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096,
|
||||
&priv->rx.phys);
|
||||
if (!priv->rx.sram) {
|
||||
dev_err(bpmp->dev, "failed to allocate from RX pool\n");
|
||||
err = -ENOMEM;
|
||||
goto free_tx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_tx:
|
||||
gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.sram, 4096);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra186_bpmp_setup_channels(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
err = tegra186_bpmp_dram_init(bpmp);
|
||||
if (err == -ENODEV) {
|
||||
err = tegra186_bpmp_sram_init(bpmp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
|
||||
bpmp->soc->channels.cpu_tx.offset);
|
||||
if (err < 0)
|
||||
goto free_rx;
|
||||
return err;
|
||||
|
||||
err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
|
||||
bpmp->soc->channels.cpu_rx.offset);
|
||||
if (err < 0)
|
||||
goto cleanup_tx_channel;
|
||||
if (err < 0) {
|
||||
tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < bpmp->threaded.count; i++) {
|
||||
unsigned int index = bpmp->soc->channels.thread.offset + i;
|
||||
@ -213,9 +301,43 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
|
||||
bpmp, index);
|
||||
if (err < 0)
|
||||
goto cleanup_channels;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
tegra186_bpmp_teardown_channels(bpmp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tegra186_bpmp_reset_channels(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* reset message channels */
|
||||
tegra186_bpmp_channel_reset(bpmp->tx_channel);
|
||||
tegra186_bpmp_channel_reset(bpmp->rx_channel);
|
||||
|
||||
for (i = 0; i < bpmp->threaded.count; i++)
|
||||
tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
|
||||
}
|
||||
|
||||
static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
struct tegra186_bpmp *priv;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->parent = bpmp;
|
||||
bpmp->priv = priv;
|
||||
|
||||
err = tegra186_bpmp_setup_channels(bpmp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* mbox registration */
|
||||
priv->mbox.client.dev = bpmp->dev;
|
||||
priv->mbox.client.rx_callback = mbox_handle_rx;
|
||||
@ -226,63 +348,27 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
if (IS_ERR(priv->mbox.channel)) {
|
||||
err = PTR_ERR(priv->mbox.channel);
|
||||
dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
|
||||
goto cleanup_channels;
|
||||
tegra186_bpmp_teardown_channels(bpmp);
|
||||
return err;
|
||||
}
|
||||
|
||||
tegra186_bpmp_channel_reset(bpmp->tx_channel);
|
||||
tegra186_bpmp_channel_reset(bpmp->rx_channel);
|
||||
|
||||
for (i = 0; i < bpmp->threaded.count; i++)
|
||||
tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
|
||||
tegra186_bpmp_reset_channels(bpmp);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_channels:
|
||||
for (i = 0; i < bpmp->threaded.count; i++) {
|
||||
if (!bpmp->threaded_channels[i].bpmp)
|
||||
continue;
|
||||
|
||||
tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
|
||||
}
|
||||
|
||||
tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
|
||||
cleanup_tx_channel:
|
||||
tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
|
||||
free_rx:
|
||||
gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
|
||||
free_tx:
|
||||
gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
struct tegra186_bpmp *priv = bpmp->priv;
|
||||
unsigned int i;
|
||||
|
||||
mbox_free_channel(priv->mbox.channel);
|
||||
|
||||
for (i = 0; i < bpmp->threaded.count; i++)
|
||||
tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
|
||||
|
||||
tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
|
||||
tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
|
||||
|
||||
gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
|
||||
gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
|
||||
tegra186_bpmp_teardown_channels(bpmp);
|
||||
}
|
||||
|
||||
static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* reset message channels */
|
||||
tegra186_bpmp_channel_reset(bpmp->tx_channel);
|
||||
tegra186_bpmp_channel_reset(bpmp->rx_channel);
|
||||
|
||||
for (i = 0; i < bpmp->threaded.count; i++)
|
||||
tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
|
||||
tegra186_bpmp_reset_channels(bpmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -735,6 +735,8 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
|
||||
if (!bpmp->threaded_channels)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, bpmp);
|
||||
|
||||
err = bpmp->soc->ops->init(bpmp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -758,8 +760,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
|
||||
|
||||
dev_info(&pdev->dev, "firmware: %.*s\n", (int)sizeof(tag), tag);
|
||||
|
||||
platform_set_drvdata(pdev, bpmp);
|
||||
|
||||
err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev);
|
||||
if (err < 0)
|
||||
goto free_mrq;
|
||||
|
@ -942,8 +942,16 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
|
||||
*/
|
||||
int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
|
||||
upper_32_bits(address), size, flags, NULL);
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
|
||||
ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
|
||||
upper_32_bits(address), size, flags,
|
||||
ret_payload);
|
||||
if (ret_payload[0])
|
||||
return -ret_payload[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
|
||||
|
||||
|
@ -30,17 +30,6 @@ config ARM_PL172_MPMC
|
||||
If you have an embedded system with an AMBA bus and a PL172
|
||||
controller, say Y or M here.
|
||||
|
||||
config ATMEL_SDRAMC
|
||||
bool "Atmel (Multi-port DDR-)SDRAM Controller"
|
||||
default y if ARCH_AT91
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
This driver is for Atmel SDRAM Controller or Atmel Multi-port
|
||||
DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs.
|
||||
Starting with the at91sam9g45, this controller supports SDR, DDR and
|
||||
LP-DDR memories.
|
||||
|
||||
config ATMEL_EBI
|
||||
bool "Atmel EBI driver"
|
||||
default y if ARCH_AT91
|
||||
|
@ -8,7 +8,6 @@ ifeq ($(CONFIG_DDR),y)
|
||||
obj-$(CONFIG_OF) += of_memory.o
|
||||
endif
|
||||
obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
|
||||
obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
|
||||
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
|
||||
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
|
||||
obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o
|
||||
|
@ -1,74 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Atmel (Multi-port DDR-)SDRAM Controller driver
|
||||
*
|
||||
* Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
*
|
||||
* Copyright (C) 2014 Atmel
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct at91_ramc_caps {
|
||||
bool has_ddrck;
|
||||
bool has_mpddr_clk;
|
||||
};
|
||||
|
||||
static const struct at91_ramc_caps at91rm9200_caps = { };
|
||||
|
||||
static const struct at91_ramc_caps at91sam9g45_caps = {
|
||||
.has_ddrck = 1,
|
||||
.has_mpddr_clk = 0,
|
||||
};
|
||||
|
||||
static const struct at91_ramc_caps sama5d3_caps = {
|
||||
.has_ddrck = 1,
|
||||
.has_mpddr_clk = 1,
|
||||
};
|
||||
|
||||
static const struct of_device_id atmel_ramc_of_match[] = {
|
||||
{ .compatible = "atmel,at91rm9200-sdramc", .data = &at91rm9200_caps, },
|
||||
{ .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, },
|
||||
{ .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, },
|
||||
{ .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, },
|
||||
{},
|
||||
};
|
||||
|
||||
static int atmel_ramc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct at91_ramc_caps *caps;
|
||||
struct clk *clk;
|
||||
|
||||
caps = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
if (caps->has_ddrck) {
|
||||
clk = devm_clk_get_enabled(&pdev->dev, "ddrck");
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
if (caps->has_mpddr_clk) {
|
||||
clk = devm_clk_get_enabled(&pdev->dev, "mpddr");
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("AT91 RAMC: couldn't get mpddr clock\n");
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver atmel_ramc_driver = {
|
||||
.probe = atmel_ramc_probe,
|
||||
.driver = {
|
||||
.name = "atmel-ramc",
|
||||
.of_match_table = atmel_ramc_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(atmel_ramc_driver);
|
@ -434,15 +434,17 @@ static void __finalize_command(struct brcmstb_dpfe_priv *priv)
|
||||
static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
|
||||
u32 result[])
|
||||
{
|
||||
const u32 *msg = priv->dpfe_api->command[cmd];
|
||||
void __iomem *regs = priv->regs;
|
||||
unsigned int i, chksum, chksum_idx;
|
||||
const u32 *msg;
|
||||
int ret = 0;
|
||||
u32 resp;
|
||||
|
||||
if (cmd >= DPFE_CMD_MAX)
|
||||
return -1;
|
||||
|
||||
msg = priv->dpfe_api->command[cmd];
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
/* Wait for DCPU to become ready */
|
||||
|
@ -7,6 +7,7 @@
|
||||
* Copyright (C) 2019-2020 Cogent Embedded, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
@ -163,6 +164,11 @@ static const struct regmap_access_table rpcif_volatile_table = {
|
||||
.n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges),
|
||||
};
|
||||
|
||||
struct rpcif_info {
|
||||
enum rpcif_type type;
|
||||
u8 strtim;
|
||||
};
|
||||
|
||||
struct rpcif_priv {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
@ -171,7 +177,7 @@ struct rpcif_priv {
|
||||
struct reset_control *rstc;
|
||||
struct platform_device *vdev;
|
||||
size_t size;
|
||||
enum rpcif_type type;
|
||||
const struct rpcif_info *info;
|
||||
enum rpcif_data_dir dir;
|
||||
u8 bus_size;
|
||||
u8 xfer_size;
|
||||
@ -186,6 +192,26 @@ struct rpcif_priv {
|
||||
u32 ddr; /* DRDRENR or SMDRENR */
|
||||
};
|
||||
|
||||
static const struct rpcif_info rpcif_info_r8a7796 = {
|
||||
.type = RPCIF_RCAR_GEN3,
|
||||
.strtim = 6,
|
||||
};
|
||||
|
||||
static const struct rpcif_info rpcif_info_gen3 = {
|
||||
.type = RPCIF_RCAR_GEN3,
|
||||
.strtim = 7,
|
||||
};
|
||||
|
||||
static const struct rpcif_info rpcif_info_rz_g2l = {
|
||||
.type = RPCIF_RZ_G2L,
|
||||
.strtim = 7,
|
||||
};
|
||||
|
||||
static const struct rpcif_info rpcif_info_gen4 = {
|
||||
.type = RPCIF_RCAR_GEN4,
|
||||
.strtim = 15,
|
||||
};
|
||||
|
||||
/*
|
||||
* Custom accessor functions to ensure SM[RW]DR[01] are always accessed with
|
||||
* proper width. Requires rpcif_priv.xfer_size to be correctly set before!
|
||||
@ -310,7 +336,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (rpc->type == RPCIF_RZ_G2L) {
|
||||
if (rpc->info->type == RPCIF_RZ_G2L) {
|
||||
ret = reset_control_reset(rpc->rstc);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -324,12 +350,10 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
|
||||
/* DMA Transfer is not supported */
|
||||
regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0);
|
||||
|
||||
if (rpc->type == RPCIF_RCAR_GEN3)
|
||||
regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
|
||||
RPCIF_PHYCNT_STRTIM(7), RPCIF_PHYCNT_STRTIM(7));
|
||||
else if (rpc->type == RPCIF_RCAR_GEN4)
|
||||
regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
|
||||
RPCIF_PHYCNT_STRTIM(15), RPCIF_PHYCNT_STRTIM(15));
|
||||
regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
|
||||
/* create mask with all affected bits set */
|
||||
RPCIF_PHYCNT_STRTIM(BIT(fls(rpc->info->strtim)) - 1),
|
||||
RPCIF_PHYCNT_STRTIM(rpc->info->strtim));
|
||||
|
||||
regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET1, RPCIF_PHYOFFSET1_DDRTMG(3),
|
||||
RPCIF_PHYOFFSET1_DDRTMG(3));
|
||||
@ -340,7 +364,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
|
||||
regmap_update_bits(rpc->regmap, RPCIF_PHYINT,
|
||||
RPCIF_PHYINT_WPVAL, 0);
|
||||
|
||||
if (rpc->type == RPCIF_RZ_G2L)
|
||||
if (rpc->info->type == RPCIF_RZ_G2L)
|
||||
regmap_update_bits(rpc->regmap, RPCIF_CMNCR,
|
||||
RPCIF_CMNCR_MOIIO(3) | RPCIF_CMNCR_IOFV(3) |
|
||||
RPCIF_CMNCR_BSZ(3),
|
||||
@ -729,9 +753,9 @@ static int rpcif_probe(struct platform_device *pdev)
|
||||
rpc->dirmap = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(rpc->dirmap))
|
||||
return PTR_ERR(rpc->dirmap);
|
||||
rpc->size = resource_size(res);
|
||||
|
||||
rpc->type = (uintptr_t)of_device_get_match_data(dev);
|
||||
rpc->size = resource_size(res);
|
||||
rpc->info = of_device_get_match_data(dev);
|
||||
rpc->rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||
if (IS_ERR(rpc->rstc))
|
||||
return PTR_ERR(rpc->rstc);
|
||||
@ -764,9 +788,10 @@ static int rpcif_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id rpcif_of_match[] = {
|
||||
{ .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 },
|
||||
{ .compatible = "renesas,rcar-gen4-rpc-if", .data = (void *)RPCIF_RCAR_GEN4 },
|
||||
{ .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L },
|
||||
{ .compatible = "renesas,r8a7796-rpc-if", .data = &rpcif_info_r8a7796 },
|
||||
{ .compatible = "renesas,rcar-gen3-rpc-if", .data = &rpcif_info_gen3 },
|
||||
{ .compatible = "renesas,rcar-gen4-rpc-if", .data = &rpcif_info_gen4 },
|
||||
{ .compatible = "renesas,rzg2l-rpc-if", .data = &rpcif_info_rz_g2l },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rpcif_of_match);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sort.h>
|
||||
#include <linux/tegra-icc.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
@ -792,6 +793,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
|
||||
mc->provider.data = &mc->provider;
|
||||
mc->provider.set = mc->soc->icc_ops->set;
|
||||
mc->provider.aggregate = mc->soc->icc_ops->aggregate;
|
||||
mc->provider.get_bw = mc->soc->icc_ops->get_bw;
|
||||
mc->provider.xlate = mc->soc->icc_ops->xlate;
|
||||
mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended;
|
||||
|
||||
icc_provider_init(&mc->provider);
|
||||
@ -824,6 +827,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
|
||||
err = icc_link_create(node, TEGRA_ICC_MC);
|
||||
if (err)
|
||||
goto remove_nodes;
|
||||
|
||||
node->data = (struct tegra_mc_client *)&(mc->soc->clients[i]);
|
||||
}
|
||||
|
||||
err = icc_provider_register(&mc->provider);
|
||||
@ -838,6 +843,23 @@ remove_nodes:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tegra_mc_num_channel_enabled(struct tegra_mc *mc)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 value;
|
||||
|
||||
value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE);
|
||||
if (value <= 0) {
|
||||
mc->num_channels = mc->soc->num_channels;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (value & BIT(i))
|
||||
mc->num_channels++;
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra_mc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_mc *mc;
|
||||
@ -876,6 +898,8 @@ static int tegra_mc_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
tegra_mc_num_channel_enabled(mc);
|
||||
|
||||
if (mc->soc->ops && mc->soc->ops->handle_irq) {
|
||||
mc->irq = platform_get_irq(pdev, 0);
|
||||
if (mc->irq < 0)
|
||||
|
@ -53,6 +53,7 @@
|
||||
#define MC_ERR_ROUTE_SANITY_ADR 0x9c4
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
|
||||
#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8
|
||||
#define MC_GLOBAL_INTSTATUS 0xf24
|
||||
#define MC_ERR_ADR_HI 0x11fc
|
||||
|
||||
|
@ -7,9 +7,11 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <soc/tegra/bpmp.h>
|
||||
#include "mc.h"
|
||||
|
||||
struct tegra186_emc_dvfs {
|
||||
unsigned long latency;
|
||||
@ -29,8 +31,15 @@ struct tegra186_emc {
|
||||
unsigned long min_rate;
|
||||
unsigned long max_rate;
|
||||
} debugfs;
|
||||
|
||||
struct icc_provider provider;
|
||||
};
|
||||
|
||||
static inline struct tegra186_emc *to_tegra186_emc(struct icc_provider *provider)
|
||||
{
|
||||
return container_of(provider, struct tegra186_emc, provider);
|
||||
}
|
||||
|
||||
/*
|
||||
* debugfs interface
|
||||
*
|
||||
@ -146,8 +155,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops,
|
||||
tegra186_emc_debug_max_rate_get,
|
||||
tegra186_emc_debug_max_rate_set, "%llu\n");
|
||||
|
||||
/*
|
||||
* tegra_emc_icc_set_bw() - Set BW api for EMC provider
|
||||
* @src: ICC node for External Memory Controller (EMC)
|
||||
* @dst: ICC node for External Memory (DRAM)
|
||||
*
|
||||
* Do nothing here as info to BPMP-FW is now passed in the BW set function
|
||||
* of the MC driver. BPMP-FW sets the final Freq based on the passed values.
|
||||
*/
|
||||
static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node *
|
||||
tegra_emc_of_icc_xlate(struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct icc_provider *provider = data;
|
||||
struct icc_node *node;
|
||||
|
||||
/* External Memory is the only possible ICC route */
|
||||
list_for_each_entry(node, &provider->nodes, node_list) {
|
||||
if (node->id != TEGRA_ICC_EMEM)
|
||||
continue;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
||||
{
|
||||
struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent);
|
||||
const struct tegra_mc_soc *soc = mc->soc;
|
||||
struct icc_node *node;
|
||||
int err;
|
||||
|
||||
emc->provider.dev = emc->dev;
|
||||
emc->provider.set = tegra_emc_icc_set_bw;
|
||||
emc->provider.data = &emc->provider;
|
||||
emc->provider.aggregate = soc->icc_ops->aggregate;
|
||||
emc->provider.xlate = tegra_emc_of_icc_xlate;
|
||||
emc->provider.get_bw = tegra_emc_icc_get_init_bw;
|
||||
|
||||
icc_provider_init(&emc->provider);
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto err_msg;
|
||||
}
|
||||
|
||||
node->name = "External Memory Controller";
|
||||
icc_node_add(node, &emc->provider);
|
||||
|
||||
/* link External Memory Controller to External Memory (DRAM) */
|
||||
err = icc_link_create(node, TEGRA_ICC_EMEM);
|
||||
if (err)
|
||||
goto remove_nodes;
|
||||
|
||||
/* create External Memory node */
|
||||
node = icc_node_create(TEGRA_ICC_EMEM);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto remove_nodes;
|
||||
}
|
||||
|
||||
node->name = "External Memory (DRAM)";
|
||||
icc_node_add(node, &emc->provider);
|
||||
|
||||
err = icc_provider_register(&emc->provider);
|
||||
if (err)
|
||||
goto remove_nodes;
|
||||
|
||||
return 0;
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->provider);
|
||||
err_msg:
|
||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
|
||||
struct mrq_emc_dvfs_latency_response response;
|
||||
struct tegra_bpmp_message msg;
|
||||
struct tegra186_emc *emc;
|
||||
@ -236,6 +339,32 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root,
|
||||
emc, &tegra186_emc_debug_max_rate_fops);
|
||||
|
||||
if (mc && mc->soc->icc_ops) {
|
||||
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) {
|
||||
mc->bwmgr_mrq_supported = true;
|
||||
|
||||
/*
|
||||
* MC driver probe can't get BPMP reference as it gets probed
|
||||
* earlier than BPMP. So, save the BPMP ref got from the EMC
|
||||
* DT node in the mc->bpmp and use it in MC's icc_set hook.
|
||||
*/
|
||||
mc->bpmp = emc->bpmp;
|
||||
barrier();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'.
|
||||
* Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return
|
||||
* EINVAL instead of passing the request to BPMP-FW later when the BW
|
||||
* request is made by client with 'icc_set_bw()' call.
|
||||
*/
|
||||
err = tegra_emc_interconnect_init(emc);
|
||||
if (err) {
|
||||
mc->bpmp = NULL;
|
||||
goto put_bpmp;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
put_bpmp:
|
||||
@ -245,9 +374,12 @@ put_bpmp:
|
||||
|
||||
static int tegra186_emc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
|
||||
struct tegra186_emc *emc = platform_get_drvdata(pdev);
|
||||
|
||||
debugfs_remove_recursive(emc->debugfs.root);
|
||||
|
||||
mc->bpmp = NULL;
|
||||
tegra_bpmp_put(emc->bpmp);
|
||||
|
||||
return 0;
|
||||
@ -272,6 +404,7 @@ static struct platform_driver tegra186_emc_driver = {
|
||||
.name = "tegra186-emc",
|
||||
.of_match_table = tegra186_emc_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
.probe = tegra186_emc_probe,
|
||||
.remove = tegra186_emc_remove,
|
||||
|
@ -1,18 +1,47 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <soc/tegra/mc.h>
|
||||
|
||||
#include <dt-bindings/memory/tegra234-mc.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/tegra-icc.h>
|
||||
|
||||
#include <soc/tegra/bpmp.h>
|
||||
#include "mc.h"
|
||||
|
||||
static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
{
|
||||
.id = TEGRA234_MEMORY_CLIENT_HDAR,
|
||||
.name = "hdar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_HDA,
|
||||
.type = TEGRA_ICC_ISO_AUDIO,
|
||||
.sid = TEGRA234_SID_HDA,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0xa8,
|
||||
.security = 0xac,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_HDAW,
|
||||
.name = "hdaw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_HDA,
|
||||
.type = TEGRA_ICC_ISO_AUDIO,
|
||||
.sid = TEGRA234_SID_HDA,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x1a8,
|
||||
.security = 0x1ac,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBEARD,
|
||||
.name = "mgbeard",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -23,6 +52,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBEBRD,
|
||||
.name = "mgbebrd",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE_VF1,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -33,6 +64,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBECRD,
|
||||
.name = "mgbecrd",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE_VF2,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -43,6 +76,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBEDRD,
|
||||
.name = "mgbedrd",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE_VF3,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -52,6 +87,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBEAWR,
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.name = "mgbeawr",
|
||||
.sid = TEGRA234_SID_MGBE,
|
||||
.regs = {
|
||||
@ -63,6 +100,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBEBWR,
|
||||
.name = "mgbebwr",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE_VF1,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -73,6 +112,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBECWR,
|
||||
.name = "mgbecwr",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE_VF2,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -83,6 +124,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_SDMMCRAB,
|
||||
.name = "sdmmcrab",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_SDMMC_4,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_SDMMC4,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -93,6 +136,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_MGBEDWR,
|
||||
.name = "mgbedwr",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_EQOS,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_MGBE_VF3,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -103,6 +148,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_SDMMCWAB,
|
||||
.name = "sdmmcwab",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_SDMMC_4,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_SDMMC4,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -110,6 +157,90 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
.security = 0x33c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_VI2W,
|
||||
.name = "vi2w",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_VI2,
|
||||
.type = TEGRA_ICC_ISO_VI,
|
||||
.sid = TEGRA234_SID_ISO_VI2,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x380,
|
||||
.security = 0x384,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_VI2FALR,
|
||||
.name = "vi2falr",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_VI2FAL,
|
||||
.type = TEGRA_ICC_ISO_VIFAL,
|
||||
.sid = TEGRA234_SID_ISO_VI2FALC,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x388,
|
||||
.security = 0x38c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_VI2FALW,
|
||||
.name = "vi2falw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_VI2FAL,
|
||||
.type = TEGRA_ICC_ISO_VIFAL,
|
||||
.sid = TEGRA234_SID_ISO_VI2FALC,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x3e0,
|
||||
.security = 0x3e4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_APER,
|
||||
.name = "aper",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_APE,
|
||||
.type = TEGRA_ICC_ISO_AUDIO,
|
||||
.sid = TEGRA234_SID_APE,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x3d0,
|
||||
.security = 0x3d4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_APEW,
|
||||
.name = "apew",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_APE,
|
||||
.type = TEGRA_ICC_ISO_AUDIO,
|
||||
.sid = TEGRA234_SID_APE,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x3d8,
|
||||
.security = 0x3dc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR,
|
||||
.name = "nvdisplayr",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_DISPLAY,
|
||||
.type = TEGRA_ICC_ISO_DISPLAY,
|
||||
.sid = TEGRA234_SID_ISO_NVDISPLAY,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x490,
|
||||
.security = 0x494,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR1,
|
||||
.name = "nvdisplayr1",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_DISPLAY,
|
||||
.type = TEGRA_ICC_ISO_DISPLAY,
|
||||
.sid = TEGRA234_SID_ISO_NVDISPLAY,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x508,
|
||||
.security = 0x50c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_BPMPR,
|
||||
.name = "bpmpr",
|
||||
@ -153,6 +284,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_APEDMAR,
|
||||
.name = "apedmar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_APEDMA,
|
||||
.type = TEGRA_ICC_ISO_AUDIO,
|
||||
.sid = TEGRA234_SID_APE,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -163,6 +296,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_APEDMAW,
|
||||
.name = "apedmaw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_APEDMA,
|
||||
.type = TEGRA_ICC_ISO_AUDIO,
|
||||
.sid = TEGRA234_SID_APE,
|
||||
.regs = {
|
||||
.sid = {
|
||||
@ -330,9 +465,466 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
|
||||
.security = 0x37c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE0R,
|
||||
.name = "pcie0r",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_0,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE0,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6c0,
|
||||
.security = 0x6c4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE0W,
|
||||
.name = "pcie0w",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_0,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE0,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6c8,
|
||||
.security = 0x6cc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE1R,
|
||||
.name = "pcie1r",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_1,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE1,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6d0,
|
||||
.security = 0x6d4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE1W,
|
||||
.name = "pcie1w",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_1,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE1,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6d8,
|
||||
.security = 0x6dc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE2AR,
|
||||
.name = "pcie2ar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_2,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE2,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6e0,
|
||||
.security = 0x6e4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE2AW,
|
||||
.name = "pcie2aw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_2,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE2,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6e8,
|
||||
.security = 0x6ec,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE3R,
|
||||
.name = "pcie3r",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_3,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE3,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6f0,
|
||||
.security = 0x6f4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE3W,
|
||||
.name = "pcie3w",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_3,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE3,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x6f8,
|
||||
.security = 0x6fc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE4R,
|
||||
.name = "pcie4r",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_4,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE4,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x700,
|
||||
.security = 0x704,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE4W,
|
||||
.name = "pcie4w",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_4,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE4,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x708,
|
||||
.security = 0x70c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE5R,
|
||||
.name = "pcie5r",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_5,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE5,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x710,
|
||||
.security = 0x714,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE5W,
|
||||
.name = "pcie5w",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_5,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE5,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x718,
|
||||
.security = 0x71c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE5R1,
|
||||
.name = "pcie5r1",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_5,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE5,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x778,
|
||||
.security = 0x77c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE6AR,
|
||||
.name = "pcie6ar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_6,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE6,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x140,
|
||||
.security = 0x144,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE6AW,
|
||||
.name = "pcie6aw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_6,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE6,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x148,
|
||||
.security = 0x14c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE6AR1,
|
||||
.name = "pcie6ar1",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_6,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE6,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x1e8,
|
||||
.security = 0x1ec,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE7AR,
|
||||
.name = "pcie7ar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_7,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE7,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x150,
|
||||
.security = 0x154,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE7AW,
|
||||
.name = "pcie7aw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_7,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE7,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x180,
|
||||
.security = 0x184,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE7AR1,
|
||||
.name = "pcie7ar1",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_7,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE7,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x248,
|
||||
.security = 0x24c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE8AR,
|
||||
.name = "pcie8ar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_8,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE8,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x190,
|
||||
.security = 0x194,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE8AW,
|
||||
.name = "pcie8aw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_8,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE8,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x1d8,
|
||||
.security = 0x1dc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE9AR,
|
||||
.name = "pcie9ar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_9,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE9,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x1e0,
|
||||
.security = 0x1e4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE9AW,
|
||||
.name = "pcie9aw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_9,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE9,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x1f0,
|
||||
.security = 0x1f4,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE10AR,
|
||||
.name = "pcie10ar",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_10,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE10,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x1f8,
|
||||
.security = 0x1fc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE10AW,
|
||||
.name = "pcie10aw",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_10,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE10,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x200,
|
||||
.security = 0x204,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA234_MEMORY_CLIENT_PCIE10AR1,
|
||||
.name = "pcie10ar1",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_PCIE_10,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
.sid = TEGRA234_SID_PCIE10,
|
||||
.regs = {
|
||||
.sid = {
|
||||
.override = 0x240,
|
||||
.security = 0x244,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER0,
|
||||
.name = "sw_cluster0",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER0,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER1,
|
||||
.name = "sw_cluster1",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER1,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER2,
|
||||
.name = "sw_cluster2",
|
||||
.bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER2,
|
||||
.type = TEGRA_ICC_NISO,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* tegra234_mc_icc_set() - Pass MC client info to the BPMP-FW
|
||||
* @src: ICC node for Memory Controller's (MC) Client
|
||||
* @dst: ICC node for Memory Controller (MC)
|
||||
*
|
||||
* Passing the current request info from the MC to the BPMP-FW where
|
||||
* LA and PTSA registers are accessed and the final EMC freq is set
|
||||
* based on client_id, type, latency and bandwidth.
|
||||
* icc_set_bw() makes set_bw calls for both MC and EMC providers in
|
||||
* sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'.
|
||||
* So, the data passed won't be updated by concurrent set calls from
|
||||
* other clients.
|
||||
*/
|
||||
static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider);
|
||||
struct mrq_bwmgr_int_request bwmgr_req = { 0 };
|
||||
struct mrq_bwmgr_int_response bwmgr_resp = { 0 };
|
||||
const struct tegra_mc_client *pclient = src->data;
|
||||
struct tegra_bpmp_message msg;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Same Src and Dst node will happen during boot from icc_node_add().
|
||||
* This can be used to pre-initialize and set bandwidth for all clients
|
||||
* before their drivers are loaded. We are skipping this case as for us,
|
||||
* the pre-initialization already happened in Bootloader(MB2) and BPMP-FW.
|
||||
*/
|
||||
if (src->id == dst->id)
|
||||
return 0;
|
||||
|
||||
if (!mc->bwmgr_mrq_supported)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mc->bpmp) {
|
||||
dev_err(mc->dev, "BPMP reference NULL\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (pclient->type == TEGRA_ICC_NISO)
|
||||
bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw;
|
||||
else
|
||||
bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw;
|
||||
|
||||
bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id;
|
||||
|
||||
bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET;
|
||||
bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw;
|
||||
bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.mrq = MRQ_BWMGR_INT;
|
||||
msg.tx.data = &bwmgr_req;
|
||||
msg.tx.size = sizeof(bwmgr_req);
|
||||
msg.rx.data = &bwmgr_resp;
|
||||
msg.rx.size = sizeof(bwmgr_resp);
|
||||
|
||||
ret = tegra_bpmp_transfer(mc->bpmp, &msg);
|
||||
if (ret < 0) {
|
||||
dev_err(mc->dev, "BPMP transfer failed: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
if (msg.rx.ret < 0) {
|
||||
pr_err("failed to set bandwidth for %u: %d\n",
|
||||
bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
struct icc_provider *p = node->provider;
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
|
||||
|
||||
if (!mc->bwmgr_mrq_supported)
|
||||
return -EINVAL;
|
||||
|
||||
if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER1 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER2) {
|
||||
if (mc)
|
||||
peak_bw = peak_bw * mc->num_channels;
|
||||
}
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max(*agg_peak, peak_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node*
|
||||
tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
|
||||
unsigned int cl_id = spec->args[0];
|
||||
struct icc_node *node;
|
||||
|
||||
list_for_each_entry(node, &mc->provider.nodes, node_list) {
|
||||
if (node->id != cl_id)
|
||||
continue;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a client driver calls devm_of_icc_get() before the MC driver
|
||||
* is probed, then return EPROBE_DEFER to the client driver.
|
||||
*/
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
|
||||
.xlate = tegra234_mc_of_icc_xlate,
|
||||
.aggregate = tegra234_mc_icc_aggregate,
|
||||
.get_bw = tegra234_mc_icc_get_init_bw,
|
||||
.set = tegra234_mc_icc_set,
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra234_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra234_mc_clients),
|
||||
.clients = tegra234_mc_clients,
|
||||
@ -345,6 +937,7 @@ const struct tegra_mc_soc tegra234_mc_soc = {
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.has_addr_hi_reg = true,
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra234_mc_icc_ops,
|
||||
.ch_intmask = 0x0000ff00,
|
||||
.global_intstatus_channel_shift = 8,
|
||||
/*
|
||||
|
@ -235,10 +235,11 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
|
||||
goto err_chunks;
|
||||
}
|
||||
if (!label)
|
||||
label = child->name;
|
||||
|
||||
block->label = devm_kstrdup(sram->dev,
|
||||
label, GFP_KERNEL);
|
||||
block->label = devm_kasprintf(sram->dev, GFP_KERNEL,
|
||||
"%s", dev_name(sram->dev));
|
||||
else
|
||||
block->label = devm_kstrdup(sram->dev,
|
||||
label, GFP_KERNEL);
|
||||
if (!block->label) {
|
||||
ret = -ENOMEM;
|
||||
goto err_chunks;
|
||||
|
@ -5025,7 +5025,7 @@ err_wq_alloc:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
|
||||
static void dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
|
||||
{
|
||||
struct device *dev;
|
||||
struct net_device *net_dev;
|
||||
@ -5073,8 +5073,6 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
|
||||
dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
|
||||
|
||||
free_netdev(net_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fsl_mc_device_id dpaa2_eth_match_id_table[] = {
|
||||
|
@ -219,7 +219,7 @@ err_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
|
||||
static void dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
|
||||
{
|
||||
struct device *dev = &mc_dev->dev;
|
||||
struct ptp_qoriq *ptp_qoriq;
|
||||
@ -232,8 +232,6 @@ static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
|
||||
fsl_mc_free_irqs(mc_dev);
|
||||
dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
|
||||
fsl_mc_portal_free(mc_dev->mc_io);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
|
||||
|
@ -3221,7 +3221,7 @@ static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev)
|
||||
dev_warn(dev, "dpsw_close err %d\n", err);
|
||||
}
|
||||
|
||||
static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
|
||||
static void dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
|
||||
{
|
||||
struct ethsw_port_priv *port_priv;
|
||||
struct ethsw_core *ethsw;
|
||||
@ -3252,8 +3252,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
|
||||
kfree(ethsw);
|
||||
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -223,6 +224,7 @@
|
||||
#define EP_STATE_ENABLED 1
|
||||
|
||||
static const unsigned int pcie_gen_freq[] = {
|
||||
GEN1_CORE_CLK_FREQ, /* PCI_EXP_LNKSTA_CLS == 0; undefined */
|
||||
GEN1_CORE_CLK_FREQ,
|
||||
GEN2_CORE_CLK_FREQ,
|
||||
GEN3_CORE_CLK_FREQ,
|
||||
@ -287,6 +289,7 @@ struct tegra_pcie_dw {
|
||||
unsigned int pex_rst_irq;
|
||||
int ep_state;
|
||||
long link_status;
|
||||
struct icc_path *icc_path;
|
||||
};
|
||||
|
||||
static inline struct tegra_pcie_dw *to_tegra_pcie(struct dw_pcie *pci)
|
||||
@ -309,6 +312,27 @@ struct tegra_pcie_soc {
|
||||
enum dw_pcie_device_mode mode;
|
||||
};
|
||||
|
||||
static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
|
||||
{
|
||||
struct dw_pcie *pci = &pcie->pci;
|
||||
u32 val, speed, width;
|
||||
|
||||
val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
|
||||
|
||||
speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, val);
|
||||
width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val);
|
||||
|
||||
val = width * (PCIE_SPEED2MBS_ENC(pcie_link_speed[speed]) / BITS_PER_BYTE);
|
||||
|
||||
if (icc_set_bw(pcie->icc_path, MBps_to_icc(val), 0))
|
||||
dev_err(pcie->dev, "can't set bw[%u]\n", val);
|
||||
|
||||
if (speed >= ARRAY_SIZE(pcie_gen_freq))
|
||||
speed = 0;
|
||||
|
||||
clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
|
||||
}
|
||||
|
||||
static void apply_bad_link_workaround(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
@ -452,14 +476,12 @@ static irqreturn_t tegra_pcie_ep_irq_thread(int irq, void *arg)
|
||||
struct tegra_pcie_dw *pcie = arg;
|
||||
struct dw_pcie_ep *ep = &pcie->pci.ep;
|
||||
struct dw_pcie *pci = &pcie->pci;
|
||||
u32 val, speed;
|
||||
u32 val;
|
||||
|
||||
if (test_and_clear_bit(0, &pcie->link_status))
|
||||
dw_pcie_ep_linkup(ep);
|
||||
|
||||
speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) &
|
||||
PCI_EXP_LNKSTA_CLS;
|
||||
clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]);
|
||||
tegra_pcie_icc_set(pcie);
|
||||
|
||||
if (pcie->of_data->has_ltr_req_fix)
|
||||
return IRQ_HANDLED;
|
||||
@ -945,9 +967,9 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
|
||||
|
||||
static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
|
||||
{
|
||||
u32 val, offset, speed, tmp;
|
||||
struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
|
||||
struct dw_pcie_rp *pp = &pci->pp;
|
||||
u32 val, offset, tmp;
|
||||
bool retry = true;
|
||||
|
||||
if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
|
||||
@ -1018,9 +1040,7 @@ retry_link:
|
||||
goto retry_link;
|
||||
}
|
||||
|
||||
speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) &
|
||||
PCI_EXP_LNKSTA_CLS;
|
||||
clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]);
|
||||
tegra_pcie_icc_set(pcie);
|
||||
|
||||
tegra_pcie_enable_interrupts(pp);
|
||||
|
||||
@ -2224,6 +2244,14 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
pcie->icc_path = devm_of_icc_get(&pdev->dev, "write");
|
||||
ret = PTR_ERR_OR_ZERO(pcie->icc_path);
|
||||
if (ret) {
|
||||
tegra_bpmp_put(pcie->bpmp);
|
||||
dev_err_probe(&pdev->dev, ret, "failed to get write interconnect\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (pcie->of_data->mode) {
|
||||
case DW_PCIE_RC_TYPE:
|
||||
ret = devm_request_irq(dev, pp->irq, tegra_pcie_rp_irq_handler,
|
||||
|
@ -70,10 +70,26 @@ static int scmi_powercap_get_power_uw(struct powercap_zone *pz,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scmi_powercap_zone_enable_set(struct powercap_zone *pz, bool mode)
|
||||
{
|
||||
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
|
||||
|
||||
return powercap_ops->cap_enable_set(spz->ph, spz->info->id, mode);
|
||||
}
|
||||
|
||||
static int scmi_powercap_zone_enable_get(struct powercap_zone *pz, bool *mode)
|
||||
{
|
||||
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
|
||||
|
||||
return powercap_ops->cap_enable_get(spz->ph, spz->info->id, mode);
|
||||
}
|
||||
|
||||
static const struct powercap_zone_ops zone_ops = {
|
||||
.get_max_power_range_uw = scmi_powercap_get_max_power_range_uw,
|
||||
.get_power_uw = scmi_powercap_get_power_uw,
|
||||
.release = scmi_powercap_zone_release,
|
||||
.set_enable = scmi_powercap_zone_enable_set,
|
||||
.get_enable = scmi_powercap_zone_enable_get,
|
||||
};
|
||||
|
||||
static void scmi_powercap_normalize_cap(const struct scmi_powercap_zone *spz,
|
||||
|
@ -81,21 +81,6 @@ enum pru_iomem {
|
||||
PRU_IOMEM_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum pru_type - PRU core type identifier
|
||||
*
|
||||
* @PRU_TYPE_PRU: Programmable Real-time Unit
|
||||
* @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit
|
||||
* @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit
|
||||
* @PRU_TYPE_MAX: just keep this one at the end
|
||||
*/
|
||||
enum pru_type {
|
||||
PRU_TYPE_PRU = 0,
|
||||
PRU_TYPE_RTU,
|
||||
PRU_TYPE_TX_PRU,
|
||||
PRU_TYPE_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pru_private_data - device data for a PRU core
|
||||
* @type: type of the PRU core (PRU, RTU, Tx_PRU)
|
||||
|
@ -150,9 +150,6 @@ config RESET_NUVOTON_MA35D1
|
||||
help
|
||||
This enables the reset controller driver for Nuvoton MA35D1 SoC.
|
||||
|
||||
config RESET_OXNAS
|
||||
bool
|
||||
|
||||
config RESET_PISTACHIO
|
||||
bool "Pistachio Reset Driver"
|
||||
depends on MIPS || COMPILE_TEST
|
||||
@ -161,7 +158,8 @@ config RESET_PISTACHIO
|
||||
|
||||
config RESET_POLARFIRE_SOC
|
||||
bool "Microchip PolarFire SoC (MPFS) Reset Driver"
|
||||
depends on AUXILIARY_BUS && MCHP_CLK_MPFS
|
||||
depends on MCHP_CLK_MPFS
|
||||
select AUXILIARY_BUS
|
||||
default MCHP_CLK_MPFS
|
||||
help
|
||||
This driver supports peripheral reset for the Microchip PolarFire SoC
|
||||
|
@ -22,7 +22,6 @@ obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
|
||||
obj-$(CONFIG_RESET_NPCM) += reset-npcm.o
|
||||
obj-$(CONFIG_RESET_NUVOTON_MA35D1) += reset-ma35d1.o
|
||||
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
|
||||
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
|
||||
obj-$(CONFIG_RESET_POLARFIRE_SOC) += reset-mpfs.o
|
||||
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
|
||||
|
@ -86,7 +86,6 @@ static int ath79_reset_restart_handler(struct notifier_block *nb,
|
||||
static int ath79_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ath79_reset *ath79_reset;
|
||||
struct resource *res;
|
||||
int err;
|
||||
|
||||
ath79_reset = devm_kzalloc(&pdev->dev,
|
||||
@ -96,8 +95,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, ath79_reset);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
ath79_reset->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
ath79_reset->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ath79_reset->base))
|
||||
return PTR_ERR(ath79_reset->base);
|
||||
|
||||
|
@ -44,14 +44,12 @@ static const struct reset_control_ops axs10x_reset_ops = {
|
||||
static int axs10x_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct axs10x_rst *rst;
|
||||
struct resource *mem;
|
||||
|
||||
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
|
||||
if (!rst)
|
||||
return -ENOMEM;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
|
||||
rst->regs_rst = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(rst->regs_rst))
|
||||
return PTR_ERR(rst->regs_rst);
|
||||
|
||||
|
@ -66,14 +66,12 @@ static const struct reset_control_ops brcm_rescal_reset_ops = {
|
||||
static int brcm_rescal_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct brcm_rescal_reset *data;
|
||||
struct resource *res;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
data->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
|
@ -92,19 +92,16 @@ static const struct reset_control_ops hsdk_reset_ops = {
|
||||
static int hsdk_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct hsdk_rst *rst;
|
||||
struct resource *mem;
|
||||
|
||||
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
|
||||
if (!rst)
|
||||
return -ENOMEM;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem);
|
||||
rst->regs_ctl = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(rst->regs_ctl))
|
||||
return PTR_ERR(rst->regs_ctl);
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
|
||||
rst->regs_rst = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(rst->regs_rst))
|
||||
return PTR_ERR(rst->regs_rst);
|
||||
|
||||
|
@ -139,7 +139,6 @@ static const struct reset_control_ops lpc18xx_rgu_ops = {
|
||||
static int lpc18xx_rgu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc18xx_rgu_data *rc;
|
||||
struct resource *res;
|
||||
u32 fcclk, firc;
|
||||
int ret;
|
||||
|
||||
@ -147,8 +146,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
|
||||
if (!rc)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rc->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
rc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(rc->base))
|
||||
return PTR_ERR(rc->base);
|
||||
|
||||
|
@ -151,11 +151,8 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, arb);
|
||||
|
||||
arb->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(arb->clk)) {
|
||||
if (PTR_ERR(arb->clk) != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get clock\n");
|
||||
return PTR_ERR(arb->clk);
|
||||
}
|
||||
if (IS_ERR(arb->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(arb->clk), "failed to get clock\n");
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
arb->regs = devm_ioremap_resource(dev, res);
|
||||
|
@ -116,14 +116,12 @@ MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
|
||||
static int meson_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct meson_reset *data;
|
||||
struct resource *res;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
data->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(data->reg_base))
|
||||
return PTR_ERR(data->reg_base);
|
||||
|
||||
|
@ -1,114 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Oxford Semiconductor Reset Controller driver
|
||||
*
|
||||
* Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
|
||||
* Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
|
||||
* Copyright (C) 2009 Oxford Semiconductor Ltd
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
/* Regmap offsets */
|
||||
#define RST_SET_REGOFFSET 0x34
|
||||
#define RST_CLR_REGOFFSET 0x38
|
||||
|
||||
struct oxnas_reset {
|
||||
struct regmap *regmap;
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct oxnas_reset *data =
|
||||
container_of(rcdev, struct oxnas_reset, rcdev);
|
||||
|
||||
regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
|
||||
msleep(50);
|
||||
regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct oxnas_reset *data =
|
||||
container_of(rcdev, struct oxnas_reset, rcdev);
|
||||
|
||||
regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct oxnas_reset *data =
|
||||
container_of(rcdev, struct oxnas_reset, rcdev);
|
||||
|
||||
regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reset_control_ops oxnas_reset_ops = {
|
||||
.reset = oxnas_reset_reset,
|
||||
.assert = oxnas_reset_assert,
|
||||
.deassert = oxnas_reset_deassert,
|
||||
};
|
||||
|
||||
static const struct of_device_id oxnas_reset_dt_ids[] = {
|
||||
{ .compatible = "oxsemi,ox810se-reset", },
|
||||
{ .compatible = "oxsemi,ox820-reset", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static int oxnas_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct oxnas_reset *data;
|
||||
struct device *parent;
|
||||
|
||||
parent = pdev->dev.parent;
|
||||
if (!parent) {
|
||||
dev_err(&pdev->dev, "no parent\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->regmap = syscon_node_to_regmap(parent->of_node);
|
||||
if (IS_ERR(data->regmap)) {
|
||||
dev_err(&pdev->dev, "failed to get parent regmap\n");
|
||||
return PTR_ERR(data->regmap);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
data->rcdev.owner = THIS_MODULE;
|
||||
data->rcdev.nr_resets = 32;
|
||||
data->rcdev.ops = &oxnas_reset_ops;
|
||||
data->rcdev.of_node = pdev->dev.of_node;
|
||||
|
||||
return devm_reset_controller_register(&pdev->dev, &data->rcdev);
|
||||
}
|
||||
|
||||
static struct platform_driver oxnas_reset_driver = {
|
||||
.probe = oxnas_reset_probe,
|
||||
.driver = {
|
||||
.name = "oxnas-reset",
|
||||
.of_match_table = oxnas_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(oxnas_reset_driver);
|
@ -13,7 +13,8 @@ config RESET_STARFIVE_JH7100
|
||||
|
||||
config RESET_STARFIVE_JH7110
|
||||
bool "StarFive JH7110 Reset Driver"
|
||||
depends on AUXILIARY_BUS && CLK_STARFIVE_JH7110_SYS
|
||||
depends on CLK_STARFIVE_JH7110_SYS
|
||||
select AUXILIARY_BUS
|
||||
select RESET_STARFIVE_JH71X0
|
||||
default ARCH_STARFIVE
|
||||
help
|
||||
|
@ -1,11 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
if ARCH_STI
|
||||
|
||||
config STI_RESET_SYSCFG
|
||||
bool
|
||||
|
||||
config STIH407_RESET
|
||||
bool
|
||||
select STI_RESET_SYSCFG
|
||||
|
||||
endif
|
||||
|
@ -1,4 +1,2 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o
|
||||
|
||||
obj-$(CONFIG_STIH407_RESET) += reset-stih407.o
|
||||
obj-$(CONFIG_STIH407_RESET) += reset-stih407.o reset-syscfg.o
|
||||
|
@ -64,22 +64,12 @@ static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev,
|
||||
return err;
|
||||
|
||||
if (ch->ack) {
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
u32 ack_val;
|
||||
|
||||
while (true) {
|
||||
err = regmap_field_read(ch->ack, &ack_val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ack_val == ctrl_val)
|
||||
break;
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
return -ETIME;
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
err = regmap_field_read_poll_timeout(ch->ack, ack_val, (ack_val == ctrl_val),
|
||||
100, USEC_PER_SEC);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -105,7 +105,7 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
|
||||
SEC_PD(ACODEC, 0),
|
||||
SEC_PD(AUDIO, 0),
|
||||
SEC_PD(OTP, 0),
|
||||
SEC_PD(DMA, 0),
|
||||
SEC_PD(DMA, GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
|
||||
SEC_PD(SD_EMMC, 0),
|
||||
SEC_PD(RAMA, 0),
|
||||
/* SRAMB is used as ATF runtime memory, and should be always on */
|
||||
|
@ -270,7 +270,7 @@ static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev)
|
||||
fsl_mc_free_irqs(dpio_dev);
|
||||
}
|
||||
|
||||
static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
|
||||
static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
|
||||
{
|
||||
struct device *dev;
|
||||
struct dpio_priv *priv;
|
||||
@ -297,14 +297,8 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
|
||||
|
||||
dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
|
||||
|
||||
fsl_mc_portal_free(dpio_dev->mc_io);
|
||||
|
||||
return 0;
|
||||
|
||||
err_open:
|
||||
fsl_mc_portal_free(dpio_dev->mc_io);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = {
|
||||
|
@ -62,6 +62,7 @@ config QE_TDM
|
||||
|
||||
config QE_USB
|
||||
bool
|
||||
depends on QUICC_ENGINE
|
||||
default y if USB_FSL_QE
|
||||
help
|
||||
QE USB Controller support
|
||||
|
@ -1051,7 +1051,6 @@ static struct platform_driver mtk_mutex_driver = {
|
||||
.probe = mtk_mutex_probe,
|
||||
.driver = {
|
||||
.name = "mediatek-mutex",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = mutex_driver_dt_match,
|
||||
},
|
||||
};
|
||||
|
@ -47,6 +47,7 @@
|
||||
|
||||
/* macro for device wrapper default value */
|
||||
#define PWRAP_DEW_READ_TEST_VAL 0x5aa5
|
||||
#define PWRAP_DEW_COMP_READ_TEST_VAL 0xa55a
|
||||
#define PWRAP_DEW_WRITE_TEST_VAL 0xa55a
|
||||
|
||||
/* macro for manual command */
|
||||
@ -169,6 +170,40 @@ static const u32 mt6323_regs[] = {
|
||||
[PWRAP_DEW_RDDMY_NO] = 0x01a4,
|
||||
};
|
||||
|
||||
static const u32 mt6331_regs[] = {
|
||||
[PWRAP_DEW_DIO_EN] = 0x018c,
|
||||
[PWRAP_DEW_READ_TEST] = 0x018e,
|
||||
[PWRAP_DEW_WRITE_TEST] = 0x0190,
|
||||
[PWRAP_DEW_CRC_SWRST] = 0x0192,
|
||||
[PWRAP_DEW_CRC_EN] = 0x0194,
|
||||
[PWRAP_DEW_CRC_VAL] = 0x0196,
|
||||
[PWRAP_DEW_MON_GRP_SEL] = 0x0198,
|
||||
[PWRAP_DEW_CIPHER_KEY_SEL] = 0x019a,
|
||||
[PWRAP_DEW_CIPHER_IV_SEL] = 0x019c,
|
||||
[PWRAP_DEW_CIPHER_EN] = 0x019e,
|
||||
[PWRAP_DEW_CIPHER_RDY] = 0x01a0,
|
||||
[PWRAP_DEW_CIPHER_MODE] = 0x01a2,
|
||||
[PWRAP_DEW_CIPHER_SWRST] = 0x01a4,
|
||||
[PWRAP_DEW_RDDMY_NO] = 0x01a6,
|
||||
};
|
||||
|
||||
static const u32 mt6332_regs[] = {
|
||||
[PWRAP_DEW_DIO_EN] = 0x80f6,
|
||||
[PWRAP_DEW_READ_TEST] = 0x80f8,
|
||||
[PWRAP_DEW_WRITE_TEST] = 0x80fa,
|
||||
[PWRAP_DEW_CRC_SWRST] = 0x80fc,
|
||||
[PWRAP_DEW_CRC_EN] = 0x80fe,
|
||||
[PWRAP_DEW_CRC_VAL] = 0x8100,
|
||||
[PWRAP_DEW_MON_GRP_SEL] = 0x8102,
|
||||
[PWRAP_DEW_CIPHER_KEY_SEL] = 0x8104,
|
||||
[PWRAP_DEW_CIPHER_IV_SEL] = 0x8106,
|
||||
[PWRAP_DEW_CIPHER_EN] = 0x8108,
|
||||
[PWRAP_DEW_CIPHER_RDY] = 0x810a,
|
||||
[PWRAP_DEW_CIPHER_MODE] = 0x810c,
|
||||
[PWRAP_DEW_CIPHER_SWRST] = 0x810e,
|
||||
[PWRAP_DEW_RDDMY_NO] = 0x8110,
|
||||
};
|
||||
|
||||
static const u32 mt6351_regs[] = {
|
||||
[PWRAP_DEW_DIO_EN] = 0x02F2,
|
||||
[PWRAP_DEW_READ_TEST] = 0x02F4,
|
||||
@ -604,6 +639,91 @@ static int mt6779_regs[] = {
|
||||
[PWRAP_WACS2_VLDCLR] = 0xC28,
|
||||
};
|
||||
|
||||
static int mt6795_regs[] = {
|
||||
[PWRAP_MUX_SEL] = 0x0,
|
||||
[PWRAP_WRAP_EN] = 0x4,
|
||||
[PWRAP_DIO_EN] = 0x8,
|
||||
[PWRAP_SIDLY] = 0xc,
|
||||
[PWRAP_RDDMY] = 0x10,
|
||||
[PWRAP_SI_CK_CON] = 0x14,
|
||||
[PWRAP_CSHEXT_WRITE] = 0x18,
|
||||
[PWRAP_CSHEXT_READ] = 0x1c,
|
||||
[PWRAP_CSLEXT_START] = 0x20,
|
||||
[PWRAP_CSLEXT_END] = 0x24,
|
||||
[PWRAP_STAUPD_PRD] = 0x28,
|
||||
[PWRAP_STAUPD_GRPEN] = 0x2c,
|
||||
[PWRAP_EINT_STA0_ADR] = 0x30,
|
||||
[PWRAP_EINT_STA1_ADR] = 0x34,
|
||||
[PWRAP_STAUPD_MAN_TRIG] = 0x40,
|
||||
[PWRAP_STAUPD_STA] = 0x44,
|
||||
[PWRAP_WRAP_STA] = 0x48,
|
||||
[PWRAP_HARB_INIT] = 0x4c,
|
||||
[PWRAP_HARB_HPRIO] = 0x50,
|
||||
[PWRAP_HIPRIO_ARB_EN] = 0x54,
|
||||
[PWRAP_HARB_STA0] = 0x58,
|
||||
[PWRAP_HARB_STA1] = 0x5c,
|
||||
[PWRAP_MAN_EN] = 0x60,
|
||||
[PWRAP_MAN_CMD] = 0x64,
|
||||
[PWRAP_MAN_RDATA] = 0x68,
|
||||
[PWRAP_MAN_VLDCLR] = 0x6c,
|
||||
[PWRAP_WACS0_EN] = 0x70,
|
||||
[PWRAP_INIT_DONE0] = 0x74,
|
||||
[PWRAP_WACS0_CMD] = 0x78,
|
||||
[PWRAP_WACS0_RDATA] = 0x7c,
|
||||
[PWRAP_WACS0_VLDCLR] = 0x80,
|
||||
[PWRAP_WACS1_EN] = 0x84,
|
||||
[PWRAP_INIT_DONE1] = 0x88,
|
||||
[PWRAP_WACS1_CMD] = 0x8c,
|
||||
[PWRAP_WACS1_RDATA] = 0x90,
|
||||
[PWRAP_WACS1_VLDCLR] = 0x94,
|
||||
[PWRAP_WACS2_EN] = 0x98,
|
||||
[PWRAP_INIT_DONE2] = 0x9c,
|
||||
[PWRAP_WACS2_CMD] = 0xa0,
|
||||
[PWRAP_WACS2_RDATA] = 0xa4,
|
||||
[PWRAP_WACS2_VLDCLR] = 0xa8,
|
||||
[PWRAP_INT_EN] = 0xac,
|
||||
[PWRAP_INT_FLG_RAW] = 0xb0,
|
||||
[PWRAP_INT_FLG] = 0xb4,
|
||||
[PWRAP_INT_CLR] = 0xb8,
|
||||
[PWRAP_SIG_ADR] = 0xbc,
|
||||
[PWRAP_SIG_MODE] = 0xc0,
|
||||
[PWRAP_SIG_VALUE] = 0xc4,
|
||||
[PWRAP_SIG_ERRVAL] = 0xc8,
|
||||
[PWRAP_CRC_EN] = 0xcc,
|
||||
[PWRAP_TIMER_EN] = 0xd0,
|
||||
[PWRAP_TIMER_STA] = 0xd4,
|
||||
[PWRAP_WDT_UNIT] = 0xd8,
|
||||
[PWRAP_WDT_SRC_EN] = 0xdc,
|
||||
[PWRAP_WDT_FLG] = 0xe0,
|
||||
[PWRAP_DEBUG_INT_SEL] = 0xe4,
|
||||
[PWRAP_DVFS_ADR0] = 0xe8,
|
||||
[PWRAP_DVFS_WDATA0] = 0xec,
|
||||
[PWRAP_DVFS_ADR1] = 0xf0,
|
||||
[PWRAP_DVFS_WDATA1] = 0xf4,
|
||||
[PWRAP_DVFS_ADR2] = 0xf8,
|
||||
[PWRAP_DVFS_WDATA2] = 0xfc,
|
||||
[PWRAP_DVFS_ADR3] = 0x100,
|
||||
[PWRAP_DVFS_WDATA3] = 0x104,
|
||||
[PWRAP_DVFS_ADR4] = 0x108,
|
||||
[PWRAP_DVFS_WDATA4] = 0x10c,
|
||||
[PWRAP_DVFS_ADR5] = 0x110,
|
||||
[PWRAP_DVFS_WDATA5] = 0x114,
|
||||
[PWRAP_DVFS_ADR6] = 0x118,
|
||||
[PWRAP_DVFS_WDATA6] = 0x11c,
|
||||
[PWRAP_DVFS_ADR7] = 0x120,
|
||||
[PWRAP_DVFS_WDATA7] = 0x124,
|
||||
[PWRAP_SPMINF_STA] = 0x128,
|
||||
[PWRAP_CIPHER_KEY_SEL] = 0x12c,
|
||||
[PWRAP_CIPHER_IV_SEL] = 0x130,
|
||||
[PWRAP_CIPHER_EN] = 0x134,
|
||||
[PWRAP_CIPHER_RDY] = 0x138,
|
||||
[PWRAP_CIPHER_MODE] = 0x13c,
|
||||
[PWRAP_CIPHER_SWRST] = 0x140,
|
||||
[PWRAP_DCM_EN] = 0x144,
|
||||
[PWRAP_DCM_DBC_PRD] = 0x148,
|
||||
[PWRAP_EXT_CK] = 0x14c,
|
||||
};
|
||||
|
||||
static int mt6797_regs[] = {
|
||||
[PWRAP_MUX_SEL] = 0x0,
|
||||
[PWRAP_WRAP_EN] = 0x4,
|
||||
@ -1181,6 +1301,8 @@ static int mt8186_regs[] = {
|
||||
|
||||
enum pmic_type {
|
||||
PMIC_MT6323,
|
||||
PMIC_MT6331,
|
||||
PMIC_MT6332,
|
||||
PMIC_MT6351,
|
||||
PMIC_MT6357,
|
||||
PMIC_MT6358,
|
||||
@ -1193,6 +1315,7 @@ enum pwrap_type {
|
||||
PWRAP_MT2701,
|
||||
PWRAP_MT6765,
|
||||
PWRAP_MT6779,
|
||||
PWRAP_MT6795,
|
||||
PWRAP_MT6797,
|
||||
PWRAP_MT6873,
|
||||
PWRAP_MT7622,
|
||||
@ -1218,11 +1341,21 @@ struct pwrap_slv_regops {
|
||||
int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pwrap_slv_type - PMIC device wrapper definitions
|
||||
* @dew_regs: Device Wrapper (DeW) register offsets
|
||||
* @type: PMIC Type (model)
|
||||
* @comp_dew_regs: Device Wrapper (DeW) register offsets for companion device
|
||||
* @comp_type: Companion PMIC Type (model)
|
||||
* @regops: Register R/W ops
|
||||
* @caps: Capability flags for the target device
|
||||
*/
|
||||
struct pwrap_slv_type {
|
||||
const u32 *dew_regs;
|
||||
enum pmic_type type;
|
||||
const u32 *comp_dew_regs;
|
||||
enum pmic_type comp_type;
|
||||
const struct pwrap_slv_regops *regops;
|
||||
/* Flags indicating the capability for the target slave */
|
||||
u32 caps;
|
||||
};
|
||||
|
||||
@ -1455,6 +1588,18 @@ static int pwrap_regmap_write(void *context, u32 adr, u32 wdata)
|
||||
return pwrap_write(context, adr, wdata);
|
||||
}
|
||||
|
||||
static bool pwrap_pmic_read_test(struct pmic_wrapper *wrp, const u32 *dew_regs,
|
||||
u16 read_test_val)
|
||||
{
|
||||
bool is_success;
|
||||
u32 rdata;
|
||||
|
||||
pwrap_read(wrp, dew_regs[PWRAP_DEW_READ_TEST], &rdata);
|
||||
is_success = ((rdata & U16_MAX) == read_test_val);
|
||||
|
||||
return is_success;
|
||||
}
|
||||
|
||||
static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
|
||||
{
|
||||
bool tmp;
|
||||
@ -1498,18 +1643,18 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
|
||||
*/
|
||||
static int pwrap_init_sidly(struct pmic_wrapper *wrp)
|
||||
{
|
||||
u32 rdata;
|
||||
u32 i;
|
||||
u32 pass = 0;
|
||||
bool read_ok;
|
||||
signed char dly[16] = {
|
||||
-1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1
|
||||
};
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pwrap_writel(wrp, i, PWRAP_SIDLY);
|
||||
pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST],
|
||||
&rdata);
|
||||
if (rdata == PWRAP_DEW_READ_TEST_VAL) {
|
||||
read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs,
|
||||
PWRAP_DEW_READ_TEST_VAL);
|
||||
if (read_ok) {
|
||||
dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
|
||||
pass |= 1 << i;
|
||||
}
|
||||
@ -1529,11 +1674,13 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
|
||||
static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
|
||||
{
|
||||
int ret;
|
||||
bool tmp;
|
||||
u32 rdata;
|
||||
bool read_ok, tmp;
|
||||
bool comp_read_ok = true;
|
||||
|
||||
/* Enable dual IO mode */
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
|
||||
if (wrp->slave->comp_dew_regs)
|
||||
pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_DIO_EN], 1);
|
||||
|
||||
/* Check IDLE & INIT_DONE in advance */
|
||||
ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp,
|
||||
@ -1546,12 +1693,15 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
|
||||
pwrap_writel(wrp, 1, PWRAP_DIO_EN);
|
||||
|
||||
/* Read Test */
|
||||
pwrap_read(wrp,
|
||||
wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata);
|
||||
if (rdata != PWRAP_DEW_READ_TEST_VAL) {
|
||||
dev_err(wrp->dev,
|
||||
"Read failed on DIO mode: 0x%04x!=0x%04x\n",
|
||||
PWRAP_DEW_READ_TEST_VAL, rdata);
|
||||
read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL);
|
||||
if (wrp->slave->comp_dew_regs)
|
||||
comp_read_ok = pwrap_pmic_read_test(wrp, wrp->slave->comp_dew_regs,
|
||||
PWRAP_DEW_COMP_READ_TEST_VAL);
|
||||
if (!read_ok || !comp_read_ok) {
|
||||
dev_err(wrp->dev, "Read failed on DIO mode. Main PMIC %s%s\n",
|
||||
!read_ok ? "fail" : "success",
|
||||
wrp->slave->comp_dew_regs && !comp_read_ok ?
|
||||
", Companion PMIC fail" : "");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -1586,6 +1736,20 @@ static void pwrap_init_chip_select_ext(struct pmic_wrapper *wrp, u8 hext_write,
|
||||
static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp)
|
||||
{
|
||||
switch (wrp->master->type) {
|
||||
case PWRAP_MT6795:
|
||||
if (wrp->slave->type == PMIC_MT6331) {
|
||||
const u32 *dew_regs = wrp->slave->dew_regs;
|
||||
|
||||
pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8);
|
||||
|
||||
if (wrp->slave->comp_type == PMIC_MT6332) {
|
||||
dew_regs = wrp->slave->comp_dew_regs;
|
||||
pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8);
|
||||
}
|
||||
}
|
||||
pwrap_writel(wrp, 0x88, PWRAP_RDDMY);
|
||||
pwrap_init_chip_select_ext(wrp, 15, 15, 15, 15);
|
||||
break;
|
||||
case PWRAP_MT8173:
|
||||
pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2);
|
||||
break;
|
||||
@ -1626,19 +1790,41 @@ static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
|
||||
return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
|
||||
}
|
||||
|
||||
static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
|
||||
static bool __pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp, const u32 *dew_regs)
|
||||
{
|
||||
u32 rdata;
|
||||
int ret;
|
||||
|
||||
ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY],
|
||||
&rdata);
|
||||
ret = pwrap_read(wrp, dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
return rdata == 1;
|
||||
}
|
||||
|
||||
|
||||
static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
|
||||
{
|
||||
bool ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->dew_regs);
|
||||
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
/* If there's any companion, wait for it to be ready too */
|
||||
if (wrp->slave->comp_dew_regs)
|
||||
ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->comp_dew_regs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pwrap_config_cipher(struct pmic_wrapper *wrp, const u32 *dew_regs)
|
||||
{
|
||||
pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
|
||||
pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
|
||||
pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
|
||||
pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
|
||||
}
|
||||
|
||||
static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
{
|
||||
int ret;
|
||||
@ -1658,6 +1844,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
case PWRAP_MT2701:
|
||||
case PWRAP_MT6765:
|
||||
case PWRAP_MT6779:
|
||||
case PWRAP_MT6795:
|
||||
case PWRAP_MT6797:
|
||||
case PWRAP_MT8173:
|
||||
case PWRAP_MT8186:
|
||||
@ -1675,10 +1862,11 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
}
|
||||
|
||||
/* Config cipher mode @PMIC */
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
|
||||
pwrap_config_cipher(wrp, wrp->slave->dew_regs);
|
||||
|
||||
/* If there is any companion PMIC, configure cipher mode there too */
|
||||
if (wrp->slave->comp_type > 0)
|
||||
pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs);
|
||||
|
||||
switch (wrp->slave->type) {
|
||||
case PMIC_MT6397:
|
||||
@ -1740,6 +1928,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
|
||||
static int pwrap_init_security(struct pmic_wrapper *wrp)
|
||||
{
|
||||
u32 crc_val;
|
||||
int ret;
|
||||
|
||||
/* Enable encryption */
|
||||
@ -1748,14 +1937,21 @@ static int pwrap_init_security(struct pmic_wrapper *wrp)
|
||||
return ret;
|
||||
|
||||
/* Signature checking - using CRC */
|
||||
if (pwrap_write(wrp,
|
||||
wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1))
|
||||
return -EFAULT;
|
||||
ret = pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1);
|
||||
if (ret == 0 && wrp->slave->comp_dew_regs)
|
||||
ret = pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_EN], 0x1);
|
||||
|
||||
pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
|
||||
pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL],
|
||||
PWRAP_SIG_ADR);
|
||||
|
||||
/* CRC value */
|
||||
crc_val = wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL];
|
||||
if (wrp->slave->comp_dew_regs)
|
||||
crc_val |= wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_VAL] << 16;
|
||||
|
||||
pwrap_writel(wrp, crc_val, PWRAP_SIG_ADR);
|
||||
|
||||
/* PMIC Wrapper Arbiter priority */
|
||||
pwrap_writel(wrp,
|
||||
wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);
|
||||
|
||||
@ -1819,6 +2015,19 @@ static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt6795_init_soc_specific(struct pmic_wrapper *wrp)
|
||||
{
|
||||
pwrap_writel(wrp, 0xf, PWRAP_STAUPD_GRPEN);
|
||||
|
||||
if (wrp->slave->type == PMIC_MT6331)
|
||||
pwrap_writel(wrp, 0x1b4, PWRAP_EINT_STA0_ADR);
|
||||
|
||||
if (wrp->slave->comp_type == PMIC_MT6332)
|
||||
pwrap_writel(wrp, 0x8112, PWRAP_EINT_STA1_ADR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp)
|
||||
{
|
||||
pwrap_writel(wrp, 0, PWRAP_STAUPD_PRD);
|
||||
@ -1854,10 +2063,16 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
||||
if (wrp->rstc_bridge)
|
||||
reset_control_reset(wrp->rstc_bridge);
|
||||
|
||||
if (wrp->master->type == PWRAP_MT8173) {
|
||||
switch (wrp->master->type) {
|
||||
case PWRAP_MT6795:
|
||||
fallthrough;
|
||||
case PWRAP_MT8173:
|
||||
/* Enable DCM */
|
||||
pwrap_writel(wrp, 3, PWRAP_DCM_EN);
|
||||
pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) {
|
||||
@ -1982,6 +2197,16 @@ static const struct pwrap_slv_type pmic_mt6323 = {
|
||||
PWRAP_SLV_CAP_SECURITY,
|
||||
};
|
||||
|
||||
static const struct pwrap_slv_type pmic_mt6331 = {
|
||||
.dew_regs = mt6331_regs,
|
||||
.type = PMIC_MT6331,
|
||||
.comp_dew_regs = mt6332_regs,
|
||||
.comp_type = PMIC_MT6332,
|
||||
.regops = &pwrap_regops16,
|
||||
.caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO |
|
||||
PWRAP_SLV_CAP_SECURITY,
|
||||
};
|
||||
|
||||
static const struct pwrap_slv_type pmic_mt6351 = {
|
||||
.dew_regs = mt6351_regs,
|
||||
.type = PMIC_MT6351,
|
||||
@ -2027,6 +2252,7 @@ static const struct pwrap_slv_type pmic_mt6397 = {
|
||||
|
||||
static const struct of_device_id of_slave_match_tbl[] = {
|
||||
{ .compatible = "mediatek,mt6323", .data = &pmic_mt6323 },
|
||||
{ .compatible = "mediatek,mt6331", .data = &pmic_mt6331 },
|
||||
{ .compatible = "mediatek,mt6351", .data = &pmic_mt6351 },
|
||||
{ .compatible = "mediatek,mt6357", .data = &pmic_mt6357 },
|
||||
{ .compatible = "mediatek,mt6358", .data = &pmic_mt6358 },
|
||||
@ -2079,6 +2305,19 @@ static const struct pmic_wrapper_type pwrap_mt6779 = {
|
||||
.init_soc_specific = NULL,
|
||||
};
|
||||
|
||||
static const struct pmic_wrapper_type pwrap_mt6795 = {
|
||||
.regs = mt6795_regs,
|
||||
.type = PWRAP_MT6795,
|
||||
.arb_en_all = 0x3f,
|
||||
.int_en_all = ~(u32)(BIT(31) | BIT(2) | BIT(1)),
|
||||
.int1_en_all = 0,
|
||||
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
|
||||
.wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD,
|
||||
.caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM,
|
||||
.init_reg_clock = pwrap_common_init_reg_clock,
|
||||
.init_soc_specific = pwrap_mt6795_init_soc_specific,
|
||||
};
|
||||
|
||||
static const struct pmic_wrapper_type pwrap_mt6797 = {
|
||||
.regs = mt6797_regs,
|
||||
.type = PWRAP_MT6797,
|
||||
@ -2212,6 +2451,7 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
|
||||
{ .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701 },
|
||||
{ .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765 },
|
||||
{ .compatible = "mediatek,mt6779-pwrap", .data = &pwrap_mt6779 },
|
||||
{ .compatible = "mediatek,mt6795-pwrap", .data = &pwrap_mt6795 },
|
||||
{ .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797 },
|
||||
{ .compatible = "mediatek,mt6873-pwrap", .data = &pwrap_mt6873 },
|
||||
{ .compatible = "mediatek,mt7622-pwrap", .data = &pwrap_mt7622 },
|
||||
|
@ -2061,9 +2061,9 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp)
|
||||
svsb = &svsp->banks[idx];
|
||||
|
||||
if (svsb->type == SVSB_HIGH)
|
||||
svsb->opp_dev = svs_add_device_link(svsp, "mali");
|
||||
svsb->opp_dev = svs_add_device_link(svsp, "gpu");
|
||||
else if (svsb->type == SVSB_LOW)
|
||||
svsb->opp_dev = svs_get_subsys_device(svsp, "mali");
|
||||
svsb->opp_dev = svs_get_subsys_device(svsp, "gpu");
|
||||
|
||||
if (IS_ERR(svsb->opp_dev))
|
||||
return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev),
|
||||
|
@ -135,6 +135,17 @@ config QCOM_RMTFS_MEM
|
||||
|
||||
Say y here if you intend to boot the modem remoteproc.
|
||||
|
||||
config QCOM_RPM_MASTER_STATS
|
||||
tristate "Qualcomm RPM Master stats"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
help
|
||||
The RPM Master sleep stats driver provides detailed per-subsystem
|
||||
sleep/wake data, read from the RPM message RAM. It can be used to
|
||||
assess whether all the low-power modes available are entered as
|
||||
expected or to check which part of the SoC prevents it from sleeping.
|
||||
|
||||
Say y here if you intend to debug or monitor platform sleep.
|
||||
|
||||
config QCOM_RPMH
|
||||
tristate "Qualcomm RPM-Hardened (RPMH) Communication"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
|
@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
|
||||
qmi_helpers-y += qmi_encdec.o qmi_interface.o
|
||||
obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o
|
||||
obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o
|
||||
obj-$(CONFIG_QCOM_RPM_MASTER_STATS) += rpm_master_stats.o
|
||||
obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o
|
||||
qcom_rpmh-y += rpmh-rsc.o
|
||||
qcom_rpmh-y += rpmh.o
|
||||
|
@ -806,7 +806,7 @@ static int bwmon_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct icc_bwmon_data msm8998_bwmon_data = {
|
||||
.sample_ms = 4,
|
||||
.count_unit_kb = 64,
|
||||
.count_unit_kb = 1024,
|
||||
.default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
|
||||
.default_medbw_kbps = 512 * 1024, /* 512 MBps */
|
||||
.default_lowbw_kbps = 0,
|
||||
|
@ -210,6 +210,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
|
||||
const struct elf32_hdr *ehdr;
|
||||
phys_addr_t min_addr = PHYS_ADDR_MAX;
|
||||
phys_addr_t max_addr = 0;
|
||||
bool relocate = false;
|
||||
size_t metadata_len;
|
||||
void *metadata;
|
||||
int ret;
|
||||
@ -224,6 +225,9 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
|
||||
if (!mdt_phdr_valid(phdr))
|
||||
continue;
|
||||
|
||||
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
|
||||
relocate = true;
|
||||
|
||||
if (phdr->p_paddr < min_addr)
|
||||
min_addr = phdr->p_paddr;
|
||||
|
||||
@ -246,11 +250,13 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
|
||||
if (ret) {
|
||||
/* Unable to set up relocation */
|
||||
dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
|
||||
goto out;
|
||||
if (relocate) {
|
||||
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
|
||||
if (ret) {
|
||||
/* Unable to set up relocation */
|
||||
dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@ -258,6 +264,34 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_mdt_pas_init);
|
||||
|
||||
static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_name)
|
||||
{
|
||||
const struct elf32_phdr *phdrs;
|
||||
const struct elf32_hdr *ehdr;
|
||||
uint64_t seg_start, seg_end;
|
||||
int i;
|
||||
|
||||
ehdr = (struct elf32_hdr *)fw->data;
|
||||
phdrs = (struct elf32_phdr *)(ehdr + 1);
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
/*
|
||||
* The size of the MDT file is not padded to include any
|
||||
* zero-sized segments at the end. Ignore these, as they should
|
||||
* not affect the decision about image being split or not.
|
||||
*/
|
||||
if (!phdrs[i].p_filesz)
|
||||
continue;
|
||||
|
||||
seg_start = phdrs[i].p_offset;
|
||||
seg_end = phdrs[i].p_offset + phdrs[i].p_filesz;
|
||||
if (seg_start > fw->size || seg_end > fw->size)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
|
||||
const char *fw_name, int pas_id, void *mem_region,
|
||||
phys_addr_t mem_phys, size_t mem_size,
|
||||
@ -270,6 +304,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
|
||||
phys_addr_t min_addr = PHYS_ADDR_MAX;
|
||||
ssize_t offset;
|
||||
bool relocate = false;
|
||||
bool is_split;
|
||||
void *ptr;
|
||||
int ret = 0;
|
||||
int i;
|
||||
@ -277,6 +312,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
|
||||
if (!fw || !mem_region || !mem_phys || !mem_size)
|
||||
return -EINVAL;
|
||||
|
||||
is_split = qcom_mdt_bins_are_split(fw, fw_name);
|
||||
ehdr = (struct elf32_hdr *)fw->data;
|
||||
phdrs = (struct elf32_phdr *)(ehdr + 1);
|
||||
|
||||
@ -330,8 +366,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
|
||||
|
||||
ptr = mem_region + offset;
|
||||
|
||||
if (phdr->p_filesz && phdr->p_offset < fw->size &&
|
||||
phdr->p_offset + phdr->p_filesz <= fw->size) {
|
||||
if (phdr->p_filesz && !is_split) {
|
||||
/* Firmware is large enough to be non-split */
|
||||
if (phdr->p_offset + phdr->p_filesz > fw->size) {
|
||||
dev_err(dev, "file %s segment %d would be truncated\n",
|
||||
|
@ -76,6 +76,10 @@ struct ocmem {
|
||||
#define OCMEM_REG_GFX_MPU_START 0x00001004
|
||||
#define OCMEM_REG_GFX_MPU_END 0x00001008
|
||||
|
||||
#define OCMEM_HW_VERSION_MAJOR(val) FIELD_GET(GENMASK(31, 28), val)
|
||||
#define OCMEM_HW_VERSION_MINOR(val) FIELD_GET(GENMASK(27, 16), val)
|
||||
#define OCMEM_HW_VERSION_STEP(val) FIELD_GET(GENMASK(15, 0), val)
|
||||
|
||||
#define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_PREP(0x0000000f, (val))
|
||||
#define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_PREP(0x00003f00, (val))
|
||||
|
||||
@ -355,6 +359,12 @@ static int ocmem_dev_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
reg = ocmem_read(ocmem, OCMEM_REG_HW_VERSION);
|
||||
dev_dbg(dev, "OCMEM hardware version: %lu.%lu.%lu\n",
|
||||
OCMEM_HW_VERSION_MAJOR(reg),
|
||||
OCMEM_HW_VERSION_MINOR(reg),
|
||||
OCMEM_HW_VERSION_STEP(reg));
|
||||
|
||||
reg = ocmem_read(ocmem, OCMEM_REG_HW_PROFILE);
|
||||
ocmem->num_ports = OCMEM_HW_PROFILE_NUM_PORTS(reg);
|
||||
ocmem->num_macros = OCMEM_HW_PROFILE_NUM_MACROS(reg);
|
||||
|
@ -338,13 +338,17 @@ static int pmic_glink_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do not handle altmode for now on those platforms */
|
||||
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
|
||||
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
|
||||
BIT(PMIC_GLINK_CLIENT_UCSI);
|
||||
|
||||
/* Do not handle altmode for now on those platforms */
|
||||
static const unsigned long pmic_glink_sm8550_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
|
||||
BIT(PMIC_GLINK_CLIENT_UCSI);
|
||||
|
||||
static const struct of_device_id pmic_glink_of_match[] = {
|
||||
{ .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
|
||||
{ .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
|
||||
{ .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8550_client_mask },
|
||||
{ .compatible = "qcom,pmic-glink" },
|
||||
{}
|
||||
};
|
||||
|
@ -281,27 +281,14 @@ static void geni_se_select_fifo_mode(struct geni_se *se)
|
||||
|
||||
geni_se_irq_clear(se);
|
||||
|
||||
/*
|
||||
* The RX path for the UART is asynchronous and so needs more
|
||||
* complex logic for enabling / disabling its interrupts.
|
||||
*
|
||||
* Specific notes:
|
||||
* - The done and TX-related interrupts are managed manually.
|
||||
* - We don't RX from the main sequencer (we use the secondary) so
|
||||
* we don't need the RX-related interrupts enabled in the main
|
||||
* sequencer for UART.
|
||||
*/
|
||||
/* UART driver manages enabling / disabling interrupts internally */
|
||||
if (proto != GENI_SE_UART) {
|
||||
/* Non-UART use only primary sequencer so dont bother about S_IRQ */
|
||||
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
|
||||
val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
|
||||
val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
|
||||
if (val != val_old)
|
||||
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
|
||||
|
||||
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
|
||||
val |= S_CMD_DONE_EN;
|
||||
if (val != val_old)
|
||||
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
|
||||
}
|
||||
|
||||
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
|
||||
@ -317,17 +304,14 @@ static void geni_se_select_dma_mode(struct geni_se *se)
|
||||
|
||||
geni_se_irq_clear(se);
|
||||
|
||||
/* UART driver manages enabling / disabling interrupts internally */
|
||||
if (proto != GENI_SE_UART) {
|
||||
/* Non-UART use only primary sequencer so dont bother about S_IRQ */
|
||||
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
|
||||
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
|
||||
val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
|
||||
if (val != val_old)
|
||||
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
|
||||
|
||||
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
|
||||
val &= ~S_CMD_DONE_EN;
|
||||
if (val != val_old)
|
||||
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
|
||||
}
|
||||
|
||||
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
|
||||
@ -344,10 +328,6 @@ static void geni_se_select_gpi_mode(struct geni_se *se)
|
||||
|
||||
writel(0, se->base + SE_IRQ_EN);
|
||||
|
||||
val = readl(se->base + SE_GENI_S_IRQ_EN);
|
||||
val &= ~S_CMD_DONE_EN;
|
||||
writel(val, se->base + SE_GENI_S_IRQ_EN);
|
||||
|
||||
val = readl(se->base + SE_GENI_M_IRQ_EN);
|
||||
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
|
||||
M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
|
||||
|
@ -650,7 +650,7 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size,
|
||||
if (!qmi->recv_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
qmi->wq = alloc_workqueue("qmi_msg_handler", WQ_UNBOUND, 1);
|
||||
qmi->wq = alloc_ordered_workqueue("qmi_msg_handler", 0);
|
||||
if (!qmi->wq) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_recv_buf;
|
||||
|
@ -308,12 +308,15 @@ static int qcom_ramp_controller_probe(struct platform_device *pdev)
|
||||
return qcom_ramp_controller_start(qrc);
|
||||
}
|
||||
|
||||
static int qcom_ramp_controller_remove(struct platform_device *pdev)
|
||||
static void qcom_ramp_controller_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_ramp_controller *qrc = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
return rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis,
|
||||
RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis);
|
||||
ret = rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis,
|
||||
RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to send disable sequence\n");
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_ramp_controller_match_table[] = {
|
||||
@ -329,7 +332,7 @@ static struct platform_driver qcom_ramp_controller_driver = {
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = qcom_ramp_controller_probe,
|
||||
.remove = qcom_ramp_controller_remove,
|
||||
.remove_new = qcom_ramp_controller_remove,
|
||||
};
|
||||
|
||||
static int __init qcom_ramp_controller_init(void)
|
||||
|
163
drivers/soc/qcom/rpm_master_stats.c
Normal file
163
drivers/soc/qcom/rpm_master_stats.c
Normal file
@ -0,0 +1,163 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*
|
||||
* This driver supports what is known as "Master Stats v2" in Qualcomm
|
||||
* downstream kernel terms, which seems to be the only version which has
|
||||
* ever shipped, all the way from 2013 to 2023.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct master_stats_data {
|
||||
void __iomem *base;
|
||||
const char *label;
|
||||
};
|
||||
|
||||
struct rpm_master_stats {
|
||||
u32 active_cores;
|
||||
u32 num_shutdowns;
|
||||
u64 shutdown_req;
|
||||
u64 wakeup_idx;
|
||||
u64 bringup_req;
|
||||
u64 bringup_ack;
|
||||
u32 wakeup_reason; /* 0 = "rude wakeup", 1 = scheduled wakeup */
|
||||
u32 last_sleep_trans_dur;
|
||||
u32 last_wake_trans_dur;
|
||||
|
||||
/* Per-subsystem (*not necessarily* SoC-wide) XO shutdown stats */
|
||||
u32 xo_count;
|
||||
u64 xo_last_enter;
|
||||
u64 last_exit;
|
||||
u64 xo_total_dur;
|
||||
} __packed;
|
||||
|
||||
static int master_stats_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct master_stats_data *data = s->private;
|
||||
struct rpm_master_stats stat;
|
||||
|
||||
memcpy_fromio(&stat, data->base, sizeof(stat));
|
||||
|
||||
seq_printf(s, "%s:\n", data->label);
|
||||
|
||||
seq_printf(s, "\tLast shutdown @ %llu\n", stat.shutdown_req);
|
||||
seq_printf(s, "\tLast bringup req @ %llu\n", stat.bringup_req);
|
||||
seq_printf(s, "\tLast bringup ack @ %llu\n", stat.bringup_ack);
|
||||
seq_printf(s, "\tLast wakeup idx: %llu\n", stat.wakeup_idx);
|
||||
seq_printf(s, "\tLast XO shutdown enter @ %llu\n", stat.xo_last_enter);
|
||||
seq_printf(s, "\tLast XO shutdown exit @ %llu\n", stat.last_exit);
|
||||
seq_printf(s, "\tXO total duration: %llu\n", stat.xo_total_dur);
|
||||
seq_printf(s, "\tLast sleep transition duration: %u\n", stat.last_sleep_trans_dur);
|
||||
seq_printf(s, "\tLast wake transition duration: %u\n", stat.last_wake_trans_dur);
|
||||
seq_printf(s, "\tXO shutdown count: %u\n", stat.xo_count);
|
||||
seq_printf(s, "\tWakeup reason: 0x%x\n", stat.wakeup_reason);
|
||||
seq_printf(s, "\tShutdown count: %u\n", stat.num_shutdowns);
|
||||
seq_printf(s, "\tActive cores bitmask: 0x%x\n", stat.active_cores);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(master_stats);
|
||||
|
||||
static int master_stats_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct master_stats_data *data;
|
||||
struct device_node *msgram_np;
|
||||
struct dentry *dent, *root;
|
||||
struct resource res;
|
||||
int count, i, ret;
|
||||
|
||||
count = of_property_count_strings(dev->of_node, "qcom,master-names");
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
||||
data = devm_kzalloc(dev, count * sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
root = debugfs_create_dir("qcom_rpm_master_stats", NULL);
|
||||
platform_set_drvdata(pdev, root);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
msgram_np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", i);
|
||||
if (!msgram_np) {
|
||||
debugfs_remove_recursive(root);
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"Couldn't parse MSG RAM phandle idx %d", i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Purposefully skip devm_platform helpers as we're using a
|
||||
* shared resource.
|
||||
*/
|
||||
ret = of_address_to_resource(msgram_np, 0, &res);
|
||||
of_node_put(msgram_np);
|
||||
if (ret < 0) {
|
||||
debugfs_remove_recursive(root);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data[i].base = devm_ioremap(dev, res.start, resource_size(&res));
|
||||
if (!data[i].base) {
|
||||
debugfs_remove_recursive(root);
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Could not map the MSG RAM slice idx %d!\n", i);
|
||||
}
|
||||
|
||||
ret = of_property_read_string_index(dev->of_node, "qcom,master-names", i,
|
||||
&data[i].label);
|
||||
if (ret < 0) {
|
||||
debugfs_remove_recursive(root);
|
||||
return dev_err_probe(dev, ret,
|
||||
"Could not read name idx %d!\n", i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generally it's not advised to fail on debugfs errors, but this
|
||||
* driver's only job is exposing data therein.
|
||||
*/
|
||||
dent = debugfs_create_file(data[i].label, 0444, root,
|
||||
&data[i], &master_stats_fops);
|
||||
if (IS_ERR(dent)) {
|
||||
debugfs_remove_recursive(root);
|
||||
return dev_err_probe(dev, PTR_ERR(dent),
|
||||
"Failed to create debugfs file %s!\n", data[i].label);
|
||||
}
|
||||
}
|
||||
|
||||
device_set_pm_not_required(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void master_stats_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dentry *root = platform_get_drvdata(pdev);
|
||||
|
||||
debugfs_remove_recursive(root);
|
||||
}
|
||||
|
||||
static const struct of_device_id rpm_master_table[] = {
|
||||
{ .compatible = "qcom,rpm-master-stats" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver master_stats_driver = {
|
||||
.probe = master_stats_probe,
|
||||
.remove_new = master_stats_remove,
|
||||
.driver = {
|
||||
.name = "qcom_rpm_master_stats",
|
||||
.of_match_table = rpm_master_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(master_stats_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm RPM Master Statistics driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -892,8 +892,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain,
|
||||
pd->corner = state;
|
||||
|
||||
/* Always send updates for vfc and vfl */
|
||||
if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
|
||||
pd->key != KEY_FLOOR_LEVEL)
|
||||
if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
|
||||
pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
|
||||
goto out;
|
||||
|
||||
ret = rpmpd_aggregate_corner(pd);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
#include <linux/soc/qcom/socinfo.h>
|
||||
|
||||
/*
|
||||
* The Qualcomm shared memory system is a allocate only heap structure that
|
||||
@ -500,7 +501,7 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_smem_alloc);
|
||||
EXPORT_SYMBOL_GPL(qcom_smem_alloc);
|
||||
|
||||
static void *qcom_smem_get_global(struct qcom_smem *smem,
|
||||
unsigned item,
|
||||
@ -674,7 +675,7 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
|
||||
return ptr;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_smem_get);
|
||||
EXPORT_SYMBOL_GPL(qcom_smem_get);
|
||||
|
||||
/**
|
||||
* qcom_smem_get_free_space() - retrieve amount of free space in a partition
|
||||
@ -719,7 +720,7 @@ int qcom_smem_get_free_space(unsigned host)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_smem_get_free_space);
|
||||
EXPORT_SYMBOL_GPL(qcom_smem_get_free_space);
|
||||
|
||||
static bool addr_in_range(void __iomem *base, size_t size, void *addr)
|
||||
{
|
||||
@ -770,7 +771,29 @@ phys_addr_t qcom_smem_virt_to_phys(void *p)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_smem_virt_to_phys);
|
||||
EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys);
|
||||
|
||||
/**
|
||||
* qcom_smem_get_soc_id() - return the SoC ID
|
||||
* @id: On success, we return the SoC ID here.
|
||||
*
|
||||
* Look up SoC ID from HW/SW build ID and return it.
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure.
|
||||
*/
|
||||
int qcom_smem_get_soc_id(u32 *id)
|
||||
{
|
||||
struct socinfo *info;
|
||||
|
||||
info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL);
|
||||
if (IS_ERR(info))
|
||||
return PTR_ERR(info);
|
||||
|
||||
*id = __le32_to_cpu(info->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id);
|
||||
|
||||
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
|
||||
{
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
#include <linux/soc/qcom/socinfo.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/sys_soc.h>
|
||||
@ -32,15 +33,6 @@
|
||||
#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id)
|
||||
#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name)
|
||||
|
||||
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
|
||||
#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
|
||||
|
||||
/*
|
||||
* SMEM item id, used to acquire handles to respective
|
||||
* SMEM region.
|
||||
*/
|
||||
#define SMEM_HW_SW_BUILD_ID 137
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
|
||||
#define SMEM_IMAGE_VERSION_SIZE 4096
|
||||
@ -126,64 +118,7 @@ static const char *const pmic_models[] = {
|
||||
[58] = "PM8450",
|
||||
[65] = "PM8010",
|
||||
};
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
/* Socinfo SMEM item structure */
|
||||
struct socinfo {
|
||||
__le32 fmt;
|
||||
__le32 id;
|
||||
__le32 ver;
|
||||
char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
|
||||
/* Version 2 */
|
||||
__le32 raw_id;
|
||||
__le32 raw_ver;
|
||||
/* Version 3 */
|
||||
__le32 hw_plat;
|
||||
/* Version 4 */
|
||||
__le32 plat_ver;
|
||||
/* Version 5 */
|
||||
__le32 accessory_chip;
|
||||
/* Version 6 */
|
||||
__le32 hw_plat_subtype;
|
||||
/* Version 7 */
|
||||
__le32 pmic_model;
|
||||
__le32 pmic_die_rev;
|
||||
/* Version 8 */
|
||||
__le32 pmic_model_1;
|
||||
__le32 pmic_die_rev_1;
|
||||
__le32 pmic_model_2;
|
||||
__le32 pmic_die_rev_2;
|
||||
/* Version 9 */
|
||||
__le32 foundry_id;
|
||||
/* Version 10 */
|
||||
__le32 serial_num;
|
||||
/* Version 11 */
|
||||
__le32 num_pmics;
|
||||
__le32 pmic_array_offset;
|
||||
/* Version 12 */
|
||||
__le32 chip_family;
|
||||
__le32 raw_device_family;
|
||||
__le32 raw_device_num;
|
||||
/* Version 13 */
|
||||
__le32 nproduct_id;
|
||||
char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
|
||||
/* Version 14 */
|
||||
__le32 num_clusters;
|
||||
__le32 ncluster_array_offset;
|
||||
__le32 num_defective_parts;
|
||||
__le32 ndefective_parts_array_offset;
|
||||
/* Version 15 */
|
||||
__le32 nmodem_supported;
|
||||
/* Version 16 */
|
||||
__le32 feature_code;
|
||||
__le32 pcode;
|
||||
__le32 npartnamemap_offset;
|
||||
__le32 nnum_partname_mapping;
|
||||
/* Version 17 */
|
||||
__le32 oem_variant;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct socinfo_params {
|
||||
u32 raw_device_family;
|
||||
u32 hw_plat_subtype;
|
||||
@ -198,12 +133,15 @@ struct socinfo_params {
|
||||
u32 nproduct_id;
|
||||
u32 num_clusters;
|
||||
u32 ncluster_array_offset;
|
||||
u32 num_defective_parts;
|
||||
u32 ndefective_parts_array_offset;
|
||||
u32 num_subset_parts;
|
||||
u32 nsubset_parts_array_offset;
|
||||
u32 nmodem_supported;
|
||||
u32 feature_code;
|
||||
u32 pcode;
|
||||
u32 oem_variant;
|
||||
u32 num_func_clusters;
|
||||
u32 boot_cluster;
|
||||
u32 boot_core;
|
||||
};
|
||||
|
||||
struct smem_image_version {
|
||||
@ -434,6 +372,9 @@ static const struct soc_id soc_id[] = {
|
||||
{ qcom_board_id(SM8350) },
|
||||
{ qcom_board_id(QCM2290) },
|
||||
{ qcom_board_id(SM6115) },
|
||||
{ qcom_board_id(IPQ5010) },
|
||||
{ qcom_board_id(IPQ5018) },
|
||||
{ qcom_board_id(IPQ5028) },
|
||||
{ qcom_board_id(SC8280XP) },
|
||||
{ qcom_board_id(IPQ6005) },
|
||||
{ qcom_board_id(QRB5165) },
|
||||
@ -447,6 +388,9 @@ static const struct soc_id soc_id[] = {
|
||||
{ qcom_board_id_named(SM8450_3, "SM8450") },
|
||||
{ qcom_board_id(SC7280) },
|
||||
{ qcom_board_id(SC7180P) },
|
||||
{ qcom_board_id(IPQ5000) },
|
||||
{ qcom_board_id(IPQ0509) },
|
||||
{ qcom_board_id(IPQ0518) },
|
||||
{ qcom_board_id(SM6375) },
|
||||
{ qcom_board_id(IPQ9514) },
|
||||
{ qcom_board_id(IPQ9550) },
|
||||
@ -454,6 +398,7 @@ static const struct soc_id soc_id[] = {
|
||||
{ qcom_board_id(IPQ9570) },
|
||||
{ qcom_board_id(IPQ9574) },
|
||||
{ qcom_board_id(SM8550) },
|
||||
{ qcom_board_id(IPQ5016) },
|
||||
{ qcom_board_id(IPQ9510) },
|
||||
{ qcom_board_id(QRB4210) },
|
||||
{ qcom_board_id(QRB2210) },
|
||||
@ -461,11 +406,15 @@ static const struct soc_id soc_id[] = {
|
||||
{ qcom_board_id(QRU1000) },
|
||||
{ qcom_board_id(QDU1000) },
|
||||
{ qcom_board_id(QDU1010) },
|
||||
{ qcom_board_id(IPQ5019) },
|
||||
{ qcom_board_id(QRU1032) },
|
||||
{ qcom_board_id(QRU1052) },
|
||||
{ qcom_board_id(QRU1062) },
|
||||
{ qcom_board_id(IPQ5332) },
|
||||
{ qcom_board_id(IPQ5322) },
|
||||
{ qcom_board_id(IPQ5312) },
|
||||
{ qcom_board_id(IPQ5302) },
|
||||
{ qcom_board_id(IPQ5300) },
|
||||
};
|
||||
|
||||
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
||||
@ -620,6 +569,19 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
||||
&qcom_socinfo->info.fmt);
|
||||
|
||||
switch (qcom_socinfo->info.fmt) {
|
||||
case SOCINFO_VERSION(0, 19):
|
||||
qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters);
|
||||
qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster);
|
||||
qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core);
|
||||
|
||||
debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.num_func_clusters);
|
||||
debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.boot_cluster);
|
||||
debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.boot_core);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 18):
|
||||
case SOCINFO_VERSION(0, 17):
|
||||
qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant);
|
||||
debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root,
|
||||
@ -643,17 +605,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
||||
case SOCINFO_VERSION(0, 14):
|
||||
qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters);
|
||||
qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset);
|
||||
qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts);
|
||||
qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset);
|
||||
qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts);
|
||||
qcom_socinfo->info.nsubset_parts_array_offset =
|
||||
__le32_to_cpu(info->nsubset_parts_array_offset);
|
||||
|
||||
debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.num_clusters);
|
||||
debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.ncluster_array_offset);
|
||||
debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.num_defective_parts);
|
||||
debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.ndefective_parts_array_offset);
|
||||
debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.num_subset_parts);
|
||||
debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.nsubset_parts_array_offset);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 13):
|
||||
qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id);
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#define WDTRSTCR_RESET 0xA55A0002
|
||||
#define WDTRSTCR 0x0054
|
||||
#define GEN4_WDTRSTCR 0x0010
|
||||
|
||||
#define CR7BAR 0x0070
|
||||
#define CR7BAREN BIT(4)
|
||||
@ -27,6 +28,12 @@ static int rcar_rst_enable_wdt_reset(void __iomem *base)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_rst_v3u_enable_wdt_reset(void __iomem *base)
|
||||
{
|
||||
iowrite32(WDTRSTCR_RESET, base + GEN4_WDTRSTCR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
|
||||
* Firmware boot address has to be set in CR7BAR before
|
||||
@ -66,6 +73,12 @@ static const struct rst_config rcar_rst_gen3 __initconst = {
|
||||
.set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr,
|
||||
};
|
||||
|
||||
/* V3U firmware doesn't enable WDT reset and there won't be updates anymore */
|
||||
static const struct rst_config rcar_rst_v3u __initconst = {
|
||||
.modemr = 0x00, /* MODEMR0 and it has CPG related bits */
|
||||
.configure = rcar_rst_v3u_enable_wdt_reset,
|
||||
};
|
||||
|
||||
static const struct rst_config rcar_rst_gen4 __initconst = {
|
||||
.modemr = 0x00, /* MODEMR0 and it has CPG related bits */
|
||||
};
|
||||
@ -101,7 +114,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
|
||||
{ .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 },
|
||||
{ .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 },
|
||||
/* R-Car Gen4 */
|
||||
{ .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_gen4 },
|
||||
{ .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_v3u },
|
||||
{ .compatible = "renesas,r8a779f0-rst", .data = &rcar_rst_gen4 },
|
||||
{ .compatible = "renesas,r8a779g0-rst", .data = &rcar_rst_gen4 },
|
||||
{ /* sentinel */ }
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <linux/clk/renesas.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm.h>
|
||||
@ -19,8 +21,6 @@
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
/* SYSC */
|
||||
#define SPDCR 0x08 /* SYS Power Down Control Register */
|
||||
#define SWUCR 0x14 /* SYS Wakeup Control Register */
|
||||
@ -47,6 +47,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
|
||||
unsigned int mask = BIT(rmobile_pd->bit_shift);
|
||||
u32 val;
|
||||
|
||||
if (rmobile_pd->suspend) {
|
||||
int ret = rmobile_pd->suspend();
|
||||
@ -56,14 +57,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
|
||||
}
|
||||
|
||||
if (readl(rmobile_pd->base + PSTR) & mask) {
|
||||
unsigned int retry_count;
|
||||
writel(mask, rmobile_pd->base + SPDCR);
|
||||
|
||||
for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
|
||||
if (!(readl(rmobile_pd->base + SPDCR) & mask))
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val,
|
||||
!(val & mask), 0, PSTR_RETRIES);
|
||||
}
|
||||
|
||||
pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask,
|
||||
@ -74,8 +71,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
|
||||
|
||||
static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
|
||||
{
|
||||
unsigned int mask = BIT(rmobile_pd->bit_shift);
|
||||
unsigned int retry_count;
|
||||
unsigned int val, mask = BIT(rmobile_pd->bit_shift);
|
||||
int ret = 0;
|
||||
|
||||
if (readl(rmobile_pd->base + PSTR) & mask)
|
||||
@ -83,16 +79,9 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
|
||||
|
||||
writel(mask, rmobile_pd->base + SWUCR);
|
||||
|
||||
for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
|
||||
if (!(readl(rmobile_pd->base + SWUCR) & mask))
|
||||
break;
|
||||
if (retry_count > PSTR_RETRIES)
|
||||
udelay(PSTR_DELAY_US);
|
||||
else
|
||||
cpu_relax();
|
||||
}
|
||||
if (!retry_count)
|
||||
ret = -EIO;
|
||||
ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val,
|
||||
(val & mask), PSTR_DELAY_US,
|
||||
PSTR_RETRIES * PSTR_DELAY_US);
|
||||
|
||||
pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
|
||||
rmobile_pd->genpd.name, mask,
|
||||
|
@ -12,33 +12,33 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static struct dtpm_node __initdata rk3399_hierarchy[] = {
|
||||
[0]{ .name = "rk3399",
|
||||
.type = DTPM_NODE_VIRTUAL },
|
||||
[1]{ .name = "package",
|
||||
.type = DTPM_NODE_VIRTUAL,
|
||||
.parent = &rk3399_hierarchy[0] },
|
||||
[2]{ .name = "/cpus/cpu@0",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[3]{ .name = "/cpus/cpu@1",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[4]{ .name = "/cpus/cpu@2",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[5]{ .name = "/cpus/cpu@3",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[6]{ .name = "/cpus/cpu@100",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[7]{ .name = "/cpus/cpu@101",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[8]{ .name = "/gpu@ff9a0000",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[9]{ /* sentinel */ }
|
||||
[0] = { .name = "rk3399",
|
||||
.type = DTPM_NODE_VIRTUAL },
|
||||
[1] = { .name = "package",
|
||||
.type = DTPM_NODE_VIRTUAL,
|
||||
.parent = &rk3399_hierarchy[0] },
|
||||
[2] = { .name = "/cpus/cpu@0",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[3] = { .name = "/cpus/cpu@1",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[4] = { .name = "/cpus/cpu@2",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[5] = { .name = "/cpus/cpu@3",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[6] = { .name = "/cpus/cpu@100",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[7] = { .name = "/cpus/cpu@101",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[8] = { .name = "/gpu@ff9a0000",
|
||||
.type = DTPM_NODE_DT,
|
||||
.parent = &rk3399_hierarchy[1] },
|
||||
[9] = { /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct of_device_id __initdata rockchip_dtpm_match_table[] = {
|
||||
|
@ -43,8 +43,10 @@ struct rockchip_domain_info {
|
||||
bool active_wakeup;
|
||||
int pwr_w_mask;
|
||||
int req_w_mask;
|
||||
int mem_status_mask;
|
||||
int repair_status_mask;
|
||||
u32 pwr_offset;
|
||||
u32 mem_offset;
|
||||
u32 req_offset;
|
||||
};
|
||||
|
||||
@ -54,6 +56,9 @@ struct rockchip_pmu_info {
|
||||
u32 req_offset;
|
||||
u32 idle_offset;
|
||||
u32 ack_offset;
|
||||
u32 mem_pwr_offset;
|
||||
u32 chain_status_offset;
|
||||
u32 mem_status_offset;
|
||||
u32 repair_status_offset;
|
||||
|
||||
u32 core_pwrcnt_offset;
|
||||
@ -119,13 +124,15 @@ struct rockchip_pmu {
|
||||
.active_wakeup = wakeup, \
|
||||
}
|
||||
|
||||
#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, wakeup) \
|
||||
#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.pwr_offset = p_offset, \
|
||||
.pwr_w_mask = (pwr) << 16, \
|
||||
.pwr_mask = (pwr), \
|
||||
.status_mask = (status), \
|
||||
.mem_offset = m_offset, \
|
||||
.mem_status_mask = (m_status), \
|
||||
.repair_status_mask = (r_status), \
|
||||
.req_offset = r_offset, \
|
||||
.req_w_mask = (req) << 16, \
|
||||
@ -269,8 +276,8 @@ void rockchip_pmu_unblock(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
|
||||
|
||||
#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \
|
||||
DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup)
|
||||
#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup) \
|
||||
DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup)
|
||||
|
||||
static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
@ -408,17 +415,92 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
|
||||
return !(val & pd->info->status_mask);
|
||||
}
|
||||
|
||||
static bool rockchip_pmu_domain_is_mem_on(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(pmu->regmap,
|
||||
pmu->info->mem_status_offset + pd->info->mem_offset, &val);
|
||||
|
||||
/* 1'b0: power on, 1'b1: power off */
|
||||
return !(val & pd->info->mem_status_mask);
|
||||
}
|
||||
|
||||
static bool rockchip_pmu_domain_is_chain_on(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(pmu->regmap,
|
||||
pmu->info->chain_status_offset + pd->info->mem_offset, &val);
|
||||
|
||||
/* 1'b1: power on, 1'b0: power off */
|
||||
return val & pd->info->mem_status_mask;
|
||||
}
|
||||
|
||||
static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
struct generic_pm_domain *genpd = &pd->genpd;
|
||||
bool is_on;
|
||||
int ret = 0;
|
||||
|
||||
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_chain_on, pd, is_on,
|
||||
is_on == true, 0, 10000);
|
||||
if (ret) {
|
||||
dev_err(pmu->dev,
|
||||
"failed to get chain status '%s', target_on=1, val=%d\n",
|
||||
genpd->name, is_on);
|
||||
goto error;
|
||||
}
|
||||
|
||||
udelay(20);
|
||||
|
||||
regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset,
|
||||
(pd->info->pwr_mask | pd->info->pwr_w_mask));
|
||||
wmb();
|
||||
|
||||
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on,
|
||||
is_on == false, 0, 10000);
|
||||
if (ret) {
|
||||
dev_err(pmu->dev,
|
||||
"failed to get mem status '%s', target_on=0, val=%d\n",
|
||||
genpd->name, is_on);
|
||||
goto error;
|
||||
}
|
||||
|
||||
regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset,
|
||||
pd->info->pwr_w_mask);
|
||||
wmb();
|
||||
|
||||
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on,
|
||||
is_on == true, 0, 10000);
|
||||
if (ret) {
|
||||
dev_err(pmu->dev,
|
||||
"failed to get mem status '%s', target_on=1, val=%d\n",
|
||||
genpd->name, is_on);
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
|
||||
bool on)
|
||||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
struct generic_pm_domain *genpd = &pd->genpd;
|
||||
u32 pd_pwr_offset = pd->info->pwr_offset;
|
||||
bool is_on;
|
||||
bool is_on, is_mem_on = false;
|
||||
|
||||
if (pd->info->pwr_mask == 0)
|
||||
return;
|
||||
else if (pd->info->pwr_w_mask)
|
||||
|
||||
if (on && pd->info->mem_status_mask)
|
||||
is_mem_on = rockchip_pmu_domain_is_mem_on(pd);
|
||||
|
||||
if (pd->info->pwr_w_mask)
|
||||
regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
|
||||
on ? pd->info->pwr_w_mask :
|
||||
(pd->info->pwr_mask | pd->info->pwr_w_mask));
|
||||
@ -428,6 +510,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
|
||||
|
||||
wmb();
|
||||
|
||||
if (is_mem_on && rockchip_pmu_domain_mem_reset(pd))
|
||||
return;
|
||||
|
||||
if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
|
||||
is_on == on, 0, 10000)) {
|
||||
dev_err(pmu->dev,
|
||||
@ -645,7 +730,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
||||
pd->genpd.flags = GENPD_FLAG_PM_CLK;
|
||||
if (pd_info->active_wakeup)
|
||||
pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
pm_genpd_init(&pd->genpd, NULL, !rockchip_pmu_domain_is_on(pd));
|
||||
pm_genpd_init(&pd->genpd, NULL,
|
||||
!rockchip_pmu_domain_is_on(pd) ||
|
||||
(pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd)));
|
||||
|
||||
pmu->genpd_data.domains[id] = &pd->genpd;
|
||||
return 0;
|
||||
@ -1024,35 +1111,35 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = {
|
||||
};
|
||||
|
||||
static const struct rockchip_domain_info rk3588_pm_domains[] = {
|
||||
[RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false),
|
||||
[RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false),
|
||||
[RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false),
|
||||
[RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false),
|
||||
[RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false),
|
||||
[RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false),
|
||||
[RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false),
|
||||
[RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false),
|
||||
[RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false),
|
||||
[RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false),
|
||||
[RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false),
|
||||
[RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false),
|
||||
[RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false),
|
||||
[RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false),
|
||||
[RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false),
|
||||
[RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false),
|
||||
[RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false),
|
||||
[RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
|
||||
[RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false),
|
||||
[RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false),
|
||||
[RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false),
|
||||
[RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false),
|
||||
[RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false),
|
||||
[RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true),
|
||||
[RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false),
|
||||
[RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false),
|
||||
[RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false),
|
||||
[RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true),
|
||||
[RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false),
|
||||
[RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false),
|
||||
[RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false),
|
||||
[RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false),
|
||||
[RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false),
|
||||
[RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false),
|
||||
[RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false),
|
||||
[RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, 0x0, BIT(14), BIT(5), 0x0, BIT(4), BIT(4), false),
|
||||
[RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, 0x0, BIT(15), BIT(6), 0x0, BIT(5), BIT(5), false),
|
||||
[RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, 0x0, BIT(16), BIT(7), 0x0, BIT(6), BIT(6), false),
|
||||
[RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, 0x0, BIT(17), BIT(8), 0x0, BIT(7), BIT(7), false),
|
||||
[RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, 0x0, BIT(18), BIT(9), 0x0, BIT(8), BIT(8), false),
|
||||
[RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, 0x0, BIT(19), BIT(10), 0x0, 0, 0, false),
|
||||
[RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, 0x0, BIT(20), BIT(11), 0x0, BIT(9), BIT(9), false),
|
||||
[RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, 0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false),
|
||||
[RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, 0x0, BIT(22), BIT(13), 0x0, 0, 0, false),
|
||||
[RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, 0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false),
|
||||
[RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, 0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false),
|
||||
[RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, 0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
|
||||
[RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, 0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false),
|
||||
[RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, 0x0, BIT(27), BIT(18), 0x4, BIT(0), BIT(16), false),
|
||||
[RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, 0x0, BIT(28), BIT(19), 0x4, BIT(1), BIT(17), false),
|
||||
[RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, 0x0, BIT(29), BIT(20), 0x4, BIT(5), BIT(21), false),
|
||||
[RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, 0x0, BIT(30), BIT(21), 0x0, 0, 0, false),
|
||||
[RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, 0x0, BIT(31), BIT(22), 0x0, 0, 0, true),
|
||||
[RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0x4, 0, 0, 0x4, BIT(2), BIT(18), false),
|
||||
[RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, 0x4, BIT(1), BIT(23), 0x0, 0, 0, false),
|
||||
[RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, 0x4, BIT(2), BIT(24), 0x4, BIT(3), BIT(19), false),
|
||||
[RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, 0x4, BIT(3), BIT(25), 0x4, BIT(4), BIT(20), true),
|
||||
[RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, 0x4, BIT(5), BIT(26), 0x0, 0, 0, false),
|
||||
};
|
||||
|
||||
static const struct rockchip_pmu_info px30_pmu = {
|
||||
@ -1207,6 +1294,9 @@ static const struct rockchip_pmu_info rk3588_pmu = {
|
||||
.req_offset = 0x10c,
|
||||
.idle_offset = 0x120,
|
||||
.ack_offset = 0x118,
|
||||
.mem_pwr_offset = 0x1a0,
|
||||
.chain_status_offset = 0x1f0,
|
||||
.mem_status_offset = 0x1f8,
|
||||
.repair_status_offset = 0x290,
|
||||
|
||||
.num_domains = ARRAY_SIZE(rk3588_pm_domains),
|
||||
|
@ -57,6 +57,12 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
|
||||
|
||||
if (pmu_data->powerdown_conf_extra)
|
||||
pmu_data->powerdown_conf_extra(mode);
|
||||
|
||||
if (pmu_data->pmu_config_extra) {
|
||||
for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
|
||||
pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
|
||||
pmu_data->pmu_config_extra[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -79,6 +85,9 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = {
|
||||
}, {
|
||||
.compatible = "samsung,exynos4210-pmu",
|
||||
.data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos4212-pmu",
|
||||
.data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos4412-pmu",
|
||||
.data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
|
||||
|
@ -20,6 +20,7 @@ struct exynos_pmu_conf {
|
||||
|
||||
struct exynos_pmu_data {
|
||||
const struct exynos_pmu_conf *pmu_config;
|
||||
const struct exynos_pmu_conf *pmu_config_extra;
|
||||
|
||||
void (*pmu_init)(void);
|
||||
void (*powerdown_conf)(enum sys_powerdown);
|
||||
@ -32,6 +33,7 @@ extern void __iomem *pmu_base_addr;
|
||||
/* list of all exported SoC specific data */
|
||||
extern const struct exynos_pmu_data exynos3250_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos4210_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos4212_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos4412_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos5250_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos5420_pmu_data;
|
||||
|
@ -86,7 +86,7 @@ static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
|
||||
static const struct exynos_pmu_conf exynos4x12_pmu_config[] = {
|
||||
{ S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
|
||||
@ -191,6 +191,10 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
|
||||
{ S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
|
||||
{ S5P_ARM_CORE2_LOWPWR, { 0x0, 0x0, 0x2 } },
|
||||
{ S5P_DIS_IRQ_CORE2, { 0x0, 0x0, 0x0 } },
|
||||
{ S5P_DIS_IRQ_CENTRAL2, { 0x0, 0x0, 0x0 } },
|
||||
@ -204,6 +208,11 @@ const struct exynos_pmu_data exynos4210_pmu_data = {
|
||||
.pmu_config = exynos4210_pmu_config,
|
||||
};
|
||||
|
||||
const struct exynos_pmu_data exynos4412_pmu_data = {
|
||||
.pmu_config = exynos4412_pmu_config,
|
||||
const struct exynos_pmu_data exynos4212_pmu_data = {
|
||||
.pmu_config = exynos4x12_pmu_config,
|
||||
};
|
||||
|
||||
const struct exynos_pmu_data exynos4412_pmu_data = {
|
||||
.pmu_config = exynos4x12_pmu_config,
|
||||
.pmu_config_extra = exynos4412_pmu_config,
|
||||
};
|
||||
|
@ -663,7 +663,7 @@ static const struct nvmem_keepout tegra234_fuse_keepouts[] = {
|
||||
|
||||
static const struct tegra_fuse_info tegra234_fuse_info = {
|
||||
.read = tegra30_fuse_read,
|
||||
.size = 0x98c,
|
||||
.size = 0xf90,
|
||||
.spare = 0x280,
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
@ -62,6 +62,7 @@ bool tegra_is_silicon(void)
|
||||
switch (tegra_get_chip_id()) {
|
||||
case TEGRA194:
|
||||
case TEGRA234:
|
||||
case TEGRA264:
|
||||
if (tegra_get_platform() == 0)
|
||||
return true;
|
||||
|
||||
|
@ -396,7 +396,6 @@ struct tegra_pmc_soc {
|
||||
* @clk: pointer to pclk clock
|
||||
* @soc: pointer to SoC data structure
|
||||
* @tz_only: flag specifying if the PMC can only be accessed via TrustZone
|
||||
* @debugfs: pointer to debugfs entry
|
||||
* @rate: currently configured rate of pclk
|
||||
* @suspend_mode: lowest suspend mode available
|
||||
* @cpu_good_time: CPU power good time (in microseconds)
|
||||
@ -431,7 +430,6 @@ struct tegra_pmc {
|
||||
void __iomem *aotag;
|
||||
void __iomem *scratch;
|
||||
struct clk *clk;
|
||||
struct dentry *debugfs;
|
||||
|
||||
const struct tegra_pmc_soc *soc;
|
||||
bool tz_only;
|
||||
@ -1190,16 +1188,6 @@ static int powergate_show(struct seq_file *s, void *data)
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(powergate);
|
||||
|
||||
static int tegra_powergate_debugfs_init(void)
|
||||
{
|
||||
pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
|
||||
&powergate_fops);
|
||||
if (!pmc->debugfs)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
|
||||
struct device_node *np)
|
||||
{
|
||||
@ -3004,7 +2992,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
||||
*/
|
||||
if (pmc->clk) {
|
||||
pmc->clk_nb.notifier_call = tegra_pmc_clk_notify_cb;
|
||||
err = clk_notifier_register(pmc->clk, &pmc->clk_nb);
|
||||
err = devm_clk_notifier_register(&pdev->dev, pmc->clk,
|
||||
&pmc->clk_nb);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to register clk notifier\n");
|
||||
@ -3026,19 +3015,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
||||
|
||||
tegra_pmc_reset_sysfs_init(pmc);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
|
||||
err = tegra_powergate_debugfs_init();
|
||||
if (err < 0)
|
||||
goto cleanup_sysfs;
|
||||
}
|
||||
|
||||
err = tegra_pmc_pinctrl_init(pmc);
|
||||
if (err)
|
||||
goto cleanup_debugfs;
|
||||
goto cleanup_sysfs;
|
||||
|
||||
err = tegra_pmc_regmap_init(pmc);
|
||||
if (err < 0)
|
||||
goto cleanup_debugfs;
|
||||
goto cleanup_sysfs;
|
||||
|
||||
err = tegra_powergate_init(pmc, pdev->dev.of_node);
|
||||
if (err < 0)
|
||||
@ -3061,16 +3044,15 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
||||
if (pmc->soc->set_wake_filters)
|
||||
pmc->soc->set_wake_filters(pmc);
|
||||
|
||||
debugfs_create_file("powergate", 0444, NULL, NULL, &powergate_fops);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_powergates:
|
||||
tegra_powergate_remove_all(pdev->dev.of_node);
|
||||
cleanup_debugfs:
|
||||
debugfs_remove(pmc->debugfs);
|
||||
cleanup_sysfs:
|
||||
device_remove_file(&pdev->dev, &dev_attr_reset_reason);
|
||||
device_remove_file(&pdev->dev, &dev_attr_reset_level);
|
||||
clk_notifier_unregister(pmc->clk, &pmc->clk_nb);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -4250,6 +4232,7 @@ static const struct tegra_wake_event tegra234_wake_events[] = {
|
||||
TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)),
|
||||
TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)),
|
||||
TEGRA_WAKE_IRQ("rtc", 73, 10),
|
||||
TEGRA_WAKE_IRQ("sw-wake", SW_WAKE_ID, 179),
|
||||
};
|
||||
|
||||
static const struct tegra_pmc_soc tegra234_pmc_soc = {
|
||||
|
@ -85,7 +85,7 @@ config TI_K3_SOCINFO
|
||||
|
||||
config TI_PRUSS
|
||||
tristate "TI PRU-ICSS Subsystem Platform drivers"
|
||||
depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3
|
||||
depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
help
|
||||
TI PRU-ICSS Subsystem platform specific support.
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Author(s):
|
||||
* Suman Anna <s-anna@ti.com>
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
* Tero Kristo <t-kristo@ti.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
@ -18,7 +19,9 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pruss_driver.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/remoteproc.h>
|
||||
#include <linux/slab.h>
|
||||
#include "pruss.h"
|
||||
|
||||
/**
|
||||
* struct pruss_private_data - PRUSS driver private data
|
||||
@ -30,6 +33,257 @@ struct pruss_private_data {
|
||||
bool has_core_mux_clock;
|
||||
};
|
||||
|
||||
/**
|
||||
* pruss_get() - get the pruss for a given PRU remoteproc
|
||||
* @rproc: remoteproc handle of a PRU instance
|
||||
*
|
||||
* Finds the parent pruss device for a PRU given the @rproc handle of the
|
||||
* PRU remote processor. This function increments the pruss device's refcount,
|
||||
* so always use pruss_put() to decrement it back once pruss isn't needed
|
||||
* anymore.
|
||||
*
|
||||
* This API doesn't check if @rproc is valid or not. It is expected the caller
|
||||
* will have done a pru_rproc_get() on @rproc, before calling this API to make
|
||||
* sure that @rproc is valid.
|
||||
*
|
||||
* Return: pruss handle on success, and an ERR_PTR on failure using one
|
||||
* of the following error values
|
||||
* -EINVAL if invalid parameter
|
||||
* -ENODEV if PRU device or PRUSS device is not found
|
||||
*/
|
||||
struct pruss *pruss_get(struct rproc *rproc)
|
||||
{
|
||||
struct pruss *pruss;
|
||||
struct device *dev;
|
||||
struct platform_device *ppdev;
|
||||
|
||||
if (IS_ERR_OR_NULL(rproc))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
dev = &rproc->dev;
|
||||
|
||||
/* make sure it is PRU rproc */
|
||||
if (!dev->parent || !is_pru_rproc(dev->parent))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
ppdev = to_platform_device(dev->parent->parent);
|
||||
pruss = platform_get_drvdata(ppdev);
|
||||
if (!pruss)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
get_device(pruss->dev);
|
||||
|
||||
return pruss;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_get);
|
||||
|
||||
/**
|
||||
* pruss_put() - decrement pruss device's usecount
|
||||
* @pruss: pruss handle
|
||||
*
|
||||
* Complimentary function for pruss_get(). Needs to be called
|
||||
* after the PRUSS is used, and only if the pruss_get() succeeds.
|
||||
*/
|
||||
void pruss_put(struct pruss *pruss)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(pruss))
|
||||
return;
|
||||
|
||||
put_device(pruss->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_put);
|
||||
|
||||
/**
|
||||
* pruss_request_mem_region() - request a memory resource
|
||||
* @pruss: the pruss instance
|
||||
* @mem_id: the memory resource id
|
||||
* @region: pointer to memory region structure to be filled in
|
||||
*
|
||||
* This function allows a client driver to request a memory resource,
|
||||
* and if successful, will let the client driver own the particular
|
||||
* memory region until released using the pruss_release_mem_region()
|
||||
* API.
|
||||
*
|
||||
* Return: 0 if requested memory region is available (in such case pointer to
|
||||
* memory region is returned via @region), an error otherwise
|
||||
*/
|
||||
int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
|
||||
struct pruss_mem_region *region)
|
||||
{
|
||||
if (!pruss || !region || mem_id >= PRUSS_MEM_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pruss->lock);
|
||||
|
||||
if (pruss->mem_in_use[mem_id]) {
|
||||
mutex_unlock(&pruss->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
*region = pruss->mem_regions[mem_id];
|
||||
pruss->mem_in_use[mem_id] = region;
|
||||
|
||||
mutex_unlock(&pruss->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_request_mem_region);
|
||||
|
||||
/**
|
||||
* pruss_release_mem_region() - release a memory resource
|
||||
* @pruss: the pruss instance
|
||||
* @region: the memory region to release
|
||||
*
|
||||
* This function is the complimentary function to
|
||||
* pruss_request_mem_region(), and allows the client drivers to
|
||||
* release back a memory resource.
|
||||
*
|
||||
* Return: 0 on success, an error code otherwise
|
||||
*/
|
||||
int pruss_release_mem_region(struct pruss *pruss,
|
||||
struct pruss_mem_region *region)
|
||||
{
|
||||
int id;
|
||||
|
||||
if (!pruss || !region)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pruss->lock);
|
||||
|
||||
/* find out the memory region being released */
|
||||
for (id = 0; id < PRUSS_MEM_MAX; id++) {
|
||||
if (pruss->mem_in_use[id] == region)
|
||||
break;
|
||||
}
|
||||
|
||||
if (id == PRUSS_MEM_MAX) {
|
||||
mutex_unlock(&pruss->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pruss->mem_in_use[id] = NULL;
|
||||
|
||||
mutex_unlock(&pruss->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_release_mem_region);
|
||||
|
||||
/**
|
||||
* pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device
|
||||
* @pruss: pruss instance
|
||||
* @pru_id: PRU identifier (0-1)
|
||||
* @mux: pointer to store the current mux value into
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
if (pru_id >= PRUSS_NUM_PRUS || !mux)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val);
|
||||
if (!ret)
|
||||
*mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >>
|
||||
PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux);
|
||||
|
||||
/**
|
||||
* pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device
|
||||
* @pruss: pruss instance
|
||||
* @pru_id: PRU identifier (0-1)
|
||||
* @mux: new mux value for PRU
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux)
|
||||
{
|
||||
if (mux >= PRUSS_GP_MUX_SEL_MAX ||
|
||||
pru_id >= PRUSS_NUM_PRUS)
|
||||
return -EINVAL;
|
||||
|
||||
return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
|
||||
PRUSS_GPCFG_PRU_MUX_SEL_MASK,
|
||||
(u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux);
|
||||
|
||||
/**
|
||||
* pruss_cfg_gpimode() - set the GPI mode of the PRU
|
||||
* @pruss: the pruss instance handle
|
||||
* @pru_id: id of the PRU core within the PRUSS
|
||||
* @mode: GPI mode to set
|
||||
*
|
||||
* Sets the GPI mode for a given PRU by programming the
|
||||
* corresponding PRUSS_CFG_GPCFGx register
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id,
|
||||
enum pruss_gpi_mode mode)
|
||||
{
|
||||
if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
|
||||
PRUSS_GPCFG_PRU_GPI_MODE_MASK,
|
||||
mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_cfg_gpimode);
|
||||
|
||||
/**
|
||||
* pruss_cfg_miirt_enable() - Enable/disable MII RT Events
|
||||
* @pruss: the pruss instance
|
||||
* @enable: enable/disable
|
||||
*
|
||||
* Enable/disable the MII RT Events for the PRUSS.
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable)
|
||||
{
|
||||
u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0;
|
||||
|
||||
return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT,
|
||||
PRUSS_MII_RT_EVENT_EN, set);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable);
|
||||
|
||||
/**
|
||||
* pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality
|
||||
* @pruss: the pruss instance
|
||||
* @pru_type: PRU core type identifier
|
||||
* @enable: enable/disable
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type,
|
||||
bool enable)
|
||||
{
|
||||
u32 mask, set;
|
||||
|
||||
switch (pru_type) {
|
||||
case PRU_TYPE_PRU:
|
||||
mask = PRUSS_SPP_XFER_SHIFT_EN;
|
||||
break;
|
||||
case PRU_TYPE_RTU:
|
||||
mask = PRUSS_SPP_RTU_XFR_SHIFT_EN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set = enable ? mask : 0;
|
||||
|
||||
return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable);
|
||||
|
||||
static void pruss_of_free_clk_provider(void *data)
|
||||
{
|
||||
struct device_node *clk_mux_np = data;
|
||||
@ -38,6 +292,11 @@ static void pruss_of_free_clk_provider(void *data)
|
||||
of_node_put(clk_mux_np);
|
||||
}
|
||||
|
||||
static void pruss_clk_unregister_mux(void *data)
|
||||
{
|
||||
clk_unregister_mux(data);
|
||||
}
|
||||
|
||||
static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
|
||||
char *mux_name, struct device_node *clks_np)
|
||||
{
|
||||
@ -93,8 +352,7 @@ static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
|
||||
goto put_clk_mux_np;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux,
|
||||
clk_mux);
|
||||
ret = devm_add_action_or_reset(dev, pruss_clk_unregister_mux, clk_mux);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add clkmux unregister action %d", ret);
|
||||
goto put_clk_mux_np;
|
||||
@ -232,6 +490,7 @@ static int pruss_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
pruss->dev = dev;
|
||||
mutex_init(&pruss->lock);
|
||||
|
||||
child = of_get_child_by_name(np, "memories");
|
||||
if (!child) {
|
||||
|
88
drivers/soc/ti/pruss.h
Normal file
88
drivers/soc/ti/pruss.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* PRU-ICSS Subsystem user interfaces
|
||||
*
|
||||
* Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com
|
||||
* MD Danish Anwar <danishanwar@ti.com>
|
||||
*/
|
||||
|
||||
#ifndef _SOC_TI_PRUSS_H_
|
||||
#define _SOC_TI_PRUSS_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/*
|
||||
* PRU_ICSS_CFG registers
|
||||
* SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only
|
||||
*/
|
||||
#define PRUSS_CFG_REVID 0x00
|
||||
#define PRUSS_CFG_SYSCFG 0x04
|
||||
#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4)
|
||||
#define PRUSS_CFG_CGR 0x10
|
||||
#define PRUSS_CFG_ISRP 0x14
|
||||
#define PRUSS_CFG_ISP 0x18
|
||||
#define PRUSS_CFG_IESP 0x1C
|
||||
#define PRUSS_CFG_IECP 0x20
|
||||
#define PRUSS_CFG_SCRP 0x24
|
||||
#define PRUSS_CFG_PMAO 0x28
|
||||
#define PRUSS_CFG_MII_RT 0x2C
|
||||
#define PRUSS_CFG_IEPCLK 0x30
|
||||
#define PRUSS_CFG_SPP 0x34
|
||||
#define PRUSS_CFG_PIN_MX 0x40
|
||||
|
||||
/* PRUSS_GPCFG register bits */
|
||||
#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0)
|
||||
#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0
|
||||
|
||||
#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26
|
||||
#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26)
|
||||
|
||||
/* PRUSS_MII_RT register bits */
|
||||
#define PRUSS_MII_RT_EVENT_EN BIT(0)
|
||||
|
||||
/* PRUSS_SPP register bits */
|
||||
#define PRUSS_SPP_XFER_SHIFT_EN BIT(1)
|
||||
#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0)
|
||||
#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3)
|
||||
|
||||
/**
|
||||
* pruss_cfg_read() - read a PRUSS CFG sub-module register
|
||||
* @pruss: the pruss instance handle
|
||||
* @reg: register offset within the CFG sub-module
|
||||
* @val: pointer to return the value in
|
||||
*
|
||||
* Reads a given register within the PRUSS CFG sub-module and
|
||||
* returns it through the passed-in @val pointer
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(pruss))
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_read(pruss->cfg_regmap, reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* pruss_cfg_update() - configure a PRUSS CFG sub-module register
|
||||
* @pruss: the pruss instance handle
|
||||
* @reg: register offset within the CFG sub-module
|
||||
* @mask: bit mask to use for programming the @val
|
||||
* @val: value to write
|
||||
*
|
||||
* Programs a given register within the PRUSS CFG sub-module
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
static int pruss_cfg_update(struct pruss *pruss, unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(pruss))
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_update_bits(pruss->cfg_regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
#endif /* _SOC_TI_PRUSS_H_ */
|
@ -815,7 +815,6 @@ static int omap_sr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_sr *sr_info;
|
||||
struct omap_sr_data *pdata = pdev->dev.platform_data;
|
||||
struct resource *mem;
|
||||
struct dentry *nvalue_dir;
|
||||
int i, ret = 0;
|
||||
|
||||
@ -835,8 +834,7 @@ static int omap_sr_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
sr_info->base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
sr_info->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(sr_info->base))
|
||||
return PTR_ERR(sr_info->base);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user