Commit 47b62edc authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm-drivers-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull ARM SoC drivers from Arnd Bergmann:
 "The SoC driver updates contain changes to improve support for
  additional SoC variants, as well as cleanups an minor bugfixes
  in a number of existing drivers.

  Notable updates this time include:

   - Support for Qualcomm MSM8909 (Snapdragon 210) in various drivers

   - Updates for interconnect drivers on Qualcomm Snapdragon

   - A new driver support for NMI interrupts on Fujitsu A64fx

   - A rework of Broadcom BCMBCA Kconfig dependencies

   - Improved support for BCM2711 (Raspberry Pi 4) power management to
     allow the use of the V3D GPU

   - Cleanups to the NXP guts driver

   - Arm SCMI firmware driver updates to add tracing support, and use
     the firmware interfaces for system power control and for power
     capping"

* tag 'arm-drivers-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (125 commits)
  soc: a64fx-diag: disable modular build
  dt-bindings: soc: qcom: qcom,smd-rpm: add power-controller
  dt-bindings: soc: qcom: aoss: document qcom,sm8450-aoss-qmp
  dt-bindings: soc: qcom,rpmh-rsc: simplify qcom,tcs-config
  ARM: mach-qcom: Add support for MSM8909
  dt-bindings: arm: cpus: Document "qcom,msm8909-smp" enable-method
  soc: qcom: spm: Add CPU data for MSM8909
  dt-bindings: soc: qcom: spm: Add MSM8909 CPU compatible
  soc: qcom: rpmpd: Add compatible for MSM8909
  dt-bindings: power: qcom-rpmpd: Add MSM8909 power domains
  soc: qcom: smd-rpm: Add compatible for MSM8909
  dt-bindings: soc: qcom: smd-rpm: Add MSM8909
  soc: qcom: icc-bwmon: Remove unnecessary print function dev_err()
  soc: fujitsu: Add A64FX diagnostic interrupt driver
  soc: qcom: socinfo: Fix the id of SA8540P SoC
  soc: qcom: Make QCOM_RPMPD depend on PM
  tty: serial: bcm63xx: bcmbca: Replace ARCH_BCM_63XX with ARCH_BCMBCA
  spi: bcm63xx-hsspi: bcmbca: Replace ARCH_BCM_63XX with ARCH_BCMBCA
  clk: bcm: bcmbca: Replace ARCH_BCM_63XX with ARCH_BCMBCA
  hwrng: bcm2835: bcmbca: Replace ARCH_BCM_63XX with ARCH_BCMBCA
  ...
