mirror of https://gitee.com/openkylin/linux.git
ARM: SoC drivers for v5.12
Updates for SoC specific drivers include a few subsystems that have their own maintainers but send them through the soc tree: SCMI firmware: - add support for a completion interrupt Reset controllers: - new driver for BCM4908 - new devm_reset_control_get_optional_exclusive_released() function Memory controllers: - Renesas RZ/G2 support - Tegra124 interconnect support - Allow more drivers to be loadable modules TEE/optee firmware: - minor code cleanup The other half of this is SoC specific drivers that do not belong into any other subsystem, most of them living in drivers/soc: - Allwinner/sunxi power management work - Allwinner H616 support - ASpeed AST2600 system identification support - AT91 SAMA7G5 SoC ID driver - AT91 SoC driver cleanups - Broadcom BCM4908 power management bus support - Marvell mbus cleanups - Mediatek MT8167 power domain support - Qualcomm socinfo driver support for PMIC - Qualcomm SoC identification for many more products - TI Keystone driver cleanups for PRUSS and elsewhere Signed-off-by: Arnd Bergmann <arnd@arndb.de> -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmApjS8ACgkQYKtH/8kJ UidDyw/6ArE2RWN1qk3GJbQKdCYQdqH4Ig/Nc9LA977ul2BX/BohYoEGCoveH5cG 16FaYK8tYDCSoTfS0+w1Y8r6TgZKcV6GCM0xLSVtaihk2CO81sUfDFBIppJd614a 2lGx9DW7205ql4vGcQsK31ncr0hVviHG2e8lOEbFc9SkQpmYuLF1dxW2JK9oWGe2 rLXHKb20N7AvgN8Y6V0YAOGNpu9MOnx0TbTGn6SMgzIKMkpYaSs/oZY11d9jrn7Y m/iIahRWzLFR/lYdrD7Jowpy2A/lcwPdQlRkOiuF1s6FFCqxe1yQsrpcbt/7fXes UzOyE494GZFtO0zjFuwglsmiAZDMwO/fQVrIzSGV0SXF8LJpiYYTG1b3Yv5SY5Hr r7EF4A7GlmNmd6K1HrXTYJz9tr4oxLDw+9LZGx74JV8x0iK3cd1hRTXb1SbspA6h S/KRQsuEjpAyQ6xXWVp2fp6VxZkrjIpPavbcQw2RsoBnbNdrcXahTk96JfpWYGjH iyJkEKmCF6/w/s5+xQfy+DYepxFDO0YsPbM7kL5qhaY83KBMOHKJFCUZVWj7md5w QIVTeeiSewIlT5bG9XyjIfmsImq1acqTW+QCaxCnvMSsZDBbdhTMK48GwyN9U9+x jdQCPQye3TKL2WU6U40FPNIr08QcNy4vmJp4fMqwK5xO3+P+Zhs= =I2Zn -----END PGP SIGNATURE----- Merge tag 'arm-drivers-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc Pull ARM SoC driver updates from Arnd Bergmann: "Updates for SoC specific drivers include a few subsystems that have their own maintainers but send them through the soc tree: SCMI firmware: - add support for a completion interrupt Reset controllers: - new driver for BCM4908 - new devm_reset_control_get_optional_exclusive_released() function Memory controllers: - Renesas RZ/G2 support - Tegra124 interconnect support - Allow more drivers to be loadable modules TEE/optee firmware: - minor code cleanup The other half of this is SoC specific drivers that do not belong into any other subsystem, most of them living in drivers/soc: - Allwinner/sunxi power management work - Allwinner H616 support - ASpeed AST2600 system identification support - AT91 SAMA7G5 SoC ID driver - AT91 SoC driver cleanups - Broadcom BCM4908 power management bus support - Marvell mbus cleanups - Mediatek MT8167 power domain support - Qualcomm socinfo driver support for PMIC - Qualcomm SoC identification for many more products - TI Keystone driver cleanups for PRUSS and elsewhere" * tag 'arm-drivers-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (89 commits) soc: aspeed: socinfo: Add new systems soc: aspeed: snoop: Add clock control logic memory: tegra186-emc: Replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE memory: samsung: exynos5422-dmc: Correct function names in kerneldoc memory: ti-emif-pm: Drop of_match_ptr from of_device_id table optee: simplify i2c access drivers: soc: atmel: fix type for same7 tee: optee: remove need_resched() before cond_resched() soc: qcom: ocmem: don't return NULL in of_get_ocmem optee: sync OP-TEE headers tee: optee: fix 'physical' typos drivers: optee: use flexible-array member instead of zero-length array tee: fix some comment typos in header files soc: ti: k3-ringacc: Use of_device_get_match_data() soc: ti: pruss: Refactor the CFG sub-module init soc: mediatek: pm-domains: Don't print an error if child domain is deferred soc: mediatek: pm-domains: Add domain regulator supply dt-bindings: power: Add domain regulator supply soc: mediatek: cmdq: Remove cmdq_pkt_flush() soc: mediatek: pm-domains: Add support for mt8167 ...
This commit is contained in:
commit
e767b3530a
|
@ -31,6 +31,14 @@ Optional properties:
|
|||
|
||||
- mbox-names: shall be "tx" or "rx" depending on mboxes entries.
|
||||
|
||||
- interrupts : when using smc or hvc transports, this optional
|
||||
property indicates that msg completion by the platform is indicated
|
||||
by an interrupt rather than by the return of the smc call. This
|
||||
should not be used except when the platform requires such behavior.
|
||||
|
||||
- interrupt-names : if "interrupts" is present, interrupt-names must also
|
||||
be present and have the value "a2p".
|
||||
|
||||
See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
|
||||
about the generic mailbox controller and client driver bindings.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Atmel system registers
|
||||
|
||||
Chipid required properties:
|
||||
- compatible: Should be "atmel,sama5d2-chipid"
|
||||
- compatible: Should be "atmel,sama5d2-chipid" or "microchip,sama7g5-chipid"
|
||||
- reg : Should contain registers location and length
|
||||
|
||||
PIT Timer required properties:
|
||||
|
|
|
@ -24,6 +24,7 @@ properties:
|
|||
- qcom,sc7180-llcc
|
||||
- qcom,sdm845-llcc
|
||||
- qcom,sm8150-llcc
|
||||
- qcom,sm8250-llcc
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
|
|
@ -21,7 +21,9 @@ properties:
|
|||
oneOf:
|
||||
- const: allwinner,sun8i-a23-rsb
|
||||
- items:
|
||||
- const: allwinner,sun8i-a83t-rsb
|
||||
- enum:
|
||||
- allwinner,sun8i-a83t-rsb
|
||||
- allwinner,sun50i-h616-rsb
|
||||
- const: allwinner,sun8i-a23-rsb
|
||||
|
||||
reg:
|
||||
|
|
|
@ -26,10 +26,14 @@ properties:
|
|||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r8a774a1-rpc-if # RZ/G2M
|
||||
- renesas,r8a774b1-rpc-if # RZ/G2N
|
||||
- renesas,r8a774c0-rpc-if # RZ/G2E
|
||||
- renesas,r8a774e1-rpc-if # RZ/G2H
|
||||
- renesas,r8a77970-rpc-if # R-Car V3M
|
||||
- renesas,r8a77980-rpc-if # R-Car V3H
|
||||
- renesas,r8a77995-rpc-if # R-Car D3
|
||||
- const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 device
|
||||
- const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 or RZ/G2 device
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/brcm,bcm-pmb.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom PMB (Power Management Bus) controller
|
||||
|
||||
description: This document describes Broadcom's PMB controller. It supports
|
||||
powering various types of connected devices (e.g. PCIe, USB, SATA).
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm4908-pmb
|
||||
|
||||
reg:
|
||||
description: register space of one or more buses
|
||||
maxItems: 1
|
||||
|
||||
big-endian:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description: Flag to use for block working in big endian mode.
|
||||
|
||||
"#power-domain-cells":
|
||||
description: cell specifies device ID (see bcm-pmb.h)
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
- "#power-domain-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/soc/bcm-pmb.h>
|
||||
|
||||
pmb: power-controller@802800e0 {
|
||||
compatible = "brcm,bcm4908-pmb";
|
||||
reg = <0x802800e0 0x40>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
foo {
|
||||
power-domains = <&pmb BCM_PMB_PCIE0>;
|
||||
};
|
|
@ -23,6 +23,7 @@ properties:
|
|||
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8167-power-controller
|
||||
- mediatek,mt8173-power-controller
|
||||
- mediatek,mt8183-power-controller
|
||||
- mediatek,mt8192-power-controller
|
||||
|
@ -59,6 +60,7 @@ patternProperties:
|
|||
reg:
|
||||
description: |
|
||||
Power domain index. Valid values are defined in:
|
||||
"include/dt-bindings/power/mt8167-power.h" - for MT8167 type power domain.
|
||||
"include/dt-bindings/power/mt8173-power.h" - for MT8173 type power domain.
|
||||
"include/dt-bindings/power/mt8183-power.h" - for MT8183 type power domain.
|
||||
"include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain.
|
||||
|
@ -82,6 +84,9 @@ patternProperties:
|
|||
be specified by order, adding first the BASIC clocks followed by the
|
||||
SUSBSYS clocks.
|
||||
|
||||
domain-supply:
|
||||
description: domain regulator supply.
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle to the device containing the INFRACFG register range.
|
||||
|
@ -130,6 +135,9 @@ patternProperties:
|
|||
be specified by order, adding first the BASIC clocks followed by the
|
||||
SUSBSYS clocks.
|
||||
|
||||
domain-supply:
|
||||
description: domain regulator supply.
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle to the device containing the INFRACFG register range.
|
||||
|
@ -178,6 +186,9 @@ patternProperties:
|
|||
be specified by order, adding first the BASIC clocks followed by the
|
||||
SUSBSYS clocks.
|
||||
|
||||
domain-supply:
|
||||
description: domain regulator supply.
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle to the device containing the INFRACFG register range.
|
||||
|
|
|
@ -19,6 +19,7 @@ properties:
|
|||
- qcom,msm8916-rpmpd
|
||||
- qcom,msm8939-rpmpd
|
||||
- qcom,msm8976-rpmpd
|
||||
- qcom,msm8994-rpmpd
|
||||
- qcom,msm8996-rpmpd
|
||||
- qcom,msm8998-rpmpd
|
||||
- qcom,qcs404-rpmpd
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/reset/brcm,bcm4908-misc-pcie-reset.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom MISC block PCIe reset controller
|
||||
|
||||
description: This document describes reset controller handling PCIe PERST#
|
||||
signals. On BCM4908 it's a part of the MISC block.
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm4908-misc-pcie-reset
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#reset-cells":
|
||||
description: PCIe core id
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#reset-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
reset-controller@ff802644 {
|
||||
compatible = "brcm,bcm4908-misc-pcie-reset";
|
||||
reg = <0xff802644 0x04>;
|
||||
#reset-cells = <1>;
|
||||
};
|
|
@ -1,44 +0,0 @@
|
|||
Hisilicon System Reset Controller
|
||||
======================================
|
||||
|
||||
Please also refer to reset.txt in this directory for common reset
|
||||
controller binding usage.
|
||||
|
||||
The reset controller registers are part of the system-ctl block on
|
||||
hi3660 and hi3670 SoCs.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of the following:
|
||||
"hisilicon,hi3660-reset" for HI3660
|
||||
"hisilicon,hi3670-reset", "hisilicon,hi3660-reset" for HI3670
|
||||
- hisi,rst-syscon: phandle of the reset's syscon.
|
||||
- #reset-cells : Specifies the number of cells needed to encode a
|
||||
reset source. The type shall be a <u32> and the value shall be 2.
|
||||
|
||||
Cell #1 : offset of the reset assert control
|
||||
register from the syscon register base
|
||||
offset + 4: deassert control register
|
||||
offset + 8: status control register
|
||||
Cell #2 : bit position of the reset in the reset control register
|
||||
|
||||
Example:
|
||||
iomcu: iomcu@ffd7e000 {
|
||||
compatible = "hisilicon,hi3660-iomcu", "syscon";
|
||||
reg = <0x0 0xffd7e000 0x0 0x1000>;
|
||||
};
|
||||
|
||||
iomcu_rst: iomcu_rst_controller {
|
||||
compatible = "hisilicon,hi3660-reset";
|
||||
hisi,rst-syscon = <&iomcu>;
|
||||
#reset-cells = <2>;
|
||||
};
|
||||
|
||||
Specifying reset lines connected to IP modules
|
||||
==============================================
|
||||
example:
|
||||
|
||||
i2c0: i2c@..... {
|
||||
...
|
||||
resets = <&iomcu_rst 0x20 3>; /* offset: 0x20; bit: 3 */
|
||||
...
|
||||
};
|
|
@ -0,0 +1,77 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/reset/hisilicon,hi3660-reset.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Hisilicon System Reset Controller
|
||||
|
||||
maintainers:
|
||||
- Wei Xu <xuwei5@hisilicon.com>
|
||||
|
||||
description: |
|
||||
Please also refer to reset.txt in this directory for common reset
|
||||
controller binding usage.
|
||||
The reset controller registers are part of the system-ctl block on
|
||||
hi3660 and hi3670 SoCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: hisilicon,hi3660-reset
|
||||
- items:
|
||||
- const: hisilicon,hi3670-reset
|
||||
- const: hisilicon,hi3660-reset
|
||||
|
||||
hisilicon,rst-syscon:
|
||||
description: phandle of the reset's syscon.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
'#reset-cells':
|
||||
description: |
|
||||
Specifies the number of cells needed to encode a reset source.
|
||||
Cell #1 : offset of the reset assert control register from the syscon
|
||||
register base
|
||||
offset + 4: deassert control register
|
||||
offset + 8: status control register
|
||||
Cell #2 : bit position of the reset in the reset control register
|
||||
const: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/hi3660-clock.h>
|
||||
|
||||
iomcu: iomcu@ffd7e000 {
|
||||
compatible = "hisilicon,hi3660-iomcu", "syscon";
|
||||
reg = <0xffd7e000 0x1000>;
|
||||
};
|
||||
|
||||
iomcu_rst: iomcu_rst_controller {
|
||||
compatible = "hisilicon,hi3660-reset";
|
||||
hisilicon,rst-syscon = <&iomcu>;
|
||||
#reset-cells = <2>;
|
||||
};
|
||||
|
||||
/* Specifying reset lines connected to IP modules */
|
||||
i2c@ffd71000 {
|
||||
compatible = "snps,designware-i2c";
|
||||
reg = <0xffd71000 0x1000>;
|
||||
interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-frequency = <400000>;
|
||||
clocks = <&crg_ctrl HI3660_CLK_GATE_I2C0>;
|
||||
resets = <&iomcu_rst 0x20 3>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_pmx_func &i2c0_cfg_func>;
|
||||
status = "disabled";
|
||||
};
|
||||
...
|
|
@ -20,6 +20,7 @@ power-domains.
|
|||
"qcom,sdm845-aoss-qmp"
|
||||
"qcom,sm8150-aoss-qmp"
|
||||
"qcom,sm8250-aoss-qmp"
|
||||
"qcom,sm8350-aoss-qmp"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
Qualcomm Shared Memory Manager binding
|
||||
|
||||
This binding describes the Qualcomm Shared Memory Manager, used to share data
|
||||
between various subsystems and OSes in Qualcomm platforms.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: must be:
|
||||
"qcom,smem"
|
||||
|
||||
- memory-region:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: handle to memory reservation for main SMEM memory region.
|
||||
|
||||
- qcom,rpm-msg-ram:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: handle to RPM message memory resource
|
||||
|
||||
- hwlocks:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: reference to a hwspinlock used to protect allocations from
|
||||
the shared memory
|
||||
|
||||
= EXAMPLE
|
||||
The following example shows the SMEM setup for MSM8974, with a main SMEM region
|
||||
at 0xfa00000 and the RPM message ram at 0xfc428000:
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
smem_region: smem@fa00000 {
|
||||
reg = <0xfa00000 0x200000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
|
||||
smem@fa00000 {
|
||||
compatible = "qcom,smem";
|
||||
|
||||
memory-region = <&smem_region>;
|
||||
qcom,rpm-msg-ram = <&rpm_msg_ram>;
|
||||
|
||||
hwlocks = <&tcsr_mutex 3>;
|
||||
};
|
||||
|
||||
soc {
|
||||
rpm_msg_ram: memory@fc428000 {
|
||||
compatible = "qcom,rpm-msg-ram";
|
||||
reg = <0xfc428000 0x4000>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,72 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/qcom/qcom,smem.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Shared Memory Manager binding
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: |
|
||||
This binding describes the Qualcomm Shared Memory Manager, used to share data
|
||||
between various subsystems and OSes in Qualcomm platforms.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,smem
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
description: handle to memory reservation for main SMEM memory region.
|
||||
|
||||
hwlocks:
|
||||
maxItems: 1
|
||||
|
||||
qcom,rpm-msg-ram:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: handle to RPM message memory resource
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- memory-region
|
||||
- hwlocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
reserved-memory {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
smem_region: smem@fa00000 {
|
||||
reg = <0xfa00000 0x200000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
|
||||
smem {
|
||||
compatible = "qcom,smem";
|
||||
|
||||
memory-region = <&smem_region>;
|
||||
qcom,rpm-msg-ram = <&rpm_msg_ram>;
|
||||
|
||||
hwlocks = <&tcsr_mutex 3>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
rpm_msg_ram: sram@fc428000 {
|
||||
compatible = "qcom,rpm-msg-ram";
|
||||
reg = <0xfc428000 0x4000>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -81,6 +81,9 @@ properties:
|
|||
ranges:
|
||||
maxItems: 1
|
||||
|
||||
dma-ranges:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
description: |
|
||||
This property is as per sci-pm-domain.txt.
|
||||
|
@ -278,6 +281,9 @@ patternProperties:
|
|||
that is common to all the PRU cores. This should be represented as an
|
||||
interrupt-controller node.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/interrupt-controller/ti,pruss-intc.yaml#
|
||||
|
||||
type: object
|
||||
|
||||
mdio@[a-f0-9]+$:
|
||||
|
@ -299,6 +305,9 @@ patternProperties:
|
|||
present on K3 SoCs have additional auxiliary PRU cores with slightly
|
||||
different IP integration.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/remoteproc/ti,pru-rproc.yaml#
|
||||
|
||||
type: object
|
||||
|
||||
required:
|
||||
|
@ -371,6 +380,36 @@ examples:
|
|||
reg = <0x32000 0x58>;
|
||||
};
|
||||
|
||||
pruss_intc: interrupt-controller@20000 {
|
||||
compatible = "ti,pruss-intc";
|
||||
reg = <0x20000 0x2000>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
interrupts = <20 21 22 23 24 25 26 27>;
|
||||
interrupt-names = "host_intr0", "host_intr1",
|
||||
"host_intr2", "host_intr3",
|
||||
"host_intr4", "host_intr5",
|
||||
"host_intr6", "host_intr7";
|
||||
};
|
||||
|
||||
pru0: pru@34000 {
|
||||
compatible = "ti,am3356-pru";
|
||||
reg = <0x34000 0x2000>,
|
||||
<0x22000 0x400>,
|
||||
<0x22400 0x100>;
|
||||
reg-names = "iram", "control", "debug";
|
||||
firmware-name = "am335x-pru0-fw";
|
||||
};
|
||||
|
||||
pru1: pru@38000 {
|
||||
compatible = "ti,am3356-pru";
|
||||
reg = <0x38000 0x2000>,
|
||||
<0x24000 0x400>,
|
||||
<0x24400 0x100>;
|
||||
reg-names = "iram", "control", "debug";
|
||||
firmware-name = "am335x-pru1-fw";
|
||||
};
|
||||
|
||||
pruss_mdio: mdio@32400 {
|
||||
compatible = "ti,davinci_mdio";
|
||||
reg = <0x32400 0x90>;
|
||||
|
@ -425,6 +464,43 @@ examples:
|
|||
reg = <0x32000 0x58>;
|
||||
};
|
||||
|
||||
pruss1_intc: interrupt-controller@20000 {
|
||||
compatible = "ti,pruss-intc";
|
||||
reg = <0x20000 0x2000>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "host_intr0", "host_intr1",
|
||||
"host_intr2", "host_intr3",
|
||||
"host_intr4",
|
||||
"host_intr6", "host_intr7";
|
||||
ti,irqs-reserved = /bits/ 8 <0x20>; /* BIT(5) */
|
||||
};
|
||||
|
||||
pru1_0: pru@34000 {
|
||||
compatible = "ti,am4376-pru";
|
||||
reg = <0x34000 0x3000>,
|
||||
<0x22000 0x400>,
|
||||
<0x22400 0x100>;
|
||||
reg-names = "iram", "control", "debug";
|
||||
firmware-name = "am437x-pru1_0-fw";
|
||||
};
|
||||
|
||||
pru1_1: pru@38000 {
|
||||
compatible = "ti,am4376-pru";
|
||||
reg = <0x38000 0x3000>,
|
||||
<0x24000 0x400>,
|
||||
<0x24400 0x100>;
|
||||
reg-names = "iram", "control", "debug";
|
||||
firmware-name = "am437x-pru1_1-fw";
|
||||
};
|
||||
|
||||
pruss1_mdio: mdio@32400 {
|
||||
compatible = "ti,davinci_mdio";
|
||||
reg = <0x32400 0x90>;
|
||||
|
|
|
@ -49,6 +49,7 @@ properties:
|
|||
- items:
|
||||
- const: allwinner,suniv-f1c100s-system-control
|
||||
- const: allwinner,sun4i-a10-system-control
|
||||
- const: allwinner,sun50i-h616-system-control
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
12
MAINTAINERS
12
MAINTAINERS
|
@ -3645,6 +3645,16 @@ L: linux-mips@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/firmware/broadcom/*
|
||||
|
||||
BROADCOM PMB (POWER MANAGEMENT BUS) DRIVER
|
||||
M: Rafał Miłecki <rafal@milecki.pl>
|
||||
M: Florian Fainelli <f.fainelli@gmail.com>
|
||||
M: bcm-kernel-feedback-list@broadcom.com
|
||||
L: linux-pm@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://github.com/broadcom/stblinux.git
|
||||
F: drivers/soc/bcm/bcm-pmb.c
|
||||
F: include/dt-bindings/soc/bcm-pmb.h
|
||||
|
||||
BROADCOM SPECIFIC AMBA DRIVER (BCMA)
|
||||
M: Rafał Miłecki <zajec5@gmail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -17165,6 +17175,7 @@ F: drivers/mfd/syscon.c
|
|||
|
||||
SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
|
||||
M: Sudeep Holla <sudeep.holla@arm.com>
|
||||
R: Cristian Marussi <cristian.marussi@arm.com>
|
||||
L: linux-arm-kernel@lists.infradead.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
|
||||
|
@ -17172,6 +17183,7 @@ F: drivers/clk/clk-sc[mp]i.c
|
|||
F: drivers/cpufreq/sc[mp]i-cpufreq.c
|
||||
F: drivers/firmware/arm_scmi/
|
||||
F: drivers/firmware/arm_scpi.c
|
||||
F: drivers/regulator/scmi-regulator.c
|
||||
F: drivers/reset/reset-scmi.c
|
||||
F: include/linux/sc[mp]i_protocol.h
|
||||
F: include/trace/events/scmi.h
|
||||
|
|
|
@ -1111,7 +1111,7 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
|
|||
|
||||
mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size);
|
||||
if (!mbus->sdramwins_base) {
|
||||
iounmap(mbus_state.mbuswins_base);
|
||||
iounmap(mbus->mbuswins_base);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -126,6 +128,7 @@ struct sunxi_rsb {
|
|||
struct completion complete;
|
||||
struct mutex lock;
|
||||
unsigned int status;
|
||||
u32 clk_freq;
|
||||
};
|
||||
|
||||
/* bus / slave device related functions */
|
||||
|
@ -170,7 +173,9 @@ static int sunxi_rsb_device_remove(struct device *dev)
|
|||
{
|
||||
const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver);
|
||||
|
||||
return drv->remove(to_sunxi_rsb_device(dev));
|
||||
drv->remove(to_sunxi_rsb_device(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bus_type sunxi_rsb_bus = {
|
||||
|
@ -335,6 +340,10 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pm_runtime_resume_and_get(rsb->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&rsb->lock);
|
||||
|
||||
writel(addr, rsb->regs + RSB_ADDR);
|
||||
|
@ -350,6 +359,9 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
|
|||
unlock:
|
||||
mutex_unlock(&rsb->lock);
|
||||
|
||||
pm_runtime_mark_last_busy(rsb->dev);
|
||||
pm_runtime_put_autosuspend(rsb->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -377,6 +389,10 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pm_runtime_resume_and_get(rsb->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&rsb->lock);
|
||||
|
||||
writel(addr, rsb->regs + RSB_ADDR);
|
||||
|
@ -387,6 +403,9 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
|
|||
|
||||
mutex_unlock(&rsb->lock);
|
||||
|
||||
pm_runtime_mark_last_busy(rsb->dev);
|
||||
pm_runtime_put_autosuspend(rsb->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -614,11 +633,100 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sunxi_rsb_of_match_table[] = {
|
||||
{ .compatible = "allwinner,sun8i-a23-rsb" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table);
|
||||
static int sunxi_rsb_hw_init(struct sunxi_rsb *rsb)
|
||||
{
|
||||
struct device *dev = rsb->dev;
|
||||
unsigned long p_clk_freq;
|
||||
u32 clk_delay, reg;
|
||||
int clk_div, ret;
|
||||
|
||||
ret = clk_prepare_enable(rsb->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(rsb->rstc);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to deassert reset line: %d\n", ret);
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
/* reset the controller */
|
||||
writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL);
|
||||
readl_poll_timeout(rsb->regs + RSB_CTRL, reg,
|
||||
!(reg & RSB_CTRL_SOFT_RST), 1000, 100000);
|
||||
|
||||
/*
|
||||
* Clock frequency and delay calculation code is from
|
||||
* Allwinner U-boot sources.
|
||||
*
|
||||
* From A83 user manual:
|
||||
* bus clock frequency = parent clock frequency / (2 * (divider + 1))
|
||||
*/
|
||||
p_clk_freq = clk_get_rate(rsb->clk);
|
||||
clk_div = p_clk_freq / rsb->clk_freq / 2;
|
||||
if (!clk_div)
|
||||
clk_div = 1;
|
||||
else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1)
|
||||
clk_div = RSB_CCR_MAX_CLK_DIV + 1;
|
||||
|
||||
clk_delay = clk_div >> 1;
|
||||
if (!clk_delay)
|
||||
clk_delay = 1;
|
||||
|
||||
dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2);
|
||||
writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1),
|
||||
rsb->regs + RSB_CCR);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(rsb->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb)
|
||||
{
|
||||
/* Keep the clock and PM reference counts consistent. */
|
||||
if (pm_runtime_status_suspended(rsb->dev))
|
||||
pm_runtime_resume(rsb->dev);
|
||||
reset_control_assert(rsb->rstc);
|
||||
clk_disable_unprepare(rsb->clk);
|
||||
}
|
||||
|
||||
static int __maybe_unused sunxi_rsb_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct sunxi_rsb *rsb = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(rsb->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused sunxi_rsb_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct sunxi_rsb *rsb = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(rsb->clk);
|
||||
}
|
||||
|
||||
static int __maybe_unused sunxi_rsb_suspend(struct device *dev)
|
||||
{
|
||||
struct sunxi_rsb *rsb = dev_get_drvdata(dev);
|
||||
|
||||
sunxi_rsb_hw_exit(rsb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused sunxi_rsb_resume(struct device *dev)
|
||||
{
|
||||
struct sunxi_rsb *rsb = dev_get_drvdata(dev);
|
||||
|
||||
return sunxi_rsb_hw_init(rsb);
|
||||
}
|
||||
|
||||
static int sunxi_rsb_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -626,10 +734,8 @@ static int sunxi_rsb_probe(struct platform_device *pdev)
|
|||
struct device_node *np = dev->of_node;
|
||||
struct resource *r;
|
||||
struct sunxi_rsb *rsb;
|
||||
unsigned long p_clk_freq;
|
||||
u32 clk_delay, clk_freq = 3000000;
|
||||
int clk_div, irq, ret;
|
||||
u32 reg;
|
||||
u32 clk_freq = 3000000;
|
||||
int irq, ret;
|
||||
|
||||
of_property_read_u32(np, "clock-frequency", &clk_freq);
|
||||
if (clk_freq > RSB_MAX_FREQ) {
|
||||
|
@ -644,6 +750,7 @@ static int sunxi_rsb_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
rsb->dev = dev;
|
||||
rsb->clk_freq = clk_freq;
|
||||
platform_set_drvdata(pdev, rsb);
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rsb->regs = devm_ioremap_resource(dev, r);
|
||||
|
@ -661,79 +768,41 @@ static int sunxi_rsb_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rsb->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
p_clk_freq = clk_get_rate(rsb->clk);
|
||||
|
||||
rsb->rstc = devm_reset_control_get(dev, NULL);
|
||||
if (IS_ERR(rsb->rstc)) {
|
||||
ret = PTR_ERR(rsb->rstc);
|
||||
dev_err(dev, "failed to retrieve reset controller: %d\n", ret);
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(rsb->rstc);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to deassert reset line: %d\n", ret);
|
||||
goto err_clk_disable;
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_completion(&rsb->complete);
|
||||
mutex_init(&rsb->lock);
|
||||
|
||||
/* reset the controller */
|
||||
writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL);
|
||||
readl_poll_timeout(rsb->regs + RSB_CTRL, reg,
|
||||
!(reg & RSB_CTRL_SOFT_RST), 1000, 100000);
|
||||
|
||||
/*
|
||||
* Clock frequency and delay calculation code is from
|
||||
* Allwinner U-boot sources.
|
||||
*
|
||||
* From A83 user manual:
|
||||
* bus clock frequency = parent clock frequency / (2 * (divider + 1))
|
||||
*/
|
||||
clk_div = p_clk_freq / clk_freq / 2;
|
||||
if (!clk_div)
|
||||
clk_div = 1;
|
||||
else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1)
|
||||
clk_div = RSB_CCR_MAX_CLK_DIV + 1;
|
||||
|
||||
clk_delay = clk_div >> 1;
|
||||
if (!clk_delay)
|
||||
clk_delay = 1;
|
||||
|
||||
dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2);
|
||||
writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1),
|
||||
rsb->regs + RSB_CCR);
|
||||
|
||||
ret = devm_request_irq(dev, irq, sunxi_rsb_irq, 0, RSB_CTRL_NAME, rsb);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't register interrupt handler irq %d: %d\n",
|
||||
irq, ret);
|
||||
goto err_reset_assert;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sunxi_rsb_hw_init(rsb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* initialize all devices on the bus into RSB mode */
|
||||
ret = sunxi_rsb_init_device_mode(rsb);
|
||||
if (ret)
|
||||
dev_warn(dev, "Initialize device mode failed: %d\n", ret);
|
||||
|
||||
pm_suspend_ignore_children(dev, true);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
of_rsb_register_devices(rsb);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reset_assert:
|
||||
reset_control_assert(rsb->rstc);
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(rsb->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sunxi_rsb_remove(struct platform_device *pdev)
|
||||
|
@ -741,18 +810,40 @@ static int sunxi_rsb_remove(struct platform_device *pdev)
|
|||
struct sunxi_rsb *rsb = platform_get_drvdata(pdev);
|
||||
|
||||
device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices);
|
||||
reset_control_assert(rsb->rstc);
|
||||
clk_disable_unprepare(rsb->clk);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
sunxi_rsb_hw_exit(rsb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sunxi_rsb_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct sunxi_rsb *rsb = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
sunxi_rsb_hw_exit(rsb);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sunxi_rsb_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(sunxi_rsb_runtime_suspend,
|
||||
sunxi_rsb_runtime_resume, NULL)
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sunxi_rsb_suspend, sunxi_rsb_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id sunxi_rsb_of_match_table[] = {
|
||||
{ .compatible = "allwinner,sun8i-a23-rsb" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table);
|
||||
|
||||
static struct platform_driver sunxi_rsb_driver = {
|
||||
.probe = sunxi_rsb_probe,
|
||||
.remove = sunxi_rsb_remove,
|
||||
.shutdown = sunxi_rsb_shutdown,
|
||||
.driver = {
|
||||
.name = RSB_CTRL_NAME,
|
||||
.of_match_table = sunxi_rsb_of_match_table,
|
||||
.pm = &sunxi_rsb_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -7,3 +7,6 @@ config TEGRA_CLK_DFLL
|
|||
depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC
|
||||
select PM_OPP
|
||||
def_bool y
|
||||
|
||||
config TEGRA124_CLK_EMC
|
||||
bool
|
||||
|
|
|
@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra20-emc.o
|
|||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
|
||||
obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
|
||||
obj-$(CONFIG_TEGRA124_EMC) += clk-tegra124-emc.o
|
||||
obj-$(CONFIG_TEGRA124_CLK_EMC) += clk-tegra124-emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
|
||||
obj-y += cvb.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
|
@ -21,7 +23,6 @@
|
|||
#include <linux/string.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <soc/tegra/emc.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
|
@ -80,6 +81,9 @@ struct tegra_clk_emc {
|
|||
int num_timings;
|
||||
struct emc_timing *timings;
|
||||
spinlock_t *lock;
|
||||
|
||||
tegra124_emc_prepare_timing_change_cb *prepare_timing_change;
|
||||
tegra124_emc_complete_timing_change_cb *complete_timing_change;
|
||||
};
|
||||
|
||||
/* Common clock framework callback implementations */
|
||||
|
@ -176,6 +180,9 @@ static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra)
|
|||
if (tegra->emc)
|
||||
return tegra->emc;
|
||||
|
||||
if (!tegra->prepare_timing_change || !tegra->complete_timing_change)
|
||||
return NULL;
|
||||
|
||||
if (!tegra->emc_node)
|
||||
return NULL;
|
||||
|
||||
|
@ -241,7 +248,7 @@ static int emc_set_timing(struct tegra_clk_emc *tegra,
|
|||
|
||||
div = timing->parent_rate / (timing->rate / 2) - 2;
|
||||
|
||||
err = tegra_emc_prepare_timing_change(emc, timing->rate);
|
||||
err = tegra->prepare_timing_change(emc, timing->rate);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -259,7 +266,7 @@ static int emc_set_timing(struct tegra_clk_emc *tegra,
|
|||
|
||||
spin_unlock_irqrestore(tegra->lock, flags);
|
||||
|
||||
tegra_emc_complete_timing_change(emc, timing->rate);
|
||||
tegra->complete_timing_change(emc, timing->rate);
|
||||
|
||||
clk_hw_reparent(&tegra->hw, __clk_get_hw(timing->parent));
|
||||
clk_disable_unprepare(tegra->prev_parent);
|
||||
|
@ -473,8 +480,8 @@ static const struct clk_ops tegra_clk_emc_ops = {
|
|||
.get_parent = emc_get_parent,
|
||||
};
|
||||
|
||||
struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
|
||||
spinlock_t *lock)
|
||||
struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct tegra_clk_emc *tegra;
|
||||
struct clk_init_data init;
|
||||
|
@ -538,3 +545,27 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
|
|||
|
||||
return clk;
|
||||
};
|
||||
|
||||
void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb,
|
||||
tegra124_emc_complete_timing_change_cb *complete_cb)
|
||||
{
|
||||
struct clk *clk = __clk_lookup("emc");
|
||||
struct tegra_clk_emc *tegra;
|
||||
struct clk_hw *hw;
|
||||
|
||||
if (clk) {
|
||||
hw = __clk_get_hw(clk);
|
||||
tegra = container_of(hw, struct tegra_clk_emc, hw);
|
||||
|
||||
tegra->prepare_timing_change = prep_cb;
|
||||
tegra->complete_timing_change = complete_cb;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra124_clk_set_emc_callbacks);
|
||||
|
||||
bool tegra124_clk_emc_driver_available(struct clk_hw *hw)
|
||||
{
|
||||
struct tegra_clk_emc *tegra = container_of(hw, struct tegra_clk_emc, hw);
|
||||
|
||||
return tegra->prepare_timing_change && tegra->complete_timing_change;
|
||||
}
|
||||
|
|
|
@ -1500,6 +1500,26 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
|
|||
writel(plld_base, clk_base + PLLD_BASE);
|
||||
}
|
||||
|
||||
static struct clk *tegra124_clk_src_onecell_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
struct clk *clk;
|
||||
|
||||
clk = of_clk_src_onecell_get(clkspec, data);
|
||||
if (IS_ERR(clk))
|
||||
return clk;
|
||||
|
||||
hw = __clk_get_hw(clk);
|
||||
|
||||
if (clkspec->args[0] == TEGRA124_CLK_EMC) {
|
||||
if (!tegra124_clk_emc_driver_available(hw))
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra124_132_clock_init_post - clock initialization postamble for T124/T132
|
||||
* @np: struct device_node * of the DT node for the SoC CAR IP block
|
||||
|
@ -1516,10 +1536,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
|
|||
&pll_x_params);
|
||||
tegra_init_special_resets(1, tegra124_reset_assert,
|
||||
tegra124_reset_deassert);
|
||||
tegra_add_of_provider(np, of_clk_src_onecell_get);
|
||||
tegra_add_of_provider(np, tegra124_clk_src_onecell_get);
|
||||
|
||||
clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
|
||||
&emc_lock);
|
||||
clks[TEGRA124_CLK_EMC] = tegra124_clk_register_emc(clk_base, np,
|
||||
&emc_lock);
|
||||
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
|
|
|
@ -881,16 +881,22 @@ void tegra_super_clk_gen5_init(void __iomem *clk_base,
|
|||
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||
struct tegra_clk_pll_params *pll_params);
|
||||
|
||||
#ifdef CONFIG_TEGRA124_EMC
|
||||
struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
|
||||
spinlock_t *lock);
|
||||
#ifdef CONFIG_TEGRA124_CLK_EMC
|
||||
struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np,
|
||||
spinlock_t *lock);
|
||||
bool tegra124_clk_emc_driver_available(struct clk_hw *emc_hw);
|
||||
#else
|
||||
static inline struct clk *tegra_clk_register_emc(void __iomem *base,
|
||||
struct device_node *np,
|
||||
spinlock_t *lock)
|
||||
static inline struct clk *
|
||||
tegra124_clk_register_emc(void __iomem *base, struct device_node *np,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool tegra124_clk_emc_driver_available(struct clk_hw *emc_hw)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void tegra114_clock_tune_cpu_trimmers_high(void);
|
||||
|
|
|
@ -848,8 +848,6 @@ static int scmi_remove(struct platform_device *pdev)
|
|||
struct scmi_info *info = platform_get_drvdata(pdev);
|
||||
struct idr *idr = &info->tx_idr;
|
||||
|
||||
scmi_notification_exit(&info->handle);
|
||||
|
||||
mutex_lock(&scmi_list_mutex);
|
||||
if (info->users)
|
||||
ret = -EBUSY;
|
||||
|
@ -860,6 +858,8 @@ static int scmi_remove(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
scmi_notification_exit(&info->handle);
|
||||
|
||||
/* Safe to free channels since no more users */
|
||||
ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
|
||||
idr_destroy(&info->tx_idr);
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
#include <linux/arm-smccc.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "common.h"
|
||||
|
@ -23,6 +25,8 @@
|
|||
* @shmem: Transmit/Receive shared memory area
|
||||
* @shmem_lock: Lock to protect access to Tx/Rx shared memory area
|
||||
* @func_id: smc/hvc call function id
|
||||
* @irq: Optional; employed when platforms indicates msg completion by intr.
|
||||
* @tx_complete: Optional, employed only when irq is valid.
|
||||
*/
|
||||
|
||||
struct scmi_smc {
|
||||
|
@ -30,8 +34,19 @@ struct scmi_smc {
|
|||
struct scmi_shared_mem __iomem *shmem;
|
||||
struct mutex shmem_lock;
|
||||
u32 func_id;
|
||||
int irq;
|
||||
struct completion tx_complete;
|
||||
};
|
||||
|
||||
static irqreturn_t smc_msg_done_isr(int irq, void *data)
|
||||
{
|
||||
struct scmi_smc *scmi_info = data;
|
||||
|
||||
complete(&scmi_info->tx_complete);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static bool smc_chan_available(struct device *dev, int idx)
|
||||
{
|
||||
struct device_node *np = of_parse_phandle(dev->of_node, "shmem", 0);
|
||||
|
@ -51,7 +66,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
|||
struct resource res;
|
||||
struct device_node *np;
|
||||
u32 func_id;
|
||||
int ret;
|
||||
int ret, irq;
|
||||
|
||||
if (!tx)
|
||||
return -ENODEV;
|
||||
|
@ -79,6 +94,24 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If there is an interrupt named "a2p", then the service and
|
||||
* completion of a message is signaled by an interrupt rather than by
|
||||
* the return of the SMC call.
|
||||
*/
|
||||
irq = of_irq_get_byname(cdev->of_node, "a2p");
|
||||
if (irq > 0) {
|
||||
ret = devm_request_irq(dev, irq, smc_msg_done_isr,
|
||||
IRQF_NO_SUSPEND,
|
||||
dev_name(dev), scmi_info);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to setup SCMI smc irq\n");
|
||||
return ret;
|
||||
}
|
||||
init_completion(&scmi_info->tx_complete);
|
||||
scmi_info->irq = irq;
|
||||
}
|
||||
|
||||
scmi_info->func_id = func_id;
|
||||
scmi_info->cinfo = cinfo;
|
||||
mutex_init(&scmi_info->shmem_lock);
|
||||
|
@ -110,7 +143,14 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
|
|||
|
||||
shmem_tx_prepare(scmi_info->shmem, xfer);
|
||||
|
||||
if (scmi_info->irq)
|
||||
reinit_completion(&scmi_info->tx_complete);
|
||||
|
||||
arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
|
||||
if (scmi_info->irq)
|
||||
wait_for_completion(&scmi_info->tx_complete);
|
||||
|
||||
scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem));
|
||||
|
||||
mutex_unlock(&scmi_info->shmem_lock);
|
||||
|
|
|
@ -173,7 +173,7 @@ config JZ4780_NEMC
|
|||
memory devices such as NAND and SRAM.
|
||||
|
||||
config MTK_SMI
|
||||
bool "Mediatek SoC Memory Controller driver" if COMPILE_TEST
|
||||
tristate "MediaTek SoC Memory Controller driver" if COMPILE_TEST
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
help
|
||||
This driver is for the Memory Controller module in MediaTek SoCs,
|
||||
|
@ -202,9 +202,9 @@ config RENESAS_RPCIF
|
|||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This supports Renesas R-Car Gen3 RPC-IF which provides either SPI
|
||||
host or HyperFlash. You'll have to select individual components
|
||||
under the corresponding menu.
|
||||
This supports Renesas R-Car Gen3 or RZ/G2 RPC-IF which provides
|
||||
either SPI host or HyperFlash. You'll have to select individual
|
||||
components under the corresponding menu.
|
||||
|
||||
config STM32_FMC2_EBI
|
||||
tristate "Support for FMC2 External Bus Interface on STM32MP SoCs"
|
||||
|
|
|
@ -70,7 +70,7 @@ struct emif_data {
|
|||
};
|
||||
|
||||
static struct emif_data *emif1;
|
||||
static spinlock_t emif_lock;
|
||||
static DEFINE_SPINLOCK(emif_lock);
|
||||
static unsigned long irq_state;
|
||||
static u32 t_ck; /* DDR clock period in ps */
|
||||
static LIST_HEAD(device_list);
|
||||
|
@ -1531,7 +1531,6 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
|
|||
/* One-time actions taken on probing the first device */
|
||||
if (!emif1) {
|
||||
emif1 = emif;
|
||||
spin_lock_init(&emif_lock);
|
||||
|
||||
/*
|
||||
* TODO: register notifiers for frequency and voltage
|
||||
|
|
|
@ -130,7 +130,7 @@ static void mtk_smi_clk_disable(const struct mtk_smi *smi)
|
|||
|
||||
int mtk_smi_larb_get(struct device *larbdev)
|
||||
{
|
||||
int ret = pm_runtime_get_sync(larbdev);
|
||||
int ret = pm_runtime_resume_and_get(larbdev);
|
||||
|
||||
return (ret < 0) ? ret : 0;
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
|
|||
int ret;
|
||||
|
||||
/* Power on smi-common. */
|
||||
ret = pm_runtime_get_sync(larb->smi_common_dev);
|
||||
ret = pm_runtime_resume_and_get(larb->smi_common_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret);
|
||||
return ret;
|
||||
|
@ -587,26 +587,22 @@ static struct platform_driver mtk_smi_common_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct platform_driver * const smidrivers[] = {
|
||||
&mtk_smi_common_driver,
|
||||
&mtk_smi_larb_driver,
|
||||
};
|
||||
|
||||
static int __init mtk_smi_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&mtk_smi_common_driver);
|
||||
if (ret != 0) {
|
||||
pr_err("Failed to register SMI driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&mtk_smi_larb_driver);
|
||||
if (ret != 0) {
|
||||
pr_err("Failed to register SMI-LARB driver\n");
|
||||
goto err_unreg_smi;
|
||||
}
|
||||
return ret;
|
||||
|
||||
err_unreg_smi:
|
||||
platform_driver_unregister(&mtk_smi_common_driver);
|
||||
return ret;
|
||||
return platform_register_drivers(smidrivers, ARRAY_SIZE(smidrivers));
|
||||
}
|
||||
|
||||
module_init(mtk_smi_init);
|
||||
|
||||
static void __exit mtk_smi_exit(void)
|
||||
{
|
||||
platform_unregister_drivers(smidrivers, ARRAY_SIZE(smidrivers));
|
||||
}
|
||||
module_exit(mtk_smi_exit);
|
||||
|
||||
MODULE_DESCRIPTION("MediaTek SMI driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -278,7 +278,7 @@ static int exynos5_counters_disable_edev(struct exynos5_dmc *dmc)
|
|||
}
|
||||
|
||||
/**
|
||||
* find_target_freq_id() - Finds requested frequency in local DMC configuration
|
||||
* find_target_freq_idx() - Finds requested frequency in local DMC configuration
|
||||
* @dmc: device for which the information is checked
|
||||
* @target_rate: requested frequency in KHz
|
||||
*
|
||||
|
@ -998,7 +998,7 @@ static struct devfreq_dev_profile exynos5_dmc_df_profile = {
|
|||
};
|
||||
|
||||
/**
|
||||
* exynos5_dmc_align_initial_frequency() - Align initial frequency value
|
||||
* exynos5_dmc_align_init_freq() - Align initial frequency value
|
||||
* @dmc: device for which the frequency is going to be set
|
||||
* @bootloader_init_freq: initial frequency set by the bootloader in KHz
|
||||
*
|
||||
|
|
|
@ -32,9 +32,11 @@ config TEGRA30_EMC
|
|||
external memory.
|
||||
|
||||
config TEGRA124_EMC
|
||||
bool "NVIDIA Tegra124 External Memory Controller driver"
|
||||
tristate "NVIDIA Tegra124 External Memory Controller driver"
|
||||
default y
|
||||
depends on TEGRA_MC && ARCH_TEGRA_124_SOC
|
||||
select TEGRA124_CLK_EMC
|
||||
select PM_OPP
|
||||
help
|
||||
This driver is for the External Memory Controller (EMC) found on
|
||||
Tegra124 chips. The EMC controls the external DRAM on the board.
|
||||
|
|
|
@ -176,6 +176,13 @@ static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev,
|
|||
if (!rst_ops)
|
||||
return -ENODEV;
|
||||
|
||||
/* DMA flushing will fail if reset is already asserted */
|
||||
if (rst_ops->reset_status) {
|
||||
/* check whether reset is asserted */
|
||||
if (rst_ops->reset_status(mc, rst))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rst_ops->block_dma) {
|
||||
/* block clients DMA requests */
|
||||
err = rst_ops->block_dma(mc, rst);
|
||||
|
|
|
@ -9,22 +9,29 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/sort.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <soc/tegra/emc.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <soc/tegra/mc.h>
|
||||
|
||||
#include "mc.h"
|
||||
|
||||
#define EMC_FBIO_CFG5 0x104
|
||||
#define EMC_FBIO_CFG5_DRAM_TYPE_MASK 0x3
|
||||
#define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0
|
||||
#define EMC_FBIO_CFG5_DRAM_WIDTH_X64 BIT(4)
|
||||
|
||||
#define EMC_INTSTATUS 0x0
|
||||
#define EMC_INTSTATUS_CLKCHANGE_COMPLETE BIT(4)
|
||||
|
@ -460,6 +467,17 @@ struct emc_timing {
|
|||
u32 emc_zcal_interval;
|
||||
};
|
||||
|
||||
enum emc_rate_request_type {
|
||||
EMC_RATE_DEBUG,
|
||||
EMC_RATE_ICC,
|
||||
EMC_RATE_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct emc_rate_request {
|
||||
unsigned long min_rate;
|
||||
unsigned long max_rate;
|
||||
};
|
||||
|
||||
struct tegra_emc {
|
||||
struct device *dev;
|
||||
|
||||
|
@ -470,6 +488,7 @@ struct tegra_emc {
|
|||
struct clk *clk;
|
||||
|
||||
enum emc_dram_type dram_type;
|
||||
unsigned int dram_bus_width;
|
||||
unsigned int dram_num;
|
||||
|
||||
struct emc_timing last_timing;
|
||||
|
@ -481,6 +500,17 @@ struct tegra_emc {
|
|||
unsigned long min_rate;
|
||||
unsigned long max_rate;
|
||||
} debugfs;
|
||||
|
||||
struct icc_provider provider;
|
||||
|
||||
/*
|
||||
* There are multiple sources in the EMC driver which could request
|
||||
* a min/max clock rate, these rates are contained in this array.
|
||||
*/
|
||||
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
|
||||
|
||||
/* protect shared rate-change code path */
|
||||
struct mutex rate_lock;
|
||||
};
|
||||
|
||||
/* Timing change sequence functions */
|
||||
|
@ -562,8 +592,8 @@ static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
|
|||
return timing;
|
||||
}
|
||||
|
||||
int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
static int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
|
||||
struct emc_timing *last = &emc->last_timing;
|
||||
|
@ -790,8 +820,8 @@ int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tegra_emc_complete_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
static void tegra_emc_complete_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
|
||||
struct emc_timing *last = &emc->last_timing;
|
||||
|
@ -869,6 +899,14 @@ static void emc_read_current_timing(struct tegra_emc *emc,
|
|||
static int emc_init(struct tegra_emc *emc)
|
||||
{
|
||||
emc->dram_type = readl(emc->regs + EMC_FBIO_CFG5);
|
||||
|
||||
if (emc->dram_type & EMC_FBIO_CFG5_DRAM_WIDTH_X64)
|
||||
emc->dram_bus_width = 64;
|
||||
else
|
||||
emc->dram_bus_width = 32;
|
||||
|
||||
dev_info(emc->dev, "%ubit DRAM bus\n", emc->dram_bus_width);
|
||||
|
||||
emc->dram_type &= EMC_FBIO_CFG5_DRAM_TYPE_MASK;
|
||||
emc->dram_type >>= EMC_FBIO_CFG5_DRAM_TYPE_SHIFT;
|
||||
|
||||
|
@ -987,6 +1025,7 @@ static const struct of_device_id tegra_emc_of_match[] = {
|
|||
{ .compatible = "nvidia,tegra132-emc" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
|
||||
|
||||
static struct device_node *
|
||||
tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
|
||||
|
@ -1007,6 +1046,83 @@ tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
|
||||
emc->requested_rate[i].min_rate = 0;
|
||||
emc->requested_rate[i].max_rate = ULONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static int emc_request_rate(struct tegra_emc *emc,
|
||||
unsigned long new_min_rate,
|
||||
unsigned long new_max_rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = emc->requested_rate;
|
||||
unsigned long min_rate = 0, max_rate = ULONG_MAX;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
/* select minimum and maximum rates among the requested rates */
|
||||
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
|
||||
if (i == type) {
|
||||
min_rate = max(new_min_rate, min_rate);
|
||||
max_rate = min(new_max_rate, max_rate);
|
||||
} else {
|
||||
min_rate = max(req->min_rate, min_rate);
|
||||
max_rate = min(req->max_rate, max_rate);
|
||||
}
|
||||
}
|
||||
|
||||
if (min_rate > max_rate) {
|
||||
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
|
||||
__func__, type, min_rate, max_rate);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/*
|
||||
* EMC rate-changes should go via OPP API because it manages voltage
|
||||
* changes.
|
||||
*/
|
||||
err = dev_pm_opp_set_rate(emc->dev, min_rate);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->requested_rate[type].min_rate = new_min_rate;
|
||||
emc->requested_rate[type].max_rate = new_max_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = &emc->requested_rate[type];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&emc->rate_lock);
|
||||
ret = emc_request_rate(emc, rate, req->max_rate, type);
|
||||
mutex_unlock(&emc->rate_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = &emc->requested_rate[type];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&emc->rate_lock);
|
||||
ret = emc_request_rate(emc, req->min_rate, rate, type);
|
||||
mutex_unlock(&emc->rate_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* debugfs interface
|
||||
*
|
||||
|
@ -1079,7 +1195,7 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
|||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_set_min_rate(emc->clk, rate);
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -1109,7 +1225,7 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
|||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_set_max_rate(emc->clk, rate);
|
||||
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -1127,15 +1243,6 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
|
|||
unsigned int i;
|
||||
int err;
|
||||
|
||||
emc->clk = devm_clk_get(dev, "emc");
|
||||
if (IS_ERR(emc->clk)) {
|
||||
if (PTR_ERR(emc->clk) != -ENODEV) {
|
||||
dev_err(dev, "failed to get EMC clock: %ld\n",
|
||||
PTR_ERR(emc->clk));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emc->debugfs.min_rate = ULONG_MAX;
|
||||
emc->debugfs.max_rate = 0;
|
||||
|
||||
|
@ -1175,6 +1282,168 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
|
|||
emc, &tegra_emc_debug_max_rate_fops);
|
||||
}
|
||||
|
||||
static inline struct tegra_emc *
|
||||
to_tegra_emc_provider(struct icc_provider *provider)
|
||||
{
|
||||
return container_of(provider, struct tegra_emc, provider);
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
emc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct icc_provider *provider = data;
|
||||
struct icc_node_data *ndata;
|
||||
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;
|
||||
|
||||
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/*
|
||||
* SRC and DST nodes should have matching TAG in order to have
|
||||
* it set by default for a requested path.
|
||||
*/
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
ndata->node = node;
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct tegra_emc *emc = to_tegra_emc_provider(dst->provider);
|
||||
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
|
||||
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
|
||||
unsigned long long rate = max(avg_bw, peak_bw);
|
||||
unsigned int dram_data_bus_width_bytes;
|
||||
const unsigned int ddr = 2;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Tegra124 EMC runs on a clock rate of SDRAM bus. This means that
|
||||
* EMC clock rate is twice smaller than the peak data rate because
|
||||
* data is sampled on both EMC clock edges.
|
||||
*/
|
||||
dram_data_bus_width_bytes = emc->dram_bus_width / 8;
|
||||
do_div(rate, ddr * dram_data_bus_width_bytes);
|
||||
rate = min_t(u64, rate, U32_MAX);
|
||||
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
{
|
||||
const struct tegra_mc_soc *soc = emc->mc->soc;
|
||||
struct icc_node *node;
|
||||
int err;
|
||||
|
||||
emc->provider.dev = emc->dev;
|
||||
emc->provider.set = emc_icc_set;
|
||||
emc->provider.data = &emc->provider;
|
||||
emc->provider.aggregate = soc->icc_ops->aggregate;
|
||||
emc->provider.xlate_extended = emc_of_icc_xlate_extended;
|
||||
|
||||
err = icc_provider_add(&emc->provider);
|
||||
if (err)
|
||||
goto err_msg;
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto del_provider;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->provider);
|
||||
del_provider:
|
||||
icc_provider_del(&emc->provider);
|
||||
err_msg:
|
||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
||||
{
|
||||
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||
struct opp_table *hw_opp_table;
|
||||
int err;
|
||||
|
||||
hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
||||
err = PTR_ERR_OR_ZERO(hw_opp_table);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dev_pm_opp_of_add_table(emc->dev);
|
||||
if (err) {
|
||||
if (err == -ENODEV)
|
||||
dev_err(emc->dev, "OPP table not found, please update your device tree\n");
|
||||
else
|
||||
dev_err(emc->dev, "failed to add OPP table: %d\n", err);
|
||||
|
||||
goto put_hw_table;
|
||||
}
|
||||
|
||||
dev_info(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
|
||||
hw_version, clk_get_rate(emc->clk) / 1000000);
|
||||
|
||||
/* first dummy rate-set initializes voltage state */
|
||||
err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk));
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err);
|
||||
goto remove_table;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
remove_table:
|
||||
dev_pm_opp_of_remove_table(emc->dev);
|
||||
put_hw_table:
|
||||
dev_pm_opp_put_supported_hw(hw_opp_table);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void devm_tegra_emc_unset_callback(void *data)
|
||||
{
|
||||
tegra124_clk_set_emc_callbacks(NULL, NULL);
|
||||
}
|
||||
|
||||
static int tegra_emc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
@ -1186,6 +1455,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
|||
if (!emc)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&emc->rate_lock);
|
||||
emc->dev = &pdev->dev;
|
||||
|
||||
emc->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
|
@ -1199,23 +1469,15 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
|||
ram_code = tegra_read_ram_code();
|
||||
|
||||
np = tegra_emc_find_node_by_ram_code(pdev->dev.of_node, ram_code);
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev,
|
||||
"no memory timings for RAM code %u found in DT\n",
|
||||
ram_code);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
err = tegra_emc_load_timings_from_dt(emc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (emc->num_timings == 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"no memory timings for RAM code %u registered\n",
|
||||
ram_code);
|
||||
return -ENOENT;
|
||||
if (np) {
|
||||
err = tegra_emc_load_timings_from_dt(emc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
dev_info(&pdev->dev,
|
||||
"no memory timings for RAM code %u found in DT\n",
|
||||
ram_code);
|
||||
}
|
||||
|
||||
err = emc_init(emc);
|
||||
|
@ -1226,9 +1488,39 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, emc);
|
||||
|
||||
tegra124_clk_set_emc_callbacks(tegra_emc_prepare_timing_change,
|
||||
tegra_emc_complete_timing_change);
|
||||
|
||||
err = devm_add_action_or_reset(&pdev->dev, devm_tegra_emc_unset_callback,
|
||||
NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->clk = devm_clk_get(&pdev->dev, "emc");
|
||||
if (IS_ERR(emc->clk)) {
|
||||
err = PTR_ERR(emc->clk);
|
||||
dev_err(&pdev->dev, "failed to get EMC clock: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tegra_emc_opp_table_init(emc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
tegra_emc_rate_requests_init(emc);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DEBUG_FS))
|
||||
emc_debugfs_init(&pdev->dev, emc);
|
||||
|
||||
tegra_emc_interconnect_init(emc);
|
||||
|
||||
/*
|
||||
* Don't allow the kernel module to be unloaded. Unloading adds some
|
||||
* extra complexity which doesn't really worth the effort in a case of
|
||||
* this driver.
|
||||
*/
|
||||
try_module_get(THIS_MODULE);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -1238,11 +1530,11 @@ static struct platform_driver tegra_emc_driver = {
|
|||
.name = "tegra-emc",
|
||||
.of_match_table = tegra_emc_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
};
|
||||
module_platform_driver(tegra_emc_driver);
|
||||
|
||||
static int tegra_emc_init(void)
|
||||
{
|
||||
return platform_driver_register(&tegra_emc_driver);
|
||||
}
|
||||
subsys_initcall(tegra_emc_init);
|
||||
MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
|
||||
MODULE_DESCRIPTION("NVIDIA Tegra124 EMC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/memory/tegra124-mc.h>
|
||||
|
||||
|
@ -1010,6 +1011,83 @@ static const struct tegra_mc_reset tegra124_mc_resets[] = {
|
|||
TEGRA124_MC_RESET(GPU, 0x970, 0x974, 2),
|
||||
};
|
||||
|
||||
static int tegra124_mc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
/* TODO: program PTSA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra124_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
/*
|
||||
* ISO clients need to reserve extra bandwidth up-front because
|
||||
* there could be high bandwidth pressure during initial filling
|
||||
* of the client's FIFO buffers. Secondly, we need to take into
|
||||
* account impurities of the memory subsystem.
|
||||
*/
|
||||
if (tag & TEGRA_MC_ICC_TAG_ISO)
|
||||
peak_bw = tegra_mc_scale_percents(peak_bw, 400);
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max(*agg_peak, peak_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
tegra124_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
|
||||
const struct tegra_mc_client *client;
|
||||
unsigned int i, idx = spec->args[0];
|
||||
struct icc_node_data *ndata;
|
||||
struct icc_node *node;
|
||||
|
||||
list_for_each_entry(node, &mc->provider.nodes, node_list) {
|
||||
if (node->id != idx)
|
||||
continue;
|
||||
|
||||
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client = &mc->soc->clients[idx];
|
||||
ndata->node = node;
|
||||
|
||||
switch (client->swgroup) {
|
||||
case TEGRA_SWGROUP_DC:
|
||||
case TEGRA_SWGROUP_DCB:
|
||||
case TEGRA_SWGROUP_PTC:
|
||||
case TEGRA_SWGROUP_VI:
|
||||
/* these clients are isochronous by default */
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
break;
|
||||
|
||||
default:
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == idx)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra124_mc_icc_ops = {
|
||||
.xlate_extended = tegra124_mc_of_icc_xlate_extended,
|
||||
.aggregate = tegra124_mc_icc_aggreate,
|
||||
.set = tegra124_mc_icc_set,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA_124_SOC
|
||||
static const unsigned long tegra124_mc_emem_regs[] = {
|
||||
MC_EMEM_ARB_CFG,
|
||||
|
@ -1061,6 +1139,7 @@ const struct tegra_mc_soc tegra124_mc_soc = {
|
|||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra124_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra124_mc_resets),
|
||||
.icc_ops = &tegra124_mc_icc_ops,
|
||||
};
|
||||
#endif /* CONFIG_ARCH_TEGRA_124_SOC */
|
||||
|
||||
|
@ -1091,5 +1170,6 @@ const struct tegra_mc_soc tegra132_mc_soc = {
|
|||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra124_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra124_mc_resets),
|
||||
.icc_ops = &tegra124_mc_icc_ops,
|
||||
};
|
||||
#endif /* CONFIG_ARCH_TEGRA_132_SOC */
|
||||
|
|
|
@ -125,9 +125,9 @@ static int tegra186_emc_debug_min_rate_set(void *data, u64 rate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(tegra186_emc_debug_min_rate_fops,
|
||||
tegra186_emc_debug_min_rate_get,
|
||||
tegra186_emc_debug_min_rate_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_min_rate_fops,
|
||||
tegra186_emc_debug_min_rate_get,
|
||||
tegra186_emc_debug_min_rate_set, "%llu\n");
|
||||
|
||||
static int tegra186_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
|
@ -155,9 +155,9 @@ static int tegra186_emc_debug_max_rate_set(void *data, u64 rate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(tegra186_emc_debug_max_rate_fops,
|
||||
tegra186_emc_debug_max_rate_get,
|
||||
tegra186_emc_debug_max_rate_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops,
|
||||
tegra186_emc_debug_max_rate_get,
|
||||
tegra186_emc_debug_max_rate_set, "%llu\n");
|
||||
|
||||
static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -911,21 +911,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
|||
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
||||
{
|
||||
u32 hw_version = BIT(tegra_sku_info.soc_process_id);
|
||||
struct opp_table *clk_opp_table, *hw_opp_table;
|
||||
struct opp_table *hw_opp_table;
|
||||
int err;
|
||||
|
||||
clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL);
|
||||
err = PTR_ERR_OR_ZERO(clk_opp_table);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to set OPP clk: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
||||
err = PTR_ERR_OR_ZERO(hw_opp_table);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
|
||||
goto put_clk_table;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dev_pm_opp_of_add_table(emc->dev);
|
||||
|
@ -954,8 +947,6 @@ static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
|||
dev_pm_opp_of_remove_table(emc->dev);
|
||||
put_hw_table:
|
||||
dev_pm_opp_put_supported_hw(hw_opp_table);
|
||||
put_clk_table:
|
||||
dev_pm_opp_put_clkname(clk_opp_table);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -1483,21 +1483,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
|||
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
||||
{
|
||||
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||
struct opp_table *clk_opp_table, *hw_opp_table;
|
||||
struct opp_table *hw_opp_table;
|
||||
int err;
|
||||
|
||||
clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL);
|
||||
err = PTR_ERR_OR_ZERO(clk_opp_table);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to set OPP clk: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
||||
err = PTR_ERR_OR_ZERO(hw_opp_table);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
|
||||
goto put_clk_table;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dev_pm_opp_of_add_table(emc->dev);
|
||||
|
@ -1526,8 +1519,6 @@ static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
|||
dev_pm_opp_of_remove_table(emc->dev);
|
||||
put_hw_table:
|
||||
dev_pm_opp_put_supported_hw(hw_opp_table);
|
||||
put_clk_table:
|
||||
dev_pm_opp_put_clkname(clk_opp_table);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -378,8 +378,10 @@ static int aemif_probe(struct platform_device *pdev)
|
|||
*/
|
||||
for_each_available_child_of_node(np, child_np) {
|
||||
ret = of_aemif_parse_abus_config(pdev, child_np);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
of_node_put(child_np);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
} else if (pdata && pdata->num_abus_data > 0) {
|
||||
for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) {
|
||||
|
@ -405,8 +407,10 @@ static int aemif_probe(struct platform_device *pdev)
|
|||
for_each_available_child_of_node(np, child_np) {
|
||||
ret = of_platform_populate(child_np, NULL,
|
||||
dev_lookup, dev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
of_node_put(child_np);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
} else if (pdata) {
|
||||
for (i = 0; i < pdata->num_sub_devices; i++) {
|
||||
|
|
|
@ -340,7 +340,7 @@ static struct platform_driver ti_emif_driver = {
|
|||
.remove = ti_emif_remove,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = of_match_ptr(ti_emif_of_match),
|
||||
.of_match_table = ti_emif_of_match,
|
||||
.pm = &ti_emif_pm_ops,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -54,7 +54,9 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
|||
{
|
||||
struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
|
||||
|
||||
return axp20x_device_remove(axp20x);
|
||||
axp20x_device_remove(axp20x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
|
@ -49,11 +49,11 @@ static int axp20x_rsb_probe(struct sunxi_rsb_device *rdev)
|
|||
return axp20x_device_probe(axp20x);
|
||||
}
|
||||
|
||||
static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
|
||||
static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
|
||||
{
|
||||
struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev);
|
||||
|
||||
return axp20x_device_remove(axp20x);
|
||||
axp20x_device_remove(axp20x);
|
||||
}
|
||||
|
||||
static const struct of_device_id axp20x_rsb_of_match[] = {
|
||||
|
|
|
@ -987,7 +987,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
|
|||
}
|
||||
EXPORT_SYMBOL(axp20x_device_probe);
|
||||
|
||||
int axp20x_device_remove(struct axp20x_dev *axp20x)
|
||||
void axp20x_device_remove(struct axp20x_dev *axp20x)
|
||||
{
|
||||
if (axp20x == axp20x_pm_power_off) {
|
||||
axp20x_pm_power_off = NULL;
|
||||
|
@ -996,8 +996,6 @@ int axp20x_device_remove(struct axp20x_dev *axp20x)
|
|||
|
||||
mfd_remove_devices(axp20x->dev);
|
||||
regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(axp20x_device_remove);
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ config RESET_SCMI
|
|||
|
||||
config RESET_SIMPLE
|
||||
bool "Simple Reset Controller Driver" if COMPILE_TEST
|
||||
default ARCH_AGILEX || ARCH_ASPEED || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARC
|
||||
default ARCH_AGILEX || ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARC
|
||||
help
|
||||
This enables a simple reset controller driver for reset lines that
|
||||
that can be asserted and deasserted by toggling bits in a contiguous,
|
||||
|
|
|
@ -875,8 +875,8 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
|
|||
EXPORT_SYMBOL_GPL(__devm_reset_control_get);
|
||||
|
||||
/**
|
||||
* device_reset - find reset controller associated with the device
|
||||
* and perform reset
|
||||
* __device_reset - find reset controller associated with the device
|
||||
* and perform reset
|
||||
* @dev: device to be reset by the controller
|
||||
* @optional: whether it is optional to reset the device
|
||||
*
|
||||
|
|
|
@ -83,9 +83,14 @@ static int hi3660_reset_probe(struct platform_device *pdev)
|
|||
if (!rc)
|
||||
return -ENOMEM;
|
||||
|
||||
rc->map = syscon_regmap_lookup_by_phandle(np, "hisi,rst-syscon");
|
||||
rc->map = syscon_regmap_lookup_by_phandle(np, "hisilicon,rst-syscon");
|
||||
if (rc->map == ERR_PTR(-ENODEV)) {
|
||||
/* fall back to the deprecated compatible */
|
||||
rc->map = syscon_regmap_lookup_by_phandle(np,
|
||||
"hisi,rst-syscon");
|
||||
}
|
||||
if (IS_ERR(rc->map)) {
|
||||
dev_err(dev, "failed to get hi3660,rst-syscon\n");
|
||||
dev_err(dev, "failed to get hisilicon,rst-syscon\n");
|
||||
return PTR_ERR(rc->map);
|
||||
}
|
||||
|
||||
|
|
|
@ -146,6 +146,8 @@ static const struct of_device_id reset_simple_dt_ids[] = {
|
|||
{ .compatible = "aspeed,ast2500-lpc-reset" },
|
||||
{ .compatible = "bitmain,bm1880-reset",
|
||||
.data = &reset_simple_active_low },
|
||||
{ .compatible = "brcm,bcm4908-misc-pcie-reset",
|
||||
.data = &reset_simple_active_low },
|
||||
{ .compatible = "snps,dw-high-reset" },
|
||||
{ .compatible = "snps,dw-low-reset",
|
||||
.data = &reset_simple_active_low },
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
@ -67,6 +68,7 @@ struct aspeed_lpc_snoop_channel {
|
|||
struct aspeed_lpc_snoop {
|
||||
struct regmap *regmap;
|
||||
int irq;
|
||||
struct clk *clk;
|
||||
struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS];
|
||||
};
|
||||
|
||||
|
@ -282,22 +284,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
lpc_snoop->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(lpc_snoop->clk)) {
|
||||
rc = PTR_ERR(lpc_snoop->clk);
|
||||
if (rc != -EPROBE_DEFER)
|
||||
dev_err(dev, "couldn't get clock\n");
|
||||
return rc;
|
||||
}
|
||||
rc = clk_prepare_enable(lpc_snoop->clk);
|
||||
if (rc) {
|
||||
dev_err(dev, "couldn't enable clock\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto err;
|
||||
|
||||
rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto err;
|
||||
|
||||
/* Configuration of 2nd snoop channel port is optional */
|
||||
if (of_property_read_u32_index(dev->of_node, "snoop-ports",
|
||||
1, &port) == 0) {
|
||||
rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
aspeed_lpc_disable_snoop(lpc_snoop, 0);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
clk_disable_unprepare(lpc_snoop->clk);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -309,6 +331,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev)
|
|||
aspeed_lpc_disable_snoop(lpc_snoop, 0);
|
||||
aspeed_lpc_disable_snoop(lpc_snoop, 1);
|
||||
|
||||
clk_disable_unprepare(lpc_snoop->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ static struct {
|
|||
/* AST2600 */
|
||||
{ "AST2600", 0x05000303 },
|
||||
{ "AST2620", 0x05010203 },
|
||||
{ "AST2605", 0x05030103 },
|
||||
};
|
||||
|
||||
static const char *siliconid_to_name(u32 siliconid)
|
||||
|
@ -43,14 +44,30 @@ static const char *siliconid_to_name(u32 siliconid)
|
|||
static const char *siliconid_to_rev(u32 siliconid)
|
||||
{
|
||||
unsigned int rev = (siliconid >> 16) & 0xff;
|
||||
unsigned int gen = (siliconid >> 24) & 0xff;
|
||||
|
||||
switch (rev) {
|
||||
case 0:
|
||||
return "A0";
|
||||
case 1:
|
||||
return "A1";
|
||||
case 3:
|
||||
return "A2";
|
||||
if (gen < 0x5) {
|
||||
/* AST2500 and below */
|
||||
switch (rev) {
|
||||
case 0:
|
||||
return "A0";
|
||||
case 1:
|
||||
return "A1";
|
||||
case 3:
|
||||
return "A2";
|
||||
}
|
||||
} else {
|
||||
/* AST2600 */
|
||||
switch (rev) {
|
||||
case 0:
|
||||
return "A0";
|
||||
case 1:
|
||||
return "A1";
|
||||
case 2:
|
||||
return "A2";
|
||||
case 3:
|
||||
return "A3";
|
||||
}
|
||||
}
|
||||
|
||||
return "??";
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2015 Atmel
|
||||
*
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com
|
||||
* Boris Brezillon <boris.brezillon@free-electrons.com
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "AT91: " fmt
|
||||
|
@ -25,136 +21,217 @@
|
|||
#define AT91_DBGU_EXID 0x44
|
||||
#define AT91_CHIPID_CIDR 0x00
|
||||
#define AT91_CHIPID_EXID 0x04
|
||||
#define AT91_CIDR_VERSION(x) ((x) & 0x1f)
|
||||
#define AT91_CIDR_VERSION(x, m) ((x) & (m))
|
||||
#define AT91_CIDR_VERSION_MASK GENMASK(4, 0)
|
||||
#define AT91_CIDR_VERSION_MASK_SAMA7G5 GENMASK(3, 0)
|
||||
#define AT91_CIDR_EXT BIT(31)
|
||||
#define AT91_CIDR_MATCH_MASK 0x7fffffe0
|
||||
#define AT91_CIDR_MATCH_MASK GENMASK(30, 5)
|
||||
#define AT91_CIDR_MASK_SAMA7G5 GENMASK(27, 5)
|
||||
|
||||
static const struct at91_soc __initconst socs[] = {
|
||||
static const struct at91_soc socs[] __initconst = {
|
||||
#ifdef CONFIG_SOC_AT91RM9200
|
||||
AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"),
|
||||
AT91_SOC(AT91RM9200_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91rm9200 BGA", "at91rm9200"),
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_AT91SAM9
|
||||
AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL),
|
||||
AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL),
|
||||
AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL),
|
||||
AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL),
|
||||
AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL),
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9260_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9260", NULL),
|
||||
AT91_SOC(AT91SAM9261_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9261", NULL),
|
||||
AT91_SOC(AT91SAM9263_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9263", NULL),
|
||||
AT91_SOC(AT91SAM9G20_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9g20", NULL),
|
||||
AT91_SOC(AT91SAM9RL64_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9rl64", NULL),
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9M11_EXID_MATCH,
|
||||
"at91sam9m11", "at91sam9g45"),
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9M10_EXID_MATCH,
|
||||
"at91sam9m10", "at91sam9g45"),
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9G46_EXID_MATCH,
|
||||
"at91sam9g46", "at91sam9g45"),
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9G45_EXID_MATCH,
|
||||
"at91sam9g45", "at91sam9g45"),
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9G15_EXID_MATCH,
|
||||
"at91sam9g15", "at91sam9x5"),
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9G35_EXID_MATCH,
|
||||
"at91sam9g35", "at91sam9x5"),
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9X35_EXID_MATCH,
|
||||
"at91sam9x35", "at91sam9x5"),
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9G25_EXID_MATCH,
|
||||
"at91sam9g25", "at91sam9x5"),
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9X25_EXID_MATCH,
|
||||
"at91sam9x25", "at91sam9x5"),
|
||||
AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9CN12_EXID_MATCH,
|
||||
"at91sam9cn12", "at91sam9n12"),
|
||||
AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9N12_EXID_MATCH,
|
||||
"at91sam9n12", "at91sam9n12"),
|
||||
AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH,
|
||||
AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, AT91SAM9CN11_EXID_MATCH,
|
||||
"at91sam9cn11", "at91sam9n12"),
|
||||
AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
|
||||
AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
|
||||
AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
|
||||
AT91_SOC(AT91SAM9XE128_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9xe128", "at91sam9xe128"),
|
||||
AT91_SOC(AT91SAM9XE256_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9xe256", "at91sam9xe256"),
|
||||
AT91_SOC(AT91SAM9XE512_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, 0, "at91sam9xe512", "at91sam9xe512"),
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_SAM9X60
|
||||
AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_EXID_MATCH, "sam9x60", "sam9x60"),
|
||||
AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
|
||||
"sam9x60", "sam9x60"),
|
||||
AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D5M_EXID_MATCH,
|
||||
AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
|
||||
"sam9x60 64MiB DDR2 SiP", "sam9x60"),
|
||||
AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D1G_EXID_MATCH,
|
||||
AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
|
||||
"sam9x60 128MiB DDR2 SiP", "sam9x60"),
|
||||
AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D6K_EXID_MATCH,
|
||||
AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
|
||||
"sam9x60 8MiB SDRAM SiP", "sam9x60"),
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_SAMA5
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D21CU_EXID_MATCH,
|
||||
"sama5d21", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D22CU_EXID_MATCH,
|
||||
"sama5d22", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D225C_D1M_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D225C_D1M_EXID_MATCH,
|
||||
"sama5d225c 16MiB SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D23CU_EXID_MATCH,
|
||||
"sama5d23", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D24CX_EXID_MATCH,
|
||||
"sama5d24", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D24CU_EXID_MATCH,
|
||||
"sama5d24", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D26CU_EXID_MATCH,
|
||||
"sama5d26", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D27CU_EXID_MATCH,
|
||||
"sama5d27", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D27CN_EXID_MATCH,
|
||||
"sama5d27", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D1G_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D27C_D1G_EXID_MATCH,
|
||||
"sama5d27c 128MiB SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D5M_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D27C_D5M_EXID_MATCH,
|
||||
"sama5d27c 64MiB SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD1G_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D27C_LD1G_EXID_MATCH,
|
||||
"sama5d27c 128MiB LPDDR2 SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD2G_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D27C_LD2G_EXID_MATCH,
|
||||
"sama5d27c 256MiB LPDDR2 SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D28CU_EXID_MATCH,
|
||||
"sama5d28", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D28CN_EXID_MATCH,
|
||||
"sama5d28", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_D1G_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D28C_D1G_EXID_MATCH,
|
||||
"sama5d28c 128MiB SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD1G_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D28C_LD1G_EXID_MATCH,
|
||||
"sama5d28c 128MiB LPDDR2 SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD2G_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D28C_LD2G_EXID_MATCH,
|
||||
"sama5d28c 256MiB LPDDR2 SiP", "sama5d2"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D31_EXID_MATCH,
|
||||
"sama5d31", "sama5d3"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D33_EXID_MATCH,
|
||||
"sama5d33", "sama5d3"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D34_EXID_MATCH,
|
||||
"sama5d34", "sama5d3"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D35_EXID_MATCH,
|
||||
"sama5d35", "sama5d3"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D36_EXID_MATCH,
|
||||
"sama5d36", "sama5d3"),
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D41_EXID_MATCH,
|
||||
"sama5d41", "sama5d4"),
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D42_EXID_MATCH,
|
||||
"sama5d42", "sama5d4"),
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D43_EXID_MATCH,
|
||||
"sama5d43", "sama5d4"),
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMA5D44_EXID_MATCH,
|
||||
"sama5d44", "sama5d4"),
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_SAMV7
|
||||
AT91_SOC(SAME70Q21_CIDR_MATCH, SAME70Q21_EXID_MATCH,
|
||||
AT91_SOC(SAME70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAME70Q21_EXID_MATCH,
|
||||
"same70q21", "same7"),
|
||||
AT91_SOC(SAME70Q20_CIDR_MATCH, SAME70Q20_EXID_MATCH,
|
||||
AT91_SOC(SAME70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAME70Q20_EXID_MATCH,
|
||||
"same70q20", "same7"),
|
||||
AT91_SOC(SAME70Q19_CIDR_MATCH, SAME70Q19_EXID_MATCH,
|
||||
AT91_SOC(SAME70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAME70Q19_EXID_MATCH,
|
||||
"same70q19", "same7"),
|
||||
AT91_SOC(SAMS70Q21_CIDR_MATCH, SAMS70Q21_EXID_MATCH,
|
||||
AT91_SOC(SAMS70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMS70Q21_EXID_MATCH,
|
||||
"sams70q21", "sams7"),
|
||||
AT91_SOC(SAMS70Q20_CIDR_MATCH, SAMS70Q20_EXID_MATCH,
|
||||
AT91_SOC(SAMS70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMS70Q20_EXID_MATCH,
|
||||
"sams70q20", "sams7"),
|
||||
AT91_SOC(SAMS70Q19_CIDR_MATCH, SAMS70Q19_EXID_MATCH,
|
||||
AT91_SOC(SAMS70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMS70Q19_EXID_MATCH,
|
||||
"sams70q19", "sams7"),
|
||||
AT91_SOC(SAMV71Q21_CIDR_MATCH, SAMV71Q21_EXID_MATCH,
|
||||
AT91_SOC(SAMV71Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMV71Q21_EXID_MATCH,
|
||||
"samv71q21", "samv7"),
|
||||
AT91_SOC(SAMV71Q20_CIDR_MATCH, SAMV71Q20_EXID_MATCH,
|
||||
AT91_SOC(SAMV71Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMV71Q20_EXID_MATCH,
|
||||
"samv71q20", "samv7"),
|
||||
AT91_SOC(SAMV71Q19_CIDR_MATCH, SAMV71Q19_EXID_MATCH,
|
||||
AT91_SOC(SAMV71Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMV71Q19_EXID_MATCH,
|
||||
"samv71q19", "samv7"),
|
||||
AT91_SOC(SAMV70Q20_CIDR_MATCH, SAMV70Q20_EXID_MATCH,
|
||||
AT91_SOC(SAMV70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMV70Q20_EXID_MATCH,
|
||||
"samv70q20", "samv7"),
|
||||
AT91_SOC(SAMV70Q19_CIDR_MATCH, SAMV70Q19_EXID_MATCH,
|
||||
AT91_SOC(SAMV70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK, SAMV70Q19_EXID_MATCH,
|
||||
"samv70q19", "samv7"),
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_SAMA7
|
||||
AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G51_EXID_MATCH,
|
||||
"sama7g51", "sama7g5"),
|
||||
AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G52_EXID_MATCH,
|
||||
"sama7g52", "sama7g5"),
|
||||
AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G53_EXID_MATCH,
|
||||
"sama7g53", "sama7g5"),
|
||||
AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
|
||||
AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G54_EXID_MATCH,
|
||||
"sama7g54", "sama7g5"),
|
||||
#endif
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
@ -191,8 +268,13 @@ static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
|
|||
{
|
||||
struct device_node *np;
|
||||
void __iomem *regs;
|
||||
static const struct of_device_id chipids[] = {
|
||||
{ .compatible = "atmel,sama5d2-chipid" },
|
||||
{ .compatible = "microchip,sama7g5-chipid" },
|
||||
{ },
|
||||
};
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid");
|
||||
np = of_find_matching_node(NULL, chipids);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -235,7 +317,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
|
|||
}
|
||||
|
||||
for (soc = socs; soc->name; soc++) {
|
||||
if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK))
|
||||
if (soc->cidr_match != (cidr & soc->cidr_mask))
|
||||
continue;
|
||||
|
||||
if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid)
|
||||
|
@ -254,7 +336,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
|
|||
soc_dev_attr->family = soc->family;
|
||||
soc_dev_attr->soc_id = soc->name;
|
||||
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
|
||||
AT91_CIDR_VERSION(cidr));
|
||||
AT91_CIDR_VERSION(cidr, soc->version_mask));
|
||||
soc_dev = soc_device_register(soc_dev_attr);
|
||||
if (IS_ERR(soc_dev)) {
|
||||
kfree(soc_dev_attr->revision);
|
||||
|
@ -266,7 +348,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
|
|||
if (soc->family)
|
||||
pr_info("Detected SoC family: %s\n", soc->family);
|
||||
pr_info("Detected SoC: %s, revision %X\n", soc->name,
|
||||
AT91_CIDR_VERSION(cidr));
|
||||
AT91_CIDR_VERSION(cidr, soc->version_mask));
|
||||
|
||||
return soc_dev;
|
||||
}
|
||||
|
@ -276,6 +358,7 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = {
|
|||
{ .compatible = "atmel,at91sam9", },
|
||||
{ .compatible = "atmel,sama5", },
|
||||
{ .compatible = "atmel,samv7", },
|
||||
{ .compatible = "microchip,sama7g5", },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2015 Atmel
|
||||
*
|
||||
* Boris Brezillon <boris.brezillon@free-electrons.com
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AT91_SOC_H
|
||||
|
@ -16,14 +12,19 @@
|
|||
|
||||
struct at91_soc {
|
||||
u32 cidr_match;
|
||||
u32 cidr_mask;
|
||||
u32 version_mask;
|
||||
u32 exid_match;
|
||||
const char *name;
|
||||
const char *family;
|
||||
};
|
||||
|
||||
#define AT91_SOC(__cidr, __exid, __name, __family) \
|
||||
#define AT91_SOC(__cidr, __cidr_mask, __version_mask, __exid, \
|
||||
__name, __family) \
|
||||
{ \
|
||||
.cidr_match = (__cidr), \
|
||||
.cidr_mask = (__cidr_mask), \
|
||||
.version_mask = (__version_mask), \
|
||||
.exid_match = (__exid), \
|
||||
.name = (__name), \
|
||||
.family = (__family), \
|
||||
|
@ -43,6 +44,7 @@ at91_soc_init(const struct at91_soc *socs);
|
|||
#define AT91SAM9X5_CIDR_MATCH 0x019a05a0
|
||||
#define AT91SAM9N12_CIDR_MATCH 0x019a07a0
|
||||
#define SAM9X60_CIDR_MATCH 0x019b35a0
|
||||
#define SAMA7G5_CIDR_MATCH 0x00162100
|
||||
|
||||
#define AT91SAM9M11_EXID_MATCH 0x00000001
|
||||
#define AT91SAM9M10_EXID_MATCH 0x00000002
|
||||
|
@ -64,6 +66,11 @@ at91_soc_init(const struct at91_soc *socs);
|
|||
#define SAM9X60_D1G_EXID_MATCH 0x00000010
|
||||
#define SAM9X60_D6K_EXID_MATCH 0x00000011
|
||||
|
||||
#define SAMA7G51_EXID_MATCH 0x3
|
||||
#define SAMA7G52_EXID_MATCH 0x2
|
||||
#define SAMA7G53_EXID_MATCH 0x1
|
||||
#define SAMA7G54_EXID_MATCH 0x0
|
||||
|
||||
#define AT91SAM9XE128_CIDR_MATCH 0x329973a0
|
||||
#define AT91SAM9XE256_CIDR_MATCH 0x329a93a0
|
||||
#define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
|
||||
obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
|
||||
obj-$(CONFIG_SOC_BCM63XX) += bcm63xx/
|
||||
obj-y += bcm63xx/
|
||||
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
|
||||
|
|
|
@ -10,3 +10,12 @@ config BCM63XX_POWER
|
|||
BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
|
||||
|
||||
endif # SOC_BCM63XX
|
||||
|
||||
config BCM_PMB
|
||||
bool "Broadcom PMB (Power Management Bus) driver"
|
||||
depends on ARCH_BCM4908 || (COMPILE_TEST && OF)
|
||||
default ARCH_BCM4908
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
This enables support for the Broadcom's PMB (Power Management Bus) that
|
||||
is used for disabling and enabling SoC devices.
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o
|
||||
obj-$(CONFIG_BCM_PMB) += bcm-pmb.o
|
||||
|
|
|
@ -0,0 +1,333 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2013 Broadcom
|
||||
* Copyright (C) 2020 Rafał Miłecki <rafal@milecki.pl>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/soc/bcm-pmb.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/reset/bcm63xx_pmb.h>
|
||||
|
||||
#define BPCM_ID_REG 0x00
|
||||
#define BPCM_CAPABILITIES 0x04
|
||||
#define BPCM_CAP_NUM_ZONES 0x000000ff
|
||||
#define BPCM_CAP_SR_REG_BITS 0x0000ff00
|
||||
#define BPCM_CAP_PLLTYPE 0x00030000
|
||||
#define BPCM_CAP_UBUS 0x00080000
|
||||
#define BPCM_CONTROL 0x08
|
||||
#define BPCM_STATUS 0x0c
|
||||
#define BPCM_ROSC_CONTROL 0x10
|
||||
#define BPCM_ROSC_THRESH_H 0x14
|
||||
#define BPCM_ROSC_THRESHOLD_BCM6838 0x14
|
||||
#define BPCM_ROSC_THRESH_S 0x18
|
||||
#define BPCM_ROSC_COUNT_BCM6838 0x18
|
||||
#define BPCM_ROSC_COUNT 0x1c
|
||||
#define BPCM_PWD_CONTROL_BCM6838 0x1c
|
||||
#define BPCM_PWD_CONTROL 0x20
|
||||
#define BPCM_SR_CONTROL_BCM6838 0x20
|
||||
#define BPCM_PWD_ACCUM_CONTROL 0x24
|
||||
#define BPCM_SR_CONTROL 0x28
|
||||
#define BPCM_GLOBAL_CONTROL 0x2c
|
||||
#define BPCM_MISC_CONTROL 0x30
|
||||
#define BPCM_MISC_CONTROL2 0x34
|
||||
#define BPCM_SGPHY_CNTL 0x38
|
||||
#define BPCM_SGPHY_STATUS 0x3c
|
||||
#define BPCM_ZONE0 0x40
|
||||
#define BPCM_ZONE_CONTROL 0x00
|
||||
#define BPCM_ZONE_CONTROL_MANUAL_CLK_EN 0x00000001
|
||||
#define BPCM_ZONE_CONTROL_MANUAL_RESET_CTL 0x00000002
|
||||
#define BPCM_ZONE_CONTROL_FREQ_SCALE_USED 0x00000004 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_DPG_CAPABLE 0x00000008 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_MANUAL_MEM_PWR 0x00000030
|
||||
#define BPCM_ZONE_CONTROL_MANUAL_ISO_CTL 0x00000040
|
||||
#define BPCM_ZONE_CONTROL_MANUAL_CTL 0x00000080
|
||||
#define BPCM_ZONE_CONTROL_DPG_CTL_EN 0x00000100
|
||||
#define BPCM_ZONE_CONTROL_PWR_DN_REQ 0x00000200
|
||||
#define BPCM_ZONE_CONTROL_PWR_UP_REQ 0x00000400
|
||||
#define BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN 0x00000800
|
||||
#define BPCM_ZONE_CONTROL_BLK_RESET_ASSERT 0x00001000
|
||||
#define BPCM_ZONE_CONTROL_MEM_STBY 0x00002000
|
||||
#define BPCM_ZONE_CONTROL_RESERVED 0x0007c000
|
||||
#define BPCM_ZONE_CONTROL_PWR_CNTL_STATE 0x00f80000
|
||||
#define BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL 0x01000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_PWR_OFF_STATE 0x02000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_PWR_ON_STATE 0x04000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_PWR_GOOD 0x08000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_DPG_PWR_STATE 0x10000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_MEM_PWR_STATE 0x20000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_ISO_STATE 0x40000000 /* R/O */
|
||||
#define BPCM_ZONE_CONTROL_RESET_STATE 0x80000000 /* R/O */
|
||||
#define BPCM_ZONE_CONFIG1 0x04
|
||||
#define BPCM_ZONE_CONFIG2 0x08
|
||||
#define BPCM_ZONE_FREQ_SCALAR_CONTROL 0x0c
|
||||
#define BPCM_ZONE_SIZE 0x10
|
||||
|
||||
struct bcm_pmb {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
spinlock_t lock;
|
||||
bool little_endian;
|
||||
struct genpd_onecell_data genpd_onecell_data;
|
||||
};
|
||||
|
||||
struct bcm_pmb_pd_data {
|
||||
const char * const name;
|
||||
int id;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
};
|
||||
|
||||
struct bcm_pmb_pm_domain {
|
||||
struct bcm_pmb *pmb;
|
||||
const struct bcm_pmb_pd_data *data;
|
||||
struct generic_pm_domain genpd;
|
||||
};
|
||||
|
||||
static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device,
|
||||
int offset, u32 *val)
|
||||
{
|
||||
void __iomem *base = pmb->base + bus * 0x20;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&pmb->lock, flags);
|
||||
err = bpcm_rd(base, device, offset, val);
|
||||
spin_unlock_irqrestore(&pmb->lock, flags);
|
||||
|
||||
if (!err)
|
||||
*val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device,
|
||||
int offset, u32 val)
|
||||
{
|
||||
void __iomem *base = pmb->base + bus * 0x20;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val);
|
||||
|
||||
spin_lock_irqsave(&pmb->lock, flags);
|
||||
err = bpcm_wr(base, device, offset, val);
|
||||
spin_unlock_irqrestore(&pmb->lock, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device,
|
||||
int zone)
|
||||
{
|
||||
int offset;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
|
||||
|
||||
err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val |= BPCM_ZONE_CONTROL_PWR_DN_REQ;
|
||||
val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ;
|
||||
|
||||
err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device,
|
||||
int zone)
|
||||
{
|
||||
int offset;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
|
||||
|
||||
err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) {
|
||||
val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ;
|
||||
val |= BPCM_ZONE_CONTROL_DPG_CTL_EN;
|
||||
val |= BPCM_ZONE_CONTROL_PWR_UP_REQ;
|
||||
val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN;
|
||||
val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT;
|
||||
|
||||
err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device)
|
||||
{
|
||||
int offset;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
/* Entire device can be powered off by powering off the 0th zone */
|
||||
offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL;
|
||||
|
||||
err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) {
|
||||
val = BPCM_ZONE_CONTROL_PWR_DN_REQ;
|
||||
|
||||
err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device)
|
||||
{
|
||||
u32 val;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) {
|
||||
err = bcm_pmb_power_on_zone(pmb, bus, device, i);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_pmb_power_on(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
|
||||
const struct bcm_pmb_pd_data *data = pd->data;
|
||||
struct bcm_pmb *pmb = pd->pmb;
|
||||
|
||||
switch (data->id) {
|
||||
case BCM_PMB_PCIE0:
|
||||
case BCM_PMB_PCIE1:
|
||||
case BCM_PMB_PCIE2:
|
||||
return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0);
|
||||
case BCM_PMB_HOST_USB:
|
||||
return bcm_pmb_power_on_device(pmb, data->bus, data->device);
|
||||
default:
|
||||
dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bcm_pmb_power_off(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
|
||||
const struct bcm_pmb_pd_data *data = pd->data;
|
||||
struct bcm_pmb *pmb = pd->pmb;
|
||||
|
||||
switch (data->id) {
|
||||
case BCM_PMB_PCIE0:
|
||||
case BCM_PMB_PCIE1:
|
||||
case BCM_PMB_PCIE2:
|
||||
return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0);
|
||||
case BCM_PMB_HOST_USB:
|
||||
return bcm_pmb_power_off_device(pmb, data->bus, data->device);
|
||||
default:
|
||||
dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bcm_pmb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct bcm_pmb_pd_data *table;
|
||||
const struct bcm_pmb_pd_data *e;
|
||||
struct resource *res;
|
||||
struct bcm_pmb *pmb;
|
||||
int max_id;
|
||||
int err;
|
||||
|
||||
pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL);
|
||||
if (!pmb)
|
||||
return -ENOMEM;
|
||||
|
||||
pmb->dev = dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pmb->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmb->base))
|
||||
return PTR_ERR(pmb->base);
|
||||
|
||||
spin_lock_init(&pmb->lock);
|
||||
|
||||
pmb->little_endian = !of_device_is_big_endian(dev->of_node);
|
||||
|
||||
table = of_device_get_match_data(dev);
|
||||
if (!table)
|
||||
return -EINVAL;
|
||||
|
||||
max_id = 0;
|
||||
for (e = table; e->name; e++)
|
||||
max_id = max(max_id, e->id);
|
||||
|
||||
pmb->genpd_onecell_data.num_domains = max_id + 1;
|
||||
pmb->genpd_onecell_data.domains =
|
||||
devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains,
|
||||
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
||||
if (!pmb->genpd_onecell_data.domains)
|
||||
return -ENOMEM;
|
||||
|
||||
for (e = table; e->name; e++) {
|
||||
struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||
|
||||
pd->pmb = pmb;
|
||||
pd->data = e;
|
||||
pd->genpd.name = e->name;
|
||||
pd->genpd.power_on = bcm_pmb_power_on;
|
||||
pd->genpd.power_off = bcm_pmb_power_off;
|
||||
|
||||
pm_genpd_init(&pd->genpd, NULL, true);
|
||||
pmb->genpd_onecell_data.domains[e->id] = &pd->genpd;
|
||||
}
|
||||
|
||||
err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to add genpd provider: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = {
|
||||
{ .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, },
|
||||
{ .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, },
|
||||
{ .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, },
|
||||
{ .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct of_device_id bcm_pmb_of_match[] = {
|
||||
{ .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver bcm_pmb_driver = {
|
||||
.driver = {
|
||||
.name = "bcm-pmb",
|
||||
.of_match_table = bcm_pmb_of_match,
|
||||
},
|
||||
.probe = bcm_pmb_probe,
|
||||
};
|
||||
|
||||
builtin_platform_driver(bcm_pmb_driver);
|
|
@ -11,8 +11,6 @@
|
|||
#include <linux/soc/brcmstb/brcmstb.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include <soc/brcmstb/common.h>
|
||||
|
||||
static u32 family_id;
|
||||
static u32 product_id;
|
||||
|
||||
|
@ -21,21 +19,6 @@ static const struct of_device_id brcmstb_machine_match[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
bool soc_is_brcmstb(void)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device_node *root;
|
||||
|
||||
root = of_find_node_by_path("/");
|
||||
if (!root)
|
||||
return false;
|
||||
|
||||
match = of_match_node(brcmstb_machine_match, root);
|
||||
of_node_put(root);
|
||||
|
||||
return match != NULL;
|
||||
}
|
||||
|
||||
u32 brcmstb_get_family_id(void)
|
||||
{
|
||||
return family_id;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
@ -29,7 +31,7 @@
|
|||
|
||||
struct imx8_soc_data {
|
||||
char *name;
|
||||
u32 (*soc_revision)(void);
|
||||
u32 (*soc_revision)(struct device *dev);
|
||||
};
|
||||
|
||||
static u64 soc_uid;
|
||||
|
@ -50,7 +52,7 @@ static u32 imx8mq_soc_revision_from_atf(void)
|
|||
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
|
||||
#endif
|
||||
|
||||
static u32 __init imx8mq_soc_revision(void)
|
||||
static u32 __init imx8mq_soc_revision(struct device *dev)
|
||||
{
|
||||
struct device_node *np;
|
||||
void __iomem *ocotp_base;
|
||||
|
@ -75,9 +77,20 @@ static u32 __init imx8mq_soc_revision(void)
|
|||
rev = REV_B1;
|
||||
}
|
||||
|
||||
soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
|
||||
soc_uid <<= 32;
|
||||
soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
|
||||
if (dev) {
|
||||
int ret;
|
||||
|
||||
ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid);
|
||||
if (ret) {
|
||||
iounmap(ocotp_base);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
|
||||
soc_uid <<= 32;
|
||||
soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
|
||||
}
|
||||
|
||||
iounmap(ocotp_base);
|
||||
of_node_put(np);
|
||||
|
@ -107,7 +120,7 @@ static void __init imx8mm_soc_uid(void)
|
|||
of_node_put(np);
|
||||
}
|
||||
|
||||
static u32 __init imx8mm_soc_revision(void)
|
||||
static u32 __init imx8mm_soc_revision(struct device *dev)
|
||||
{
|
||||
struct device_node *np;
|
||||
void __iomem *anatop_base;
|
||||
|
@ -125,7 +138,15 @@ static u32 __init imx8mm_soc_revision(void)
|
|||
iounmap(anatop_base);
|
||||
of_node_put(np);
|
||||
|
||||
imx8mm_soc_uid();
|
||||
if (dev) {
|
||||
int ret;
|
||||
|
||||
ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
imx8mm_soc_uid();
|
||||
}
|
||||
|
||||
return rev;
|
||||
}
|
||||
|
@ -150,7 +171,7 @@ static const struct imx8_soc_data imx8mp_soc_data = {
|
|||
.soc_revision = imx8mm_soc_revision,
|
||||
};
|
||||
|
||||
static __maybe_unused const struct of_device_id imx8_soc_match[] = {
|
||||
static __maybe_unused const struct of_device_id imx8_machine_match[] = {
|
||||
{ .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
|
||||
{ .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, },
|
||||
{ .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, },
|
||||
|
@ -158,12 +179,20 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static __maybe_unused const struct of_device_id imx8_soc_match[] = {
|
||||
{ .compatible = "fsl,imx8mq-soc", .data = &imx8mq_soc_data, },
|
||||
{ .compatible = "fsl,imx8mm-soc", .data = &imx8mm_soc_data, },
|
||||
{ .compatible = "fsl,imx8mn-soc", .data = &imx8mn_soc_data, },
|
||||
{ .compatible = "fsl,imx8mp-soc", .data = &imx8mp_soc_data, },
|
||||
{ }
|
||||
};
|
||||
|
||||
#define imx8_revision(soc_rev) \
|
||||
soc_rev ? \
|
||||
kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \
|
||||
"unknown"
|
||||
|
||||
static int __init imx8_soc_init(void)
|
||||
static int imx8_soc_info(struct platform_device *pdev)
|
||||
{
|
||||
struct soc_device_attribute *soc_dev_attr;
|
||||
struct soc_device *soc_dev;
|
||||
|
@ -182,7 +211,10 @@ static int __init imx8_soc_init(void)
|
|||
if (ret)
|
||||
goto free_soc;
|
||||
|
||||
id = of_match_node(imx8_soc_match, of_root);
|
||||
if (pdev)
|
||||
id = of_match_node(imx8_soc_match, pdev->dev.of_node);
|
||||
else
|
||||
id = of_match_node(imx8_machine_match, of_root);
|
||||
if (!id) {
|
||||
ret = -ENODEV;
|
||||
goto free_soc;
|
||||
|
@ -191,8 +223,16 @@ static int __init imx8_soc_init(void)
|
|||
data = id->data;
|
||||
if (data) {
|
||||
soc_dev_attr->soc_id = data->name;
|
||||
if (data->soc_revision)
|
||||
soc_rev = data->soc_revision();
|
||||
if (data->soc_revision) {
|
||||
if (pdev) {
|
||||
soc_rev = data->soc_revision(&pdev->dev);
|
||||
ret = soc_rev;
|
||||
if (ret < 0)
|
||||
goto free_soc;
|
||||
} else {
|
||||
soc_rev = data->soc_revision(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
soc_dev_attr->revision = imx8_revision(soc_rev);
|
||||
|
@ -230,4 +270,24 @@ static int __init imx8_soc_init(void)
|
|||
kfree(soc_dev_attr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Retain device_initcall is for backward compatibility with DTS. */
|
||||
static int __init imx8_soc_init(void)
|
||||
{
|
||||
if (of_find_matching_node_and_match(NULL, imx8_soc_match, NULL))
|
||||
return 0;
|
||||
|
||||
return imx8_soc_info(NULL);
|
||||
}
|
||||
device_initcall(imx8_soc_init);
|
||||
|
||||
static struct platform_driver imx8_soc_info_driver = {
|
||||
.probe = imx8_soc_info,
|
||||
.driver = {
|
||||
.name = "imx8_soc_info",
|
||||
.of_match_table = imx8_soc_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(imx8_soc_info_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
|
||||
#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
|
||||
|
||||
#include "mtk-pm-domains.h"
|
||||
#include <dt-bindings/power/mt8167-power.h>
|
||||
|
||||
#define MT8167_PWR_STATUS_MFG_2D BIT(24)
|
||||
#define MT8167_PWR_STATUS_MFG_ASYNC BIT(25)
|
||||
|
||||
/*
|
||||
* MT8167 power domain support
|
||||
*/
|
||||
|
||||
static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
|
||||
[MT8167_POWER_DOMAIN_MM] = {
|
||||
.sta_mask = PWR_STATUS_DISP,
|
||||
.ctl_offs = SPM_DIS_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||
.bp_infracfg = {
|
||||
BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI |
|
||||
MT8167_TOP_AXI_PROT_EN_MCU_MM),
|
||||
},
|
||||
.caps = MTK_SCPD_ACTIVE_WAKEUP,
|
||||
},
|
||||
[MT8167_POWER_DOMAIN_VDEC] = {
|
||||
.sta_mask = PWR_STATUS_VDEC,
|
||||
.ctl_offs = SPM_VDE_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(8, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||
.caps = MTK_SCPD_ACTIVE_WAKEUP,
|
||||
},
|
||||
[MT8167_POWER_DOMAIN_ISP] = {
|
||||
.sta_mask = PWR_STATUS_ISP,
|
||||
.ctl_offs = SPM_ISP_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(13, 12),
|
||||
.caps = MTK_SCPD_ACTIVE_WAKEUP,
|
||||
},
|
||||
[MT8167_POWER_DOMAIN_MFG_ASYNC] = {
|
||||
.sta_mask = MT8167_PWR_STATUS_MFG_ASYNC,
|
||||
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
|
||||
.sram_pdn_bits = 0,
|
||||
.sram_pdn_ack_bits = 0,
|
||||
.bp_infracfg = {
|
||||
BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG |
|
||||
MT8167_TOP_AXI_PROT_EN_MFG_EMI),
|
||||
},
|
||||
},
|
||||
[MT8167_POWER_DOMAIN_MFG_2D] = {
|
||||
.sta_mask = MT8167_PWR_STATUS_MFG_2D,
|
||||
.ctl_offs = SPM_MFG_2D_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||
},
|
||||
[MT8167_POWER_DOMAIN_MFG] = {
|
||||
.sta_mask = PWR_STATUS_MFG,
|
||||
.ctl_offs = SPM_MFG_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||
},
|
||||
[MT8167_POWER_DOMAIN_CONN] = {
|
||||
.sta_mask = PWR_STATUS_CONN,
|
||||
.ctl_offs = SPM_CONN_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(8, 8),
|
||||
.sram_pdn_ack_bits = 0,
|
||||
.caps = MTK_SCPD_ACTIVE_WAKEUP,
|
||||
.bp_infracfg = {
|
||||
BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI |
|
||||
MT8167_TOP_AXI_PROT_EN_CONN_MCU |
|
||||
MT8167_TOP_AXI_PROT_EN_MCU_CONN),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct scpsys_soc_data mt8167_scpsys_data = {
|
||||
.domains_data = scpsys_domain_data_mt8167,
|
||||
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167),
|
||||
.pwr_sta_offs = SPM_PWR_STATUS,
|
||||
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
|
||||
};
|
||||
|
||||
#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */
|
||||
|
|
@ -38,6 +38,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
|
|||
.ctl_offs = 0x0338,
|
||||
.sram_pdn_bits = GENMASK(8, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||
.caps = MTK_SCPD_DOMAIN_SUPPLY,
|
||||
},
|
||||
[MT8183_POWER_DOMAIN_MFG_CORE0] = {
|
||||
.sta_mask = BIT(7),
|
||||
|
|
|
@ -463,36 +463,4 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
|
|||
}
|
||||
EXPORT_SYMBOL(cmdq_pkt_flush_async);
|
||||
|
||||
struct cmdq_flush_completion {
|
||||
struct completion cmplt;
|
||||
bool err;
|
||||
};
|
||||
|
||||
static void cmdq_pkt_flush_cb(struct cmdq_cb_data data)
|
||||
{
|
||||
struct cmdq_flush_completion *cmplt;
|
||||
|
||||
cmplt = (struct cmdq_flush_completion *)data.data;
|
||||
if (data.sta != CMDQ_CB_NORMAL)
|
||||
cmplt->err = true;
|
||||
else
|
||||
cmplt->err = false;
|
||||
complete(&cmplt->cmplt);
|
||||
}
|
||||
|
||||
int cmdq_pkt_flush(struct cmdq_pkt *pkt)
|
||||
{
|
||||
struct cmdq_flush_completion cmplt;
|
||||
int err;
|
||||
|
||||
init_completion(&cmplt.cmplt);
|
||||
err = cmdq_pkt_flush_async(pkt, cmdq_pkt_flush_cb, &cmplt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
wait_for_completion(&cmplt.cmplt);
|
||||
|
||||
return cmplt.err ? -EFAULT : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cmdq_pkt_flush);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/soc/mediatek/infracfg.h>
|
||||
|
||||
#include "mt8167-pm-domains.h"
|
||||
#include "mt8173-pm-domains.h"
|
||||
#include "mt8183-pm-domains.h"
|
||||
#include "mt8192-pm-domains.h"
|
||||
|
@ -40,6 +42,7 @@ struct scpsys_domain {
|
|||
struct clk_bulk_data *subsys_clks;
|
||||
struct regmap *infracfg;
|
||||
struct regmap *smi;
|
||||
struct regulator *supply;
|
||||
};
|
||||
|
||||
struct scpsys {
|
||||
|
@ -187,6 +190,16 @@ static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
|
|||
return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg);
|
||||
}
|
||||
|
||||
static int scpsys_regulator_enable(struct regulator *supply)
|
||||
{
|
||||
return supply ? regulator_enable(supply) : 0;
|
||||
}
|
||||
|
||||
static int scpsys_regulator_disable(struct regulator *supply)
|
||||
{
|
||||
return supply ? regulator_disable(supply) : 0;
|
||||
}
|
||||
|
||||
static int scpsys_power_on(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
|
||||
|
@ -194,10 +207,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
|
|||
bool tmp;
|
||||
int ret;
|
||||
|
||||
ret = clk_bulk_enable(pd->num_clks, pd->clks);
|
||||
ret = scpsys_regulator_enable(pd->supply);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_bulk_enable(pd->num_clks, pd->clks);
|
||||
if (ret)
|
||||
goto err_reg;
|
||||
|
||||
/* subsys power on */
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
|
||||
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
|
||||
|
@ -232,6 +249,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
|
|||
clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks);
|
||||
err_pwr_ack:
|
||||
clk_bulk_disable(pd->num_clks, pd->clks);
|
||||
err_reg:
|
||||
scpsys_regulator_disable(pd->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -267,6 +286,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
|
|||
|
||||
clk_bulk_disable(pd->num_clks, pd->clks);
|
||||
|
||||
scpsys_regulator_disable(pd->supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -275,6 +296,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
|||
{
|
||||
const struct scpsys_domain_data *domain_data;
|
||||
struct scpsys_domain *pd;
|
||||
struct device_node *root_node = scpsys->dev->of_node;
|
||||
struct property *prop;
|
||||
const char *clk_name;
|
||||
int i, ret, num_clks;
|
||||
|
@ -307,6 +329,25 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
|||
pd->data = domain_data;
|
||||
pd->scpsys = scpsys;
|
||||
|
||||
if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
|
||||
/*
|
||||
* Find regulator in current power domain node.
|
||||
* devm_regulator_get() finds regulator in a node and its child
|
||||
* node, so set of_node to current power domain node then change
|
||||
* back to original node after regulator is found for current
|
||||
* power domain node.
|
||||
*/
|
||||
scpsys->dev->of_node = node;
|
||||
pd->supply = devm_regulator_get(scpsys->dev, "domain");
|
||||
scpsys->dev->of_node = root_node;
|
||||
if (IS_ERR(pd->supply)) {
|
||||
dev_err_probe(scpsys->dev, PTR_ERR(pd->supply),
|
||||
"%pOF: failed to get power supply.\n",
|
||||
node);
|
||||
return ERR_CAST(pd->supply);
|
||||
}
|
||||
}
|
||||
|
||||
pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
|
||||
if (IS_ERR(pd->infracfg))
|
||||
return ERR_CAST(pd->infracfg);
|
||||
|
@ -446,8 +487,8 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
|
|||
|
||||
child_pd = scpsys_add_one_domain(scpsys, child);
|
||||
if (IS_ERR(child_pd)) {
|
||||
ret = PTR_ERR(child_pd);
|
||||
dev_err(scpsys->dev, "%pOF: failed to get child domain id\n", child);
|
||||
dev_err_probe(scpsys->dev, PTR_ERR(child_pd),
|
||||
"%pOF: failed to get child domain id\n", child);
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
|
@ -514,6 +555,10 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
|
|||
}
|
||||
|
||||
static const struct of_device_id scpsys_of_match[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt8167-power-controller",
|
||||
.data = &mt8167_scpsys_data,
|
||||
},
|
||||
{
|
||||
.compatible = "mediatek,mt8173-power-controller",
|
||||
.data = &mt8173_scpsys_data,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define MTK_SCPD_FWAIT_SRAM BIT(1)
|
||||
#define MTK_SCPD_SRAM_ISO BIT(2)
|
||||
#define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3)
|
||||
#define MTK_SCPD_DOMAIN_SUPPLY BIT(4)
|
||||
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
|
||||
|
||||
#define SPM_VDE_PWR_CON 0x0210
|
||||
|
@ -14,6 +15,7 @@
|
|||
#define SPM_VEN_PWR_CON 0x0230
|
||||
#define SPM_ISP_PWR_CON 0x0238
|
||||
#define SPM_DIS_PWR_CON 0x023c
|
||||
#define SPM_CONN_PWR_CON 0x0280
|
||||
#define SPM_VEN2_PWR_CON 0x0298
|
||||
#define SPM_AUDIO_PWR_CON 0x029c
|
||||
#define SPM_MFG_2D_PWR_CON 0x02c0
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -35,6 +36,9 @@
|
|||
|
||||
#define CACHE_LINE_SIZE_SHIFT 6
|
||||
|
||||
#define LLCC_COMMON_HW_INFO 0x00030000
|
||||
#define LLCC_MAJOR_VERSION_MASK GENMASK(31, 24)
|
||||
|
||||
#define LLCC_COMMON_STATUS0 0x0003000c
|
||||
#define LLCC_LB_CNT_MASK GENMASK(31, 28)
|
||||
#define LLCC_LB_CNT_SHIFT 28
|
||||
|
@ -47,6 +51,7 @@
|
|||
|
||||
#define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00
|
||||
#define LLCC_TRP_PCB_ACT 0x21f04
|
||||
#define LLCC_TRP_WRSC_EN 0x21f20
|
||||
|
||||
#define BANK_OFFSET_STRIDE 0x80000
|
||||
|
||||
|
@ -73,6 +78,7 @@
|
|||
* then the ways assigned to this client are not flushed on power
|
||||
* collapse.
|
||||
* @activate_on_init: Activate the slice immediately after it is programmed
|
||||
* @write_scid_en: Bit enables write cache support for a given scid.
|
||||
*/
|
||||
struct llcc_slice_config {
|
||||
u32 usecase_id;
|
||||
|
@ -87,6 +93,7 @@ struct llcc_slice_config {
|
|||
bool dis_cap_alloc;
|
||||
bool retain_on_pc;
|
||||
bool activate_on_init;
|
||||
bool write_scid_en;
|
||||
};
|
||||
|
||||
struct qcom_llcc_config {
|
||||
|
@ -147,6 +154,25 @@ static const struct llcc_slice_config sm8150_data[] = {
|
|||
{ LLCC_WRCACHE, 31, 128, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct llcc_slice_config sm8250_data[] = {
|
||||
{ LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 },
|
||||
{ LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_AUDIO, 6, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
|
||||
{ LLCC_CMPT, 10, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
|
||||
{ LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 },
|
||||
{ LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
|
||||
{ LLCC_CMPTDMA, 15, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_DISP, 16, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_VIDFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_NPU, 23, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_WLHW, 24, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_CVP, 28, 256, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_APTCM, 30, 128, 3, 0, 0x0, 0x3, 1, 0, 0, 1, 0, 0 },
|
||||
{ LLCC_WRCACHE, 31, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config sc7180_cfg = {
|
||||
.sct_data = sc7180_data,
|
||||
.size = ARRAY_SIZE(sc7180_data),
|
||||
|
@ -164,6 +190,11 @@ static const struct qcom_llcc_config sm8150_cfg = {
|
|||
.size = ARRAY_SIZE(sm8150_data),
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config sm8250_cfg = {
|
||||
.sct_data = sm8250_data,
|
||||
.size = ARRAY_SIZE(sm8250_data),
|
||||
};
|
||||
|
||||
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
|
||||
|
||||
/**
|
||||
|
@ -413,6 +444,16 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (drv_data->major_version == 2) {
|
||||
u32 wren;
|
||||
|
||||
wren = config->write_scid_en << config->slice_id;
|
||||
ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_WRSC_EN,
|
||||
BIT(config->slice_id), wren);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (config->activate_on_init) {
|
||||
desc.slice_id = config->slice_id;
|
||||
ret = llcc_slice_activate(&desc);
|
||||
|
@ -476,6 +517,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
|
|||
const struct qcom_llcc_config *cfg;
|
||||
const struct llcc_slice_config *llcc_cfg;
|
||||
u32 sz;
|
||||
u32 version;
|
||||
|
||||
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
|
||||
if (!drv_data) {
|
||||
|
@ -496,6 +538,13 @@ static int qcom_llcc_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* Extract major version of the IP */
|
||||
ret = regmap_read(drv_data->bcast_regmap, LLCC_COMMON_HW_INFO, &version);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
drv_data->major_version = FIELD_GET(LLCC_MAJOR_VERSION_MASK, version);
|
||||
|
||||
ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
|
||||
&num_banks);
|
||||
if (ret)
|
||||
|
@ -559,6 +608,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
|
|||
{ .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg },
|
||||
{ .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
|
||||
{ .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
|
||||
{ .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -189,6 +189,7 @@ struct ocmem *of_get_ocmem(struct device *dev)
|
|||
{
|
||||
struct platform_device *pdev;
|
||||
struct device_node *devnode;
|
||||
struct ocmem *ocmem;
|
||||
|
||||
devnode = of_parse_phandle(dev->of_node, "sram", 0);
|
||||
if (!devnode || !devnode->parent) {
|
||||
|
@ -202,7 +203,12 @@ struct ocmem *of_get_ocmem(struct device *dev)
|
|||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
return platform_get_drvdata(pdev);
|
||||
ocmem = platform_get_drvdata(pdev);
|
||||
if (!ocmem) {
|
||||
dev_err(dev, "Cannot get ocmem\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
return ocmem;
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_ocmem);
|
||||
|
||||
|
|
|
@ -600,6 +600,7 @@ static const struct of_device_id qmp_dt_match[] = {
|
|||
{ .compatible = "qcom,sdm845-aoss-qmp", },
|
||||
{ .compatible = "qcom,sm8150-aoss-qmp", },
|
||||
{ .compatible = "qcom,sm8250-aoss-qmp", },
|
||||
{ .compatible = "qcom,sm8350-aoss-qmp", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qmp_dt_match);
|
||||
|
|
|
@ -231,10 +231,9 @@ static void tcs_invalidate(struct rsc_drv *drv, int type)
|
|||
if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS))
|
||||
return;
|
||||
|
||||
for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) {
|
||||
for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++)
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0);
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0);
|
||||
}
|
||||
|
||||
bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
|
||||
}
|
||||
|
||||
|
@ -364,7 +363,7 @@ static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger)
|
|||
enable = TCS_AMC_MODE_ENABLE;
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
|
||||
enable |= TCS_AMC_MODE_TRIGGER;
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
|
||||
write_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, enable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,7 +442,6 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
|
|||
skip:
|
||||
/* Reclaim the TCS */
|
||||
write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0);
|
||||
write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0);
|
||||
writel_relaxed(BIT(i), drv->tcs_base + RSC_DRV_IRQ_CLEAR);
|
||||
spin_lock(&drv->lock);
|
||||
clear_bit(i, drv->tcs_in_use);
|
||||
|
@ -476,23 +474,23 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
|
|||
static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
|
||||
const struct tcs_request *msg)
|
||||
{
|
||||
u32 msgid, cmd_msgid;
|
||||
u32 msgid;
|
||||
u32 cmd_msgid = CMD_MSGID_LEN | CMD_MSGID_WRITE;
|
||||
u32 cmd_enable = 0;
|
||||
u32 cmd_complete;
|
||||
struct tcs_cmd *cmd;
|
||||
int i, j;
|
||||
|
||||
cmd_msgid = CMD_MSGID_LEN;
|
||||
/* Convert all commands to RR when the request has wait_for_compl set */
|
||||
cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0;
|
||||
cmd_msgid |= CMD_MSGID_WRITE;
|
||||
|
||||
cmd_complete = read_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id);
|
||||
|
||||
for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) {
|
||||
cmd = &msg->cmds[i];
|
||||
cmd_enable |= BIT(j);
|
||||
cmd_complete |= cmd->wait << j;
|
||||
msgid = cmd_msgid;
|
||||
/*
|
||||
* Additionally, if the cmd->wait is set, make the command
|
||||
* response reqd even if the overall request was fire-n-forget.
|
||||
*/
|
||||
msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0;
|
||||
|
||||
write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid);
|
||||
|
@ -501,7 +499,6 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
|
|||
trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd);
|
||||
}
|
||||
|
||||
write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete);
|
||||
cmd_enable |= read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id);
|
||||
write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable);
|
||||
}
|
||||
|
@ -652,7 +649,6 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
|
|||
* cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
|
||||
*/
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0);
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0);
|
||||
enable_tcs_irq(drv, tcs_id, true);
|
||||
}
|
||||
spin_unlock_irqrestore(&drv->lock, flags);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
* RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
|
||||
#define RPMPD_SMPA 0x61706d73
|
||||
#define RPMPD_LDOA 0x616f646c
|
||||
#define RPMPD_SMPB 0x62706d73
|
||||
#define RPMPD_LDOB 0x626f646c
|
||||
#define RPMPD_RWCX 0x78637772
|
||||
#define RPMPD_RWMX 0x786d7772
|
||||
#define RPMPD_RWLC 0x636c7772
|
||||
|
@ -184,6 +186,31 @@ static const struct rpmpd_desc msm8976_desc = {
|
|||
.max_state = RPM_SMD_LEVEL_TURBO_HIGH,
|
||||
};
|
||||
|
||||
/* msm8994 RPM Power domains */
|
||||
DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1);
|
||||
DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2);
|
||||
/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
|
||||
DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2);
|
||||
|
||||
DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1);
|
||||
DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2);
|
||||
|
||||
static struct rpmpd *msm8994_rpmpds[] = {
|
||||
[MSM8994_VDDCX] = &msm8994_vddcx,
|
||||
[MSM8994_VDDCX_AO] = &msm8994_vddcx_ao,
|
||||
[MSM8994_VDDCX_VFC] = &msm8994_vddcx_vfc,
|
||||
[MSM8994_VDDMX] = &msm8994_vddmx,
|
||||
[MSM8994_VDDMX_AO] = &msm8994_vddmx_ao,
|
||||
[MSM8994_VDDGFX] = &msm8994_vddgfx,
|
||||
[MSM8994_VDDGFX_VFC] = &msm8994_vddgfx_vfc,
|
||||
};
|
||||
|
||||
static const struct rpmpd_desc msm8994_desc = {
|
||||
.rpmpds = msm8994_rpmpds,
|
||||
.num_pds = ARRAY_SIZE(msm8994_rpmpds),
|
||||
.max_state = MAX_CORNER_RPMPD_STATE,
|
||||
};
|
||||
|
||||
/* msm8996 RPM Power domains */
|
||||
DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1);
|
||||
DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2);
|
||||
|
@ -302,6 +329,7 @@ static const struct of_device_id rpmpd_match_table[] = {
|
|||
{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
|
||||
{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
|
||||
{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
|
||||
{ .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
|
||||
{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
|
||||
{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
|
||||
{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
|
||||
|
|
|
@ -732,9 +732,7 @@ qcom_smem_partition_header(struct qcom_smem *smem,
|
|||
header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
|
||||
|
||||
if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) {
|
||||
dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n",
|
||||
header->magic[0], header->magic[1],
|
||||
header->magic[2], header->magic[3]);
|
||||
dev_err(smem->dev, "bad partition magic %4ph\n", header->magic);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/sys_soc.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/*
|
||||
* SoC version type with major number in the upper 16 bits and minor
|
||||
* number in the lower 16 bits.
|
||||
|
@ -83,6 +85,11 @@ static const char *const pmic_models[] = {
|
|||
[23] = "PM8038",
|
||||
[24] = "PM8922",
|
||||
[25] = "PM8917",
|
||||
[30] = "PM8150",
|
||||
[31] = "PM8150L",
|
||||
[32] = "PM8150B",
|
||||
[33] = "PMK8002",
|
||||
[36] = "PM8009",
|
||||
};
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
|
@ -217,23 +224,39 @@ static const struct soc_id soc_id[] = {
|
|||
{ 250, "MSM8616" },
|
||||
{ 251, "MSM8992" },
|
||||
{ 253, "APQ8094" },
|
||||
{ 290, "MDM9607" },
|
||||
{ 291, "APQ8096" },
|
||||
{ 292, "MSM8998" },
|
||||
{ 293, "MSM8953" },
|
||||
{ 296, "MDM8207" },
|
||||
{ 297, "MDM9207" },
|
||||
{ 298, "MDM9307" },
|
||||
{ 299, "MDM9628" },
|
||||
{ 304, "APQ8053" },
|
||||
{ 305, "MSM8996SG" },
|
||||
{ 310, "MSM8996AU" },
|
||||
{ 311, "APQ8096AU" },
|
||||
{ 312, "APQ8096SG" },
|
||||
{ 317, "SDM660" },
|
||||
{ 318, "SDM630" },
|
||||
{ 319, "APQ8098" },
|
||||
{ 321, "SDM845" },
|
||||
{ 322, "MDM9206" },
|
||||
{ 324, "SDA660" },
|
||||
{ 325, "SDM658" },
|
||||
{ 326, "SDA658" },
|
||||
{ 327, "SDA630" },
|
||||
{ 338, "SDM450" },
|
||||
{ 341, "SDA845" },
|
||||
{ 345, "SDM636" },
|
||||
{ 346, "SDA636" },
|
||||
{ 349, "SDM632" },
|
||||
{ 350, "SDA632" },
|
||||
{ 351, "SDA450" },
|
||||
{ 356, "SM8250" },
|
||||
{ 402, "IPQ6018" },
|
||||
{ 425, "SC7180" },
|
||||
{ 455, "QRB5165" },
|
||||
};
|
||||
|
||||
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
||||
|
@ -264,7 +287,7 @@ static const struct file_operations qcom_ ##name## _ops = { \
|
|||
}
|
||||
|
||||
#define DEBUGFS_ADD(info, name) \
|
||||
debugfs_create_file(__stringify(name), 0400, \
|
||||
debugfs_create_file(__stringify(name), 0444, \
|
||||
qcom_socinfo->dbg_root, \
|
||||
info, &qcom_ ##name## _ops)
|
||||
|
||||
|
@ -286,7 +309,7 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p)
|
|||
if (model < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model])
|
||||
if (model < ARRAY_SIZE(pmic_models) && pmic_models[model])
|
||||
seq_printf(seq, "%s\n", pmic_models[model]);
|
||||
else
|
||||
seq_printf(seq, "unknown (%d)\n", model);
|
||||
|
@ -294,6 +317,32 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_show_pmic_model_array(struct seq_file *seq, void *p)
|
||||
{
|
||||
struct socinfo *socinfo = seq->private;
|
||||
unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics);
|
||||
unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset);
|
||||
int i;
|
||||
void *ptr = socinfo;
|
||||
|
||||
ptr += pmic_array_offset;
|
||||
|
||||
/* No need for bounds checking, it happened at socinfo_debugfs_init */
|
||||
for (i = 0; i < num_pmics; i++) {
|
||||
unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32)));
|
||||
unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32));
|
||||
|
||||
if (model < ARRAY_SIZE(pmic_models) && pmic_models[model])
|
||||
seq_printf(seq, "%s %u.%u\n", pmic_models[model],
|
||||
SOCINFO_MAJOR(die_rev),
|
||||
SOCINFO_MINOR(die_rev));
|
||||
else
|
||||
seq_printf(seq, "unknown (%d)\n", model);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
|
||||
{
|
||||
struct socinfo *socinfo = seq->private;
|
||||
|
@ -316,6 +365,7 @@ static int qcom_show_chip_id(struct seq_file *seq, void *p)
|
|||
|
||||
QCOM_OPEN(build_id, qcom_show_build_id);
|
||||
QCOM_OPEN(pmic_model, qcom_show_pmic_model);
|
||||
QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array);
|
||||
QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
|
||||
QCOM_OPEN(chip_id, qcom_show_chip_id);
|
||||
|
||||
|
@ -344,25 +394,27 @@ DEFINE_IMAGE_OPS(variant);
|
|||
DEFINE_IMAGE_OPS(oem);
|
||||
|
||||
static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
||||
struct socinfo *info)
|
||||
struct socinfo *info, size_t info_size)
|
||||
{
|
||||
struct smem_image_version *versions;
|
||||
struct dentry *dentry;
|
||||
size_t size;
|
||||
int i;
|
||||
unsigned int num_pmics;
|
||||
unsigned int pmic_array_offset;
|
||||
|
||||
qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL);
|
||||
|
||||
qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt);
|
||||
|
||||
debugfs_create_x32("info_fmt", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_x32("info_fmt", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.fmt);
|
||||
|
||||
switch (qcom_socinfo->info.fmt) {
|
||||
case SOCINFO_VERSION(0, 15):
|
||||
qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported);
|
||||
|
||||
debugfs_create_u32("nmodem_supported", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("nmodem_supported", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.nmodem_supported);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 14):
|
||||
|
@ -371,19 +423,19 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
|||
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);
|
||||
|
||||
debugfs_create_u32("num_clusters", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.num_clusters);
|
||||
debugfs_create_u32("ncluster_array_offset", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.ncluster_array_offset);
|
||||
debugfs_create_u32("num_defective_parts", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.num_defective_parts);
|
||||
debugfs_create_u32("ndefective_parts_array_offset", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.ndefective_parts_array_offset);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 13):
|
||||
qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id);
|
||||
|
||||
debugfs_create_u32("nproduct_id", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("nproduct_id", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.nproduct_id);
|
||||
DEBUGFS_ADD(info, chip_id);
|
||||
fallthrough;
|
||||
|
@ -395,21 +447,26 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
|||
qcom_socinfo->info.raw_device_num =
|
||||
__le32_to_cpu(info->raw_device_num);
|
||||
|
||||
debugfs_create_x32("chip_family", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_x32("chip_family", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.chip_family);
|
||||
debugfs_create_x32("raw_device_family", 0400,
|
||||
debugfs_create_x32("raw_device_family", 0444,
|
||||
qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.raw_device_family);
|
||||
debugfs_create_x32("raw_device_number", 0400,
|
||||
debugfs_create_x32("raw_device_number", 0444,
|
||||
qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.raw_device_num);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 11):
|
||||
num_pmics = le32_to_cpu(info->num_pmics);
|
||||
pmic_array_offset = le32_to_cpu(info->pmic_array_offset);
|
||||
if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size)
|
||||
DEBUGFS_ADD(info, pmic_model_array);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 10):
|
||||
case SOCINFO_VERSION(0, 9):
|
||||
qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id);
|
||||
|
||||
debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("foundry_id", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.foundry_id);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 8):
|
||||
|
@ -421,7 +478,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
|||
qcom_socinfo->info.hw_plat_subtype =
|
||||
__le32_to_cpu(info->hw_plat_subtype);
|
||||
|
||||
debugfs_create_u32("hardware_platform_subtype", 0400,
|
||||
debugfs_create_u32("hardware_platform_subtype", 0444,
|
||||
qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.hw_plat_subtype);
|
||||
fallthrough;
|
||||
|
@ -429,28 +486,28 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
|||
qcom_socinfo->info.accessory_chip =
|
||||
__le32_to_cpu(info->accessory_chip);
|
||||
|
||||
debugfs_create_u32("accessory_chip", 0400,
|
||||
debugfs_create_u32("accessory_chip", 0444,
|
||||
qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.accessory_chip);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 4):
|
||||
qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver);
|
||||
|
||||
debugfs_create_u32("platform_version", 0400,
|
||||
debugfs_create_u32("platform_version", 0444,
|
||||
qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.plat_ver);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 3):
|
||||
qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat);
|
||||
|
||||
debugfs_create_u32("hardware_platform", 0400,
|
||||
debugfs_create_u32("hardware_platform", 0444,
|
||||
qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.hw_plat);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 2):
|
||||
qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver);
|
||||
|
||||
debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root,
|
||||
debugfs_create_u32("raw_version", 0444, qcom_socinfo->dbg_root,
|
||||
&qcom_socinfo->info.raw_ver);
|
||||
fallthrough;
|
||||
case SOCINFO_VERSION(0, 1):
|
||||
|
@ -467,11 +524,11 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
|||
|
||||
dentry = debugfs_create_dir(socinfo_image_names[i],
|
||||
qcom_socinfo->dbg_root);
|
||||
debugfs_create_file("name", 0400, dentry, &versions[i],
|
||||
debugfs_create_file("name", 0444, dentry, &versions[i],
|
||||
&qcom_image_name_ops);
|
||||
debugfs_create_file("variant", 0400, dentry, &versions[i],
|
||||
debugfs_create_file("variant", 0444, dentry, &versions[i],
|
||||
&qcom_image_variant_ops);
|
||||
debugfs_create_file("oem", 0400, dentry, &versions[i],
|
||||
debugfs_create_file("oem", 0444, dentry, &versions[i],
|
||||
&qcom_image_oem_ops);
|
||||
}
|
||||
}
|
||||
|
@ -482,7 +539,7 @@ static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo)
|
|||
}
|
||||
#else
|
||||
static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
|
||||
struct socinfo *info)
|
||||
struct socinfo *info, size_t info_size)
|
||||
{
|
||||
}
|
||||
static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { }
|
||||
|
@ -522,7 +579,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(qs->soc_dev))
|
||||
return PTR_ERR(qs->soc_dev);
|
||||
|
||||
socinfo_debugfs_init(qs, info);
|
||||
socinfo_debugfs_init(qs, info, item_size);
|
||||
|
||||
/* Feed the soc specific unique data into entropy pool */
|
||||
add_device_randomness(info, item_size);
|
||||
|
|
|
@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev)
|
|||
EXPORT_SYMBOL(sunxi_sram_release);
|
||||
|
||||
struct sunxi_sramc_variant {
|
||||
bool has_emac_clock;
|
||||
int num_emac_clocks;
|
||||
};
|
||||
|
||||
static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
|
||||
|
@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
|
|||
};
|
||||
|
||||
static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
|
||||
.has_emac_clock = true,
|
||||
.num_emac_clocks = 1,
|
||||
};
|
||||
|
||||
static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
|
||||
.has_emac_clock = true,
|
||||
.num_emac_clocks = 1,
|
||||
};
|
||||
|
||||
static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = {
|
||||
.num_emac_clocks = 2,
|
||||
};
|
||||
|
||||
#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
|
||||
static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
|
||||
unsigned int reg)
|
||||
{
|
||||
if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
|
||||
return true;
|
||||
return false;
|
||||
const struct sunxi_sramc_variant *variant;
|
||||
|
||||
variant = of_device_get_match_data(dev);
|
||||
|
||||
if (reg < SUNXI_SRAM_EMAC_CLOCK_REG)
|
||||
return false;
|
||||
if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct regmap_config sunxi_sram_emac_clock_regmap = {
|
||||
|
@ -312,7 +323,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
|
|||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
/* last defined register */
|
||||
.max_register = SUNXI_SRAM_EMAC_CLOCK_REG,
|
||||
.max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4,
|
||||
/* other devices have no business accessing other registers */
|
||||
.readable_reg = sunxi_sram_regmap_accessible_reg,
|
||||
.writeable_reg = sunxi_sram_regmap_accessible_reg,
|
||||
|
@ -343,7 +354,7 @@ static int sunxi_sram_probe(struct platform_device *pdev)
|
|||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
if (variant->has_emac_clock) {
|
||||
if (variant->num_emac_clocks > 0) {
|
||||
emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
&sunxi_sram_emac_clock_regmap);
|
||||
|
||||
|
@ -387,6 +398,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
|
|||
.compatible = "allwinner,sun50i-h5-system-control",
|
||||
.data = &sun50i_a64_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun50i-h616-system-control",
|
||||
.data = &sun50i_h616_sramc_variant,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include <linux/dma/ti-cppi5.h>
|
||||
|
@ -1517,15 +1518,13 @@ EXPORT_SYMBOL_GPL(k3_ringacc_dmarings_init);
|
|||
static int k3_ringacc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct ringacc_match_data *match_data;
|
||||
const struct of_device_id *match;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct k3_ringacc *ringacc;
|
||||
int ret;
|
||||
|
||||
match = of_match_node(k3_ringacc_of_match, dev->of_node);
|
||||
if (!match)
|
||||
match_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!match_data)
|
||||
return -ENODEV;
|
||||
match_data = match->data;
|
||||
|
||||
ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL);
|
||||
if (!ringacc)
|
||||
|
|
|
@ -758,6 +758,7 @@ static int knav_dma_probe(struct platform_device *pdev)
|
|||
for_each_child_of_node(node, child) {
|
||||
ret = dma_init(node, child);
|
||||
if (ret) {
|
||||
of_node_put(child);
|
||||
dev_err(&pdev->dev, "init failed with %d\n", ret);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1087,6 +1087,7 @@ static int knav_queue_setup_regions(struct knav_device *kdev,
|
|||
for_each_child_of_node(regions, child) {
|
||||
region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
|
||||
if (!region) {
|
||||
of_node_put(child);
|
||||
dev_err(dev, "out of memory allocating region\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -1399,6 +1400,7 @@ static int knav_queue_init_qmgrs(struct knav_device *kdev,
|
|||
for_each_child_of_node(qmgrs, child) {
|
||||
qmgr = devm_kzalloc(dev, sizeof(*qmgr), GFP_KERNEL);
|
||||
if (!qmgr) {
|
||||
of_node_put(child);
|
||||
dev_err(dev, "out of memory allocating qmgr\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -1498,6 +1500,7 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
|
|||
for_each_child_of_node(pdsps, child) {
|
||||
pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL);
|
||||
if (!pdsp) {
|
||||
of_node_put(child);
|
||||
dev_err(dev, "out of memory allocating pdsp\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -535,7 +535,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
|
|||
|
||||
ret = am33xx_push_sram_idle();
|
||||
if (ret)
|
||||
goto err_free_sram;
|
||||
goto err_unsetup_rtc;
|
||||
|
||||
am33xx_pm_set_ipc_ops();
|
||||
|
||||
|
@ -575,6 +575,9 @@ static int am33xx_pm_probe(struct platform_device *pdev)
|
|||
err_pm_runtime_disable:
|
||||
pm_runtime_disable(dev);
|
||||
wkup_m3_ipc_put(m3_ipc);
|
||||
err_unsetup_rtc:
|
||||
iounmap(rtc_base_virt);
|
||||
clk_put(rtc_fck);
|
||||
err_free_sram:
|
||||
am33xx_pm_free_sram();
|
||||
pm33xx_dev = NULL;
|
||||
|
|
|
@ -161,6 +161,53 @@ static struct regmap_config regmap_conf = {
|
|||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss)
|
||||
{
|
||||
struct device_node *np = dev_of_node(dev);
|
||||
struct device_node *child;
|
||||
struct resource res;
|
||||
int ret;
|
||||
|
||||
child = of_get_child_by_name(np, "cfg");
|
||||
if (!child) {
|
||||
dev_err(dev, "%pOF is missing its 'cfg' node\n", child);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_address_to_resource(child, 0, &res)) {
|
||||
ret = -ENOMEM;
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res));
|
||||
if (!pruss->cfg_base) {
|
||||
ret = -ENOMEM;
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child,
|
||||
(u64)res.start);
|
||||
regmap_conf.max_register = resource_size(&res) - 4;
|
||||
|
||||
pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base,
|
||||
®map_conf);
|
||||
kfree(regmap_conf.name);
|
||||
if (IS_ERR(pruss->cfg_regmap)) {
|
||||
dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n",
|
||||
PTR_ERR(pruss->cfg_regmap));
|
||||
ret = PTR_ERR(pruss->cfg_regmap);
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
ret = pruss_clk_init(pruss, child);
|
||||
if (ret)
|
||||
dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret);
|
||||
|
||||
node_put:
|
||||
of_node_put(child);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pruss_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -239,56 +286,18 @@ static int pruss_probe(struct platform_device *pdev)
|
|||
goto rpm_disable;
|
||||
}
|
||||
|
||||
child = of_get_child_by_name(np, "cfg");
|
||||
if (!child) {
|
||||
dev_err(dev, "%pOF is missing its 'cfg' node\n", child);
|
||||
ret = -ENODEV;
|
||||
ret = pruss_cfg_of_init(dev, pruss);
|
||||
if (ret < 0)
|
||||
goto rpm_put;
|
||||
}
|
||||
|
||||
if (of_address_to_resource(child, 0, &res)) {
|
||||
ret = -ENOMEM;
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res));
|
||||
if (!pruss->cfg_base) {
|
||||
ret = -ENOMEM;
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child,
|
||||
(u64)res.start);
|
||||
regmap_conf.max_register = resource_size(&res) - 4;
|
||||
|
||||
pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base,
|
||||
®map_conf);
|
||||
kfree(regmap_conf.name);
|
||||
if (IS_ERR(pruss->cfg_regmap)) {
|
||||
dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n",
|
||||
PTR_ERR(pruss->cfg_regmap));
|
||||
ret = PTR_ERR(pruss->cfg_regmap);
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
ret = pruss_clk_init(pruss, child);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to setup coreclk-mux\n");
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
ret = devm_of_platform_populate(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register child devices\n");
|
||||
goto node_put;
|
||||
goto rpm_put;
|
||||
}
|
||||
|
||||
of_node_put(child);
|
||||
|
||||
return 0;
|
||||
|
||||
node_put:
|
||||
of_node_put(child);
|
||||
rpm_put:
|
||||
pm_runtime_put_sync(dev);
|
||||
rpm_disable:
|
||||
|
|
|
@ -149,8 +149,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
|
|||
*/
|
||||
optee_cq_wait_for_completion(&optee->call_queue, &w);
|
||||
} else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
|
||||
if (need_resched())
|
||||
cond_resched();
|
||||
cond_resched();
|
||||
param.a0 = res.a0;
|
||||
param.a1 = res.a1;
|
||||
param.a2 = res.a2;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright (c) 2015-2019, Linaro Limited
|
||||
* Copyright (c) 2015-2021, Linaro Limited
|
||||
*/
|
||||
#ifndef _OPTEE_MSG_H
|
||||
#define _OPTEE_MSG_H
|
||||
|
@ -12,11 +12,9 @@
|
|||
* This file defines the OP-TEE message protocol used to communicate
|
||||
* with an instance of OP-TEE running in secure world.
|
||||
*
|
||||
* This file is divided into three sections.
|
||||
* This file is divided into two sections.
|
||||
* 1. Formatting of messages.
|
||||
* 2. Requests from normal world
|
||||
* 3. Requests from secure world, Remote Procedure Call (RPC), handled by
|
||||
* tee-supplicant.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -54,8 +52,8 @@
|
|||
* Every entry in buffer should point to a 4k page beginning (12 least
|
||||
* significant bits must be equal to zero).
|
||||
*
|
||||
* 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
|
||||
* offset of the user buffer.
|
||||
* 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold
|
||||
* page offset of user buffer.
|
||||
*
|
||||
* So, entries should be placed like members of this structure:
|
||||
*
|
||||
|
@ -176,17 +174,9 @@ struct optee_msg_param {
|
|||
* @params: the parameters supplied to the OS Command
|
||||
*
|
||||
* All normal calls to Trusted OS uses this struct. If cmd requires further
|
||||
* information than what these field holds it can be passed as a parameter
|
||||
* information than what these fields hold it can be passed as a parameter
|
||||
* tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
|
||||
* attrs field). All parameters tagged as meta has to come first.
|
||||
*
|
||||
* Temp memref parameters can be fragmented if supported by the Trusted OS
|
||||
* (when optee_smc.h is bearer of this protocol this is indicated with
|
||||
* OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
|
||||
* fragmented then has all but the last fragment the
|
||||
* OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
|
||||
* it will still be presented as a single logical memref to the Trusted
|
||||
* Application.
|
||||
* attrs field). All parameters tagged as meta have to come first.
|
||||
*/
|
||||
struct optee_msg_arg {
|
||||
u32 cmd;
|
||||
|
@ -199,7 +189,7 @@ struct optee_msg_arg {
|
|||
u32 num_params;
|
||||
|
||||
/* num_params tells the actual number of element in params */
|
||||
struct optee_msg_param params[0];
|
||||
struct optee_msg_param params[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -290,15 +280,12 @@ struct optee_msg_arg {
|
|||
* OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
|
||||
* information is passed as:
|
||||
* [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
|
||||
* [| OPTEE_MSG_ATTR_FRAGMENT]
|
||||
* [| OPTEE_MSG_ATTR_NONCONTIG]
|
||||
* [in] param[0].u.tmem.buf_ptr physical address (of first fragment)
|
||||
* [in] param[0].u.tmem.size size (of first fragment)
|
||||
* [in] param[0].u.tmem.shm_ref holds shared memory reference
|
||||
* ...
|
||||
* The shared memory can optionally be fragmented, temp memrefs can follow
|
||||
* each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
|
||||
*
|
||||
* OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
|
||||
* OPTEE_MSG_CMD_UNREGISTER_SHM unregisters a previously registered shared
|
||||
* memory reference. The information is passed as:
|
||||
* [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
|
||||
* [in] param[0].u.rmem.shm_ref holds shared memory reference
|
||||
|
@ -313,131 +300,4 @@ struct optee_msg_arg {
|
|||
#define OPTEE_MSG_CMD_UNREGISTER_SHM 5
|
||||
#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
|
||||
|
||||
/*****************************************************************************
|
||||
* Part 3 - Requests from secure world, RPC
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* All RPC is done with a struct optee_msg_arg as bearer of information,
|
||||
* struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
|
||||
*
|
||||
* RPC communication with tee-supplicant is reversed compared to normal
|
||||
* client communication desribed above. The supplicant receives requests
|
||||
* and sends responses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Load a TA into memory, defined in tee-supplicant
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_LOAD_TA 0
|
||||
|
||||
/*
|
||||
* Reserved
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_RPMB 1
|
||||
|
||||
/*
|
||||
* File system access, defined in tee-supplicant
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_FS 2
|
||||
|
||||
/*
|
||||
* Get time
|
||||
*
|
||||
* Returns number of seconds and nano seconds since the Epoch,
|
||||
* 1970-01-01 00:00:00 +0000 (UTC).
|
||||
*
|
||||
* [out] param[0].u.value.a Number of seconds
|
||||
* [out] param[0].u.value.b Number of nano seconds.
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_GET_TIME 3
|
||||
|
||||
/*
|
||||
* Wait queue primitive, helper for secure world to implement a wait queue.
|
||||
*
|
||||
* If secure world need to wait for a secure world mutex it issues a sleep
|
||||
* request instead of spinning in secure world. Conversely is a wakeup
|
||||
* request issued when a secure world mutex with a thread waiting thread is
|
||||
* unlocked.
|
||||
*
|
||||
* Waiting on a key
|
||||
* [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
|
||||
* [in] param[0].u.value.b wait key
|
||||
*
|
||||
* Waking up a key
|
||||
* [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
|
||||
* [in] param[0].u.value.b wakeup key
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4
|
||||
#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
|
||||
#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1
|
||||
|
||||
/*
|
||||
* Suspend execution
|
||||
*
|
||||
* [in] param[0].value .a number of milliseconds to suspend
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_SUSPEND 5
|
||||
|
||||
/*
|
||||
* Allocate a piece of shared memory
|
||||
*
|
||||
* Shared memory can optionally be fragmented, to support that additional
|
||||
* spare param entries are allocated to make room for eventual fragments.
|
||||
* The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
|
||||
* unused. All returned temp memrefs except the last should have the
|
||||
* OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
|
||||
*
|
||||
* [in] param[0].u.value.a type of memory one of
|
||||
* OPTEE_MSG_RPC_SHM_TYPE_* below
|
||||
* [in] param[0].u.value.b requested size
|
||||
* [in] param[0].u.value.c required alignment
|
||||
*
|
||||
* [out] param[0].u.tmem.buf_ptr physical address (of first fragment)
|
||||
* [out] param[0].u.tmem.size size (of first fragment)
|
||||
* [out] param[0].u.tmem.shm_ref shared memory reference
|
||||
* ...
|
||||
* [out] param[n].u.tmem.buf_ptr physical address
|
||||
* [out] param[n].u.tmem.size size
|
||||
* [out] param[n].u.tmem.shm_ref shared memory reference (same value
|
||||
* as in param[n-1].u.tmem.shm_ref)
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6
|
||||
/* Memory that can be shared with a non-secure user space application */
|
||||
#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0
|
||||
/* Memory only shared with non-secure kernel */
|
||||
#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1
|
||||
|
||||
/*
|
||||
* Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
|
||||
*
|
||||
* [in] param[0].u.value.a type of memory one of
|
||||
* OPTEE_MSG_RPC_SHM_TYPE_* above
|
||||
* [in] param[0].u.value.b value of shared memory reference
|
||||
* returned in param[0].u.tmem.shm_ref
|
||||
* above
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_SHM_FREE 7
|
||||
|
||||
/*
|
||||
* Access a device on an i2c bus
|
||||
*
|
||||
* [in] param[0].u.value.a mode: RD(0), WR(1)
|
||||
* [in] param[0].u.value.b i2c adapter
|
||||
* [in] param[0].u.value.c i2c chip
|
||||
*
|
||||
* [in] param[1].u.value.a i2c control flags
|
||||
*
|
||||
* [in/out] memref[2] buffer to exchange the transfer data
|
||||
* with the secure world
|
||||
*
|
||||
* [out] param[3].u.value.a bytes transferred by the driver
|
||||
*/
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21
|
||||
/* I2C master transfer modes */
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1
|
||||
/* I2C master control flags */
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0)
|
||||
|
||||
#endif /* _OPTEE_MSG_H */
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (c) 2016-2021, Linaro Limited
|
||||
*/
|
||||
|
||||
#ifndef __OPTEE_RPC_CMD_H
|
||||
#define __OPTEE_RPC_CMD_H
|
||||
|
||||
/*
|
||||
* All RPC is done with a struct optee_msg_arg as bearer of information,
|
||||
* struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below.
|
||||
* Only the commands handled by the kernel driver are defined here.
|
||||
*
|
||||
* RPC communication with tee-supplicant is reversed compared to normal
|
||||
* client communication described above. The supplicant receives requests
|
||||
* and sends responses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get time
|
||||
*
|
||||
* Returns number of seconds and nano seconds since the Epoch,
|
||||
* 1970-01-01 00:00:00 +0000 (UTC).
|
||||
*
|
||||
* [out] value[0].a Number of seconds
|
||||
* [out] value[0].b Number of nano seconds.
|
||||
*/
|
||||
#define OPTEE_RPC_CMD_GET_TIME 3
|
||||
|
||||
/*
|
||||
* Wait queue primitive, helper for secure world to implement a wait queue.
|
||||
*
|
||||
* If secure world needs to wait for a secure world mutex it issues a sleep
|
||||
* request instead of spinning in secure world. Conversely is a wakeup
|
||||
* request issued when a secure world mutex with a thread waiting thread is
|
||||
* unlocked.
|
||||
*
|
||||
* Waiting on a key
|
||||
* [in] value[0].a OPTEE_RPC_WAIT_QUEUE_SLEEP
|
||||
* [in] value[0].b Wait key
|
||||
*
|
||||
* Waking up a key
|
||||
* [in] value[0].a OPTEE_RPC_WAIT_QUEUE_WAKEUP
|
||||
* [in] value[0].b Wakeup key
|
||||
*/
|
||||
#define OPTEE_RPC_CMD_WAIT_QUEUE 4
|
||||
#define OPTEE_RPC_WAIT_QUEUE_SLEEP 0
|
||||
#define OPTEE_RPC_WAIT_QUEUE_WAKEUP 1
|
||||
|
||||
/*
|
||||
* Suspend execution
|
||||
*
|
||||
* [in] value[0].a Number of milliseconds to suspend
|
||||
*/
|
||||
#define OPTEE_RPC_CMD_SUSPEND 5
|
||||
|
||||
/*
|
||||
* Allocate a piece of shared memory
|
||||
*
|
||||
* [in] value[0].a Type of memory one of
|
||||
* OPTEE_RPC_SHM_TYPE_* below
|
||||
* [in] value[0].b Requested size
|
||||
* [in] value[0].c Required alignment
|
||||
* [out] memref[0] Buffer
|
||||
*/
|
||||
#define OPTEE_RPC_CMD_SHM_ALLOC 6
|
||||
/* Memory that can be shared with a non-secure user space application */
|
||||
#define OPTEE_RPC_SHM_TYPE_APPL 0
|
||||
/* Memory only shared with non-secure kernel */
|
||||
#define OPTEE_RPC_SHM_TYPE_KERNEL 1
|
||||
|
||||
/*
|
||||
* Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC
|
||||
*
|
||||
* [in] value[0].a Type of memory one of
|
||||
* OPTEE_RPC_SHM_TYPE_* above
|
||||
* [in] value[0].b Value of shared memory reference or cookie
|
||||
*/
|
||||
#define OPTEE_RPC_CMD_SHM_FREE 7
|
||||
|
||||
/*
|
||||
* Issue master requests (read and write operations) to an I2C chip.
|
||||
*
|
||||
* [in] value[0].a Transfer mode (OPTEE_RPC_I2C_TRANSFER_*)
|
||||
* [in] value[0].b The I2C bus (a.k.a adapter).
|
||||
* 16 bit field.
|
||||
* [in] value[0].c The I2C chip (a.k.a address).
|
||||
* 16 bit field (either 7 or 10 bit effective).
|
||||
* [in] value[1].a The I2C master control flags (ie, 10 bit address).
|
||||
* 16 bit field.
|
||||
* [in/out] memref[2] Buffer used for data transfers.
|
||||
* [out] value[3].a Number of bytes transferred by the REE.
|
||||
*/
|
||||
#define OPTEE_RPC_CMD_I2C_TRANSFER 21
|
||||
|
||||
/* I2C master transfer modes */
|
||||
#define OPTEE_RPC_I2C_TRANSFER_RD 0
|
||||
#define OPTEE_RPC_I2C_TRANSFER_WR 1
|
||||
|
||||
/* I2C master control flags */
|
||||
#define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0)
|
||||
|
||||
#endif /*__OPTEE_RPC_CMD_H*/
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright (c) 2015-2019, Linaro Limited
|
||||
* Copyright (c) 2015-2021, Linaro Limited
|
||||
*/
|
||||
#ifndef OPTEE_SMC_H
|
||||
#define OPTEE_SMC_H
|
||||
|
@ -39,10 +39,10 @@
|
|||
/*
|
||||
* Function specified by SMC Calling convention
|
||||
*
|
||||
* Return one of the following UIDs if using API specified in this file
|
||||
* without further extentions:
|
||||
* 65cb6b93-af0c-4617-8ed6-644a8d1140f8
|
||||
* see also OPTEE_SMC_UID_* in optee_msg.h
|
||||
* Return the following UID if using API specified in this file
|
||||
* without further extensions:
|
||||
* 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
|
||||
* see also OPTEE_MSG_UID_* in optee_msg.h
|
||||
*/
|
||||
#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
|
||||
#define OPTEE_SMC_CALLS_UID \
|
||||
|
@ -53,7 +53,7 @@
|
|||
/*
|
||||
* Function specified by SMC Calling convention
|
||||
*
|
||||
* Returns 2.0 if using API specified in this file without further extentions.
|
||||
* Returns 2.0 if using API specified in this file without further extensions.
|
||||
* see also OPTEE_MSG_REVISION_* in optee_msg.h
|
||||
*/
|
||||
#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
|
||||
|
@ -109,8 +109,8 @@ struct optee_smc_call_get_os_revision_result {
|
|||
*
|
||||
* Call register usage:
|
||||
* a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
|
||||
* a1 Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
|
||||
* a2 Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
|
||||
* a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg
|
||||
* a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg
|
||||
* a3 Cache settings, not used if physical pointer is in a predefined shared
|
||||
* memory area else per OPTEE_SMC_SHM_*
|
||||
* a4-6 Not used
|
||||
|
@ -139,7 +139,7 @@ struct optee_smc_call_get_os_revision_result {
|
|||
* optee_msg_arg.
|
||||
* OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded,
|
||||
* try again later.
|
||||
* OPTEE_SMC_RETURN_EBADADDR Bad physcial pointer to struct
|
||||
* OPTEE_SMC_RETURN_EBADADDR Bad physical pointer to struct
|
||||
* optee_msg_arg.
|
||||
* OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg
|
||||
* OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal
|
||||
|
@ -214,8 +214,9 @@ struct optee_smc_get_shm_config_result {
|
|||
* secure world accepts command buffers located in any parts of non-secure RAM
|
||||
*/
|
||||
#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2)
|
||||
|
||||
/* Secure world supports Shared Memory with a NULL buffer reference */
|
||||
/* Secure world is built with virtualization support */
|
||||
#define OPTEE_SMC_SEC_CAP_VIRTUALIZATION BIT(3)
|
||||
/* Secure world supports Shared Memory with a NULL reference */
|
||||
#define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4)
|
||||
|
||||
#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
|
||||
|
@ -245,8 +246,8 @@ struct optee_smc_exchange_capabilities_result {
|
|||
*
|
||||
* Normal return register usage:
|
||||
* a0 OPTEE_SMC_RETURN_OK
|
||||
* a1 Upper 32bit of a 64bit Shared memory cookie
|
||||
* a2 Lower 32bit of a 64bit Shared memory cookie
|
||||
* a1 Upper 32 bits of a 64-bit Shared memory cookie
|
||||
* a2 Lower 32 bits of a 64-bit Shared memory cookie
|
||||
* a3-7 Preserved
|
||||
*
|
||||
* Cache empty return register usage:
|
||||
|
@ -293,6 +294,31 @@ struct optee_smc_disable_shm_cache_result {
|
|||
#define OPTEE_SMC_ENABLE_SHM_CACHE \
|
||||
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
|
||||
|
||||
/*
|
||||
* Query OP-TEE about number of supported threads
|
||||
*
|
||||
* Normal World OS or Hypervisor issues this call to find out how many
|
||||
* threads OP-TEE supports. That is how many standard calls can be issued
|
||||
* in parallel before OP-TEE will return OPTEE_SMC_RETURN_ETHREAD_LIMIT.
|
||||
*
|
||||
* Call requests usage:
|
||||
* a0 SMC Function ID, OPTEE_SMC_GET_THREAD_COUNT
|
||||
* a1-6 Not used
|
||||
* a7 Hypervisor Client ID register
|
||||
*
|
||||
* Normal return register usage:
|
||||
* a0 OPTEE_SMC_RETURN_OK
|
||||
* a1 Number of threads
|
||||
* a2-7 Preserved
|
||||
*
|
||||
* Error return:
|
||||
* a0 OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Requested call is not implemented
|
||||
* a1-7 Preserved
|
||||
*/
|
||||
#define OPTEE_SMC_FUNCID_GET_THREAD_COUNT 15
|
||||
#define OPTEE_SMC_GET_THREAD_COUNT \
|
||||
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT)
|
||||
|
||||
/*
|
||||
* Resume from RPC (for example after processing a foreign interrupt)
|
||||
*
|
||||
|
@ -341,16 +367,16 @@ struct optee_smc_disable_shm_cache_result {
|
|||
*
|
||||
* "Return" register usage:
|
||||
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
|
||||
* a1 Upper 32bits of 64bit physical pointer to allocated
|
||||
* a1 Upper 32 bits of 64-bit physical pointer to allocated
|
||||
* memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
|
||||
* be allocated.
|
||||
* a2 Lower 32bits of 64bit physical pointer to allocated
|
||||
* a2 Lower 32 bits of 64-bit physical pointer to allocated
|
||||
* memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
|
||||
* be allocated
|
||||
* a3 Preserved
|
||||
* a4 Upper 32bits of 64bit Shared memory cookie used when freeing
|
||||
* a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing
|
||||
* the memory or doing an RPC
|
||||
* a5 Lower 32bits of 64bit Shared memory cookie used when freeing
|
||||
* a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing
|
||||
* the memory or doing an RPC
|
||||
* a6-7 Preserved
|
||||
*/
|
||||
|
@ -363,9 +389,9 @@ struct optee_smc_disable_shm_cache_result {
|
|||
*
|
||||
* "Call" register usage:
|
||||
* a0 This value, OPTEE_SMC_RETURN_RPC_FREE
|
||||
* a1 Upper 32bits of 64bit shared memory cookie belonging to this
|
||||
* a1 Upper 32 bits of 64-bit shared memory cookie belonging to this
|
||||
* argument memory
|
||||
* a2 Lower 32bits of 64bit shared memory cookie belonging to this
|
||||
* a2 Lower 32 bits of 64-bit shared memory cookie belonging to this
|
||||
* argument memory
|
||||
* a3-7 Resume information, must be preserved
|
||||
*
|
||||
|
@ -379,7 +405,7 @@ struct optee_smc_disable_shm_cache_result {
|
|||
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
|
||||
|
||||
/*
|
||||
* Deliver foreign interrupt to normal world.
|
||||
* Deliver a foreign interrupt in normal world.
|
||||
*
|
||||
* "Call" register usage:
|
||||
* a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
|
||||
|
@ -389,7 +415,7 @@ struct optee_smc_disable_shm_cache_result {
|
|||
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
|
||||
* a1-7 Preserved
|
||||
*/
|
||||
#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
|
||||
#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
|
||||
#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
|
||||
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
|
||||
|
||||
|
@ -405,10 +431,10 @@ struct optee_smc_disable_shm_cache_result {
|
|||
*
|
||||
* "Call" register usage:
|
||||
* a0 OPTEE_SMC_RETURN_RPC_CMD
|
||||
* a1 Upper 32bit of a 64bit Shared memory cookie holding a
|
||||
* a1 Upper 32 bits of a 64-bit Shared memory cookie holding a
|
||||
* struct optee_msg_arg, must be preserved, only the data should
|
||||
* be updated
|
||||
* a2 Lower 32bit of a 64bit Shared memory cookie holding a
|
||||
* a2 Lower 32 bits of a 64-bit Shared memory cookie holding a
|
||||
* struct optee_msg_arg, must be preserved, only the data should
|
||||
* be updated
|
||||
* a3-7 Resume information, must be preserved
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/tee_drv.h>
|
||||
#include "optee_private.h"
|
||||
#include "optee_smc.h"
|
||||
#include "optee_rpc_cmd.h"
|
||||
|
||||
struct wq_entry {
|
||||
struct list_head link;
|
||||
|
@ -54,8 +55,9 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
|
|||
static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
|
||||
struct optee_msg_arg *arg)
|
||||
{
|
||||
struct i2c_client client = { 0 };
|
||||
struct tee_param *params;
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_msg msg = { };
|
||||
size_t i;
|
||||
int ret = -EOPNOTSUPP;
|
||||
u8 attr[] = {
|
||||
|
@ -85,48 +87,48 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
|
|||
goto bad;
|
||||
}
|
||||
|
||||
client.adapter = i2c_get_adapter(params[0].u.value.b);
|
||||
if (!client.adapter)
|
||||
adapter = i2c_get_adapter(params[0].u.value.b);
|
||||
if (!adapter)
|
||||
goto bad;
|
||||
|
||||
if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) {
|
||||
if (!i2c_check_functionality(client.adapter,
|
||||
if (params[1].u.value.a & OPTEE_RPC_I2C_FLAGS_TEN_BIT) {
|
||||
if (!i2c_check_functionality(adapter,
|
||||
I2C_FUNC_10BIT_ADDR)) {
|
||||
i2c_put_adapter(client.adapter);
|
||||
i2c_put_adapter(adapter);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
client.flags = I2C_CLIENT_TEN;
|
||||
msg.flags = I2C_M_TEN;
|
||||
}
|
||||
|
||||
client.addr = params[0].u.value.c;
|
||||
snprintf(client.name, I2C_NAME_SIZE, "i2c%d", client.adapter->nr);
|
||||
msg.addr = params[0].u.value.c;
|
||||
msg.buf = params[2].u.memref.shm->kaddr;
|
||||
msg.len = params[2].u.memref.size;
|
||||
|
||||
switch (params[0].u.value.a) {
|
||||
case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD:
|
||||
ret = i2c_master_recv(&client, params[2].u.memref.shm->kaddr,
|
||||
params[2].u.memref.size);
|
||||
case OPTEE_RPC_I2C_TRANSFER_RD:
|
||||
msg.flags |= I2C_M_RD;
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR:
|
||||
ret = i2c_master_send(&client, params[2].u.memref.shm->kaddr,
|
||||
params[2].u.memref.size);
|
||||
case OPTEE_RPC_I2C_TRANSFER_WR:
|
||||
break;
|
||||
default:
|
||||
i2c_put_adapter(client.adapter);
|
||||
i2c_put_adapter(adapter);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ret = i2c_transfer(adapter, &msg, 1);
|
||||
|
||||
if (ret < 0) {
|
||||
arg->ret = TEEC_ERROR_COMMUNICATION;
|
||||
} else {
|
||||
params[3].u.value.a = ret;
|
||||
params[3].u.value.a = msg.len;
|
||||
if (optee_to_msg_param(arg->params, arg->num_params, params))
|
||||
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
else
|
||||
arg->ret = TEEC_SUCCESS;
|
||||
}
|
||||
|
||||
i2c_put_adapter(client.adapter);
|
||||
i2c_put_adapter(adapter);
|
||||
kfree(params);
|
||||
return;
|
||||
bad:
|
||||
|
@ -194,10 +196,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee,
|
|||
goto bad;
|
||||
|
||||
switch (arg->params[0].u.value.a) {
|
||||
case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
|
||||
case OPTEE_RPC_WAIT_QUEUE_SLEEP:
|
||||
wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
|
||||
case OPTEE_RPC_WAIT_QUEUE_WAKEUP:
|
||||
wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
|
||||
break;
|
||||
default:
|
||||
|
@ -267,11 +269,11 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
|
|||
struct tee_shm *shm;
|
||||
|
||||
param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
|
||||
param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
|
||||
param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
|
||||
param.u.value.b = sz;
|
||||
param.u.value.c = 0;
|
||||
|
||||
ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m);
|
||||
ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m);
|
||||
if (ret)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -308,10 +310,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
|
|||
|
||||
sz = arg->params[0].u.value.b;
|
||||
switch (arg->params[0].u.value.a) {
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_APPL:
|
||||
case OPTEE_RPC_SHM_TYPE_APPL:
|
||||
shm = cmd_alloc_suppl(ctx, sz);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
|
||||
case OPTEE_RPC_SHM_TYPE_KERNEL:
|
||||
shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
|
||||
break;
|
||||
default:
|
||||
|
@ -383,7 +385,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
|
|||
struct tee_param param;
|
||||
|
||||
param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
|
||||
param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
|
||||
param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
|
||||
param.u.value.b = tee_shm_get_id(shm);
|
||||
param.u.value.c = 0;
|
||||
|
||||
|
@ -400,7 +402,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
|
|||
*/
|
||||
tee_shm_put(shm);
|
||||
|
||||
optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m);
|
||||
optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, ¶m);
|
||||
}
|
||||
|
||||
static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
|
||||
|
@ -418,10 +420,10 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
|
|||
|
||||
shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
|
||||
switch (arg->params[0].u.value.a) {
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_APPL:
|
||||
case OPTEE_RPC_SHM_TYPE_APPL:
|
||||
cmd_free_suppl(ctx, shm);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
|
||||
case OPTEE_RPC_SHM_TYPE_KERNEL:
|
||||
tee_shm_free(shm);
|
||||
break;
|
||||
default:
|
||||
|
@ -458,23 +460,23 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
|
|||
}
|
||||
|
||||
switch (arg->cmd) {
|
||||
case OPTEE_MSG_RPC_CMD_GET_TIME:
|
||||
case OPTEE_RPC_CMD_GET_TIME:
|
||||
handle_rpc_func_cmd_get_time(arg);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
|
||||
case OPTEE_RPC_CMD_WAIT_QUEUE:
|
||||
handle_rpc_func_cmd_wq(optee, arg);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_SUSPEND:
|
||||
case OPTEE_RPC_CMD_SUSPEND:
|
||||
handle_rpc_func_cmd_wait(arg);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
|
||||
case OPTEE_RPC_CMD_SHM_ALLOC:
|
||||
free_pages_list(call_ctx);
|
||||
handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_SHM_FREE:
|
||||
case OPTEE_RPC_CMD_SHM_FREE:
|
||||
handle_rpc_func_cmd_shm_free(ctx, arg);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
|
||||
case OPTEE_RPC_CMD_I2C_TRANSFER:
|
||||
handle_rpc_func_cmd_i2c_transfer(ctx, arg);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (c) 2020 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_POWER_MT8167_POWER_H
|
||||
#define _DT_BINDINGS_POWER_MT8167_POWER_H
|
||||
|
||||
#define MT8167_POWER_DOMAIN_MM 0
|
||||
#define MT8167_POWER_DOMAIN_VDEC 1
|
||||
#define MT8167_POWER_DOMAIN_ISP 2
|
||||
#define MT8167_POWER_DOMAIN_CONN 3
|
||||
#define MT8167_POWER_DOMAIN_MFG_ASYNC 4
|
||||
#define MT8167_POWER_DOMAIN_MFG_2D 5
|
||||
#define MT8167_POWER_DOMAIN_MFG 6
|
||||
|
||||
#endif /* _DT_BINDINGS_POWER_MT8167_POWER_H */
|
|
@ -94,6 +94,15 @@
|
|||
#define MSM8976_VDDMX_AO 4
|
||||
#define MSM8976_VDDMX_VFL 5
|
||||
|
||||
/* MSM8994 Power Domain Indexes */
|
||||
#define MSM8994_VDDCX 0
|
||||
#define MSM8994_VDDCX_AO 1
|
||||
#define MSM8994_VDDCX_VFC 2
|
||||
#define MSM8994_VDDMX 3
|
||||
#define MSM8994_VDDMX_AO 4
|
||||
#define MSM8994_VDDGFX 5
|
||||
#define MSM8994_VDDGFX_VFC 6
|
||||
|
||||
/* MSM8996 Power Domain Indexes */
|
||||
#define MSM8996_VDDCX 0
|
||||
#define MSM8996_VDDCX_AO 1
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later OR MIT */
|
||||
|
||||
#ifndef __DT_BINDINGS_SOC_BCM_PMB_H
|
||||
#define __DT_BINDINGS_SOC_BCM_PMB_H
|
||||
|
||||
#define BCM_PMB_PCIE0 0x01
|
||||
#define BCM_PMB_PCIE1 0x02
|
||||
#define BCM_PMB_PCIE2 0x03
|
||||
#define BCM_PMB_HOST_USB 0x04
|
||||
|
||||
#endif
|
|
@ -136,6 +136,7 @@ extern void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value);
|
|||
extern void tegra210_clk_emc_update_setting(u32 emc_src_value);
|
||||
|
||||
struct clk;
|
||||
struct tegra_emc;
|
||||
|
||||
typedef long (tegra20_clk_emc_round_cb)(unsigned long rate,
|
||||
unsigned long min_rate,
|
||||
|
@ -146,6 +147,13 @@ void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb,
|
|||
void *cb_arg);
|
||||
int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same);
|
||||
|
||||
typedef int (tegra124_emc_prepare_timing_change_cb)(struct tegra_emc *emc,
|
||||
unsigned long rate);
|
||||
typedef void (tegra124_emc_complete_timing_change_cb)(struct tegra_emc *emc,
|
||||
unsigned long rate);
|
||||
void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb,
|
||||
tegra124_emc_complete_timing_change_cb *complete_cb);
|
||||
|
||||
struct tegra210_clk_emc_config {
|
||||
unsigned long rate;
|
||||
bool same_freq;
|
||||
|
|
|
@ -696,6 +696,6 @@ int axp20x_device_probe(struct axp20x_dev *axp20x);
|
|||
*
|
||||
* This tells the axp20x core to remove the associated mfd devices
|
||||
*/
|
||||
int axp20x_device_remove(struct axp20x_dev *axp20x);
|
||||
void axp20x_device_remove(struct axp20x_dev *axp20x);
|
||||
|
||||
#endif /* __LINUX_MFD_AXP20X_H */
|
||||
|
|
|
@ -362,6 +362,25 @@ __must_check devm_reset_control_get_exclusive_released(struct device *dev,
|
|||
return __devm_reset_control_get(dev, id, 0, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_exclusive_released - resource managed
|
||||
* reset_control_get_optional_exclusive_released()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed-and-optional variant of reset_control_get_exclusive_released(). For
|
||||
* reset controllers returned from this function, reset_control_put() is called
|
||||
* automatically on driver detach.
|
||||
*
|
||||
* See reset_control_get_exclusive_released() for more information.
|
||||
*/
|
||||
static inline struct reset_control *
|
||||
__must_check devm_reset_control_get_optional_exclusive_released(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, false, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_shared - resource managed reset_control_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef __BRCMSTB_SOC_H
|
||||
#define __BRCMSTB_SOC_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
|
||||
static inline u32 BRCM_ID(u32 reg)
|
||||
{
|
||||
return reg >> 28 ? reg >> 16 : reg >> 8;
|
||||
|
@ -12,6 +14,8 @@ static inline u32 BRCM_REV(u32 reg)
|
|||
return reg & 0xff;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SOC_BRCMSTB)
|
||||
|
||||
/*
|
||||
* Helper functions for getting family or product id from the
|
||||
* SoC driver.
|
||||
|
@ -19,4 +23,16 @@ static inline u32 BRCM_REV(u32 reg)
|
|||
u32 brcmstb_get_family_id(void);
|
||||
u32 brcmstb_get_product_id(void);
|
||||
|
||||
#else
|
||||
static inline u32 brcmstb_get_family_id(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 brcmstb_get_product_id(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BRCMSTB_SOC_H */
|
||||
|
|
|
@ -123,6 +123,14 @@
|
|||
#define MT8173_TOP_AXI_PROT_EN_MFG_M1 BIT(22)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT BIT(23)
|
||||
|
||||
#define MT8167_TOP_AXI_PROT_EN_MM_EMI BIT(1)
|
||||
#define MT8167_TOP_AXI_PROT_EN_MCU_MFG BIT(2)
|
||||
#define MT8167_TOP_AXI_PROT_EN_CONN_EMI BIT(4)
|
||||
#define MT8167_TOP_AXI_PROT_EN_MFG_EMI BIT(5)
|
||||
#define MT8167_TOP_AXI_PROT_EN_CONN_MCU BIT(8)
|
||||
#define MT8167_TOP_AXI_PROT_EN_MCU_CONN BIT(9)
|
||||
#define MT8167_TOP_AXI_PROT_EN_MCU_MM BIT(11)
|
||||
|
||||
#define MT2701_TOP_AXI_PROT_EN_MM_M0 BIT(1)
|
||||
#define MT2701_TOP_AXI_PROT_EN_CONN_M BIT(2)
|
||||
#define MT2701_TOP_AXI_PROT_EN_CONN_S BIT(8)
|
||||
|
|
|
@ -280,16 +280,4 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt);
|
|||
int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* cmdq_pkt_flush() - trigger CMDQ to execute the CMDQ packet
|
||||
* @pkt: the CMDQ packet
|
||||
*
|
||||
* Return: 0 for success; else the error code is returned
|
||||
*
|
||||
* Trigger CMDQ to execute the CMDQ packet. Note that this is a
|
||||
* synchronous flush function. When the function returned, the recorded
|
||||
* commands have been done.
|
||||
*/
|
||||
int cmdq_pkt_flush(struct cmdq_pkt *pkt);
|
||||
|
||||
#endif /* __MTK_CMDQ_H__ */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define LLCC_AUDHW 22
|
||||
#define LLCC_NPU 23
|
||||
#define LLCC_WLHW 24
|
||||
#define LLCC_CVP 28
|
||||
#define LLCC_MODPE 29
|
||||
#define LLCC_APTCM 30
|
||||
#define LLCC_WRCACHE 31
|
||||
|
@ -79,6 +80,7 @@ struct llcc_edac_reg_data {
|
|||
* @bitmap: Bit map to track the active slice ids
|
||||
* @offsets: Pointer to the bank offsets array
|
||||
* @ecc_irq: interrupt for llcc cache error detection and reporting
|
||||
* @major_version: Indicates the LLCC major version
|
||||
*/
|
||||
struct llcc_drv_data {
|
||||
struct regmap *regmap;
|
||||
|
@ -91,6 +93,7 @@ struct llcc_drv_data {
|
|||
unsigned long *bitmap;
|
||||
u32 *offsets;
|
||||
int ecc_irq;
|
||||
u32 major_version;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_LLCC)
|
||||
|
|
|
@ -59,7 +59,7 @@ static inline void sunxi_rsb_device_set_drvdata(struct sunxi_rsb_device *rdev,
|
|||
struct sunxi_rsb_driver {
|
||||
struct device_driver driver;
|
||||
int (*probe)(struct sunxi_rsb_device *rdev);
|
||||
int (*remove)(struct sunxi_rsb_device *rdev);
|
||||
void (*remove)(struct sunxi_rsb_device *rdev);
|
||||
};
|
||||
|
||||
static inline struct sunxi_rsb_driver *to_sunxi_rsb_driver(struct device_driver *d)
|
||||
|
|
|
@ -88,7 +88,7 @@ struct tee_param {
|
|||
* @close_session: close a session
|
||||
* @invoke_func: invoke a trusted function
|
||||
* @cancel_req: request cancel of an ongoing invoke or open
|
||||
* @supp_revc: called for supplicant to get a command
|
||||
* @supp_recv: called for supplicant to get a command
|
||||
* @supp_send: called for supplicant to send a response
|
||||
* @shm_register: register shared memory buffer in TEE
|
||||
* @shm_unregister: unregister shared memory buffer in TEE
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright © 2014 NVIDIA Corporation
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*/
|
||||
|
||||
#ifndef __SOC_BRCMSTB_COMMON_H__
|
||||
#define __SOC_BRCMSTB_COMMON_H__
|
||||
|
||||
bool soc_is_brcmstb(void);
|
||||
|
||||
#endif /* __SOC_BRCMSTB_COMMON_H__ */
|
|
@ -9,7 +9,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#ifdef CONFIG_MTK_SMI
|
||||
#if IS_ENABLED(CONFIG_MTK_SMI)
|
||||
|
||||
#define MTK_LARB_NR_MAX 16
|
||||
|
||||
|
|
|
@ -30,7 +30,13 @@ enum rpmh_state {
|
|||
*
|
||||
* @addr: the address of the resource slv_id:18:16 | offset:0:15
|
||||
* @data: the resource state request
|
||||
* @wait: wait for this request to be complete before sending the next
|
||||
* @wait: ensure that this command is complete before returning.
|
||||
* Setting "wait" here only makes sense during rpmh_write_batch() for
|
||||
* active-only transfers, this is because:
|
||||
* rpmh_write() - Always waits.
|
||||
* (DEFINE_RPMH_MSG_ONSTACK will set .wait_for_compl)
|
||||
* rpmh_write_async() - Never waits.
|
||||
* (There's no request completion callback)
|
||||
*/
|
||||
struct tcs_cmd {
|
||||
u32 addr;
|
||||
|
@ -43,6 +49,7 @@ struct tcs_cmd {
|
|||
*
|
||||
* @state: state for the request.
|
||||
* @wait_for_compl: wait until we get a response from the h/w accelerator
|
||||
* (same as setting cmd->wait for all commands in the request)
|
||||
* @num_cmds: the number of @cmds in this request
|
||||
* @cmds: an array of tcs_cmds
|
||||
*/
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014 NVIDIA Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_TEGRA_EMC_H__
|
||||
#define __SOC_TEGRA_EMC_H__
|
||||
|
||||
struct tegra_emc;
|
||||
|
||||
int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate);
|
||||
void tegra_emc_complete_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate);
|
||||
|
||||
#endif /* __SOC_TEGRA_EMC_H__ */
|
|
@ -355,7 +355,7 @@ struct tee_iocl_supp_send_arg {
|
|||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function
|
||||
* TEE_IOC_SUPPL_SEND - Send a response to a received request
|
||||
*
|
||||
* Takes a struct tee_ioctl_buf_data which contains a struct
|
||||
* tee_iocl_supp_send_arg followed by any array of struct tee_param
|
||||
|
|
Loading…
Reference in New Issue