parents e233cc59 99978d2f
......@@ -221,6 +221,7 @@ properties:
- qcom,kpss-acc-v1
- qcom,kpss-acc-v2
- qcom,msm8226-smp
- qcom,msm8909-smp
# Only valid on ARM 32-bit, see above for ARM v8 64-bit
- qcom,msm8916-smp
- renesas,apmu
......
......@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: QCOM device tree bindings
maintainers:
- Stephen Boyd <sboyd@codeaurora.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
Some qcom based bootloaders identify the dtb blob based on a set of
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/arm/tegra/nvidia,tegra194-axi2apb.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: NVIDIA Tegra194 AXI2APB bridge
maintainers:
- Sumit Gupta <sumitg@nvidia.com>
properties:
$nodename:
pattern: "^axi2apb@([0-9a-f]+)$"
compatible:
enum:
- nvidia,tegra194-axi2apb
reg:
maxItems: 6
description: Physical base address and length of registers for all bridges
additionalProperties: false
required:
- compatible
- reg
examples:
- |
axi2apb: axi2apb@2390000 {
compatible = "nvidia,tegra194-axi2apb";
reg = <0x02390000 0x1000>,
<0x023a0000 0x1000>,
<0x023b0000 0x1000>,
<0x023c0000 0x1000>,
<0x023d0000 0x1000>,
<0x023e0000 0x1000>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/arm/tegra/nvidia,tegra194-cbb.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: NVIDIA Tegra194 CBB 1.0 bindings
maintainers:
- Sumit Gupta <sumitg@nvidia.com>
description: |+
The Control Backbone (CBB) is comprised of the physical path from an
initiator to a target's register configuration space. CBB 1.0 has
multiple hierarchical sub-NOCs (Network-on-Chip) and connects various
initiators and targets using different bridges like AXIP2P, AXI2APB.
This driver handles errors due to illegal register accesses reported
by the NOCs inside the CBB. NOCs reporting errors are cluster NOCs
"AON-NOC, SCE-NOC, RCE-NOC, BPMP-NOC, CV-NOC" and "CBB Central NOC"
which is the main NOC.
By default, the access issuing initiator is informed about the error
using SError or Data Abort exception unless the ERD (Error Response
Disable) is enabled/set for that initiator. If the ERD is enabled, then
SError or Data Abort is masked and the error is reported with interrupt.
- For CCPLEX (CPU Complex) initiator, the driver sets ERD bit. So, the
errors due to illegal accesses from CCPLEX are reported by interrupts.
If ERD is not set, then error is reported by SError.
- For other initiators, the ERD is disabled. So, the access issuing
initiator is informed about the illegal access by Data Abort exception.
In addition, an interrupt is also generated to CCPLEX. These initiators
include all engines using Cortex-R5 (which is ARMv7 CPU cluster) and
engines like TSEC (Security co-processor), NVDEC (NVIDIA Video Decoder
engine) etc which can initiate transactions.
The driver prints relevant debug information like Error Code, Error
Description, Master, Address, AXI ID, Cache, Protection, Security Group
etc on receiving error notification.
properties:
$nodename:
pattern: "^[a-z]+-noc@[0-9a-f]+$"
compatible:
enum:
- nvidia,tegra194-cbb-noc
- nvidia,tegra194-aon-noc
- nvidia,tegra194-bpmp-noc
- nvidia,tegra194-rce-noc
- nvidia,tegra194-sce-noc
reg:
maxItems: 1
interrupts:
description:
CCPLEX receives secure or nonsecure interrupt depending on error type.
A secure interrupt is received for SEC(firewall) & SLV errors and a
non-secure interrupt is received for TMO & DEC errors.
items:
- description: non-secure interrupt
- description: secure interrupt
nvidia,axi2apb:
$ref: '/schemas/types.yaml#/definitions/phandle'
description:
Specifies the node having all axi2apb bridges which need to be checked
for any error logged in their status register.
nvidia,apbmisc:
$ref: '/schemas/types.yaml#/definitions/phandle'
description:
Specifies the apbmisc node which need to be used for reading the ERD
register.
additionalProperties: false
required:
- compatible
- reg
- interrupts
- nvidia,apbmisc
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
cbb-noc@2300000 {
compatible = "nvidia,tegra194-cbb-noc";
reg = <0x02300000 0x1000>;
interrupts = <GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>;
nvidia,axi2apb = <&axi2apb>;
nvidia,apbmisc = <&apbmisc>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/arm/tegra/nvidia,tegra234-cbb.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: NVIDIA Tegra CBB 2.0 bindings
maintainers:
- Sumit Gupta <sumitg@nvidia.com>
description: |+
The Control Backbone (CBB) is comprised of the physical path from an
initiator to a target's register configuration space. CBB 2.0 consists
of multiple sub-blocks connected to each other to create a topology.
The Tegra234 SoC has different fabrics based on CBB 2.0 architecture
which include cluster fabrics BPMP, AON, PSC, SCE, RCE, DCE, FSI and
"CBB central fabric".
In CBB 2.0, each initiator which can issue transactions connects to a
Root Master Node (MN) before it connects to any other element of the
fabric. Each Root MN contains a Error Monitor (EM) which detects and
logs error. Interrupts from various EM blocks are collated by Error
Notifier (EN) which is per fabric and presents a single interrupt from
fabric to the SoC interrupt controller.
The driver handles errors from CBB due to illegal register accesses
and prints debug information about failed transaction on receiving
the interrupt from EN. Debug information includes Error Code, Error
Description, MasterID, Fabric, SlaveID, Address, Cache, Protection,
Security Group etc on receiving error notification.
If the Error Response Disable (ERD) is set/enabled for an initiator,
then SError or Data abort exception error response is masked and an
interrupt is used for reporting errors due to illegal accesses from
that initiator. The value returned on read failures is '0xFFFFFFFF'
for compatibility with PCIE.
properties:
$nodename:
pattern: "^[a-z]+-fabric@[0-9a-f]+$"
compatible:
enum:
- nvidia,tegra234-aon-fabric
- nvidia,tegra234-bpmp-fabric
- nvidia,tegra234-cbb-fabric
- nvidia,tegra234-dce-fabric
- nvidia,tegra234-rce-fabric
- nvidia,tegra234-sce-fabric
reg:
maxItems: 1
interrupts:
items:
- description: secure interrupt from error notifier
additionalProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
cbb-fabric@1300000 {
compatible = "nvidia,tegra234-cbb-fabric";
reg = <0x13a00000 0x400000>;
interrupts = <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -183,6 +183,12 @@ properties:
required:
- reg
protocol@18:
type: object
properties:
reg:
const: 0x18
additionalProperties: false
patternProperties:
......@@ -323,6 +329,10 @@ examples:
};
};
};
scmi_powercap: protocol@18 {
reg = <0x18>;
};
};
};
......
......@@ -23,10 +23,13 @@ Required properties:
* "qcom,scm-msm8994"
* "qcom,scm-msm8996"
* "qcom,scm-msm8998"
* "qcom,scm-qcs404"
* "qcom,scm-sc7180"
* "qcom,scm-sc7280"
* "qcom,scm-sm6125"
* "qcom,scm-sdm845"
* "qcom,scm-sdx55"
* "qcom,scm-sdx65"
* "qcom,scm-sm6350"
* "qcom,scm-sm8150"
* "qcom,scm-sm8250"
......@@ -43,6 +46,7 @@ Required properties:
clock and "bus" for the bus clock per the requirements of the compatible.
- qcom,dload-mode: phandle to the TCSR hardware block and offset of the
download mode control register (optional)
- interconnects: Specifies the bandwidth requirements of the SCM interface (optional)
Example for MSM8916:
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/interconnect/qcom,msm8998-bwmon.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Interconnect Bandwidth Monitor
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
description: |
Bandwidth Monitor measures current throughput on buses between various NoC
fabrics and provides information when it crosses configured thresholds.
Certain SoCs might have more than one Bandwidth Monitors, for example on SDM845::
- Measuring the bandwidth between CPUs and Last Level Cache Controller -
called just BWMON,
- Measuring the bandwidth between Last Level Cache Controller and memory
(DDR) - called LLCC BWMON.
properties:
compatible:
oneOf:
- items:
- enum:
- qcom,sdm845-bwmon
- const: qcom,msm8998-bwmon
- const: qcom,msm8998-bwmon # BWMON v4
interconnects:
maxItems: 1
interrupts:
maxItems: 1
operating-points-v2: true
opp-table: true
reg:
# BWMON v4 (currently described) and BWMON v5 use one register address
# space. BWMON v2 uses two register spaces - not yet described.
maxItems: 1
required:
- compatible
- interconnects
- interrupts
- operating-points-v2
- opp-table
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/interconnect/qcom,sdm845.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
pmu@1436400 {
compatible = "qcom,sdm845-bwmon", "qcom,msm8998-bwmon";
reg = <0x01436400 0x600>;
interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_LLCC 3>;
operating-points-v2 = <&cpu_bwmon_opp_table>;
cpu_bwmon_opp_table: opp-table {
compatible = "operating-points-v2";
opp-0 {
opp-peak-kBps = <4800000>;
};
opp-1 {
opp-peak-kBps = <9216000>;
};
opp-2 {
opp-peak-kBps = <15052800>;
};
opp-3 {
opp-peak-kBps = <20889600>;
};
opp-4 {
opp-peak-kBps = <25497600>;
};
};
};
......@@ -32,6 +32,7 @@ properties:
- mediatek,mt2701-smi-common
- mediatek,mt2712-smi-common
- mediatek,mt6779-smi-common
- mediatek,mt6795-smi-common
- mediatek,mt8167-smi-common
- mediatek,mt8173-smi-common
- mediatek,mt8183-smi-common
......
......@@ -20,6 +20,7 @@ properties:
- mediatek,mt2701-smi-larb
- mediatek,mt2712-smi-larb
- mediatek,mt6779-smi-larb
- mediatek,mt6795-smi-larb
- mediatek,mt8167-smi-larb
- mediatek,mt8173-smi-larb
- mediatek,mt8183-smi-larb
......
......@@ -23,6 +23,7 @@ properties:
compatible:
enum:
- mediatek,mt6795-power-controller
- mediatek,mt8167-power-controller
- mediatek,mt8173-power-controller
- mediatek,mt8183-power-controller
......@@ -62,6 +63,7 @@ patternProperties:
reg:
description: |
Power domain index. Valid values are defined in:
"include/dt-bindings/power/mt6795-power.h" - for MT8167 type power domain.
"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.
......
......@@ -18,6 +18,7 @@ properties:
enum:
- qcom,mdm9607-rpmpd
- qcom,msm8226-rpmpd
- qcom,msm8909-rpmpd
- qcom,msm8916-rpmpd
- qcom,msm8939-rpmpd
- qcom,msm8953-rpmpd
......
......@@ -20,6 +20,7 @@ properties:
compatible:
enum:
- mediatek,mt6779-devapc
- mediatek,mt8186-devapc
reg:
description: The base address of devapc register bank
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/mediatek/mediatek,mutex.yaml#
$id: http://devicetree.org/schemas/soc/mediatek/mediatek,mutex.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek mutex
......@@ -55,6 +55,18 @@ properties:
include/dt-bindings/gce/<chip>-gce.h of each chips.
$ref: /schemas/types.yaml#/definitions/uint32-array
mediatek,gce-client-reg:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
items:
- description: phandle of GCE
- description: GCE subsys id
- description: register offset
- description: register size
description: The register of client driver can be configured by gce with
4 arguments defined in this property. Each GCE subsys id is mapping to
a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
required:
- compatible
- reg
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/mediatek/mtk-svs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek Smart Voltage Scaling (SVS) Device Tree Bindings
maintainers:
- Roger Lu <roger.lu@mediatek.com>
- Matthias Brugger <matthias.bgg@gmail.com>
- Kevin Hilman <khilman@kernel.org>
description: |+
The SVS engine is a piece of hardware which has several
controllers(banks) for calculating suitable voltage to
different power domains(CPU/GPU/CCI) according to
chip process corner, temperatures and other factors. Then DVFS
driver could apply SVS bank voltage to PMIC/Buck.
properties:
compatible:
enum:
- mediatek,mt8183-svs
- mediatek,mt8192-svs
reg:
maxItems: 1
description: Address range of the MTK SVS controller.
interrupts:
maxItems: 1
clocks:
maxItems: 1
description: Main clock for MTK SVS controller to work.
clock-names:
const: main
nvmem-cells:
minItems: 1
description:
Phandle to the calibration data provided by a nvmem device.
items:
- description: SVS efuse for SVS controller
- description: Thermal efuse for SVS controller
nvmem-cell-names:
items:
- const: svs-calibration-data
- const: t-calibration-data
resets:
maxItems: 1
reset-names:
items:
- const: svs_rst
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- nvmem-cells
- nvmem-cell-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8183-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
svs@1100b000 {
compatible = "mediatek,mt8183-svs";
reg = <0 0x1100b000 0 0x1000>;
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg CLK_INFRA_THERM>;
clock-names = "main";
nvmem-cells = <&svs_calibration>, <&thermal_calibration>;
nvmem-cell-names = "svs-calibration-data", "t-calibration-data";
};
};
......@@ -33,6 +33,7 @@ properties:
- qcom,sm8150-aoss-qmp
- qcom,sm8250-aoss-qmp
- qcom,sm8350-aoss-qmp
- qcom,sm8450-aoss-qmp
- const: qcom,aoss-qmp
reg:
......
......@@ -65,33 +65,22 @@ properties:
qcom,tcs-config:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
minItems: 4
maxItems: 4
items:
- items:
- description: TCS type
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
- items:
- description: TCS type
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
- items:
- description: TCS type
enum: [ 0, 1, 2, 3]
- description: Numbe r of TCS
- items:
- description: TCS type
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
items:
- description: |
TCS type::
- ACTIVE_TCS
- SLEEP_TCS
- WAKE_TCS
- CONTROL_TCS
enum: [ 0, 1, 2, 3 ]
- description: Number of TCS
description: |
The tuple defining the configuration of TCS. Must have two cells which
describe each TCS type. The order of the TCS must match the hardware
configuration.
Cell 1 (TCS Type):: TCS types to be specified::
- ACTIVE_TCS
- SLEEP_TCS
- WAKE_TCS
- CONTROL_TCS
Cell 2 (Number of TCS):: <u32>
qcom,tcs-offset:
$ref: /schemas/types.yaml#/definitions/uint32
......
......@@ -34,6 +34,7 @@ properties:
- qcom,rpm-apq8084
- qcom,rpm-ipq6018
- qcom,rpm-msm8226
- qcom,rpm-msm8909
- qcom,rpm-msm8916
- qcom,rpm-msm8936
- qcom,rpm-msm8953
......@@ -51,6 +52,9 @@ properties:
$ref: /schemas/clock/qcom,rpmcc.yaml#
unevaluatedProperties: false
power-controller:
$ref: /schemas/power/qcom,rpmpd.yaml#
qcom,smd-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the RPM communication
......
......@@ -22,6 +22,7 @@ properties:
- qcom,sdm660-silver-saw2-v4.1-l2
- qcom,msm8998-gold-saw2-v4.1-l2
- qcom,msm8998-silver-saw2-v4.1-l2
- qcom,msm8909-saw2-v3.0-cpu
- qcom,msm8916-saw2-v3.0-cpu
- qcom,msm8226-saw2-v2.1-cpu
- qcom,msm8974-saw2-v2.1-cpu
......
......@@ -77,7 +77,6 @@ properties:
Should reference the tx-enable and tx-rings-empty SMEM states.
qcom,smem-state-names:
$ref: /schemas/types.yaml#/definitions/string-array
items:
- const: tx-enable
- const: tx-rings-empty
......
......@@ -65,10 +65,11 @@ properties:
- ti,am4376-pruss0 # for AM437x SoC family and PRUSS unit 0
- ti,am4376-pruss1 # for AM437x SoC family and PRUSS unit 1
- ti,am5728-pruss # for AM57xx SoC family
- ti,k2g-pruss # for 66AK2G SoC family
- ti,am625-pruss # for K3 AM62x SoC family
- ti,am642-icssg # for K3 AM64x SoC family
- ti,am654-icssg # for K3 AM65x SoC family
- ti,j721e-icssg # for K3 J721E SoC family
- ti,am642-icssg # for K3 AM64x SoC family
- ti,k2g-pruss # for 66AK2G SoC family
reg:
maxItems: 1
......
......@@ -242,6 +242,11 @@ F: include/trace/events/9p.h
F: include/uapi/linux/virtio_9p.h
F: net/9p/
A64FX DIAG DRIVER
M: Hitomi Hasegawa <hasegawa-hitomi@fujitsu.com>
S: Supported
F: drivers/soc/fujitsu/a64fx-diag.c
A8293 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
......@@ -16674,6 +16679,13 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
F: drivers/i2c/busses/i2c-qcom-cci.c
QUALCOMM INTERCONNECT BWMON DRIVER
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
F: drivers/soc/qcom/icc-bwmon.c
QUALCOMM IOMMU
M: Rob Clark <robdclark@gmail.com>
L: iommu@lists.linux.dev
......
......@@ -20,6 +20,10 @@ config ARCH_MSM8X60
bool "Enable support for MSM8X60"
select CLKSRC_QCOM
config ARCH_MSM8909
bool "Enable support for MSM8909"
select HAVE_ARM_ARCH_TIMER
config ARCH_MSM8916
bool "Enable support for MSM8916"
select HAVE_ARM_ARCH_TIMER
......
......@@ -384,6 +384,7 @@ static const struct smp_operations qcom_smp_cortex_a7_ops __initconst = {
#endif
};
CPU_METHOD_OF_DECLARE(qcom_smp_msm8226, "qcom,msm8226-smp", &qcom_smp_cortex_a7_ops);
CPU_METHOD_OF_DECLARE(qcom_smp_msm8909, "qcom,msm8909-smp", &qcom_smp_cortex_a7_ops);
CPU_METHOD_OF_DECLARE(qcom_smp_msm8916, "qcom,msm8916-smp", &qcom_smp_cortex_a7_ops);
static const struct smp_operations qcom_smp_kpssv1_ops __initconst = {
......
......@@ -148,7 +148,7 @@ config SATA_AHCI_PLATFORM
config AHCI_BRCM
tristate "Broadcom AHCI SATA support"
depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM_NSP || \
ARCH_BCM_63XX || COMPILE_TEST
ARCH_BCMBCA || COMPILE_TEST
select SATA_HOST
help
This option enables support for the AHCI SATA3 controller found on
......
......@@ -87,7 +87,7 @@ config HW_RANDOM_BA431
config HW_RANDOM_BCM2835
tristate "Broadcom BCM2835/BCM63xx Random Number Generator support"
depends on ARCH_BCM2835 || ARCH_BCM_NSP || ARCH_BCM_5301X || \
ARCH_BCM_63XX || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
default HW_RANDOM
help
This driver provides kernel-side support for the Random Number
......
......@@ -22,9 +22,9 @@ config CLK_BCM2835
config CLK_BCM_63XX
bool "Broadcom BCM63xx clock support"
depends on ARCH_BCM_63XX || COMPILE_TEST
depends on ARCH_BCMBCA || COMPILE_TEST
select COMMON_CLK_IPROC
default ARCH_BCM_63XX
default ARCH_BCMBCA
help
Enable common clock framework support for Broadcom BCM63xx DSL SoCs
based on the ARM architecture
......
......@@ -149,4 +149,16 @@ config ARM_SCMI_POWER_DOMAIN
will be called scmi_pm_domain. Note this may needed early in boot
before rootfs may be available.
config ARM_SCMI_POWER_CONTROL
tristate "SCMI system power control driver"
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
help
This enables System Power control logic which binds system shutdown or
reboot actions to SCMI System Power notifications generated by SCP
firmware.
This driver can also be built as a module. If so, the module will be
called scmi_power_control. Note this may needed early in boot to catch
early shutdown/reboot SCMI requests.
endmenu
......@@ -7,11 +7,12 @@ scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o
scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o powercap.o
scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \
$(scmi-transport-y)
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
......
This diff is collapsed.
......@@ -10,13 +10,14 @@
#include <linux/bits.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/scmi_protocol.h>
#include <linux/sort.h>
#include <trace/events/scmi.h>
#include "protocols.h"
#include "notify.h"
......@@ -35,6 +36,12 @@ enum scmi_performance_protocol_cmd {
PERF_DOMAIN_NAME_GET = 0xc,
};
enum {
PERF_FC_LEVEL,
PERF_FC_LIMIT,
PERF_FC_MAX,
};
struct scmi_opp {
u32 perf;
u32 power;
......@@ -115,43 +122,6 @@ struct scmi_msg_resp_perf_describe_levels {
} opp[];
};
struct scmi_perf_get_fc_info {
__le32 domain;
__le32 message_id;
};
struct scmi_msg_resp_perf_desc_fc {
__le32 attr;
#define SUPPORTS_DOORBELL(x) ((x) & BIT(0))
#define DOORBELL_REG_WIDTH(x) FIELD_GET(GENMASK(2, 1), (x))
__le32 rate_limit;
__le32 chan_addr_low;
__le32 chan_addr_high;
__le32 chan_size;
__le32 db_addr_low;
__le32 db_addr_high;
__le32 db_set_lmask;
__le32 db_set_hmask;
__le32 db_preserve_lmask;
__le32 db_preserve_hmask;
};
struct scmi_fc_db_info {
int width;
u64 set;
u64 mask;
void __iomem *addr;
};
struct scmi_fc_info {
void __iomem *level_set_addr;
void __iomem *limit_set_addr;
void __iomem *level_get_addr;
void __iomem *limit_get_addr;
struct scmi_fc_db_info *level_set_db;
struct scmi_fc_db_info *limit_set_db;
};
struct perf_dom_info {
bool set_limits;
bool set_perf;
......@@ -360,40 +330,6 @@ scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain,
return ret;
}
#define SCMI_PERF_FC_RING_DB(w) \
do { \
u##w val = 0; \
\
if (db->mask) \
val = ioread##w(db->addr) & db->mask; \
iowrite##w((u##w)db->set | val, db->addr); \
} while (0)
static void scmi_perf_fc_ring_db(struct scmi_fc_db_info *db)
{
if (!db || !db->addr)
return;
if (db->width == 1)
SCMI_PERF_FC_RING_DB(8);
else if (db->width == 2)
SCMI_PERF_FC_RING_DB(16);
else if (db->width == 4)
SCMI_PERF_FC_RING_DB(32);
else /* db->width == 8 */
#ifdef CONFIG_64BIT
SCMI_PERF_FC_RING_DB(64);
#else
{
u64 val = 0;
if (db->mask)
val = ioread64_hi_lo(db->addr) & db->mask;
iowrite64_hi_lo(db->set | val, db->addr);
}
#endif
}
static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
u32 domain, u32 max_perf, u32 min_perf)
{
......@@ -426,10 +362,14 @@ static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf)
return -EINVAL;
if (dom->fc_info && dom->fc_info->limit_set_addr) {
iowrite32(max_perf, dom->fc_info->limit_set_addr);
iowrite32(min_perf, dom->fc_info->limit_set_addr + 4);
scmi_perf_fc_ring_db(dom->fc_info->limit_set_db);
if (dom->fc_info && dom->fc_info[PERF_FC_LIMIT].set_addr) {
struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT];
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LIMITS_SET,
domain, min_perf, max_perf);
iowrite32(max_perf, fci->set_addr);
iowrite32(min_perf, fci->set_addr + 4);
ph->hops->fastchannel_db_ring(fci->set_db);
return 0;
}
......@@ -468,9 +408,13 @@ static int scmi_perf_limits_get(const struct scmi_protocol_handle *ph,
struct scmi_perf_info *pi = ph->get_priv(ph);
struct perf_dom_info *dom = pi->dom_info + domain;
if (dom->fc_info && dom->fc_info->limit_get_addr) {
*max_perf = ioread32(dom->fc_info->limit_get_addr);
*min_perf = ioread32(dom->fc_info->limit_get_addr + 4);
if (dom->fc_info && dom->fc_info[PERF_FC_LIMIT].get_addr) {
struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT];
*max_perf = ioread32(fci->get_addr);
*min_perf = ioread32(fci->get_addr + 4);
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LIMITS_GET,
domain, *min_perf, *max_perf);
return 0;
}
......@@ -505,9 +449,13 @@ static int scmi_perf_level_set(const struct scmi_protocol_handle *ph,
struct scmi_perf_info *pi = ph->get_priv(ph);
struct perf_dom_info *dom = pi->dom_info + domain;
if (dom->fc_info && dom->fc_info->level_set_addr) {
iowrite32(level, dom->fc_info->level_set_addr);
scmi_perf_fc_ring_db(dom->fc_info->level_set_db);
if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr) {
struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LEVEL];
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LEVEL_SET,
domain, level, 0);
iowrite32(level, fci->set_addr);
ph->hops->fastchannel_db_ring(fci->set_db);
return 0;
}
......@@ -542,8 +490,10 @@ static int scmi_perf_level_get(const struct scmi_protocol_handle *ph,
struct scmi_perf_info *pi = ph->get_priv(ph);
struct perf_dom_info *dom = pi->dom_info + domain;
if (dom->fc_info && dom->fc_info->level_get_addr) {
*level = ioread32(dom->fc_info->level_get_addr);
if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].get_addr) {
*level = ioread32(dom->fc_info[PERF_FC_LEVEL].get_addr);
trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LEVEL_GET,
domain, *level, 0);
return 0;
}
......@@ -572,100 +522,33 @@ static int scmi_perf_level_limits_notify(const struct scmi_protocol_handle *ph,
return ret;
}
static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size)
{
if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4)
return true;
if ((msg == PERF_LIMITS_GET || msg == PERF_LIMITS_SET) && size == 8)
return true;
return false;
}
static void
scmi_perf_domain_desc_fc(const struct scmi_protocol_handle *ph, u32 domain,
u32 message_id, void __iomem **p_addr,
struct scmi_fc_db_info **p_db)
{
int ret;
u32 flags;
u64 phys_addr;
u8 size;
void __iomem *addr;
struct scmi_xfer *t;
struct scmi_fc_db_info *db;
struct scmi_perf_get_fc_info *info;
struct scmi_msg_resp_perf_desc_fc *resp;
if (!p_addr)
return;
ret = ph->xops->xfer_get_init(ph, PERF_DESCRIBE_FASTCHANNEL,
sizeof(*info), sizeof(*resp), &t);
if (ret)
return;
info = t->tx.buf;
info->domain = cpu_to_le32(domain);
info->message_id = cpu_to_le32(message_id);
ret = ph->xops->do_xfer(ph, t);
if (ret)
goto err_xfer;
resp = t->rx.buf;
flags = le32_to_cpu(resp->attr);
size = le32_to_cpu(resp->chan_size);
if (!scmi_perf_fc_size_is_valid(message_id, size))
goto err_xfer;
phys_addr = le32_to_cpu(resp->chan_addr_low);
phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32;
addr = devm_ioremap(ph->dev, phys_addr, size);
if (!addr)
goto err_xfer;
*p_addr = addr;
if (p_db && SUPPORTS_DOORBELL(flags)) {
db = devm_kzalloc(ph->dev, sizeof(*db), GFP_KERNEL);
if (!db)
goto err_xfer;
size = 1 << DOORBELL_REG_WIDTH(flags);
phys_addr = le32_to_cpu(resp->db_addr_low);
phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32;
addr = devm_ioremap(ph->dev, phys_addr, size);
if (!addr)
goto err_xfer;
db->addr = addr;
db->width = size;
db->set = le32_to_cpu(resp->db_set_lmask);
db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32;
db->mask = le32_to_cpu(resp->db_preserve_lmask);
db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32;
*p_db = db;
}
err_xfer:
ph->xops->xfer_put(ph, t);
}
static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
u32 domain, struct scmi_fc_info **p_fc)
{
struct scmi_fc_info *fc;
fc = devm_kzalloc(ph->dev, sizeof(*fc), GFP_KERNEL);
fc = devm_kcalloc(ph->dev, PERF_FC_MAX, sizeof(*fc), GFP_KERNEL);
if (!fc)
return;
scmi_perf_domain_desc_fc(ph, domain, PERF_LEVEL_SET,
&fc->level_set_addr, &fc->level_set_db);
scmi_perf_domain_desc_fc(ph, domain, PERF_LEVEL_GET,
&fc->level_get_addr, NULL);
scmi_perf_domain_desc_fc(ph, domain, PERF_LIMITS_SET,
&fc->limit_set_addr, &fc->limit_set_db);
scmi_perf_domain_desc_fc(ph, domain, PERF_LIMITS_GET,
&fc->limit_get_addr, NULL);
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
PERF_LEVEL_SET, 4, domain,
&fc[PERF_FC_LEVEL].set_addr,
&fc[PERF_FC_LEVEL].set_db);
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
PERF_LEVEL_GET, 4, domain,
&fc[PERF_FC_LEVEL].get_addr, NULL);
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
PERF_LIMITS_SET, 8, domain,
&fc[PERF_FC_LIMIT].set_addr,
&fc[PERF_FC_LIMIT].set_db);
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
PERF_LIMITS_GET, 8, domain,
&fc[PERF_FC_LIMIT].get_addr, NULL);
*p_fc = fc;
}
......@@ -789,7 +672,7 @@ static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
dom = pi->dom_info + scmi_dev_domain_id(dev);
return dom->fc_info && dom->fc_info->level_set_addr;
return dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr;
}
static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph)
......
This diff is collapsed.
......@@ -215,6 +215,19 @@ struct scmi_iterator_ops {
struct scmi_iterator_state *st, void *priv);
};
struct scmi_fc_db_info {
int width;
u64 set;
u64 mask;
void __iomem *addr;
};
struct scmi_fc_info {
void __iomem *set_addr;
void __iomem *get_addr;
struct scmi_fc_db_info *set_db;
};
/**
* struct scmi_proto_helpers_ops - References to common protocol helpers
* @extended_name_get: A common helper function to retrieve extended naming
......@@ -230,6 +243,9 @@ struct scmi_iterator_ops {
* provided in @ops.
* @iter_response_run: A common helper to trigger the run of a previously
* initialized iterator.
* @fastchannel_init: A common helper used to initialize FC descriptors by
* gathering FC descriptions from the SCMI platform server.
* @fastchannel_db_ring: A common helper to ring a FC doorbell.
*/
struct scmi_proto_helpers_ops {
int (*extended_name_get)(const struct scmi_protocol_handle *ph,
......@@ -239,6 +255,12 @@ struct scmi_proto_helpers_ops {
unsigned int max_resources, u8 msg_id,
size_t tx_size, void *priv);
int (*iter_response_run)(void *iter);
void (*fastchannel_init)(const struct scmi_protocol_handle *ph,
u8 describe_id, u32 message_id,
u32 valid_size, u32 domain,
void __iomem **p_addr,
struct scmi_fc_db_info **p_db);
void (*fastchannel_db_ring)(struct scmi_fc_db_info *db);
};
/**
......@@ -315,5 +337,6 @@ DECLARE_SCMI_REGISTER_UNREGISTER(reset);
DECLARE_SCMI_REGISTER_UNREGISTER(sensors);
DECLARE_SCMI_REGISTER_UNREGISTER(voltage);
DECLARE_SCMI_REGISTER_UNREGISTER(system);
DECLARE_SCMI_REGISTER_UNREGISTER(powercap);
#endif /* _SCMI_PROTOCOLS_H */
This diff is collapsed.
......@@ -27,10 +27,12 @@ struct scmi_system_power_state_notifier_payld {
__le32 agent_id;
__le32 flags;
__le32 system_state;
__le32 timeout;
};
struct scmi_system_info {
u32 version;
bool graceful_timeout_supported;
};
static int scmi_system_request_notify(const struct scmi_protocol_handle *ph,
......@@ -72,17 +74,27 @@ scmi_system_fill_custom_report(const struct scmi_protocol_handle *ph,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
{
size_t expected_sz;
const struct scmi_system_power_state_notifier_payld *p = payld;
struct scmi_system_power_state_notifier_report *r = report;
struct scmi_system_info *pinfo = ph->get_priv(ph);
expected_sz = pinfo->graceful_timeout_supported ?
sizeof(*p) : sizeof(*p) - sizeof(__le32);
if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER ||
sizeof(*p) != payld_sz)
payld_sz != expected_sz)
return NULL;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->flags = le32_to_cpu(p->flags);
r->system_state = le32_to_cpu(p->system_state);
if (pinfo->graceful_timeout_supported &&
r->system_state == SCMI_SYSTEM_SHUTDOWN &&
SCMI_SYSPOWER_IS_REQUEST_GRACEFUL(r->flags))
r->timeout = le32_to_cpu(p->timeout);
else
r->timeout = 0x00;
*src_id = 0;
return r;
......@@ -129,6 +141,9 @@ static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)
return -ENOMEM;
pinfo->version = version;
if (PROTOCOL_REV_MAJOR(pinfo->version) >= 0x2)
pinfo->graceful_timeout_supported = true;
return ph->set_priv(ph, pinfo);
}
......
......@@ -815,7 +815,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
info->firmware_version = le32_to_cpu(caps.platform_version);
}
/* Ignore error if not implemented */
if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
if (info->is_legacy && ret == -EOPNOTSUPP)
return 0;
return ret;
......@@ -913,13 +913,14 @@ static int scpi_probe(struct platform_device *pdev)
struct resource res;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct scpi_drvinfo *scpi_drvinfo;
scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
if (!scpi_info)
scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL);
if (!scpi_drvinfo)
return -ENOMEM;
if (of_match_device(legacy_scpi_of_match, &pdev->dev))
scpi_info->is_legacy = true;
scpi_drvinfo->is_legacy = true;
count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
if (count < 0) {
......@@ -927,19 +928,19 @@ static int scpi_probe(struct platform_device *pdev)
return -ENODEV;
}
scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan),
GFP_KERNEL);
if (!scpi_info->channels)
scpi_drvinfo->channels =
devm_kcalloc(dev, count, sizeof(struct scpi_chan), GFP_KERNEL);
if (!scpi_drvinfo->channels)
return -ENOMEM;
ret = devm_add_action(dev, scpi_free_channels, scpi_info);
ret = devm_add_action(dev, scpi_free_channels, scpi_drvinfo);
if (ret)
return ret;
for (; scpi_info->num_chans < count; scpi_info->num_chans++) {
for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) {
resource_size_t size;
int idx = scpi_info->num_chans;
struct scpi_chan *pchan = scpi_info->channels + idx;
int idx = scpi_drvinfo->num_chans;
struct scpi_chan *pchan = scpi_drvinfo->channels + idx;
struct mbox_client *cl = &pchan->cl;
struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
......@@ -986,45 +987,53 @@ static int scpi_probe(struct platform_device *pdev)
return ret;
}
scpi_info->commands = scpi_std_commands;
scpi_drvinfo->commands = scpi_std_commands;
platform_set_drvdata(pdev, scpi_info);
platform_set_drvdata(pdev, scpi_drvinfo);
if (scpi_info->is_legacy) {
if (scpi_drvinfo->is_legacy) {
/* Replace with legacy variants */
scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
scpi_info->commands = scpi_legacy_commands;
scpi_drvinfo->commands = scpi_legacy_commands;
/* Fill priority bitmap */
for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
set_bit(legacy_hpriority_cmds[idx],
scpi_info->cmd_priority);
scpi_drvinfo->cmd_priority);
}
ret = scpi_init_versions(scpi_info);
scpi_info = scpi_drvinfo;
ret = scpi_init_versions(scpi_drvinfo);
if (ret) {
dev_err(dev, "incorrect or no SCP firmware found\n");
scpi_info = NULL;
return ret;
}
if (scpi_info->is_legacy && !scpi_info->protocol_version &&
!scpi_info->firmware_version)
if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version &&
!scpi_drvinfo->firmware_version)
dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n");
else
dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n",
FIELD_GET(PROTO_REV_MAJOR_MASK,
scpi_info->protocol_version),
scpi_drvinfo->protocol_version),
FIELD_GET(PROTO_REV_MINOR_MASK,
scpi_info->protocol_version),
scpi_drvinfo->protocol_version),
FIELD_GET(FW_REV_MAJOR_MASK,
scpi_info->firmware_version),
scpi_drvinfo->firmware_version),
FIELD_GET(FW_REV_MINOR_MASK,
scpi_info->firmware_version),
scpi_drvinfo->firmware_version),
FIELD_GET(FW_REV_PATCH_MASK,
scpi_info->firmware_version));
scpi_info->scpi_ops = &scpi_ops;
scpi_drvinfo->firmware_version));
scpi_drvinfo->scpi_ops = &scpi_ops;
return devm_of_platform_populate(dev);
ret = devm_of_platform_populate(dev);
if (ret)
scpi_info = NULL;
return ret;
}
static const struct of_device_id scpi_of_match[] = {
......
......@@ -120,6 +120,9 @@ static void __scm_legacy_do(const struct arm_smccc_args *smc,
/**
* scm_legacy_call() - Sends a command to the SCM and waits for the command to
* finish processing.
* @dev: device
* @desc: descriptor structure containing arguments and return values
* @res: results from SMC call
*
* A note on cache maintenance:
* Note that any buffers that are expected to be accessed by the secure world
......@@ -211,6 +214,7 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
/**
* scm_legacy_call_atomic() - Send an atomic SCM command with up to 5 arguments
* and 3 return values
* @unused: device, legacy argument, not used, can be NULL
* @desc: SCM call descriptor containing arguments
* @res: SCM call return values
*
......
......@@ -7,6 +7,7 @@
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/dma-mapping.h>
#include <linux/interconnect.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/qcom_scm.h>
......@@ -31,8 +32,13 @@ struct qcom_scm {
struct clk *core_clk;
struct clk *iface_clk;
struct clk *bus_clk;
struct icc_path *path;
struct reset_controller_dev reset;
/* control access to the interconnect path */
struct mutex scm_bw_lock;
int scm_vote_count;
u64 dload_mode_addr;
};
......@@ -99,6 +105,42 @@ static void qcom_scm_clk_disable(void)
clk_disable_unprepare(__scm->bus_clk);
}
static int qcom_scm_bw_enable(void)
{
int ret = 0;
if (!__scm->path)
return 0;
if (IS_ERR(__scm->path))
return -EINVAL;
mutex_lock(&__scm->scm_bw_lock);
if (!__scm->scm_vote_count) {
ret = icc_set_bw(__scm->path, 0, UINT_MAX);
if (ret < 0) {
dev_err(__scm->dev, "failed to set bandwidth request\n");
goto err_bw;
}
}
__scm->scm_vote_count++;
err_bw:
mutex_unlock(&__scm->scm_bw_lock);
return ret;
}
static void qcom_scm_bw_disable(void)
{
if (IS_ERR_OR_NULL(__scm->path))
return;
mutex_lock(&__scm->scm_bw_lock);
if (__scm->scm_vote_count-- == 1)
icc_set_bw(__scm->path, 0, 0);
mutex_unlock(&__scm->scm_bw_lock);
}
enum qcom_scm_convention qcom_scm_convention = SMC_CONVENTION_UNKNOWN;
static DEFINE_SPINLOCK(scm_query_lock);
......@@ -444,10 +486,15 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size,
if (ret)
goto out;
ret = qcom_scm_bw_enable();
if (ret)
return ret;
desc.args[1] = mdata_phys;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
qcom_scm_clk_disable();
out:
......@@ -507,7 +554,12 @@ int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
if (ret)
return ret;
ret = qcom_scm_bw_enable();
if (ret)
return ret;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
qcom_scm_clk_disable();
return ret ? : res.result[0];
......@@ -537,7 +589,12 @@ int qcom_scm_pas_auth_and_reset(u32 peripheral)
if (ret)
return ret;
ret = qcom_scm_bw_enable();
if (ret)
return ret;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
qcom_scm_clk_disable();
return ret ? : res.result[0];
......@@ -566,8 +623,13 @@ int qcom_scm_pas_shutdown(u32 peripheral)
if (ret)
return ret;
ret = qcom_scm_bw_enable();
if (ret)
return ret;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
qcom_scm_clk_disable();
return ret ? : res.result[0];
......@@ -1277,8 +1339,15 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
mutex_init(&scm->scm_bw_lock);
clks = (unsigned long)of_device_get_match_data(&pdev->dev);
scm->path = devm_of_icc_get(&pdev->dev, NULL);
if (IS_ERR(scm->path))
return dev_err_probe(&pdev->dev, PTR_ERR(scm->path),
"failed to acquire interconnect path\n");
scm->core_clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(scm->core_clk)) {
if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
......@@ -1337,7 +1406,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
/*
* If requested enable "download mode", from this point on warmboot
* will cause the the boot stages to enter download mode, unless
* will cause the boot stages to enter download mode, unless
* disabled below by a clean shutdown/reboot.
*/
if (download_mode)
......
......@@ -474,7 +474,7 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0;
dentry = debugfs_create_file(name, mode, parent, bpmp,
&bpmp_debug_fops);
if (!dentry) {
if (IS_ERR(dentry)) {
err = -ENOMEM;
goto out;
}
......@@ -725,7 +725,7 @@ static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
if (t & DEBUGFS_S_ISDIR) {
dentry = debugfs_create_dir(name, parent);
if (!dentry)
if (IS_ERR(dentry))
return -ENOMEM;
err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
if (err < 0)
......@@ -738,7 +738,7 @@ static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
dentry = debugfs_create_file(name, mode,
parent, bpmp,
&debugfs_fops);
if (!dentry)
if (IS_ERR(dentry))
return -ENOMEM;
}
}
......@@ -788,11 +788,11 @@ int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
return 0;
root = debugfs_create_dir("bpmp", NULL);
if (!root)
if (IS_ERR(root))
return -ENOMEM;
bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
if (!bpmp->debugfs_mirror) {
if (IS_ERR(bpmp->debugfs_mirror)) {
err = -ENOMEM;
goto out;
}
......
......@@ -201,7 +201,7 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
int err;
if (data && size > 0)
memcpy(data, channel->ib->data, size);
memcpy_fromio(data, channel->ib->data, size);
err = tegra_bpmp_ack_response(channel);
if (err < 0)
......@@ -245,7 +245,7 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
channel->ob->flags = flags;
if (data && size > 0)
memcpy(channel->ob->data, data, size);
memcpy_toio(channel->ob->data, data, size);
return tegra_bpmp_post_request(channel);
}
......@@ -420,7 +420,7 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
channel->ob->code = code;
if (data && size > 0)
memcpy(channel->ob->data, data, size);
memcpy_toio(channel->ob->data, data, size);
err = tegra_bpmp_post_response(channel);
if (WARN_ON(err < 0))
......
......@@ -486,7 +486,7 @@ config I2C_BCM_KONA
config I2C_BRCMSTB
tristate "BRCM Settop/DSL I2C controller"
depends on ARCH_BCM2835 || ARCH_BCM4908 || ARCH_BCM_63XX || \
depends on ARCH_BCM2835 || ARCH_BCM4908 || ARCH_BCMBCA || \
ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
default y
help
......
......@@ -21,11 +21,13 @@
/* SMI COMMON */
#define SMI_L1LEN 0x100
#define SMI_L1_ARB 0x200
#define SMI_BUS_SEL 0x220
#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
/* All are MMU0 defaultly. Only specialize mmu1 here. */
#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
#define SMI_READ_FIFO_TH 0x230
#define SMI_M4U_TH 0x234
#define SMI_FIFO_TH1 0x238
#define SMI_FIFO_TH2 0x23c
......@@ -360,6 +362,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
{.compatible = "mediatek,mt2701-smi-larb", .data = &mtk_smi_larb_mt2701},
{.compatible = "mediatek,mt2712-smi-larb", .data = &mtk_smi_larb_mt2712},
{.compatible = "mediatek,mt6779-smi-larb", .data = &mtk_smi_larb_mt6779},
{.compatible = "mediatek,mt6795-smi-larb", .data = &mtk_smi_larb_mt8173},
{.compatible = "mediatek,mt8167-smi-larb", .data = &mtk_smi_larb_mt8167},
{.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173},
{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
......@@ -544,6 +547,13 @@ static struct platform_driver mtk_smi_larb_driver = {
}
};
static const struct mtk_smi_reg_pair mtk_smi_common_mt6795_init[SMI_COMMON_INIT_REGS_NR] = {
{SMI_L1_ARB, 0x1b},
{SMI_M4U_TH, 0xce810c85},
{SMI_FIFO_TH1, 0x43214c8},
{SMI_READ_FIFO_TH, 0x191f},
};
static const struct mtk_smi_reg_pair mtk_smi_common_mt8195_init[SMI_COMMON_INIT_REGS_NR] = {
{SMI_L1LEN, 0xb},
{SMI_M4U_TH, 0xe100e10},
......@@ -568,6 +578,12 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt6779 = {
F_MMU1_LARB(5) | F_MMU1_LARB(6) | F_MMU1_LARB(7),
};
static const struct mtk_smi_common_plat mtk_smi_common_mt6795 = {
.type = MTK_SMI_GEN2,
.bus_sel = F_MMU1_LARB(0),
.init = mtk_smi_common_mt6795_init,
};
static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
.type = MTK_SMI_GEN2,
.has_gals = true,
......@@ -612,6 +628,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
{.compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1},
{.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2},
{.compatible = "mediatek,mt6779-smi-common", .data = &mtk_smi_common_mt6779},
{.compatible = "mediatek,mt6795-smi-common", .data = &mtk_smi_common_mt6795},
{.compatible = "mediatek,mt8167-smi-common", .data = &mtk_smi_common_gen2},
{.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2},
{.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183},
......
......@@ -11,6 +11,76 @@
static const struct tegra_mc_client tegra234_mc_clients[] = {
{
.id = TEGRA234_MEMORY_CLIENT_MGBEARD,
.name = "mgbeard",
.sid = TEGRA234_SID_MGBE,
.regs = {
.sid = {
.override = 0x2c0,
.security = 0x2c4,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEBRD,
.name = "mgbebrd",
.sid = TEGRA234_SID_MGBE_VF1,
.regs = {
.sid = {
.override = 0x2c8,
.security = 0x2cc,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBECRD,
.name = "mgbecrd",
.sid = TEGRA234_SID_MGBE_VF2,
.regs = {
.sid = {
.override = 0x2d0,
.security = 0x2d4,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEDRD,
.name = "mgbedrd",
.sid = TEGRA234_SID_MGBE_VF3,
.regs = {
.sid = {
.override = 0x2d8,
.security = 0x2dc,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEAWR,
.name = "mgbeawr",
.sid = TEGRA234_SID_MGBE,
.regs = {
.sid = {
.override = 0x2e0,
.security = 0x2e4,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEBWR,
.name = "mgbebwr",
.sid = TEGRA234_SID_MGBE_VF1,
.regs = {
.sid = {
.override = 0x2f8,
.security = 0x2fc,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBECWR,
.name = "mgbecwr",
.sid = TEGRA234_SID_MGBE_VF2,
.regs = {
.sid = {
.override = 0x308,
.security = 0x30c,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_SDMMCRAB,
.name = "sdmmcrab",
.sid = TEGRA234_SID_SDMMC4,
......@@ -20,6 +90,16 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
.security = 0x31c,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEDWR,
.name = "mgbedwr",
.sid = TEGRA234_SID_MGBE_VF3,
.regs = {
.sid = {
.override = 0x328,
.security = 0x32c,
},
},
}, {
.id = TEGRA234_MEMORY_CLIENT_SDMMCWAB,
.name = "sdmmcwab",
......
......@@ -25,9 +25,52 @@ static const struct mfd_cell bcm2835_power_devs[] = {
{ .name = "bcm2835-power" },
};
static int bcm2835_pm_get_pdata(struct platform_device *pdev,
struct bcm2835_pm *pm)
{
if (of_find_property(pm->dev->of_node, "reg-names", NULL)) {
struct resource *res;
pm->base = devm_platform_ioremap_resource_byname(pdev, "pm");
if (IS_ERR(pm->base))
return PTR_ERR(pm->base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "asb");
if (res) {
pm->asb = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pm->asb))
pm->asb = NULL;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"rpivid_asb");
if (res) {
pm->rpivid_asb = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pm->rpivid_asb))
pm->rpivid_asb = NULL;
}
return 0;
}
/* If no 'reg-names' property is found we can assume we're using old DTB. */
pm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pm->base))
return PTR_ERR(pm->base);
pm->asb = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(pm->asb))
pm->asb = NULL;
pm->rpivid_asb = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(pm->rpivid_asb))
pm->rpivid_asb = NULL;
return 0;
}
static int bcm2835_pm_probe(struct platform_device *pdev)
{
struct resource *res;
struct device *dev = &pdev->dev;
struct bcm2835_pm *pm;
int ret;
......@@ -39,10 +82,9 @@ static int bcm2835_pm_probe(struct platform_device *pdev)
pm->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pm->base = devm_ioremap_resource(dev, res);
if (IS_ERR(pm->base))
return PTR_ERR(pm->base);
ret = bcm2835_pm_get_pdata(pdev, pm);
if (ret)
return ret;
ret = devm_mfd_add_devices(dev, -1,
bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
......@@ -50,30 +92,22 @@ static int bcm2835_pm_probe(struct platform_device *pdev)
if (ret)
return ret;
/* We'll use the presence of the AXI ASB regs in the
/*
* We'll use the presence of the AXI ASB regs in the
* bcm2835-pm binding as the key for whether we can reference
* the full PM register range and support power domains.
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) {
pm->asb = devm_ioremap_resource(dev, res);
if (IS_ERR(pm->asb))
return PTR_ERR(pm->asb);
ret = devm_mfd_add_devices(dev, -1,
bcm2835_power_devs,
ARRAY_SIZE(bcm2835_power_devs),
NULL, 0, NULL);
if (ret)
return ret;
}
if (pm->asb)
return devm_mfd_add_devices(dev, -1, bcm2835_power_devs,
ARRAY_SIZE(bcm2835_power_devs),
NULL, 0, NULL);
return 0;
}
static const struct of_device_id bcm2835_pm_of_match[] = {
{ .compatible = "brcm,bcm2835-pm-wdt", },
{ .compatible = "brcm,bcm2835-pm", },
{ .compatible = "brcm,bcm2711-pm", },
{},
};
MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
......
......@@ -83,7 +83,7 @@ config PHY_NS2_USB_DRD
config PHY_BRCM_SATA
tristate "Broadcom SATA PHY driver"
depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || \
ARCH_BCM_63XX || COMPILE_TEST
ARCH_BCMBCA || COMPILE_TEST
depends on OF
select GENERIC_PHY
default ARCH_BCM_IPROC
......
......@@ -9,6 +9,7 @@ source "drivers/soc/atmel/Kconfig"
source "drivers/soc/bcm/Kconfig"
source "drivers/soc/canaan/Kconfig"
source "drivers/soc/fsl/Kconfig"
source "drivers/soc/fujitsu/Kconfig"
source "drivers/soc/imx/Kconfig"
source "drivers/soc/ixp4xx/Kconfig"
source "drivers/soc/litex/Kconfig"
......
......@@ -12,6 +12,7 @@ obj-$(CONFIG_SOC_CANAAN) += canaan/
obj-$(CONFIG_ARCH_DOVE) += dove/
obj-$(CONFIG_MACH_DOVE) += dove/
obj-y += fsl/
obj-y += fujitsu/
obj-$(CONFIG_ARCH_GEMINI) += gemini/
obj-y += imx/
obj-y += ixp4xx/
......
......@@ -126,6 +126,7 @@ static int __init meson_mx_socinfo_init(void)
np = of_find_matching_node(NULL, meson_mx_socinfo_analog_top_ids);
if (np) {
analog_top_regmap = syscon_node_to_regmap(np);
of_node_put(np);
if (IS_ERR(analog_top_regmap))
return PTR_ERR(analog_top_regmap);
......
......@@ -152,8 +152,10 @@ static int meson_secure_pwrc_probe(struct platform_device *pdev)
}
pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
if (!pwrc)
if (!pwrc) {
of_node_put(sm_np);
return -ENOMEM;
}
pwrc->fw = meson_sm_get(sm_np);
of_node_put(sm_np);
......
......@@ -126,8 +126,7 @@
#define ASB_AXI_BRDG_ID 0x20
#define ASB_READ(reg) readl(power->asb + (reg))
#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
#define BCM2835_BRDG_ID 0x62726467
struct bcm2835_power_domain {
struct generic_pm_domain base;
......@@ -142,24 +141,41 @@ struct bcm2835_power {
void __iomem *base;
/* AXI Async bridge registers. */
void __iomem *asb;
/* RPiVid bridge registers. */
void __iomem *rpivid_asb;
struct genpd_onecell_data pd_xlate;
struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
struct reset_controller_dev reset;
};
static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
{
void __iomem *base = power->asb;
u64 start;
u32 val;
if (!reg)
switch (reg) {
case 0:
return 0;
case ASB_V3D_S_CTRL:
case ASB_V3D_M_CTRL:
if (power->rpivid_asb)
base = power->rpivid_asb;
break;
}
start = ktime_get_ns();
/* Enable the module's async AXI bridges. */
ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
while (ASB_READ(reg) & ASB_ACK) {
if (enable) {
val = readl(base + reg) & ~ASB_REQ_STOP;
} else {
val = readl(base + reg) | ASB_REQ_STOP;
}
writel(PM_PASSWORD | val, base + reg);
while (readl(base + reg) & ASB_ACK) {
cpu_relax();
if (ktime_get_ns() - start >= 1000)
return -ETIMEDOUT;
......@@ -168,30 +184,24 @@ static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
return 0;
}
static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
{
u64 start;
if (!reg)
return 0;
start = ktime_get_ns();
/* Enable the module's async AXI bridges. */
ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
while (!(ASB_READ(reg) & ASB_ACK)) {
cpu_relax();
if (ktime_get_ns() - start >= 1000)
return -ETIMEDOUT;
}
return bcm2835_asb_control(power, reg, true);
}
return 0;
static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
{
return bcm2835_asb_control(power, reg, false);
}
static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
{
struct bcm2835_power *power = pd->power;
/* We don't run this on BCM2711 */
if (power->rpivid_asb)
return 0;
/* Enable functional isolation */
PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
......@@ -213,6 +223,10 @@ static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
int inrush;
bool powok;
/* We don't run this on BCM2711 */
if (power->rpivid_asb)
return 0;
/* If it was already powered on by the fw, leave it that way. */
if (PM_READ(pm_reg) & PM_POWUP)
return 0;
......@@ -626,13 +640,23 @@ static int bcm2835_power_probe(struct platform_device *pdev)
power->dev = dev;
power->base = pm->base;
power->asb = pm->asb;
power->rpivid_asb = pm->rpivid_asb;
id = ASB_READ(ASB_AXI_BRDG_ID);
if (id != 0x62726467 /* "BRDG" */) {
id = readl(power->asb + ASB_AXI_BRDG_ID);
if (id != BCM2835_BRDG_ID /* "BRDG" */) {
dev_err(dev, "ASB register ID returned 0x%08x\n", id);
return -ENODEV;
}
if (power->rpivid_asb) {
id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);
if (id != BCM2835_BRDG_ID /* "BRDG" */) {
dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",
id);
return -ENODEV;
}
}
power->pd_xlate.domains = devm_kcalloc(dev,
ARRAY_SIZE(power_domain_names),
sizeof(*power->pd_xlate.domains),
......
......@@ -340,12 +340,12 @@ static int __init brcmstb_biuctrl_init(void)
ret = setup_hifcpubiuctrl_regs(np);
if (ret)
return ret;
goto out_put;
ret = mcp_write_pairing_set();
if (ret) {
pr_err("MCP: Unable to disable write pairing!\n");
return ret;
goto out_put;
}
a72_b53_rac_enable_all(np);
......@@ -353,6 +353,9 @@ static int __init brcmstb_biuctrl_init(void)
#ifdef CONFIG_PM_SLEEP
register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
#endif
return 0;
ret = 0;
out_put:
of_node_put(np);
return ret;
}
early_initcall(brcmstb_biuctrl_init);
......@@ -721,7 +721,7 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
ctrl.phy_a_standby_ctrl_offs = ddr_phy_data->phy_a_standby_ctrl_offs;
ctrl.phy_b_standby_ctrl_offs = ddr_phy_data->phy_b_standby_ctrl_offs;
/*
* Slightly grosss to use the phy ver to get a memc,
* Slightly gross to use the phy ver to get a memc,
* offset but that is the only versioned things so far
* we can test for.
*/
......
......@@ -14,21 +14,16 @@
#include <linux/platform_device.h>
#include <linux/fsl/guts.h>
struct guts {
struct ccsr_guts __iomem *regs;
bool little_endian;
};
struct fsl_soc_die_attr {
char *die;
u32 svr;
u32 mask;
};
static struct guts *guts;
static struct soc_device_attribute soc_dev_attr;
static struct soc_device *soc_dev;
struct fsl_soc_data {
const char *sfp_compat;
u32 uid_offset;
};
/* SoC die attribute definition for QorIQ platform */
static const struct fsl_soc_die_attr fsl_soc_die[] = {
......@@ -120,88 +115,36 @@ static const struct fsl_soc_die_attr *fsl_soc_die_match(
return NULL;
}
static u32 fsl_guts_get_svr(void)
{
u32 svr = 0;
if (!guts || !guts->regs)
return svr;
if (guts->little_endian)
svr = ioread32(&guts->regs->svr);
else
svr = ioread32be(&guts->regs->svr);
return svr;
}
static int fsl_guts_probe(struct platform_device *pdev)
static u64 fsl_guts_get_soc_uid(const char *compat, unsigned int offset)
{
struct device_node *root, *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
const struct fsl_soc_die_attr *soc_die;
const char *machine;
u32 svr;
/* Initialize guts */
guts = devm_kzalloc(dev, sizeof(*guts), GFP_KERNEL);
if (!guts)
return -ENOMEM;
guts->little_endian = of_property_read_bool(np, "little-endian");
struct device_node *np;
void __iomem *sfp_base;
u64 uid;
guts->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(guts->regs))
return PTR_ERR(guts->regs);
np = of_find_compatible_node(NULL, NULL, compat);
if (!np)
return 0;
/* Register soc device */
root = of_find_node_by_path("/");
if (of_property_read_string(root, "model", &machine))
of_property_read_string_index(root, "compatible", 0, &machine);
if (machine) {
soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
if (!soc_dev_attr.machine) {
of_node_put(root);
return -ENOMEM;
}
sfp_base = of_iomap(np, 0);
if (!sfp_base) {
of_node_put(np);
return 0;
}
of_node_put(root);
svr = fsl_guts_get_svr();
soc_die = fsl_soc_die_match(svr, fsl_soc_die);
if (soc_die) {
soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL,
"QorIQ %s", soc_die->die);
} else {
soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, "QorIQ");
}
if (!soc_dev_attr.family)
return -ENOMEM;
soc_dev_attr.soc_id = devm_kasprintf(dev, GFP_KERNEL,
"svr:0x%08x", svr);
if (!soc_dev_attr.soc_id)
return -ENOMEM;
soc_dev_attr.revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d",
(svr >> 4) & 0xf, svr & 0xf);
if (!soc_dev_attr.revision)
return -ENOMEM;
uid = ioread32(sfp_base + offset);
uid <<= 32;
uid |= ioread32(sfp_base + offset + 4);
soc_dev = soc_device_register(&soc_dev_attr);
if (IS_ERR(soc_dev))
return PTR_ERR(soc_dev);
iounmap(sfp_base);
of_node_put(np);
pr_info("Machine: %s\n", soc_dev_attr.machine);
pr_info("SoC family: %s\n", soc_dev_attr.family);
pr_info("SoC ID: %s, Revision: %s\n",
soc_dev_attr.soc_id, soc_dev_attr.revision);
return 0;
return uid;
}
static int fsl_guts_remove(struct platform_device *dev)
{
soc_device_unregister(soc_dev);
return 0;
}
static const struct fsl_soc_data ls1028a_data = {
.sfp_compat = "fsl,ls1028a-sfp",
.uid_offset = 0x21c,
};
/*
* Table for matching compatible strings, for device tree
......@@ -231,28 +174,106 @@ static const struct of_device_id fsl_guts_of_match[] = {
{ .compatible = "fsl,ls1012a-dcfg", },
{ .compatible = "fsl,ls1046a-dcfg", },
{ .compatible = "fsl,lx2160a-dcfg", },
{ .compatible = "fsl,ls1028a-dcfg", },
{ .compatible = "fsl,ls1028a-dcfg", .data = &ls1028a_data},
{}
};
MODULE_DEVICE_TABLE(of, fsl_guts_of_match);
static struct platform_driver fsl_guts_driver = {
.driver = {
.name = "fsl-guts",
.of_match_table = fsl_guts_of_match,
},
.probe = fsl_guts_probe,
.remove = fsl_guts_remove,
};
static int __init fsl_guts_init(void)
{
return platform_driver_register(&fsl_guts_driver);
}
core_initcall(fsl_guts_init);
struct soc_device_attribute *soc_dev_attr;
static struct soc_device *soc_dev;
const struct fsl_soc_die_attr *soc_die;
const struct fsl_soc_data *soc_data;
const struct of_device_id *match;
struct ccsr_guts __iomem *regs;
const char *machine = NULL;
struct device_node *np;
bool little_endian;
u64 soc_uid = 0;
u32 svr;
int ret;
static void __exit fsl_guts_exit(void)
{
platform_driver_unregister(&fsl_guts_driver);
np = of_find_matching_node_and_match(NULL, fsl_guts_of_match, &match);
if (!np)
return 0;
soc_data = match->data;
regs = of_iomap(np, 0);
if (!regs) {
of_node_put(np);
return -ENOMEM;
}
little_endian = of_property_read_bool(np, "little-endian");
if (little_endian)
svr = ioread32(&regs->svr);
else
svr = ioread32be(&regs->svr);
iounmap(regs);
of_node_put(np);
/* Register soc device */
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
if (of_property_read_string(of_root, "model", &machine))
of_property_read_string_index(of_root, "compatible", 0, &machine);
if (machine) {
soc_dev_attr->machine = kstrdup(machine, GFP_KERNEL);
if (!soc_dev_attr->machine)
goto err_nomem;
}
soc_die = fsl_soc_die_match(svr, fsl_soc_die);
if (soc_die) {
soc_dev_attr->family = kasprintf(GFP_KERNEL, "QorIQ %s",
soc_die->die);
} else {
soc_dev_attr->family = kasprintf(GFP_KERNEL, "QorIQ");
}
if (!soc_dev_attr->family)
goto err_nomem;
soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "svr:0x%08x", svr);
if (!soc_dev_attr->soc_id)
goto err_nomem;
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
(svr >> 4) & 0xf, svr & 0xf);
if (!soc_dev_attr->revision)
goto err_nomem;
if (soc_data)
soc_uid = fsl_guts_get_soc_uid(soc_data->sfp_compat,
soc_data->uid_offset);
if (soc_uid)
soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX",
soc_uid);
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
ret = PTR_ERR(soc_dev);
goto err;
}
pr_info("Machine: %s\n", soc_dev_attr->machine);
pr_info("SoC family: %s\n", soc_dev_attr->family);
pr_info("SoC ID: %s, Revision: %s\n",
soc_dev_attr->soc_id, soc_dev_attr->revision);
return 0;
err_nomem:
ret = -ENOMEM;
err:
kfree(soc_dev_attr->machine);
kfree(soc_dev_attr->family);
kfree(soc_dev_attr->soc_id);
kfree(soc_dev_attr->revision);
kfree(soc_dev_attr->serial_number);
kfree(soc_dev_attr);
return ret;
}
module_exit(fsl_guts_exit);
core_initcall(fsl_guts_init);
# SPDX-License-Identifier: GPL-2.0-only
menu "fujitsu SoC drivers"
config A64FX_DIAG
bool "A64FX diag driver"
depends on ARM64
depends on ACPI
help
Say Y here if you want to enable diag interrupt on Fujitsu A64FX.
This driver enables BMC's diagnostic requests and enables
A64FX-specific interrupts. This allows administrators to obtain
kernel dumps via diagnostic requests using ipmitool, etc.
If unsure, say N.
endmenu
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_A64FX_DIAG) += a64fx-diag.o
// SPDX-License-Identifier: GPL-2.0-only
/*
* A64FX diag driver.
* Copyright (c) 2022 Fujitsu Ltd.
*/
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#define A64FX_DIAG_IRQ 1
#define BMC_DIAG_INTERRUPT_ENABLE 0x40
#define BMC_DIAG_INTERRUPT_STATUS 0x44
#define BMC_DIAG_INTERRUPT_MASK BIT(31)
struct a64fx_diag_priv {
void __iomem *mmsc_reg_base;
int irq;
bool has_nmi;
};
static irqreturn_t a64fx_diag_handler_nmi(int irq, void *dev_id)
{
nmi_panic(NULL, "a64fx_diag: interrupt received\n");
return IRQ_HANDLED;
}
static irqreturn_t a64fx_diag_handler_irq(int irq, void *dev_id)
{
panic("a64fx_diag: interrupt received\n");
return IRQ_HANDLED;
}
static void a64fx_diag_interrupt_clear(struct a64fx_diag_priv *priv)
{
void __iomem *diag_status_reg_addr;
u32 mmsc;
diag_status_reg_addr = priv->mmsc_reg_base + BMC_DIAG_INTERRUPT_STATUS;
mmsc = readl(diag_status_reg_addr);
if (mmsc & BMC_DIAG_INTERRUPT_MASK)
writel(BMC_DIAG_INTERRUPT_MASK, diag_status_reg_addr);
}
static void a64fx_diag_interrupt_enable(struct a64fx_diag_priv *priv)
{
void __iomem *diag_enable_reg_addr;
u32 mmsc;
diag_enable_reg_addr = priv->mmsc_reg_base + BMC_DIAG_INTERRUPT_ENABLE;
mmsc = readl(diag_enable_reg_addr);
if (!(mmsc & BMC_DIAG_INTERRUPT_MASK)) {
mmsc |= BMC_DIAG_INTERRUPT_MASK;
writel(mmsc, diag_enable_reg_addr);
}
}
static void a64fx_diag_interrupt_disable(struct a64fx_diag_priv *priv)
{
void __iomem *diag_enable_reg_addr;
u32 mmsc;
diag_enable_reg_addr = priv->mmsc_reg_base + BMC_DIAG_INTERRUPT_ENABLE;
mmsc = readl(diag_enable_reg_addr);
if (mmsc & BMC_DIAG_INTERRUPT_MASK) {
mmsc &= ~BMC_DIAG_INTERRUPT_MASK;
writel(mmsc, diag_enable_reg_addr);
}
}
static int a64fx_diag_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct a64fx_diag_priv *priv;
unsigned long irq_flags;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
priv->mmsc_reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->mmsc_reg_base))
return PTR_ERR(priv->mmsc_reg_base);
priv->irq = platform_get_irq(pdev, A64FX_DIAG_IRQ);
if (priv->irq < 0)
return priv->irq;
platform_set_drvdata(pdev, priv);
irq_flags = IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_AUTOEN |
IRQF_NO_THREAD;
ret = request_nmi(priv->irq, &a64fx_diag_handler_nmi, irq_flags,
"a64fx_diag_nmi", NULL);
if (ret) {
ret = request_irq(priv->irq, &a64fx_diag_handler_irq,
irq_flags, "a64fx_diag_irq", NULL);
if (ret) {
dev_err(dev, "cannot register IRQ %d\n", ret);
return ret;
}
enable_irq(priv->irq);
} else {
enable_nmi(priv->irq);
priv->has_nmi = true;
}
a64fx_diag_interrupt_clear(priv);
a64fx_diag_interrupt_enable(priv);
return 0;
}
static int a64fx_diag_remove(struct platform_device *pdev)
{
struct a64fx_diag_priv *priv = platform_get_drvdata(pdev);
a64fx_diag_interrupt_disable(priv);
a64fx_diag_interrupt_clear(priv);
if (priv->has_nmi)
free_nmi(priv->irq, NULL);
else
free_irq(priv->irq, NULL);
return 0;
}
static const struct acpi_device_id a64fx_diag_acpi_match[] = {
{ "FUJI2007", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, a64fx_diag_acpi_match);
static struct platform_driver a64fx_diag_driver = {
.driver = {
.name = "a64fx_diag_driver",
.acpi_match_table = ACPI_PTR(a64fx_diag_acpi_match),
},
.probe = a64fx_diag_probe,
.remove = a64fx_diag_remove,
};
module_platform_driver(a64fx_diag_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Hitomi Hasegawa <hasegawa-hitomi@fujitsu.com>");
MODULE_DESCRIPTION("A64FX diag driver");
......@@ -328,7 +328,9 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
if (!IS_ERR(domain->regulator)) {
ret = regulator_enable(domain->regulator);
if (ret) {
dev_err(domain->dev, "failed to enable regulator\n");
dev_err(domain->dev,
"failed to enable regulator: %pe\n",
ERR_PTR(ret));
goto out_put_pm;
}
}
......@@ -467,7 +469,9 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
if (!IS_ERR(domain->regulator)) {
ret = regulator_disable(domain->regulator);
if (ret) {
dev_err(domain->dev, "failed to disable regulator\n");
dev_err(domain->dev,
"failed to disable regulator: %pe\n",
ERR_PTR(ret));
return ret;
}
}
......
......@@ -216,7 +216,7 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
if (IS_ERR(bc->bus_power_dev))
return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
"failed to attach power domain\n");
"failed to attach power domain \"bus\"\n");
for (i = 0; i < bc_data->num_domains; i++) {
const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
......@@ -238,7 +238,8 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
dev_pm_domain_attach_by_name(dev, data->gpc_name);
if (IS_ERR(domain->power_dev)) {
dev_err_probe(dev, PTR_ERR(domain->power_dev),
"failed to attach power domain\n");
"failed to attach power domain \"%s\"\n",
data->gpc_name);
ret = PTR_ERR(domain->power_dev);
goto cleanup_pds;
}
......@@ -251,7 +252,9 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
ret = pm_genpd_init(&domain->genpd, NULL, true);
if (ret) {
dev_err_probe(dev, ret, "failed to init power domain\n");
dev_err_probe(dev, ret,
"failed to init power domain \"%s\"\n",
data->gpc_name);
dev_pm_domain_detach(domain->power_dev, true);
goto cleanup_pds;
}
......
......@@ -73,4 +73,14 @@ config MTK_MMSYS
Say yes here to add support for the MediaTek Multimedia
Subsystem (MMSYS).
config MTK_SVS
tristate "MediaTek Smart Voltage Scaling(SVS)"
depends on MTK_EFUSE && NVMEM
help
The Smart Voltage Scaling(SVS) engine is a piece of hardware
which has several controllers(banks) for calculating suitable
voltage to different power domains(CPU/GPU/CCI) according to
chip process corner, temperatures and other factors. Then DVFS
driver could apply SVS bank voltage to PMIC/Buck.
endmenu
......@@ -7,3 +7,4 @@ obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
obj-$(CONFIG_MTK_MMSYS) += mtk-mmsys.o
obj-$(CONFIG_MTK_MMSYS) += mtk-mutex.o
obj-$(CONFIG_MTK_SVS) += mtk-svs.o
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
#define __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
#include "mtk-pm-domains.h"
#include <dt-bindings/power/mt6795-power.h>
/*
* MT6795 power domain support
*/
static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
[MT6795_POWER_DOMAIN_VDEC] = {
.name = "vdec",
.sta_mask = PWR_STATUS_VDEC,
.ctl_offs = SPM_VDE_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT6795_POWER_DOMAIN_VENC] = {
.name = "venc",
.sta_mask = PWR_STATUS_VENC,
.ctl_offs = SPM_VEN_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT6795_POWER_DOMAIN_ISP] = {
.name = "isp",
.sta_mask = PWR_STATUS_ISP,
.ctl_offs = SPM_ISP_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
},
[MT6795_POWER_DOMAIN_MM] = {
.name = "mm",
.sta_mask = PWR_STATUS_DISP,
.ctl_offs = SPM_DIS_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
MT8173_TOP_AXI_PROT_EN_MM_M1),
},
},
[MT6795_POWER_DOMAIN_MJC] = {
.name = "mjc",
.sta_mask = BIT(20),
.ctl_offs = 0x298,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT6795_POWER_DOMAIN_AUDIO] = {
.name = "audio",
.sta_mask = PWR_STATUS_AUDIO,
.ctl_offs = SPM_AUDIO_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT6795_POWER_DOMAIN_MFG_ASYNC] = {
.name = "mfg_async",
.sta_mask = PWR_STATUS_MFG_ASYNC,
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = 0,
},
[MT6795_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d",
.sta_mask = PWR_STATUS_MFG_2D,
.ctl_offs = SPM_MFG_2D_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
},
[MT6795_POWER_DOMAIN_MFG] = {
.name = "mfg",
.sta_mask = PWR_STATUS_MFG,
.ctl_offs = SPM_MFG_PWR_CON,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
.sram_pdn_bits = GENMASK(13, 8),
.sram_pdn_ack_bits = GENMASK(21, 16),
.bp_infracfg = {
BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
MT8173_TOP_AXI_PROT_EN_MFG_M0 |
MT8173_TOP_AXI_PROT_EN_MFG_M1 |
MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
},
},
};
static const struct scpsys_soc_data mt6795_scpsys_data = {
.domains_data = scpsys_domain_data_mt6795,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt6795),
};
#endif /* __SOC_MEDIATEK_MT6795_PM_DOMAINS_H */
......@@ -41,6 +41,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
.pwr_sta2nd_offs = 0x0184,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.caps = MTK_SCPD_DOMAIN_SUPPLY,
},
[MT8183_POWER_DOMAIN_MFG] = {
.name = "mfg",
......
......@@ -51,7 +51,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
MT8186_TOP_AXI_PROT_EN_1_CLR,
MT8186_TOP_AXI_PROT_EN_1_STA),
},
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
.caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
},
[MT8186_POWER_DOMAIN_MFG2] = {
.name = "mfg2",
......
......@@ -58,6 +58,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
.pwr_sta2nd_offs = 0x0170,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.caps = MTK_SCPD_DOMAIN_SUPPLY,
},
[MT8192_POWER_DOMAIN_MFG1] = {
.name = "mfg1",
......@@ -85,6 +86,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
MT8192_TOP_AXI_PROT_EN_2_CLR,
MT8192_TOP_AXI_PROT_EN_2_STA1),
},
.caps = MTK_SCPD_DOMAIN_SUPPLY,
},
[MT8192_POWER_DOMAIN_MFG2] = {
.name = "mfg2",
......
......@@ -67,7 +67,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
.ctl_offs = 0x334,
.pwr_sta_offs = 0x174,
.pwr_sta2nd_offs = 0x178,
.caps = MTK_SCPD_ACTIVE_WAKEUP,
.caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_ALWAYS_ON,
},
[MT8195_POWER_DOMAIN_CSI_RX_TOP] = {
.name = "csi_rx_top",
......@@ -162,7 +162,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
},
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
.caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
},
[MT8195_POWER_DOMAIN_MFG2] = {
.name = "mfg2",
......
......@@ -10,6 +10,9 @@
#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN 0xf60
#define MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0xf64
#define MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN 0xf68
#define MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL 0xfd0
#define MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN 0xfd8
#define MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00 0xfdc
#define MT8365_RDMA0_SOUT_COLOR0 0x1
#define MT8365_DITHER_MOUT_EN_DSI0 0x1
......@@ -18,6 +21,10 @@
#define MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 0x0
#define MT8365_DISP_COLOR_SEL_IN_COLOR0 0x0
#define MT8365_OVL0_MOUT_PATH0_SEL BIT(0)
#define MT8365_RDMA1_SOUT_DPI0 0x1
#define MT8365_DPI0_SEL_IN_RDMA1 0x0
#define MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK 0x1
#define MT8365_DPI0_SEL_IN_RDMA1 0x0
static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = {
{
......@@ -55,6 +62,21 @@ static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = {
MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN,
MT8365_RDMA0_RSZ0_SEL_IN_RDMA0, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0
},
{
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00,
MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK, MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK
},
{
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN,
MT8365_DPI0_SEL_IN_RDMA1, MT8365_DPI0_SEL_IN_RDMA1
},
{
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL,
MT8365_RDMA1_SOUT_DPI0, MT8365_RDMA1_SOUT_DPI0
},
};
#endif /* __SOC_MEDIATEK_MT8365_MMSYS_H */
......@@ -31,10 +31,7 @@ struct mtk_devapc_vio_dbgs {
u32 vio_dbg1;
};
struct mtk_devapc_data {
/* numbers of violation index */
u32 vio_idx_num;
struct mtk_devapc_regs_ofs {
/* reg offset */
u32 vio_mask_offset;
u32 vio_sta_offset;
......@@ -46,6 +43,12 @@ struct mtk_devapc_data {
u32 vio_shift_con_offset;
};
struct mtk_devapc_data {
/* numbers of violation index */
u32 vio_idx_num;
const struct mtk_devapc_regs_ofs *regs_ofs;
};
struct mtk_devapc_context {
struct device *dev;
void __iomem *infra_base;
......@@ -58,7 +61,7 @@ static void clear_vio_status(struct mtk_devapc_context *ctx)
void __iomem *reg;
int i;
reg = ctx->infra_base + ctx->data->vio_sta_offset;
reg = ctx->infra_base + ctx->data->regs_ofs->vio_sta_offset;
for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->data->vio_idx_num) - 1; i++)
writel(GENMASK(31, 0), reg + 4 * i);
......@@ -73,7 +76,7 @@ static void mask_module_irq(struct mtk_devapc_context *ctx, bool mask)
u32 val;
int i;
reg = ctx->infra_base + ctx->data->vio_mask_offset;
reg = ctx->infra_base + ctx->data->regs_ofs->vio_mask_offset;
if (mask)
val = GENMASK(31, 0);
......@@ -116,11 +119,11 @@ static int devapc_sync_vio_dbg(struct mtk_devapc_context *ctx)
u32 val;
pd_vio_shift_sta_reg = ctx->infra_base +
ctx->data->vio_shift_sta_offset;
ctx->data->regs_ofs->vio_shift_sta_offset;
pd_vio_shift_sel_reg = ctx->infra_base +
ctx->data->vio_shift_sel_offset;
ctx->data->regs_ofs->vio_shift_sel_offset;
pd_vio_shift_con_reg = ctx->infra_base +
ctx->data->vio_shift_con_offset;
ctx->data->regs_ofs->vio_shift_con_offset;
/* Find the minimum shift group which has violation */
val = readl(pd_vio_shift_sta_reg);
......@@ -161,8 +164,8 @@ static void devapc_extract_vio_dbg(struct mtk_devapc_context *ctx)
void __iomem *vio_dbg0_reg;
void __iomem *vio_dbg1_reg;
vio_dbg0_reg = ctx->infra_base + ctx->data->vio_dbg0_offset;
vio_dbg1_reg = ctx->infra_base + ctx->data->vio_dbg1_offset;
vio_dbg0_reg = ctx->infra_base + ctx->data->regs_ofs->vio_dbg0_offset;
vio_dbg1_reg = ctx->infra_base + ctx->data->regs_ofs->vio_dbg1_offset;
vio_dbgs.vio_dbg0 = readl(vio_dbg0_reg);
vio_dbgs.vio_dbg1 = readl(vio_dbg1_reg);
......@@ -200,7 +203,7 @@ static irqreturn_t devapc_violation_irq(int irq_number, void *data)
*/
static void start_devapc(struct mtk_devapc_context *ctx)
{
writel(BIT(31), ctx->infra_base + ctx->data->apc_con_offset);
writel(BIT(31), ctx->infra_base + ctx->data->regs_ofs->apc_con_offset);
mask_module_irq(ctx, false);
}
......@@ -212,11 +215,10 @@ static void stop_devapc(struct mtk_devapc_context *ctx)
{
mask_module_irq(ctx, true);
writel(BIT(2), ctx->infra_base + ctx->data->apc_con_offset);
writel(BIT(2), ctx->infra_base + ctx->data->regs_ofs->apc_con_offset);
}
static const struct mtk_devapc_data devapc_mt6779 = {
.vio_idx_num = 511,
static const struct mtk_devapc_regs_ofs devapc_regs_ofs_mt6779 = {
.vio_mask_offset = 0x0,
.vio_sta_offset = 0x400,
.vio_dbg0_offset = 0x900,
......@@ -227,10 +229,23 @@ static const struct mtk_devapc_data devapc_mt6779 = {
.vio_shift_con_offset = 0xF20,
};
static const struct mtk_devapc_data devapc_mt6779 = {
.vio_idx_num = 511,
.regs_ofs = &devapc_regs_ofs_mt6779,
};
static const struct mtk_devapc_data devapc_mt8186 = {
.vio_idx_num = 519,
.regs_ofs = &devapc_regs_ofs_mt6779,
};
static const struct of_device_id mtk_devapc_dt_match[] = {
{
.compatible = "mediatek,mt6779-devapc",
.data = &devapc_mt6779,
}, {
.compatible = "mediatek,mt8186-devapc",
.data = &devapc_mt8186,
}, {
},
};
......
......@@ -7,10 +7,12 @@
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#define MT2701_MUTEX0_MOD0 0x2c
#define MT2701_MUTEX0_SOF0 0x30
......@@ -80,6 +82,15 @@
#define MT8183_MUTEX_MOD_DISP_GAMMA0 16
#define MT8183_MUTEX_MOD_DISP_DITHER0 17
#define MT8183_MUTEX_MOD_MDP_RDMA0 2
#define MT8183_MUTEX_MOD_MDP_RSZ0 4
#define MT8183_MUTEX_MOD_MDP_RSZ1 5
#define MT8183_MUTEX_MOD_MDP_TDSHP0 6
#define MT8183_MUTEX_MOD_MDP_WROT0 7
#define MT8183_MUTEX_MOD_MDP_WDMA 8
#define MT8183_MUTEX_MOD_MDP_AAL0 23
#define MT8183_MUTEX_MOD_MDP_CCORR0 24
#define MT8173_MUTEX_MOD_DISP_OVL0 11
#define MT8173_MUTEX_MOD_DISP_OVL1 12
#define MT8173_MUTEX_MOD_DISP_RDMA0 13
......@@ -110,6 +121,20 @@
#define MT8195_MUTEX_MOD_DISP_DP_INTF0 21
#define MT8195_MUTEX_MOD_DISP_PWM0 27
#define MT8365_MUTEX_MOD_DISP_OVL0 7
#define MT8365_MUTEX_MOD_DISP_OVL0_2L 8
#define MT8365_MUTEX_MOD_DISP_RDMA0 9
#define MT8365_MUTEX_MOD_DISP_RDMA1 10
#define MT8365_MUTEX_MOD_DISP_WDMA0 11
#define MT8365_MUTEX_MOD_DISP_COLOR0 12
#define MT8365_MUTEX_MOD_DISP_CCORR 13
#define MT8365_MUTEX_MOD_DISP_AAL 14
#define MT8365_MUTEX_MOD_DISP_GAMMA 15
#define MT8365_MUTEX_MOD_DISP_DITHER 16
#define MT8365_MUTEX_MOD_DISP_DSI0 17
#define MT8365_MUTEX_MOD_DISP_PWM0 20
#define MT8365_MUTEX_MOD_DISP_DPI0 22
#define MT2712_MUTEX_MOD_DISP_PWM2 10
#define MT2712_MUTEX_MOD_DISP_OVL0 11
#define MT2712_MUTEX_MOD_DISP_OVL1 12
......@@ -185,6 +210,7 @@ struct mtk_mutex_data {
const unsigned int *mutex_sof;
const unsigned int mutex_mod_reg;
const unsigned int mutex_sof_reg;
const unsigned int *mutex_table_mod;
const bool no_clk;
};
......@@ -194,6 +220,8 @@ struct mtk_mutex_ctx {
void __iomem *regs;
struct mtk_mutex mutex[10];
const struct mtk_mutex_data *data;
phys_addr_t addr;
struct cmdq_client_reg cmdq_reg;
};
static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
......@@ -272,6 +300,17 @@ static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0,
};
static const unsigned int mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8183_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RSZ0] = MT8183_MUTEX_MOD_MDP_RSZ0,
[MUTEX_MOD_IDX_MDP_RSZ1] = MT8183_MUTEX_MOD_MDP_RSZ1,
[MUTEX_MOD_IDX_MDP_TDSHP0] = MT8183_MUTEX_MOD_MDP_TDSHP0,
[MUTEX_MOD_IDX_MDP_WROT0] = MT8183_MUTEX_MOD_MDP_WROT0,
[MUTEX_MOD_IDX_MDP_WDMA] = MT8183_MUTEX_MOD_MDP_WDMA,
[MUTEX_MOD_IDX_MDP_AAL0] = MT8183_MUTEX_MOD_MDP_AAL0,
[MUTEX_MOD_IDX_MDP_CCORR0] = MT8183_MUTEX_MOD_MDP_CCORR0,
};
static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8186_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8186_MUTEX_MOD_DISP_CCORR0,
......@@ -315,6 +354,22 @@ static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_DP_INTF0] = MT8195_MUTEX_MOD_DISP_DP_INTF0,
};
static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
[DDP_COMPONENT_COLOR0] = MT8365_MUTEX_MOD_DISP_COLOR0,
[DDP_COMPONENT_DITHER0] = MT8365_MUTEX_MOD_DISP_DITHER,
[DDP_COMPONENT_DPI0] = MT8365_MUTEX_MOD_DISP_DPI0,
[DDP_COMPONENT_DSI0] = MT8365_MUTEX_MOD_DISP_DSI0,
[DDP_COMPONENT_GAMMA] = MT8365_MUTEX_MOD_DISP_GAMMA,
[DDP_COMPONENT_OVL0] = MT8365_MUTEX_MOD_DISP_OVL0,
[DDP_COMPONENT_OVL_2L0] = MT8365_MUTEX_MOD_DISP_OVL0_2L,
[DDP_COMPONENT_PWM0] = MT8365_MUTEX_MOD_DISP_PWM0,
[DDP_COMPONENT_RDMA0] = MT8365_MUTEX_MOD_DISP_RDMA0,
[DDP_COMPONENT_RDMA1] = MT8365_MUTEX_MOD_DISP_RDMA1,
[DDP_COMPONENT_WDMA0] = MT8365_MUTEX_MOD_DISP_WDMA0,
};
static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
......@@ -399,6 +454,7 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = {
.mutex_sof = mt8183_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.mutex_table_mod = mt8183_mutex_table_mod,
.no_clk = true,
};
......@@ -423,6 +479,14 @@ static const struct mtk_mutex_data mt8195_mutex_driver_data = {
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
};
static const struct mtk_mutex_data mt8365_mutex_driver_data = {
.mutex_mod = mt8365_mutex_mod,
.mutex_sof = mt8183_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.no_clk = true,
};
struct mtk_mutex *mtk_mutex_get(struct device *dev)
{
struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev);
......@@ -572,6 +636,30 @@ void mtk_mutex_enable(struct mtk_mutex *mutex)
}
EXPORT_SYMBOL_GPL(mtk_mutex_enable);
int mtk_mutex_enable_by_cmdq(struct mtk_mutex *mutex, void *pkt)
{
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
mutex[mutex->id]);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
struct cmdq_pkt *cmdq_pkt = (struct cmdq_pkt *)pkt;
WARN_ON(&mtx->mutex[mutex->id] != mutex);
if (!mtx->cmdq_reg.size) {
dev_err(mtx->dev, "mediatek,gce-client-reg hasn't been set");
return -EINVAL;
}
cmdq_pkt_write(cmdq_pkt, mtx->cmdq_reg.subsys,
mtx->addr + DISP_REG_MUTEX_EN(mutex->id), 1);
return 0;
#else
dev_err(mtx->dev, "Not support for enable MUTEX by CMDQ");
return -ENODEV;
#endif
}
EXPORT_SYMBOL_GPL(mtk_mutex_enable_by_cmdq);
void mtk_mutex_disable(struct mtk_mutex *mutex)
{
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
......@@ -606,12 +694,67 @@ void mtk_mutex_release(struct mtk_mutex *mutex)
}
EXPORT_SYMBOL_GPL(mtk_mutex_release);
int mtk_mutex_write_mod(struct mtk_mutex *mutex,
enum mtk_mutex_mod_index idx, bool clear)
{
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
mutex[mutex->id]);
unsigned int reg;
unsigned int offset;
WARN_ON(&mtx->mutex[mutex->id] != mutex);
if (idx < MUTEX_MOD_IDX_MDP_RDMA0 ||
idx >= MUTEX_MOD_IDX_MAX) {
dev_err(mtx->dev, "Not supported MOD table index : %d", idx);
return -EINVAL;
}
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
reg = readl_relaxed(mtx->regs + offset);
if (clear)
reg &= ~BIT(mtx->data->mutex_table_mod[idx]);
else
reg |= BIT(mtx->data->mutex_table_mod[idx]);
writel_relaxed(reg, mtx->regs + offset);
return 0;
}
EXPORT_SYMBOL_GPL(mtk_mutex_write_mod);
int mtk_mutex_write_sof(struct mtk_mutex *mutex,
enum mtk_mutex_sof_index idx)
{
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
mutex[mutex->id]);
WARN_ON(&mtx->mutex[mutex->id] != mutex);
if (idx < MUTEX_SOF_IDX_SINGLE_MODE ||
idx >= MUTEX_SOF_IDX_MAX) {
dev_err(mtx->dev, "Not supported SOF index : %d", idx);
return -EINVAL;
}
writel_relaxed(idx, mtx->regs +
DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
return 0;
}
EXPORT_SYMBOL_GPL(mtk_mutex_write_sof);
static int mtk_mutex_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_mutex_ctx *mtx;
struct resource *regs;
int i;
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
int ret;
#endif
mtx = devm_kzalloc(dev, sizeof(*mtx), GFP_KERNEL);
if (!mtx)
......@@ -631,12 +774,18 @@ static int mtk_mutex_probe(struct platform_device *pdev)
}
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mtx->regs = devm_ioremap_resource(dev, regs);
mtx->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
if (IS_ERR(mtx->regs)) {
dev_err(dev, "Failed to map mutex registers\n");
return PTR_ERR(mtx->regs);
}
mtx->addr = regs->start;
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &mtx->cmdq_reg, 0);
if (ret)
dev_dbg(dev, "No mediatek,gce-client-reg!\n");
#endif
platform_set_drvdata(pdev, mtx);
......@@ -665,6 +814,8 @@ static const struct of_device_id mutex_driver_dt_match[] = {
.data = &mt8192_mutex_driver_data},
{ .compatible = "mediatek,mt8195-disp-mutex",
.data = &mt8195_mutex_driver_data},
{ .compatible = "mediatek,mt8365-disp-mutex",
.data = &mt8365_mutex_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mutex_driver_dt_match);
......
......@@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/soc/mediatek/infracfg.h>
#include "mt6795-pm-domains.h"
#include "mt8167-pm-domains.h"
#include "mt8173-pm-domains.h"
#include "mt8183-pm-domains.h"
......@@ -428,6 +429,9 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
goto err_put_subsys_clocks;
}
if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
}
if (scpsys->domains[id]) {
......@@ -555,6 +559,10 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
}
static const struct of_device_id scpsys_of_match[] = {
{
.compatible = "mediatek,mt6795-power-controller",
.data = &mt6795_scpsys_data,
},
{
.compatible = "mediatek,mt8167-power-controller",
.data = &mt8167_scpsys_data,
......
......@@ -8,6 +8,8 @@
#define MTK_SCPD_SRAM_ISO BIT(2)
#define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3)
#define MTK_SCPD_DOMAIN_SUPPLY BIT(4)
/* can't set MTK_SCPD_KEEP_DEFAULT_OFF at the same time */
#define MTK_SCPD_ALWAYS_ON BIT(5)
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
#define SPM_VDE_PWR_CON 0x0210
......
This diff is collapsed.
This diff is collapsed.
......@@ -129,7 +129,10 @@ config QCOM_RPMHPD
config QCOM_RPMPD
tristate "Qualcomm RPM Power domain driver"
depends on PM
depends on QCOM_SMD_RPM
select PM_GENERIC_DOMAINS
select PM_GENERIC_DOMAINS_OF
help
QCOM RPM Power domain driver to support power-domains with
performance states. The driver communicates a performance state
......@@ -228,4 +231,19 @@ config QCOM_APR
application processor and QDSP6. APR is
used by audio driver to configure QDSP6
ASM, ADM and AFE modules.
config QCOM_ICC_BWMON
tristate "QCOM Interconnect Bandwidth Monitor driver"
depends on ARCH_QCOM || COMPILE_TEST
select PM_OPP
help
Sets up driver monitoring bandwidth on various interconnects and
based on that voting for interconnect bandwidth, adjusting their
speed to current demand.
Current implementation brings support for BWMON v4, used for example
on SDM845 to measure bandwidth between CPU (gladiator_noc) and Last
Level Cache (memnoc). Usage of this BWMON allows to remove some of
the fixed bandwidth votes from cpufreq (CPU nodes) thus achieve high
memory throughput even with lower CPU frequencies.
endmenu
......@@ -28,3 +28,4 @@ obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o
obj-$(CONFIG_QCOM_ICC_BWMON) += icc-bwmon.o
......@@ -377,17 +377,14 @@ static int apr_device_probe(struct device *dev)
static void apr_device_remove(struct device *dev)
{
struct apr_device *adev = to_apr_device(dev);
struct apr_driver *adrv;
struct apr_driver *adrv = to_apr_driver(dev->driver);
struct packet_router *apr = dev_get_drvdata(adev->dev.parent);
if (dev->driver) {
adrv = to_apr_driver(dev->driver);
if (adrv->remove)
adrv->remove(adev);
spin_lock(&apr->svcs_lock);
idr_remove(&apr->svcs_idr, adev->svc.id);
spin_unlock(&apr->svcs_lock);
}
if (adrv->remove)
adrv->remove(adev);
spin_lock(&apr->svcs_lock);
idr_remove(&apr->svcs_idr, adev->svc.id);
spin_unlock(&apr->svcs_lock);
}
static int apr_uevent(struct device *dev, struct kobj_uevent_env *env)
......
......@@ -141,13 +141,17 @@ static int cmd_db_get_header(const char *id, const struct entry_header **eh,
const struct rsc_hdr *rsc_hdr;
const struct entry_header *ent;
int ret, i, j;
u8 query[8];
u8 query[sizeof(ent->id)] __nonstring;
ret = cmd_db_ready();
if (ret)
return ret;
/* Pad out query string to same length as in DB */
/*
* Pad out query string to same length as in DB. NOTE: the output
* query string is not necessarily '\0' terminated if it bumps up
* against the max size. That's OK and expected.
*/
strncpy(query, id, sizeof(query));
for (i = 0; i < MAX_SLV_ID; i++) {
......
This diff is collapsed.
......@@ -382,7 +382,7 @@ static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
* llcc_slice_getd - get llcc slice descriptor
* @uid: usecase_id for the client
*
* A pointer to llcc slice descriptor will be returned on success and
* A pointer to llcc slice descriptor will be returned on success
* and error pointer is returned on failure
*/
struct llcc_slice_desc *llcc_slice_getd(u32 uid)
......
......@@ -108,6 +108,8 @@ EXPORT_SYMBOL_GPL(qcom_mdt_get_size);
* qcom_mdt_read_metadata() - read header and metadata from mdt or mbn
* @fw: firmware of mdt header or mbn
* @data_len: length of the read metadata blob
* @fw_name: name of the firmware, for construction of segment file names
* @dev: device handle to associate resources with
*
* The mechanism that performs the authentication of the loading firmware
* expects an ELF header directly followed by the segment of hashes, with no
......@@ -192,7 +194,7 @@ EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);
* qcom_mdt_pas_init() - initialize PAS region for firmware loading
* @dev: device handle to associate resources with
* @fw: firmware object for the mdt file
* @firmware: name of the firmware, for construction of segment file names
* @fw_name: name of the firmware, for construction of segment file names
* @pas_id: PAS identifier
* @mem_phys: physical address of allocated memory region
* @ctx: PAS metadata context, to be released by caller
......
......@@ -194,14 +194,17 @@ struct ocmem *of_get_ocmem(struct device *dev)
devnode = of_parse_phandle(dev->of_node, "sram", 0);
if (!devnode || !devnode->parent) {
dev_err(dev, "Cannot look up sram phandle\n");
of_node_put(devnode);
return ERR_PTR(-ENODEV);
}
pdev = of_find_device_by_node(devnode->parent);
if (!pdev) {
dev_err(dev, "Cannot find device node %s\n", devnode->name);
of_node_put(devnode);
return ERR_PTR(-EPROBE_DEFER);
}
of_node_put(devnode);
ocmem = platform_get_drvdata(pdev);
if (!ocmem) {
......
......@@ -399,8 +399,10 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
continue;
ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
child);
if (ret)
if (ret) {
of_node_put(child);
goto unroll;
}
}
if (!count)
......
......@@ -23,8 +23,8 @@
/**
* struct rpmhpd - top level RPMh power domain resource data structure
* @dev: rpmh power domain controller device
* @pd: generic_pm_domain corrresponding to the power domain
* @parent: generic_pm_domain corrresponding to the parent's power domain
* @pd: generic_pm_domain corresponding to the power domain
* @parent: generic_pm_domain corresponding to the parent's power domain
* @peer: A peer power domain in case Active only Voting is
* supported
* @active_only: True if it represents an Active only peer
......
......@@ -453,6 +453,7 @@ static const struct rpmpd_desc qcm2290_desc = {
static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
{ .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
{ .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
{ .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
......
......@@ -234,6 +234,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-apq8084" },
{ .compatible = "qcom,rpm-ipq6018" },
{ .compatible = "qcom,rpm-msm8226" },
{ .compatible = "qcom,rpm-msm8909" },
{ .compatible = "qcom,rpm-msm8916" },
{ .compatible = "qcom,rpm-msm8936" },
{ .compatible = "qcom,rpm-msm8953" },
......
......@@ -119,6 +119,9 @@ struct smp2p_entry {
* @out: pointer to the outbound smem item
* @smem_items: ids of the two smem items
* @valid_entries: already scanned inbound entries
* @ssr_ack_enabled: SMP2P_FEATURE_SSR_ACK feature is supported and was enabled
* @ssr_ack: current cached state of the local ack bit
* @negotiation_done: whether negotiating finished
* @local_pid: processor id of the inbound edge
* @remote_pid: processor id of the outbound edge
* @ipc_regmap: regmap for the outbound ipc
......
......@@ -328,10 +328,12 @@ static const struct soc_id soc_id[] = {
{ 455, "QRB5165" },
{ 457, "SM8450" },
{ 459, "SM7225" },
{ 460, "SA8540P" },
{ 460, "SA8295P" },
{ 461, "SA8540P" },
{ 480, "SM8450" },
{ 482, "SM8450" },
{ 487, "SC7280" },
{ 495, "SC7180P" },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
......
......@@ -74,6 +74,18 @@ static const u16 spm_reg_offset_v3_0[SPM_REG_NR] = {
[SPM_REG_SEQ_ENTRY] = 0x400,
};
/* SPM register data for 8909 */
static const struct spm_reg_data spm_reg_8909_cpu = {
.reg_offset = spm_reg_offset_v3_0,
.spm_cfg = 0x1,
.spm_dly = 0x3C102800,
.seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90,
0x5B, 0x60, 0x03, 0x60, 0x76, 0x76, 0x0B, 0x94, 0x5B, 0x80,
0x10, 0x26, 0x30, 0x0F },
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 5,
};
/* SPM register data for 8916 */
static const struct spm_reg_data spm_reg_8916_cpu = {
.reg_offset = spm_reg_offset_v3_0,
......@@ -195,6 +207,8 @@ static const struct of_device_id spm_match_table[] = {
.data = &spm_reg_660_silver_l2 },
{ .compatible = "qcom,msm8226-saw2-v2.1-cpu",
.data = &spm_reg_8226_cpu },
{ .compatible = "qcom,msm8909-saw2-v3.0-cpu",
.data = &spm_reg_8909_cpu },
{ .compatible = "qcom,msm8916-saw2-v3.0-cpu",
.data = &spm_reg_8916_cpu },
{ .compatible = "qcom,msm8974-saw2-v2.1-cpu",
......
......@@ -57,11 +57,11 @@ static struct rcar_gen4_sysc_area r8a779a0_areas[] __initdata = {
{ "a2cv6", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR },
{ "a2cn2", R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR },
{ "a2imp23", R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR },
{ "a2dp1", R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR },
{ "a2cv2", R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR },
{ "a2cv3", R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR },
{ "a2cv5", R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR },
{ "a2cv7", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR },
{ "a2dp1", R8A779A0_PD_A2DP1, R8A779A0_PD_A3IR },
{ "a2cv2", R8A779A0_PD_A2CV2, R8A779A0_PD_A3IR },
{ "a2cv3", R8A779A0_PD_A2CV3, R8A779A0_PD_A3IR },
{ "a2cv5", R8A779A0_PD_A2CV5, R8A779A0_PD_A3IR },
{ "a2cv7", R8A779A0_PD_A2CV7, R8A779A0_PD_A3IR },
{ "a2cn1", R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR },
{ "a1cnn0", R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 },
{ "a1cnn2", R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 },
......
......@@ -25,8 +25,8 @@
struct rcar_gen4_sysc_area {
const char *name;
u8 pdr; /* PDRn */
int parent; /* -1 if none */
unsigned int flags; /* See PD_* */
s8 parent; /* -1 if none */
u8 flags; /* See PD_* */
};
/*
......
......@@ -31,8 +31,8 @@ struct rcar_sysc_area {
u16 chan_offs; /* Offset of PWRSR register for this area */
u8 chan_bit; /* Bit in PWR* (except for PWRUP in PWRSR) */
u8 isr_bit; /* Bit in SYSCI*R */
int parent; /* -1 if none */
unsigned int flags; /* See PD_* */
s8 parent; /* -1 if none */
u8 flags; /* See PD_* */
};
......
......@@ -6,6 +6,7 @@
config SUNXI_MBUS
bool
default ARCH_SUNXI
depends on ARM || ARM64
help
Say y to enable the fixups needed to support the Allwinner
MBUS DMA quirks.
......
......@@ -338,6 +338,7 @@ static const struct of_device_id pruss_of_match[] = {
{ .compatible = "ti,am654-icssg", .data = &am65x_j721e_pruss_data, },
{ .compatible = "ti,j721e-icssg", .data = &am65x_j721e_pruss_data, },
{ .compatible = "ti,am642-icssg", .data = &am65x_j721e_pruss_data, },
{ .compatible = "ti,am625-pruss", .data = &am65x_j721e_pruss_data, },
{},
};
MODULE_DEVICE_TABLE(of, pruss_of_match);
......
......@@ -688,7 +688,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
&m3_ipc->sd_fw_name);
if (ret) {
dev_dbg(dev, "Voltage scaling data blob not provided from DT.\n");
};
}
/*
* Wait for firmware loading completion in a thread so we
......
......@@ -183,7 +183,7 @@ config SPI_BCM63XX
config SPI_BCM63XX_HSSPI
tristate "Broadcom BCM63XX HS SPI controller driver"
depends on BCM63XX || BMIPS_GENERIC || ARCH_BCM_63XX || COMPILE_TEST
depends on BCM63XX || BMIPS_GENERIC || ARCH_BCMBCA || COMPILE_TEST
help
This enables support for the High Speed SPI controller present on
newer Broadcom BCM63XX SoCs.
......
......@@ -1099,8 +1099,8 @@ config SERIAL_TIMBERDALE
config SERIAL_BCM63XX
tristate "Broadcom BCM63xx/BCM33xx UART support"
select SERIAL_CORE
depends on ARCH_BCM4908 || ARCH_BCM_63XX || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
default ARCH_BCM4908 || ARCH_BCM_63XX || BCM63XX || BMIPS_GENERIC
depends on ARCH_BCM4908 || ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
default ARCH_BCM4908 || ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC
help
This enables the driver for the onchip UART core found on
the following chipsets:
......
......@@ -164,10 +164,111 @@
#define TEGRA234_CLK_PEX1_C5_CORE 225U
/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC4_BASE */
#define TEGRA234_CLK_PLLC4 237U
/** @brief RX clock recovered from MGBE0 lane input */
#define TEGRA234_CLK_MGBE0_RX_INPUT 248U
/** @brief RX clock recovered from MGBE1 lane input */
#define TEGRA234_CLK_MGBE1_RX_INPUT 249U
/** @brief RX clock recovered from MGBE2 lane input */
#define TEGRA234_CLK_MGBE2_RX_INPUT 250U
/** @brief RX clock recovered from MGBE3 lane input */
#define TEGRA234_CLK_MGBE3_RX_INPUT 251U
/** @brief 32K input clock provided by PMIC */
#define TEGRA234_CLK_CLK_32K 289U
/** @brief Monitored branch of MBGE0 RX input clock */
#define TEGRA234_CLK_MGBE0_RX_INPUT_M 357U
/** @brief Monitored branch of MBGE1 RX input clock */
#define TEGRA234_CLK_MGBE1_RX_INPUT_M 358U
/** @brief Monitored branch of MBGE2 RX input clock */
#define TEGRA234_CLK_MGBE2_RX_INPUT_M 359U
/** @brief Monitored branch of MBGE3 RX input clock */
#define TEGRA234_CLK_MGBE3_RX_INPUT_M 360U
/** @brief Monitored branch of MGBE0 RX PCS mux output */
#define TEGRA234_CLK_MGBE0_RX_PCS_M 361U
/** @brief Monitored branch of MGBE1 RX PCS mux output */
#define TEGRA234_CLK_MGBE1_RX_PCS_M 362U
/** @brief Monitored branch of MGBE2 RX PCS mux output */
#define TEGRA234_CLK_MGBE2_RX_PCS_M 363U
/** @brief Monitored branch of MGBE3 RX PCS mux output */
#define TEGRA234_CLK_MGBE3_RX_PCS_M 364U
/** @brief RX PCS clock recovered from MGBE0 lane input */
#define TEGRA234_CLK_MGBE0_RX_PCS_INPUT 369U
/** @brief RX PCS clock recovered from MGBE1 lane input */
#define TEGRA234_CLK_MGBE1_RX_PCS_INPUT 370U
/** @brief RX PCS clock recovered from MGBE2 lane input */
#define TEGRA234_CLK_MGBE2_RX_PCS_INPUT 371U
/** @brief RX PCS clock recovered from MGBE3 lane input */
#define TEGRA234_CLK_MGBE3_RX_PCS_INPUT 372U
/** @brief output of mux controlled by GBE_UPHY_MGBE0_RX_PCS_CLK_SRC_SEL */
#define TEGRA234_CLK_MGBE0_RX_PCS 373U
/** @brief GBE_UPHY_MGBE0_TX_CLK divider gated output */
#define TEGRA234_CLK_MGBE0_TX 374U
/** @brief GBE_UPHY_MGBE0_TX_PCS_CLK divider gated output */
#define TEGRA234_CLK_MGBE0_TX_PCS 375U
/** @brief GBE_UPHY_MGBE0_MAC_CLK divider output */
#define TEGRA234_CLK_MGBE0_MAC_DIVIDER 376U
/** @brief GBE_UPHY_MGBE0_MAC_CLK gate output */
#define TEGRA234_CLK_MGBE0_MAC 377U
/** @brief GBE_UPHY_MGBE0_MACSEC_CLK gate output */
#define TEGRA234_CLK_MGBE0_MACSEC 378U
/** @brief GBE_UPHY_MGBE0_EEE_PCS_CLK gate output */
#define TEGRA234_CLK_MGBE0_EEE_PCS 379U
/** @brief GBE_UPHY_MGBE0_APP_CLK gate output */
#define TEGRA234_CLK_MGBE0_APP 380U
/** @brief GBE_UPHY_MGBE0_PTP_REF_CLK divider gated output */
#define TEGRA234_CLK_MGBE0_PTP_REF 381U
/** @brief output of mux controlled by GBE_UPHY_MGBE1_RX_PCS_CLK_SRC_SEL */
#define TEGRA234_CLK_MGBE1_RX_PCS 382U
/** @brief GBE_UPHY_MGBE1_TX_CLK divider gated output */
#define TEGRA234_CLK_MGBE1_TX 383U
/** @brief GBE_UPHY_MGBE1_TX_PCS_CLK divider gated output */
#define TEGRA234_CLK_MGBE1_TX_PCS 384U
/** @brief GBE_UPHY_MGBE1_MAC_CLK divider output */
#define TEGRA234_CLK_MGBE1_MAC_DIVIDER 385U
/** @brief GBE_UPHY_MGBE1_MAC_CLK gate output */
#define TEGRA234_CLK_MGBE1_MAC 386U
/** @brief GBE_UPHY_MGBE1_EEE_PCS_CLK gate output */
#define TEGRA234_CLK_MGBE1_EEE_PCS 388U
/** @brief GBE_UPHY_MGBE1_APP_CLK gate output */
#define TEGRA234_CLK_MGBE1_APP 389U
/** @brief GBE_UPHY_MGBE1_PTP_REF_CLK divider gated output */
#define TEGRA234_CLK_MGBE1_PTP_REF 390U
/** @brief output of mux controlled by GBE_UPHY_MGBE2_RX_PCS_CLK_SRC_SEL */
#define TEGRA234_CLK_MGBE2_RX_PCS 391U
/** @brief GBE_UPHY_MGBE2_TX_CLK divider gated output */
#define TEGRA234_CLK_MGBE2_TX 392U
/** @brief GBE_UPHY_MGBE2_TX_PCS_CLK divider gated output */
#define TEGRA234_CLK_MGBE2_TX_PCS 393U
/** @brief GBE_UPHY_MGBE2_MAC_CLK divider output */
#define TEGRA234_CLK_MGBE2_MAC_DIVIDER 394U
/** @brief GBE_UPHY_MGBE2_MAC_CLK gate output */
#define TEGRA234_CLK_MGBE2_MAC 395U
/** @brief GBE_UPHY_MGBE2_EEE_PCS_CLK gate output */
#define TEGRA234_CLK_MGBE2_EEE_PCS 397U
/** @brief GBE_UPHY_MGBE2_APP_CLK gate output */
#define TEGRA234_CLK_MGBE2_APP 398U
/** @brief GBE_UPHY_MGBE2_PTP_REF_CLK divider gated output */
#define TEGRA234_CLK_MGBE2_PTP_REF 399U
/** @brief output of mux controlled by GBE_UPHY_MGBE3_RX_PCS_CLK_SRC_SEL */
#define TEGRA234_CLK_MGBE3_RX_PCS 400U
/** @brief GBE_UPHY_MGBE3_TX_CLK divider gated output */
#define TEGRA234_CLK_MGBE3_TX 401U
/** @brief GBE_UPHY_MGBE3_TX_PCS_CLK divider gated output */
#define TEGRA234_CLK_MGBE3_TX_PCS 402U
/** @brief GBE_UPHY_MGBE3_MAC_CLK divider output */
#define TEGRA234_CLK_MGBE3_MAC_DIVIDER 403U
/** @brief GBE_UPHY_MGBE3_MAC_CLK gate output */
#define TEGRA234_CLK_MGBE3_MAC 404U
/** @brief GBE_UPHY_MGBE3_MACSEC_CLK gate output */
#define TEGRA234_CLK_MGBE3_MACSEC 405U
/** @brief GBE_UPHY_MGBE3_EEE_PCS_CLK gate output */
#define TEGRA234_CLK_MGBE3_EEE_PCS 406U
/** @brief GBE_UPHY_MGBE3_APP_CLK gate output */
#define TEGRA234_CLK_MGBE3_APP 407U
/** @brief GBE_UPHY_MGBE3_PTP_REF_CLK divider gated output */
#define TEGRA234_CLK_MGBE3_PTP_REF 408U
/** @brief CLK_RST_CONTROLLER_AZA2XBITCLK_OUT_SWITCH_DIVIDER switch divider output (aza_2xbitclk) */
#define TEGRA234_CLK_AZA_2XBIT 457U
/** @brief aza_2xbitclk / 2 (aza_bitclk) */
#define TEGRA234_CLK_AZA_BIT 458U
#endif
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
#ifndef _DT_BINDINGS_POWER_MT6795_POWER_H
#define _DT_BINDINGS_POWER_MT6795_POWER_H
#define MT6795_POWER_DOMAIN_MM 0
#define MT6795_POWER_DOMAIN_VDEC 1
#define MT6795_POWER_DOMAIN_VENC 2
#define MT6795_POWER_DOMAIN_ISP 3
#define MT6795_POWER_DOMAIN_MJC 4
#define MT6795_POWER_DOMAIN_AUDIO 5
#define MT6795_POWER_DOMAIN_MFG_ASYNC 6
#define MT6795_POWER_DOMAIN_MFG_2D 7
#define MT6795_POWER_DOMAIN_MFG 8
#define MT6795_POWER_DOMAIN_MODEM 9
#endif /* _DT_BINDINGS_POWER_MT6795_POWER_H */
......@@ -187,6 +187,13 @@
#define MSM8916_VDDMX 3
#define MSM8916_VDDMX_AO 4
/* MSM8909 Power Domain Indexes */
#define MSM8909_VDDCX MSM8916_VDDCX
#define MSM8909_VDDCX_AO MSM8916_VDDCX_AO
#define MSM8909_VDDCX_VFC MSM8916_VDDCX_VFC
#define MSM8909_VDDMX MSM8916_VDDMX
#define MSM8909_VDDMX_AO MSM8916_VDDMX_AO
/* MSM8953 Power Domain Indexes */
#define MSM8953_VDDMD 0
#define MSM8953_VDDMD_AO 1
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment