Commit b4bc93bd authored by Linus Torvalds's avatar Linus Torvalds

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

Pull ARM driver updates from Arnd Bergmann:
 "There are a few separately maintained driver subsystems that we merge
  through the SoC tree, notable changes are:

   - Memory controller updates, mainly for Tegra and Mediatek SoCs, and
     clarifications for the memory controller DT bindings

   - SCMI firmware interface updates, in particular a new transport
     based on OPTEE and support for atomic operations.

   - Cleanups to the TEE subsystem, refactoring its memory management

  For SoC specific drivers without a separate subsystem, changes include

   - Smaller updates and fixes for TI, AT91/SAMA5, Qualcomm and NXP
     Layerscape SoCs.

   - Driver support for Microchip SAMA5D29, Tesla FSD, Renesas RZ/G2L,
     and Qualcomm SM8450.

   - Better power management on Mediatek MT81xx, NXP i.MX8MQ and older
     NVIDIA Tegra chips"

* tag 'arm-drivers-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (154 commits)
  ARM: spear: fix typos in comments
  soc/microchip: fix invalid free in mpfs_sys_controller_delete
  soc: s4: Add support for power domains controller
  dt-bindings: power: add Amlogic s4 power domains bindings
  ARM: at91: add support in soc driver for new SAMA5D29
  soc: mediatek: mmsys: add sw0_rst_offset in mmsys driver data
  dt-bindings: memory: renesas,rpc-if: Document RZ/V2L SoC
  memory: emif: check the pointer temp in get_device_details()
  memory: emif: Add check for setup_interrupts
  dt-bindings: arm: mediatek: mmsys: add support for MT8186
  dt-bindings: mediatek: add compatible for MT8186 pwrap
  soc: mediatek: pwrap: add pwrap driver for MT8186 SoC
  soc: mediatek: mmsys: add mmsys reset control for MT8186
  soc: mediatek: mtk-infracfg: Disable ACP on MT8192
  soc: ti: k3-socinfo: Add AM62x JTAG ID
  soc: mediatek: add MTK mutex support for MT8186
  soc: mediatek: mmsys: add mt8186 mmsys routing table
  soc: mediatek: pm-domains: Add support for mt8186
  dt-bindings: power: Add MT8186 power domains
  soc: mediatek: pm-domains: Add support for mt8195
  ...
parents baaa68a9 339ac71b
......@@ -29,6 +29,7 @@ properties:
- mediatek,mt8167-mmsys
- mediatek,mt8173-mmsys
- mediatek,mt8183-mmsys
- mediatek,mt8186-mmsys
- mediatek,mt8192-mmsys
- mediatek,mt8365-mmsys
- const: syscon
......
......@@ -27,6 +27,8 @@ properties:
- qcom,sm6350-llcc
- qcom,sm8150-llcc
- qcom,sm8250-llcc
- qcom,sm8350-llcc
- qcom,sm8450-llcc
reg:
items:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/tesla,fsd-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tesla FSD (Full Self-Driving) SoC clock controller
maintainers:
- Alim Akhtar <alim.akhtar@samsung.com>
- linux-fsd@tesla.com
description: |
FSD clock controller consist of several clock management unit
(CMU), which generates clocks for various inteernal SoC blocks.
The root clock comes from external OSC clock (24 MHz).
All available clocks are defined as preprocessor macros in
'dt-bindings/clock/fsd-clk.h' header.
properties:
compatible:
enum:
- tesla,fsd-clock-cmu
- tesla,fsd-clock-imem
- tesla,fsd-clock-peric
- tesla,fsd-clock-fsys0
- tesla,fsd-clock-fsys1
- tesla,fsd-clock-mfc
- tesla,fsd-clock-cam_csi
clocks:
minItems: 1
maxItems: 6
clock-names:
minItems: 1
maxItems: 6
"#clock-cells":
const: 1
reg:
maxItems: 1
allOf:
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-cmu
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
clock-names:
items:
- const: fin_pll
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-imem
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
- description: IMEM TCU clock (from CMU_CMU)
- description: IMEM bus clock (from CMU_CMU)
- description: IMEM DMA clock (from CMU_CMU)
clock-names:
items:
- const: fin_pll
- const: dout_cmu_imem_tcuclk
- const: dout_cmu_imem_aclk
- const: dout_cmu_imem_dmaclk
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-peric
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
- description: Shared0 PLL div4 clock (from CMU_CMU)
- description: PERIC shared1 div36 clock (from CMU_CMU)
- description: PERIC shared0 div3 TBU clock (from CMU_CMU)
- description: PERIC shared0 div20 clock (from CMU_CMU)
- description: PERIC shared1 div4 DMAclock (from CMU_CMU)
clock-names:
items:
- const: fin_pll
- const: dout_cmu_pll_shared0_div4
- const: dout_cmu_peric_shared1div36
- const: dout_cmu_peric_shared0div3_tbuclk
- const: dout_cmu_peric_shared0div20
- const: dout_cmu_peric_shared1div4_dmaclk
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-fsys0
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
- description: Shared0 PLL div6 clock (from CMU_CMU)
- description: FSYS0 shared1 div4 clock (from CMU_CMU)
- description: FSYS0 shared0 div4 clock (from CMU_CMU)
clock-names:
items:
- const: fin_pll
- const: dout_cmu_pll_shared0_div6
- const: dout_cmu_fsys0_shared1div4
- const: dout_cmu_fsys0_shared0div4
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-fsys1
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
- description: FSYS1 shared0 div8 clock (from CMU_CMU)
- description: FSYS1 shared0 div4 clock (from CMU_CMU)
clock-names:
items:
- const: fin_pll
- const: dout_cmu_fsys1_shared0div8
- const: dout_cmu_fsys1_shared0div4
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-mfc
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
clock-names:
items:
- const: fin_pll
- if:
properties:
compatible:
contains:
const: tesla,fsd-clock-cam_csi
then:
properties:
clocks:
items:
- description: External reference clock (24 MHz)
clock-names:
items:
- const: fin_pll
required:
- compatible
- "#clock-cells"
- clocks
- clock-names
- reg
additionalProperties: false
examples:
# Clock controller node for CMU_FSYS1
- |
#include <dt-bindings/clock/fsd-clk.h>
clock_fsys1: clock-controller@16810000 {
compatible = "tesla,fsd-clock-fsys1";
reg = <0x16810000 0x3000>;
#clock-cells = <1>;
clocks = <&fin_pll>,
<&clock_cmu DOUT_CMU_FSYS1_SHARED0DIV8>,
<&clock_cmu DOUT_CMU_FSYS1_SHARED0DIV4>;
clock-names = "fin_pll",
"dout_cmu_fsys1_shared0div8",
"dout_cmu_fsys1_shared0div4";
};
...
......@@ -38,6 +38,9 @@ properties:
The virtio transport only supports a single device.
items:
- const: arm,scmi-virtio
- description: SCMI compliant firmware with OP-TEE transport
items:
- const: linaro,scmi-optee
interrupts:
description:
......@@ -78,11 +81,24 @@ properties:
'#size-cells':
const: 0
atomic-threshold-us:
description:
An optional time value, expressed in microseconds, representing, on this
platform, the threshold above which any SCMI command, advertised to have
an higher-than-threshold execution latency, should not be considered for
atomic mode of operation, even if requested.
default: 0
arm,smc-id:
$ref: /schemas/types.yaml#/definitions/uint32
description:
SMC id required when using smc or hvc transports
linaro,optee-channel-id:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Channel specifier required when using OP-TEE transport.
protocol@11:
type: object
properties:
......@@ -195,6 +211,12 @@ patternProperties:
minItems: 1
maxItems: 2
linaro,optee-channel-id:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Channel specifier required when using OP-TEE transport and
protocol has a dedicated communication channel.
required:
- reg
......@@ -226,6 +248,16 @@ else:
- arm,smc-id
- shmem
else:
if:
properties:
compatible:
contains:
const: linaro,scmi-optee
then:
required:
- linaro,optee-channel-id
examples:
- |
firmware {
......@@ -240,6 +272,8 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
atomic-threshold-us = <10000>;
scmi_devpd: protocol@11 {
reg = <0x11>;
#power-domain-cells = <1>;
......@@ -340,7 +374,48 @@ examples:
reg = <0x11>;
#power-domain-cells = <1>;
};
};
};
- |
firmware {
scmi {
compatible = "linaro,scmi-optee";
linaro,optee-channel-id = <0>;
#address-cells = <1>;
#size-cells = <0>;
scmi_dvfs1: protocol@13 {
reg = <0x13>;
linaro,optee-channel-id = <1>;
shmem = <&cpu_optee_lpri0>;
#clock-cells = <1>;
};
scmi_clk0: protocol@14 {
reg = <0x14>;
#clock-cells = <1>;
};
};
};
soc {
#address-cells = <2>;
#size-cells = <2>;
sram@51000000 {
compatible = "mmio-sram";
reg = <0x0 0x51000000 0x0 0x10000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x0 0x51000000 0x10000>;
cpu_optee_lpri0: optee-sram-section@0 {
compatible = "arm,scmi-shmem";
reg = <0x0 0x80>;
};
};
};
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr2-timings.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPDDR2 SDRAM AC timing parameters for a given speed-bin
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
properties:
compatible:
const: jedec,lpddr2-timings
max-freq:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Maximum DDR clock frequency for the speed-bin, in Hz.
min-freq:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Minimum DDR clock frequency for the speed-bin, in Hz.
tCKESR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
CKE minimum pulse width during SELF REFRESH (low pulse width during
SELF REFRESH) in pico seconds.
tDQSCK-max:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
DQS output data access time from CK_t/CK_c in pico seconds.
tDQSCK-max-derated:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
DQS output data access time from CK_t/CK_c, temperature de-rated, in pico
seconds.
tFAW:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Four-bank activate window in pico seconds.
tRAS-max-ns:
description: |
Row active time in nano seconds.
tRAS-min:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Row active time in pico seconds.
tRCD:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
RAS-to-CAS delay in pico seconds.
tRPab:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Row precharge time (all banks) in pico seconds.
tRRD:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Active bank A to active bank B in pico seconds.
tRTP:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Internal READ to PRECHARGE command delay in pico seconds.
tWR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
WRITE recovery time in pico seconds.
tWTR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Internal WRITE-to-READ command delay in pico seconds.
tXP:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Exit power-down to next valid command delay in pico seconds.
tZQCL:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Long calibration time in pico seconds.
tZQCS:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Short calibration time in pico seconds.
tZQinit:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Initialization calibration time in pico seconds.
required:
- compatible
- min-freq
- max-freq
additionalProperties: false
examples:
- |
timings {
compatible = "jedec,lpddr2-timings";
min-freq = <10000000>;
max-freq = <400000000>;
tCKESR = <15000>;
tDQSCK-max = <5500>;
tFAW = <50000>;
tRAS-max-ns = <70000>;
tRAS-min = <42000>;
tRPab = <21000>;
tRCD = <18000>;
tRRD = <10000>;
tRTP = <7500>;
tWR = <15000>;
tWTR = <7500>;
tXP = <7500>;
tZQCL = <360000>;
tZQCS = <90000>;
tZQinit = <1000000>;
};
......@@ -30,12 +30,26 @@ properties:
maximum: 255
description: |
Revision 1 value of SDRAM chip. Obtained from device datasheet.
Property is deprecated, use revision-id instead.
deprecated: true
revision-id2:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 255
description: |
Revision 2 value of SDRAM chip. Obtained from device datasheet.
Property is deprecated, use revision-id instead.
deprecated: true
revision-id:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
Revision IDs read from Mode Register 6 and 7. One byte per uint32 cell (i.e. <MR6 MR7>).
minItems: 2
maxItems: 2
items:
minimum: 0
maximum: 255
density:
$ref: /schemas/types.yaml#/definitions/uint32
......@@ -142,14 +156,12 @@ properties:
patternProperties:
"^lpddr2-timings":
type: object
$ref: jedec,lpddr2-timings.yaml
description: |
The lpddr2 node may have one or more child nodes of type "lpddr2-timings".
"lpddr2-timings" provides AC timing parameters of the device for
a given speed-bin. The user may provide the timings for as many
speed-bins as is required. Please see Documentation/devicetree/
bindings/memory-controllers/ddr/lpddr2-timings.txt for more information
on "lpddr2-timings".
speed-bins as is required.
required:
- compatible
......@@ -164,8 +176,7 @@ examples:
compatible = "elpida,ECB240ABACN", "jedec,lpddr2-s4";
density = <2048>;
io-width = <32>;
revision-id1 = <1>;
revision-id2 = <0>;
revision-id = <1 0>;
tRPab-min-tck = <3>;
tRCD-min-tck = <3>;
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr3-timings.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPDDR3 SDRAM AC timing parameters for a given speed-bin
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
properties:
compatible:
const: jedec,lpddr3-timings
reg:
maxItems: 1
description: |
Maximum DDR clock frequency for the speed-bin, in Hz.
Property is deprecated, use max-freq.
deprecated: true
max-freq:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Maximum DDR clock frequency for the speed-bin, in Hz.
min-freq:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Minimum DDR clock frequency for the speed-bin, in Hz.
tCKE:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
CKE minimum pulse width (HIGH and LOW pulse width) in pico seconds.
tCKESR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
CKE minimum pulse width during SELF REFRESH (low pulse width during
SELF REFRESH) in pico seconds.
tFAW:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Four-bank activate window in pico seconds.
tMRD:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Mode register set command delay in pico seconds.
tR2R-C2C:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Additional READ-to-READ delay in chip-to-chip cases in pico seconds.
tRAS:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Row active time in pico seconds.
tRC:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
ACTIVATE-to-ACTIVATE command period in pico seconds.
tRCD:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
RAS-to-CAS delay in pico seconds.
tRFC:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Refresh Cycle time in pico seconds.
tRPab:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Row precharge time (all banks) in pico seconds.
tRPpb:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Row precharge time (single banks) in pico seconds.
tRRD:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Active bank A to active bank B in pico seconds.
tRTP:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Internal READ to PRECHARGE command delay in pico seconds.
tW2W-C2C:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Additional WRITE-to-WRITE delay in chip-to-chip cases in pico seconds.
tWR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
WRITE recovery time in pico seconds.
tWTR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Internal WRITE-to-READ command delay in pico seconds.
tXP:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Exit power-down to next valid command delay in pico seconds.
tXSR:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
SELF REFRESH exit to next valid command delay in pico seconds.
required:
- compatible
- min-freq
- max-freq
additionalProperties: false
examples:
- |
lpddr3 {
timings {
compatible = "jedec,lpddr3-timings";
max-freq = <800000000>;
min-freq = <100000000>;
tCKE = <3750>;
tCKESR = <3750>;
tFAW = <25000>;
tMRD = <7000>;
tR2R-C2C = <0>;
tRAS = <23000>;
tRC = <33750>;
tRCD = <10000>;
tRFC = <65000>;
tRPab = <12000>;
tRPpb = <12000>;
tRRD = <6000>;
tRTP = <3750>;
tW2W-C2C = <0>;
tWR = <7500>;
tWTR = <3750>;
tXP = <3750>;
tXSR = <70000>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPDDR3 SDRAM compliant to JEDEC JESD209-3
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
properties:
compatible:
items:
- enum:
- samsung,K3QF2F20DB
- const: jedec,lpddr3
'#address-cells':
const: 1
deprecated: true
density:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Density in megabits of SDRAM chip.
enum:
- 4096
- 8192
- 16384
- 32768
io-width:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
IO bus width in bits of SDRAM chip.
enum:
- 32
- 16
manufacturer-id:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Manufacturer ID value read from Mode Register 5. The property is
deprecated, manufacturer should be derived from the compatible.
deprecated: true
revision-id:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 2
maxItems: 2
items:
maximum: 255
description: |
Revision value of SDRAM chip read from Mode Registers 6 and 7.
'#size-cells':
const: 0
deprecated: true
tCKE-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
CKE minimum pulse width (HIGH and LOW pulse width) in terms of number
of clock cycles.
tCKESR-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
CKE minimum pulse width during SELF REFRESH (low pulse width during
SELF REFRESH) in terms of number of clock cycles.
tDQSCK-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
DQS output data access time from CK_t/CK_c in terms of number of clock
cycles.
tFAW-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 63
description: |
Four-bank activate window in terms of number of clock cycles.
tMRD-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
Mode register set command delay in terms of number of clock cycles.
tR2R-C2C-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description: |
Additional READ-to-READ delay in chip-to-chip cases in terms of number
of clock cycles.
tRAS-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 63
description: |
Row active time in terms of number of clock cycles.
tRC-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 63
description: |
ACTIVATE-to-ACTIVATE command period in terms of number of clock cycles.
tRCD-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
RAS-to-CAS delay in terms of number of clock cycles.
tRFC-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 255
description: |
Refresh Cycle time in terms of number of clock cycles.
tRL-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
READ data latency in terms of number of clock cycles.
tRPab-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
Row precharge time (all banks) in terms of number of clock cycles.
tRPpb-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
Row precharge time (single banks) in terms of number of clock cycles.
tRRD-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
Active bank A to active bank B in terms of number of clock cycles.
tRTP-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
Internal READ to PRECHARGE command delay in terms of number of clock
cycles.
tW2W-C2C-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description: |
Additional WRITE-to-WRITE delay in chip-to-chip cases in terms of number
of clock cycles.
tWL-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
WRITE data latency in terms of number of clock cycles.
tWR-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
WRITE recovery time in terms of number of clock cycles.
tWTR-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 15
description: |
Internal WRITE-to-READ command delay in terms of number of clock cycles.
tXP-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 255
description: |
Exit power-down to next valid command delay in terms of number of clock
cycles.
tXSR-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 1023
description: |
SELF REFRESH exit to next valid command delay in terms of number of clock
cycles.
patternProperties:
"^timings((-[0-9])+|(@[0-9a-f]+))?$":
$ref: jedec,lpddr3-timings.yaml
description: |
The lpddr3 node may have one or more child nodes with timings.
Each timing node provides AC timing parameters of the device for a given
speed-bin. The user may provide the timings for as many speed-bins as is
required.
required:
- compatible
- density
- io-width
additionalProperties: false
examples:
- |
lpddr3 {
compatible = "samsung,K3QF2F20DB", "jedec,lpddr3";
density = <16384>;
io-width = <32>;
tCKE-min-tck = <2>;
tCKESR-min-tck = <2>;
tDQSCK-min-tck = <5>;
tFAW-min-tck = <5>;
tMRD-min-tck = <5>;
tR2R-C2C-min-tck = <0>;
tRAS-min-tck = <5>;
tRC-min-tck = <6>;
tRCD-min-tck = <3>;
tRFC-min-tck = <17>;
tRL-min-tck = <14>;
tRPab-min-tck = <2>;
tRPpb-min-tck = <2>;
tRRD-min-tck = <2>;
tRTP-min-tck = <2>;
tW2W-C2C-min-tck = <0>;
tWL-min-tck = <8>;
tWR-min-tck = <7>;
tWTR-min-tck = <2>;
tXP-min-tck = <2>;
tXSR-min-tck = <12>;
timings {
compatible = "jedec,lpddr3-timings";
max-freq = <800000000>;
min-freq = <100000000>;
tCKE = <3750>;
tCKESR = <3750>;
tFAW = <25000>;
tMRD = <7000>;
tR2R-C2C = <0>;
tRAS = <23000>;
tRC = <33750>;
tRCD = <10000>;
tRFC = <65000>;
tRPab = <12000>;
tRPpb = <12000>;
tRRD = <6000>;
tRTP = <3750>;
tW2W-C2C = <0>;
tWR = <7500>;
tWTR = <3750>;
tXP = <3750>;
tXSR = <70000>;
};
};
* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin
Required properties:
- compatible : Should be "jedec,lpddr2-timings"
- min-freq : minimum DDR clock frequency for the speed-bin. Type is <u32>
- max-freq : maximum DDR clock frequency for the speed-bin. Type is <u32>
Optional properties:
The following properties represent AC timing parameters from the memory
data-sheet of the device for a given speed-bin. All these properties are
of type <u32> and the default unit is ps (pico seconds). Parameters with
a different unit have a suffix indicating the unit such as 'tRAS-max-ns'
- tRCD
- tWR
- tRAS-min
- tRRD
- tWTR
- tXP
- tRTP
- tDQSCK-max
- tFAW
- tZQCS
- tZQinit
- tRPab
- tZQCL
- tCKESR
- tRAS-max-ns
- tDQSCK-max-derated
Example:
timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 {
compatible = "jedec,lpddr2-timings";
min-freq = <10000000>;
max-freq = <400000000>;
tRPab = <21000>;
tRCD = <18000>;
tWR = <15000>;
tRAS-min = <42000>;
tRRD = <10000>;
tWTR = <7500>;
tXP = <7500>;
tRTP = <7500>;
tCKESR = <15000>;
tDQSCK-max = <5500>;
tFAW = <50000>;
tZQCS = <90000>;
tZQCL = <360000>;
tZQinit = <1000000>;
tRAS-max-ns = <70000>;
};
* AC timing parameters of LPDDR3 memories for a given speed-bin.
The structures are based on LPDDR2 and extended where needed.
Required properties:
- compatible : Should be "jedec,lpddr3-timings"
- min-freq : minimum DDR clock frequency for the speed-bin. Type is <u32>
- reg : maximum DDR clock frequency for the speed-bin. Type is <u32>
Optional properties:
The following properties represent AC timing parameters from the memory
data-sheet of the device for a given speed-bin. All these properties are
of type <u32> and the default unit is ps (pico seconds).
- tRFC
- tRRD
- tRPab
- tRPpb
- tRCD
- tRC
- tRAS
- tWTR
- tWR
- tRTP
- tW2W-C2C
- tR2R-C2C
- tFAW
- tXSR
- tXP
- tCKE
- tCKESR
- tMRD
Example:
timings_samsung_K3QF2F20DB_800mhz: lpddr3-timings@800000000 {
compatible = "jedec,lpddr3-timings";
reg = <800000000>; /* workaround: it shows max-freq */
min-freq = <100000000>;
tRFC = <65000>;
tRRD = <6000>;
tRPab = <12000>;
tRPpb = <12000>;
tRCD = <10000>;
tRC = <33750>;
tRAS = <23000>;
tWTR = <3750>;
tWR = <7500>;
tRTP = <3750>;
tW2W-C2C = <0>;
tR2R-C2C = <0>;
tFAW = <25000>;
tXSR = <70000>;
tXP = <3750>;
tCKE = <3750>;
tCKESR = <3750>;
tMRD = <7000>;
};
* LPDDR3 SDRAM memories compliant to JEDEC JESD209-3C
Required properties:
- compatible : Should be "<vendor>,<type>", and generic value "jedec,lpddr3".
Example "<vendor>,<type>" values:
"samsung,K3QF2F20DB"
- density : <u32> representing density in Mb (Mega bits)
- io-width : <u32> representing bus width. Possible values are 8, 16, 32, 64
- #address-cells: Must be set to 1
- #size-cells: Must be set to 0
Optional properties:
- manufacturer-id : <u32> Manufacturer ID value read from Mode Register 5
- revision-id : <u32 u32> Revision IDs read from Mode Registers 6 and 7
The following optional properties represent the minimum value of some AC
timing parameters of the DDR device in terms of number of clock cycles.
These values shall be obtained from the device data-sheet.
- tRFC-min-tck
- tRRD-min-tck
- tRPab-min-tck
- tRPpb-min-tck
- tRCD-min-tck
- tRC-min-tck
- tRAS-min-tck
- tWTR-min-tck
- tWR-min-tck
- tRTP-min-tck
- tW2W-C2C-min-tck
- tR2R-C2C-min-tck
- tWL-min-tck
- tDQSCK-min-tck
- tRL-min-tck
- tFAW-min-tck
- tXSR-min-tck
- tXP-min-tck
- tCKE-min-tck
- tCKESR-min-tck
- tMRD-min-tck
Child nodes:
- The lpddr3 node may have one or more child nodes of type "lpddr3-timings".
"lpddr3-timings" provides AC timing parameters of the device for
a given speed-bin. Please see
Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3-timings.txt
for more information on "lpddr3-timings"
Example:
samsung_K3QF2F20DB: lpddr3 {
compatible = "samsung,K3QF2F20DB", "jedec,lpddr3";
density = <16384>;
io-width = <32>;
manufacturer-id = <1>;
revision-id = <123 234>;
#address-cells = <1>;
#size-cells = <0>;
tRFC-min-tck = <17>;
tRRD-min-tck = <2>;
tRPab-min-tck = <2>;
tRPpb-min-tck = <2>;
tRCD-min-tck = <3>;
tRC-min-tck = <6>;
tRAS-min-tck = <5>;
tWTR-min-tck = <2>;
tWR-min-tck = <7>;
tRTP-min-tck = <2>;
tW2W-C2C-min-tck = <0>;
tR2R-C2C-min-tck = <0>;
tWL-min-tck = <8>;
tDQSCK-min-tck = <5>;
tRL-min-tck = <14>;
tFAW-min-tck = <5>;
tXSR-min-tck = <12>;
tXP-min-tck = <2>;
tCKE-min-tck = <2>;
tCKESR-min-tck = <2>;
tMRD-min-tck = <5>;
timings_samsung_K3QF2F20DB_800mhz: lpddr3-timings@800000000 {
compatible = "jedec,lpddr3-timings";
/* workaround: 'reg' shows max-freq */
reg = <800000000>;
min-freq = <100000000>;
tRFC = <65000>;
tRRD = <6000>;
tRPab = <12000>;
tRPpb = <12000>;
tRCD = <10000>;
tRC = <33750>;
tRAS = <23000>;
tWTR = <3750>;
tWR = <7500>;
tRTP = <3750>;
tW2W-C2C = <0>;
tR2R-C2C = <0>;
tFAW = <25000>;
tXSR = <70000>;
tXP = <3750>;
tCKE = <3750>;
tCKESR = <3750>;
tMRD = <7000>;
};
}
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/fsl/fsl,ifc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: FSL/NXP Integrated Flash Controller
maintainers:
- Li Yang <leoyang.li@nxp.com>
description: |
NXP's integrated flash controller (IFC) is an advanced version of the
enhanced local bus controller which includes similar programming and signal
interfaces with an extended feature set. The IFC provides access to multiple
external memory types, such as NAND flash (SLC and MLC), NOR flash, EPROM,
SRAM and other memories where address and data are shared on a bus.
properties:
$nodename:
pattern: "^memory-controller@[0-9a-f]+$"
compatible:
const: fsl,ifc
"#address-cells":
enum: [2, 3]
description: |
Should be either two or three. The first cell is the chipselect
number, and the remaining cells are the offset into the chipselect.
"#size-cells":
enum: [1, 2]
description: |
Either one or two, depending on how large each chipselect can be.
reg:
maxItems: 1
interrupts:
minItems: 1
maxItems: 2
description: |
IFC may have one or two interrupts. If two interrupt specifiers are
present, the first is the "common" interrupt (CM_EVTER_STAT), and the
second is the NAND interrupt (NAND_EVTER_STAT). If there is only one,
that interrupt reports both types of event.
little-endian:
type: boolean
description: |
If this property is absent, the big-endian mode will be in use as default
for registers.
ranges:
description: |
Each range corresponds to a single chipselect, and covers the entire
access window as configured.
patternProperties:
"^.*@[a-f0-9]+(,[a-f0-9]+)+$":
type: object
description: |
Child device nodes describe the devices connected to IFC such as NOR (e.g.
cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices
like FPGAs, CPLDs, etc.
required:
- compatible
- reg
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
memory-controller@ffe1e000 {
compatible = "fsl,ifc";
#address-cells = <2>;
#size-cells = <1>;
reg = <0x0 0xffe1e000 0 0x2000>;
interrupts = <16 2 19 2>;
little-endian;
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0x0 0xee000000 0x02000000>,
<0x1 0x0 0x0 0xffa00000 0x00010000>,
<0x3 0x0 0x0 0xffb00000 0x00020000>;
flash@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x0 0x0 0x2000000>;
bank-width = <2>;
device-width = <1>;
partition@0 {
/* 32MB for user data */
reg = <0x0 0x02000000>;
label = "NOR Data";
};
};
};
};
Integrated Flash Controller
Properties:
- name : Should be ifc
- compatible : should contain "fsl,ifc". The version of the integrated
flash controller can be found in the IFC_REV register at
offset zero.
- #address-cells : Should be either two or three. The first cell is the
chipselect number, and the remaining cells are the
offset into the chipselect.
- #size-cells : Either one or two, depending on how large each chipselect
can be.
- reg : Offset and length of the register set for the device
- interrupts: IFC may have one or two interrupts. If two interrupt
specifiers are present, the first is the "common"
interrupt (CM_EVTER_STAT), and the second is the NAND
interrupt (NAND_EVTER_STAT). If there is only one,
that interrupt reports both types of event.
- little-endian : If this property is absent, the big-endian mode will
be in use as default for registers.
- ranges : Each range corresponds to a single chipselect, and covers
the entire access window as configured.
Child device nodes describe the devices connected to IFC such as NOR (e.g.
cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices
like FPGAs, CPLDs, etc.
Example:
ifc@ffe1e000 {
compatible = "fsl,ifc", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
reg = <0x0 0xffe1e000 0 0x2000>;
interrupts = <16 2 19 2>;
little-endian;
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0x0 0xee000000 0x02000000
0x1 0x0 0x0 0xffa00000 0x00010000
0x3 0x0 0x0 0xffb00000 0x00020000>;
flash@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x0 0x0 0x2000000>;
bank-width = <2>;
device-width = <1>;
partition@0 {
/* 32MB for user data */
reg = <0x0 0x02000000>;
label = "NOR Data";
};
};
flash@1,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,ifc-nand";
reg = <0x1 0x0 0x10000>;
partition@0 {
/* This location must not be altered */
/* 1MB for u-boot Bootloader Image */
reg = <0x0 0x00100000>;
label = "NAND U-Boot Image";
read-only;
};
};
cpld@3,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,p1010rdb-cpld";
reg = <0x3 0x0 0x000001f>;
};
};
......@@ -16,7 +16,7 @@ description: |
MediaTek SMI have two generations of HW architecture, here is the list
which generation the SoCs use:
generation 1: mt2701 and mt7623.
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8192 and mt8195.
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8192 and mt8195.
There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
......@@ -35,6 +35,7 @@ properties:
- mediatek,mt8167-smi-common
- mediatek,mt8173-smi-common
- mediatek,mt8183-smi-common
- mediatek,mt8186-smi-common
- mediatek,mt8192-smi-common
- mediatek,mt8195-smi-common-vdo
- mediatek,mt8195-smi-common-vpp
......@@ -88,10 +89,9 @@ allOf:
- mediatek,mt2701-smi-common
then:
properties:
clock:
items:
minItems: 3
maxItems: 3
clocks:
minItems: 3
maxItems: 3
clock-names:
items:
- const: apb
......@@ -108,10 +108,9 @@ allOf:
required:
- mediatek,smi
properties:
clock:
items:
minItems: 3
maxItems: 3
clocks:
minItems: 3
maxItems: 3
clock-names:
items:
- const: apb
......@@ -127,16 +126,16 @@ allOf:
enum:
- mediatek,mt6779-smi-common
- mediatek,mt8183-smi-common
- mediatek,mt8186-smi-common
- mediatek,mt8192-smi-common
- mediatek,mt8195-smi-common-vdo
- mediatek,mt8195-smi-common-vpp
then:
properties:
clock:
items:
minItems: 4
maxItems: 4
clocks:
minItems: 4
maxItems: 4
clock-names:
items:
- const: apb
......@@ -146,10 +145,9 @@ allOf:
else: # for gen2 HW that don't have gals
properties:
clock:
items:
minItems: 2
maxItems: 2
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: apb
......
......@@ -23,6 +23,7 @@ properties:
- mediatek,mt8167-smi-larb
- mediatek,mt8173-smi-larb
- mediatek,mt8183-smi-larb
- mediatek,mt8186-smi-larb
- mediatek,mt8192-smi-larb
- mediatek,mt8195-smi-larb
......@@ -75,15 +76,16 @@ allOf:
compatible:
enum:
- mediatek,mt8183-smi-larb
- mediatek,mt8186-smi-larb
- mediatek,mt8195-smi-larb
then:
properties:
clock:
items:
minItems: 3
maxItems: 3
clocks:
minItems: 2
maxItems: 3
clock-names:
minItems: 2
items:
- const: apb
- const: smi
......@@ -91,10 +93,9 @@ allOf:
else:
properties:
clock:
items:
minItems: 2
maxItems: 2
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: apb
......@@ -108,7 +109,7 @@ allOf:
- mediatek,mt2701-smi-larb
- mediatek,mt2712-smi-larb
- mediatek,mt6779-smi-larb
- mediatek,mt8167-smi-larb
- mediatek,mt8186-smi-larb
- mediatek,mt8192-smi-larb
- mediatek,mt8195-smi-larb
......
......@@ -40,7 +40,8 @@ properties:
- items:
- enum:
- renesas,r9a07g044-rpc-if # RZ/G2{L,LC}
- const: renesas,rzg2l-rpc-if # RZ/G2L family
- renesas,r9a07g054-rpc-if # RZ/V2L
- const: renesas,rzg2l-rpc-if
reg:
items:
......
......@@ -51,8 +51,7 @@ properties:
$ref: '/schemas/types.yaml#/definitions/phandle'
description: |
phandle of the connected DRAM memory device. For more information please
refer to documentation file:
Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3.txt
refer to jedec,lpddr3.yaml.
operating-points-v2: true
......
......@@ -12,13 +12,14 @@ maintainers:
- Jianxin Pan <jianxin.pan@amlogic.com>
description: |+
Secure Power Domains used in Meson A1/C1 SoCs, and should be the child node
Secure Power Domains used in Meson A1/C1/S4 SoCs, and should be the child node
of secure-monitor.
properties:
compatible:
enum:
- amlogic,meson-a1-pwrc
- amlogic,meson-s4-pwrc
"#power-domain-cells":
const: 1
......
......@@ -26,7 +26,9 @@ properties:
- mediatek,mt8167-power-controller
- mediatek,mt8173-power-controller
- mediatek,mt8183-power-controller
- mediatek,mt8186-power-controller
- mediatek,mt8192-power-controller
- mediatek,mt8195-power-controller
'#power-domain-cells':
const: 1
......@@ -64,6 +66,7 @@ patternProperties:
"include/dt-bindings/power/mt8173-power.h" - for MT8173 type power domain.
"include/dt-bindings/power/mt8183-power.h" - for MT8183 type power domain.
"include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain.
"include/dt-bindings/power/mt8195-power.h" - for MT8195 type power domain.
maxItems: 1
clocks:
......
......@@ -17,6 +17,7 @@ properties:
compatible:
enum:
- qcom,mdm9607-rpmpd
- qcom,msm8226-rpmpd
- qcom,msm8916-rpmpd
- qcom,msm8939-rpmpd
- qcom,msm8953-rpmpd
......
......@@ -47,6 +47,10 @@ properties:
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8350-mpss-pas
- qcom,sm8450-adsp-pas
- qcom,sm8450-cdsp-pas
- qcom,sm8450-mpss-pas
- qcom,sm8450-slpi-pas
reg:
maxItems: 1
......@@ -175,6 +179,10 @@ allOf:
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8350-mpss-pas
- qcom,sm8450-adsp-pas
- qcom,sm8450-cdsp-pas
- qcom,sm8450-slpi-pas
- qcom,sm8450-mpss-pas
then:
properties:
clocks:
......@@ -283,6 +291,9 @@ allOf:
- qcom,sm8350-adsp-pas
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8450-adsp-pas
- qcom,sm8450-cdsp-pas
- qcom,sm8450-slpi-pas
then:
properties:
interrupts:
......@@ -312,6 +323,7 @@ allOf:
- qcom,sm6350-mpss-pas
- qcom,sm8150-mpss-pas
- qcom,sm8350-mpss-pas
- qcom,sm8450-mpss-pas
then:
properties:
interrupts:
......@@ -434,6 +446,7 @@ allOf:
- qcom,sm6350-mpss-pas
- qcom,sm8150-mpss-pas
- qcom,sm8350-mpss-pas
- qcom,sm8450-mpss-pas
then:
properties:
power-domains:
......@@ -458,6 +471,8 @@ allOf:
- qcom,sm8250-slpi-pas
- qcom,sm8350-adsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8450-adsp-pas
- qcom,sm8450-slpi-pas
then:
properties:
power-domains:
......@@ -475,6 +490,7 @@ allOf:
contains:
enum:
- qcom,sm8350-cdsp-pas
- qcom,sm8450-cdsp-pas
then:
properties:
power-domains:
......
......@@ -27,6 +27,7 @@ Required properties in pwrap device node.
"mediatek,mt8135-pwrap" for MT8135 SoCs
"mediatek,mt8173-pwrap" for MT8173 SoCs
"mediatek,mt8183-pwrap" for MT8183 SoCs
"mediatek,mt8186-pwrap" for MT8186 SoCs
"mediatek,mt8195-pwrap" for MT8195 SoCs
"mediatek,mt8516-pwrap" for MT8516 SoCs
- interrupts: IRQ for pwrap in SOC
......
......@@ -357,8 +357,7 @@ static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
{
int cpu;
if (qcom_scm_set_cold_boot_addr(secondary_startup_arm,
cpu_present_mask)) {
if (qcom_scm_set_cold_boot_addr(secondary_startup_arm)) {
for_each_present_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
......
......@@ -29,7 +29,7 @@ void __init spear13xx_l2x0_init(void)
/*
* 512KB (64KB/way), 8-way associativity, parity supported
*
* FIXME: 9th bit, of Auxillary Controller register must be set
* FIXME: 9th bit, of Auxiliary Controller register must be set
* for some spear13xx devices for stable L2 operation.
*
* Enable Early BRESP, L2 prefetch for Instruction and Data,
......
......@@ -64,6 +64,11 @@ struct cs_timing_state {
struct cs_timing cs[MAX_CS_COUNT];
};
struct weim_priv {
void __iomem *base;
struct cs_timing_state timing_state;
};
static const struct of_device_id weim_id_table[] = {
/* i.MX1/21 */
{ .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, },
......@@ -128,21 +133,26 @@ static int imx_weim_gpr_setup(struct platform_device *pdev)
}
/* Parse and set the timing for this device. */
static int weim_timing_setup(struct device *dev,
struct device_node *np, void __iomem *base,
const struct imx_weim_devtype *devtype,
struct cs_timing_state *ts)
static int weim_timing_setup(struct device *dev, struct device_node *np,
const struct imx_weim_devtype *devtype)
{
u32 cs_idx, value[MAX_CS_REGS_COUNT];
int i, ret;
int reg_idx, num_regs;
struct cs_timing *cst;
struct weim_priv *priv;
struct cs_timing_state *ts;
void __iomem *base;
if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
return -EINVAL;
if (WARN_ON(devtype->cs_count > MAX_CS_COUNT))
return -EINVAL;
priv = dev_get_drvdata(dev);
base = priv->base;
ts = &priv->timing_state;
ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
value, devtype->cs_regs_count);
if (ret)
......@@ -189,14 +199,15 @@ static int weim_timing_setup(struct device *dev,
return 0;
}
static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
static int weim_parse_dt(struct platform_device *pdev)
{
const struct of_device_id *of_id = of_match_device(weim_id_table,
&pdev->dev);
const struct imx_weim_devtype *devtype = of_id->data;
struct device_node *child;
int ret, have_child = 0;
struct cs_timing_state ts = {};
struct weim_priv *priv;
void __iomem *base;
u32 reg;
if (devtype == &imx50_weim_devtype) {
......@@ -205,6 +216,9 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
return ret;
}
priv = dev_get_drvdata(&pdev->dev);
base = priv->base;
if (of_property_read_bool(pdev->dev.of_node, "fsl,burst-clk-enable")) {
if (devtype->wcr_bcm) {
reg = readl(base + devtype->wcr_offset);
......@@ -229,7 +243,7 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
}
for_each_available_child_of_node(pdev->dev.of_node, child) {
ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
ret = weim_timing_setup(&pdev->dev, child, devtype);
if (ret)
dev_warn(&pdev->dev, "%pOF set timing failed.\n",
child);
......@@ -248,17 +262,25 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
static int weim_probe(struct platform_device *pdev)
{
struct weim_priv *priv;
struct resource *res;
struct clk *clk;
void __iomem *base;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* get the resource */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
priv->base = base;
dev_set_drvdata(&pdev->dev, priv);
/* get the clock */
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk))
......@@ -269,7 +291,7 @@ static int weim_probe(struct platform_device *pdev)
return ret;
/* parse the device node */
ret = weim_parse_dt(pdev, base);
ret = weim_parse_dt(pdev);
if (ret)
clk_disable_unprepare(clk);
else
......@@ -278,6 +300,81 @@ static int weim_probe(struct platform_device *pdev)
return ret;
}
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
static int of_weim_notify(struct notifier_block *nb, unsigned long action,
void *arg)
{
const struct imx_weim_devtype *devtype;
struct of_reconfig_data *rd = arg;
const struct of_device_id *of_id;
struct platform_device *pdev;
int ret = NOTIFY_OK;
switch (of_reconfig_get_state_change(action, rd)) {
case OF_RECONFIG_CHANGE_ADD:
of_id = of_match_node(weim_id_table, rd->dn->parent);
if (!of_id)
return NOTIFY_OK; /* not for us */
devtype = of_id->data;
pdev = of_find_device_by_node(rd->dn->parent);
if (!pdev) {
pr_err("%s: could not find platform device for '%pOF'\n",
__func__, rd->dn->parent);
return notifier_from_errno(-EINVAL);
}
if (weim_timing_setup(&pdev->dev, rd->dn, devtype))
dev_warn(&pdev->dev,
"Failed to setup timing for '%pOF'\n", rd->dn);
if (!of_node_check_flag(rd->dn, OF_POPULATED)) {
if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) {
dev_err(&pdev->dev,
"Failed to create child device '%pOF'\n",
rd->dn);
ret = notifier_from_errno(-EINVAL);
}
}
platform_device_put(pdev);
break;
case OF_RECONFIG_CHANGE_REMOVE:
if (!of_node_check_flag(rd->dn, OF_POPULATED))
return NOTIFY_OK; /* device already destroyed */
of_id = of_match_node(weim_id_table, rd->dn->parent);
if (!of_id)
return NOTIFY_OK; /* not for us */
pdev = of_find_device_by_node(rd->dn);
if (!pdev) {
dev_err(&pdev->dev,
"Could not find platform device for '%pOF'\n",
rd->dn);
ret = notifier_from_errno(-EINVAL);
} else {
of_platform_device_destroy(&pdev->dev, NULL);
platform_device_put(pdev);
}
break;
default:
break;
}
return ret;
}
struct notifier_block weim_of_notifier = {
.notifier_call = of_weim_notify,
};
#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */
static struct platform_driver weim_driver = {
.driver = {
.name = "imx-weim",
......@@ -285,7 +382,27 @@ static struct platform_driver weim_driver = {
},
.probe = weim_probe,
};
module_platform_driver(weim_driver);
static int __init weim_init(void)
{
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
WARN_ON(of_reconfig_notifier_register(&weim_of_notifier));
#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */
return platform_driver_register(&weim_driver);
}
module_init(weim_init);
static void __exit weim_exit(void)
{
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
of_reconfig_notifier_unregister(&weim_of_notifier);
#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */
return platform_driver_unregister(&weim_driver);
}
module_exit(weim_exit);
MODULE_AUTHOR("Freescale Semiconductor Inc.");
MODULE_DESCRIPTION("i.MX EIM Controller Driver");
......
......@@ -145,10 +145,10 @@ static int optee_rng_init(struct hwrng *rng)
struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
struct tee_shm *entropy_shm_pool = NULL;
entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ,
TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
entropy_shm_pool = tee_shm_alloc_kernel_buf(pvt_data->ctx,
MAX_ENTROPY_REQ_SZ);
if (IS_ERR(entropy_shm_pool)) {
dev_err(pvt_data->dev, "tee_shm_alloc failed\n");
dev_err(pvt_data->dev, "tee_shm_alloc_kernel_buf failed\n");
return PTR_ERR(entropy_shm_pool);
}
......
......@@ -2,7 +2,7 @@
/*
* System Control and Power Interface (SCMI) Protocol based clock driver
*
* Copyright (C) 2018-2021 ARM Ltd.
* Copyright (C) 2018-2022 ARM Ltd.
*/
#include <linux/clk-provider.h>
......@@ -88,21 +88,51 @@ static void scmi_clk_disable(struct clk_hw *hw)
scmi_proto_clk_ops->disable(clk->ph, clk->id);
}
static int scmi_clk_atomic_enable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
return scmi_proto_clk_ops->enable_atomic(clk->ph, clk->id);
}
static void scmi_clk_atomic_disable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
scmi_proto_clk_ops->disable_atomic(clk->ph, clk->id);
}
/*
* We can provide enable/disable atomic callbacks only if the underlying SCMI
* transport for an SCMI instance is configured to handle SCMI commands in an
* atomic manner.
*
* When no SCMI atomic transport support is available we instead provide only
* the prepare/unprepare API, as allowed by the clock framework when atomic
* calls are not available.
*
* Two distinct sets of clk_ops are provided since we could have multiple SCMI
* instances with different underlying transport quality, so they cannot be
* shared.
*/
static const struct clk_ops scmi_clk_ops = {
.recalc_rate = scmi_clk_recalc_rate,
.round_rate = scmi_clk_round_rate,
.set_rate = scmi_clk_set_rate,
/*
* We can't provide enable/disable callback as we can't perform the same
* in atomic context. Since the clock framework provides standard API
* clk_prepare_enable that helps cases using clk_enable in non-atomic
* context, it should be fine providing prepare/unprepare.
*/
.prepare = scmi_clk_enable,
.unprepare = scmi_clk_disable,
};
static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
static const struct clk_ops scmi_atomic_clk_ops = {
.recalc_rate = scmi_clk_recalc_rate,
.round_rate = scmi_clk_round_rate,
.set_rate = scmi_clk_set_rate,
.enable = scmi_clk_atomic_enable,
.disable = scmi_clk_atomic_disable,
};
static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
const struct clk_ops *scmi_ops)
{
int ret;
unsigned long min_rate, max_rate;
......@@ -110,7 +140,7 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
struct clk_init_data init = {
.flags = CLK_GET_RATE_NOCACHE,
.num_parents = 0,
.ops = &scmi_clk_ops,
.ops = scmi_ops,
.name = sclk->info->name,
};
......@@ -139,6 +169,8 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
static int scmi_clocks_probe(struct scmi_device *sdev)
{
int idx, count, err;
unsigned int atomic_threshold;
bool is_atomic;
struct clk_hw **hws;
struct clk_hw_onecell_data *clk_data;
struct device *dev = &sdev->dev;
......@@ -168,8 +200,11 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
clk_data->num = count;
hws = clk_data->hws;
is_atomic = handle->is_transport_atomic(handle, &atomic_threshold);
for (idx = 0; idx < count; idx++) {
struct scmi_clk *sclk;
const struct clk_ops *scmi_ops;
sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
if (!sclk)
......@@ -184,13 +219,27 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
sclk->id = idx;
sclk->ph = ph;
err = scmi_clk_ops_init(dev, sclk);
/*
* Note that when transport is atomic but SCMI protocol did not
* specify (or support) an enable_latency associated with a
* clock, we default to use atomic operations mode.
*/
if (is_atomic &&
sclk->info->enable_latency <= atomic_threshold)
scmi_ops = &scmi_atomic_clk_ops;
else
scmi_ops = &scmi_clk_ops;
err = scmi_clk_ops_init(dev, sclk, scmi_ops);
if (err) {
dev_err(dev, "failed to register clock %d\n", idx);
devm_kfree(dev, sclk);
hws[idx] = NULL;
} else {
dev_dbg(dev, "Registered clock:%s\n", sclk->info->name);
dev_dbg(dev, "Registered clock:%s%s\n",
sclk->info->name,
scmi_ops == &scmi_atomic_clk_ops ?
" (atomic ops)" : "");
hws[idx] = &sclk->hw;
}
}
......
......@@ -11,6 +11,7 @@ config COMMON_CLK_SAMSUNG
select EXYNOS_5410_COMMON_CLK if ARM && SOC_EXYNOS5410
select EXYNOS_5420_COMMON_CLK if ARM && SOC_EXYNOS5420
select EXYNOS_ARM64_COMMON_CLK if ARM64 && ARCH_EXYNOS
select TESLA_FSD_COMMON_CLK if ARM64 && ARCH_TESLA_FSD
config S3C64XX_COMMON_CLK
bool "Samsung S3C64xx clock controller support" if COMPILE_TEST
......@@ -124,3 +125,11 @@ config S3C2443_COMMON_CLK
help
Support for the clock controller present on the Samsung
S3C2416/S3C2443 SoCs. Choose Y here only if you build for this SoC.
config TESLA_FSD_COMMON_CLK
bool "Tesla FSD clock controller support" if COMPILE_TEST
depends on COMMON_CLK_SAMSUNG
depends on EXYNOS_ARM64_COMMON_CLK
help
Support for the clock controller present on the Tesla FSD SoC.
Choose Y here only if you build for this SoC.
......@@ -26,3 +26,4 @@ obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o
obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o
obj-$(CONFIG_TESLA_FSD_COMMON_CLK) += clk-fsd.o
This diff is collapsed.
......@@ -1469,6 +1469,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
case pll_1450x:
case pll_1451x:
case pll_1452x:
case pll_142xx:
pll->enable_offs = PLL35XX_ENABLE_SHIFT;
pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT;
if (!pll->rate_table)
......
......@@ -39,6 +39,7 @@ enum samsung_pll_type {
pll_1460x,
pll_0822x,
pll_0831x,
pll_142xx,
};
#define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \
......
......@@ -122,10 +122,6 @@ static int spm_cpuidle_register(struct device *cpuidle_dev, int cpu)
if (ret <= 0)
return ret ? : -ENODEV;
ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm, cpumask_of(cpu));
if (ret)
return ret;
return cpuidle_register(&data->cpuidle_driver, NULL);
}
......@@ -136,6 +132,10 @@ static int spm_cpuidle_drv_probe(struct platform_device *pdev)
if (!qcom_scm_is_available())
return -EPROBE_DEFER;
ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm);
if (ret)
return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed");
for_each_possible_cpu(cpu) {
ret = spm_cpuidle_register(&pdev->dev, cpu);
if (ret && ret != -ENODEV) {
......@@ -155,6 +155,22 @@ static struct platform_driver spm_cpuidle_driver = {
},
};
static bool __init qcom_spm_find_any_cpu(void)
{
struct device_node *cpu_node, *saw_node;
for_each_of_cpu_node(cpu_node) {
saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
if (of_device_is_available(saw_node)) {
of_node_put(saw_node);
of_node_put(cpu_node);
return true;
}
of_node_put(saw_node);
}
return false;
}
static int __init qcom_spm_cpuidle_init(void)
{
struct platform_device *pdev;
......@@ -164,6 +180,10 @@ static int __init qcom_spm_cpuidle_init(void)
if (ret)
return ret;
/* Make sure there is actually any CPU managed by the SPM */
if (!qcom_spm_find_any_cpu())
return 0;
pdev = platform_device_register_simple("qcom-spm-cpuidle",
-1, NULL, 0);
if (IS_ERR(pdev)) {
......
......@@ -54,6 +54,18 @@ config ARM_SCMI_TRANSPORT_MAILBOX
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on mailboxes, answer Y.
config ARM_SCMI_TRANSPORT_OPTEE
bool "SCMI transport based on OP-TEE service"
depends on OPTEE=y || OPTEE=ARM_SCMI_PROTOCOL
select ARM_SCMI_HAVE_TRANSPORT
select ARM_SCMI_HAVE_SHMEM
default y
help
This enables the OP-TEE service based transport for SCMI.
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on OP-TEE SCMI service, answer Y.
config ARM_SCMI_TRANSPORT_SMC
bool "SCMI transport based on SMC"
depends on HAVE_ARM_SMCCC_DISCOVERY
......@@ -66,6 +78,20 @@ config ARM_SCMI_TRANSPORT_SMC
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on SMC, answer Y.
config ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE
bool "Enable atomic mode support for SCMI SMC transport"
depends on ARM_SCMI_TRANSPORT_SMC
help
Enable support of atomic operation for SCMI SMC based transport.
If you want the SCMI SMC based transport to operate in atomic
mode, avoiding any kind of sleeping behaviour for selected
transactions on the TX path, answer Y.
Enabling atomic mode operations allows any SCMI driver using this
transport to optionally ask for atomic SCMI transactions and operate
in atomic context too, at the price of using a number of busy-waiting
primitives all over instead. If unsure say N.
config ARM_SCMI_TRANSPORT_VIRTIO
bool "SCMI transport based on VirtIO"
depends on VIRTIO=y || VIRTIO=ARM_SCMI_PROTOCOL
......@@ -77,6 +103,36 @@ config ARM_SCMI_TRANSPORT_VIRTIO
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on VirtIO, answer Y.
config ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE
bool "SCMI VirtIO transport Version 1 compliance"
depends on ARM_SCMI_TRANSPORT_VIRTIO
default y
help
This enforces strict compliance with VirtIO Version 1 specification.
If you want the ARM SCMI VirtIO transport layer to refuse to work
with Legacy VirtIO backends and instead support only VirtIO Version 1
devices (or above), answer Y.
If you want instead to support also old Legacy VirtIO backends (like
the ones implemented by kvmtool) and let the core Kernel VirtIO layer
take care of the needed conversions, say N.
config ARM_SCMI_TRANSPORT_VIRTIO_ATOMIC_ENABLE
bool "Enable atomic mode for SCMI VirtIO transport"
depends on ARM_SCMI_TRANSPORT_VIRTIO
help
Enable support of atomic operation for SCMI VirtIO based transport.
If you want the SCMI VirtIO based transport to operate in atomic
mode, avoiding any kind of sleeping behaviour for selected
transactions on the TX path, answer Y.
Enabling atomic mode operations allows any SCMI driver using this
transport to optionally ask for atomic SCMI transactions and operate
in atomic context too, at the price of using a number of busy-waiting
primitives all over instead. If unsure say N.
endif #ARM_SCMI_PROTOCOL
config ARM_SCMI_POWER_DOMAIN
......
......@@ -6,8 +6,16 @@ scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += mailbox.o
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-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
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
# pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
# hooks are inserted via the -pg switch.
CFLAGS_REMOVE_smc.o += $(CC_FLAGS_FTRACE)
endif
......@@ -27,7 +27,8 @@ struct scmi_msg_resp_clock_protocol_attributes {
struct scmi_msg_resp_clock_attributes {
__le32 attributes;
#define CLOCK_ENABLE BIT(0)
u8 name[SCMI_MAX_STR_SIZE];
u8 name[SCMI_MAX_STR_SIZE];
__le32 clock_enable_latency;
};
struct scmi_clock_set_config {
......@@ -116,10 +117,15 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
attr = t->rx.buf;
ret = ph->xops->do_xfer(ph, t);
if (!ret)
if (!ret) {
strlcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE);
else
/* Is optional field clock_enable_latency provided ? */
if (t->rx.len == sizeof(*attr))
clk->enable_latency =
le32_to_cpu(attr->clock_enable_latency);
} else {
clk->name[0] = '\0';
}
ph->xops->xfer_put(ph, t);
return ret;
......@@ -273,7 +279,7 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
static int
scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
u32 config)
u32 config, bool atomic)
{
int ret;
struct scmi_xfer *t;
......@@ -284,6 +290,8 @@ scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
if (ret)
return ret;
t->hdr.poll_completion = atomic;
cfg = t->tx.buf;
cfg->id = cpu_to_le32(clk_id);
cfg->attributes = cpu_to_le32(config);
......@@ -296,12 +304,24 @@ scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
static int scmi_clock_enable(const struct scmi_protocol_handle *ph, u32 clk_id)
{
return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE);
return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE, false);
}
static int scmi_clock_disable(const struct scmi_protocol_handle *ph, u32 clk_id)
{
return scmi_clock_config_set(ph, clk_id, 0);
return scmi_clock_config_set(ph, clk_id, 0, false);
}
static int scmi_clock_enable_atomic(const struct scmi_protocol_handle *ph,
u32 clk_id)
{
return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE, true);
}
static int scmi_clock_disable_atomic(const struct scmi_protocol_handle *ph,
u32 clk_id)
{
return scmi_clock_config_set(ph, clk_id, 0, true);
}
static int scmi_clock_count_get(const struct scmi_protocol_handle *ph)
......@@ -330,6 +350,8 @@ static const struct scmi_clk_proto_ops clk_proto_ops = {
.rate_set = scmi_clock_rate_set,
.enable = scmi_clock_enable,
.disable = scmi_clock_disable,
.enable_atomic = scmi_clock_enable_atomic,
.disable_atomic = scmi_clock_disable_atomic,
};
static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
......
......@@ -339,11 +339,16 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
* @dev: Reference to device in the SCMI hierarchy corresponding to this
* channel
* @handle: Pointer to SCMI entity handle
* @no_completion_irq: Flag to indicate that this channel has no completion
* interrupt mechanism for synchronous commands.
* This can be dynamically set by transports at run-time
* inside their provided .chan_setup().
* @transport_info: Transport layer related information
*/
struct scmi_chan_info {
struct device *dev;
struct scmi_handle *handle;
bool no_completion_irq;
void *transport_info;
};
......@@ -373,7 +378,8 @@ struct scmi_transport_ops {
unsigned int (*get_max_msg)(struct scmi_chan_info *base_cinfo);
int (*send_message)(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer);
void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret);
void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret,
struct scmi_xfer *xfer);
void (*fetch_response)(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer);
void (*fetch_notification)(struct scmi_chan_info *cinfo,
......@@ -402,6 +408,18 @@ struct scmi_device *scmi_child_dev_find(struct device *parent,
* be pending simultaneously in the system. May be overridden by the
* get_max_msg op.
* @max_msg_size: Maximum size of data per message that can be handled.
* @force_polling: Flag to force this whole transport to use SCMI core polling
* mechanism instead of completion interrupts even if available.
* @sync_cmds_completed_on_ret: Flag to indicate that the transport assures
* synchronous-command messages are atomically
* completed on .send_message: no need to poll
* actively waiting for a response.
* Used by core internally only when polling is
* selected as a waiting for reply method: i.e.
* if a completion irq was found use that anyway.
* @atomic_enabled: Flag to indicate that this transport, which is assured not
* to sleep anywhere on the TX path, can be used in atomic mode
* when requested.
*/
struct scmi_desc {
int (*transport_init)(void);
......@@ -410,6 +428,9 @@ struct scmi_desc {
int max_rx_timeout_ms;
int max_msg;
int max_msg_size;
const bool force_polling;
const bool sync_cmds_completed_on_ret;
const bool atomic_enabled;
};
#ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX
......@@ -421,6 +442,9 @@ extern const struct scmi_desc scmi_smc_desc;
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
extern const struct scmi_desc scmi_virtio_desc;
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_OPTEE
extern const struct scmi_desc scmi_optee_desc;
#endif
void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv);
void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id);
......
This diff is collapsed.
......@@ -140,7 +140,8 @@ static int mailbox_send_message(struct scmi_chan_info *cinfo,
return ret;
}
static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret)
static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret,
struct scmi_xfer *__unused)
{
struct scmi_mailbox *smbox = cinfo->transport_info;
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
*/
#include <linux/arm-smccc.h>
#include <linux/atomic.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
......@@ -14,6 +15,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/processor.h>
#include <linux/slab.h>
#include "common.h"
......@@ -23,26 +25,29 @@
*
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
* @shmem_lock: Lock to protect access to Tx/Rx shared memory area
* @shmem_lock: Lock to protect access to Tx/Rx shared memory area.
* Used when NOT operating in atomic mode.
* @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
* Used when operating in atomic mode.
* @func_id: smc/hvc call function id
* @irq: Optional; employed when platforms indicates msg completion by intr.
* @tx_complete: Optional, employed only when irq is valid.
*/
struct scmi_smc {
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
/* Protect access to shmem area */
struct mutex shmem_lock;
#define INFLIGHT_NONE MSG_TOKEN_MAX
atomic_t inflight;
u32 func_id;
int irq;
struct completion tx_complete;
};
static irqreturn_t smc_msg_done_isr(int irq, void *data)
{
struct scmi_smc *scmi_info = data;
complete(&scmi_info->tx_complete);
scmi_rx_callback(scmi_info->cinfo,
shmem_read_header(scmi_info->shmem), NULL);
return IRQ_HANDLED;
}
......@@ -57,6 +62,41 @@ static bool smc_chan_available(struct device *dev, int idx)
return true;
}
static inline void smc_channel_lock_init(struct scmi_smc *scmi_info)
{
if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE))
atomic_set(&scmi_info->inflight, INFLIGHT_NONE);
else
mutex_init(&scmi_info->shmem_lock);
}
static bool smc_xfer_inflight(struct scmi_xfer *xfer, atomic_t *inflight)
{
int ret;
ret = atomic_cmpxchg(inflight, INFLIGHT_NONE, xfer->hdr.seq);
return ret == INFLIGHT_NONE;
}
static inline void
smc_channel_lock_acquire(struct scmi_smc *scmi_info,
struct scmi_xfer *xfer __maybe_unused)
{
if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE))
spin_until_cond(smc_xfer_inflight(xfer, &scmi_info->inflight));
else
mutex_lock(&scmi_info->shmem_lock);
}
static inline void smc_channel_lock_release(struct scmi_smc *scmi_info)
{
if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE))
atomic_set(&scmi_info->inflight, INFLIGHT_NONE);
else
mutex_unlock(&scmi_info->shmem_lock);
}
static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
bool tx)
{
......@@ -111,13 +151,13 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
dev_err(dev, "failed to setup SCMI smc irq\n");
return ret;
}
init_completion(&scmi_info->tx_complete);
scmi_info->irq = irq;
} else {
cinfo->no_completion_irq = true;
}
scmi_info->func_id = func_id;
scmi_info->cinfo = cinfo;
mutex_init(&scmi_info->shmem_lock);
smc_channel_lock_init(scmi_info);
cinfo->transport_info = scmi_info;
return 0;
......@@ -142,26 +182,22 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
struct scmi_smc *scmi_info = cinfo->transport_info;
struct arm_smccc_res res;
mutex_lock(&scmi_info->shmem_lock);
/*
* Channel will be released only once response has been
* surely fully retrieved, so after .mark_txdone()
*/
smc_channel_lock_acquire(scmi_info, xfer);
shmem_tx_prepare(scmi_info->shmem, xfer);
if (scmi_info->irq)
reinit_completion(&scmi_info->tx_complete);
arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
if (scmi_info->irq)
wait_for_completion(&scmi_info->tx_complete);
scmi_rx_callback(scmi_info->cinfo,
shmem_read_header(scmi_info->shmem), NULL);
mutex_unlock(&scmi_info->shmem_lock);
/* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
if (res.a0)
if (res.a0) {
smc_channel_lock_release(scmi_info);
return -EOPNOTSUPP;
}
return 0;
}
......@@ -173,12 +209,12 @@ static void smc_fetch_response(struct scmi_chan_info *cinfo,
shmem_fetch_response(scmi_info->shmem, xfer);
}
static bool
smc_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret,
struct scmi_xfer *__unused)
{
struct scmi_smc *scmi_info = cinfo->transport_info;
return shmem_poll_done(scmi_info->shmem, xfer);
smc_channel_lock_release(scmi_info);
}
static const struct scmi_transport_ops scmi_smc_ops = {
......@@ -186,8 +222,8 @@ static const struct scmi_transport_ops scmi_smc_ops = {
.chan_setup = smc_chan_setup,
.chan_free = smc_chan_free,
.send_message = smc_send_message,
.mark_txdone = smc_mark_txdone,
.fetch_response = smc_fetch_response,
.poll_done = smc_poll_done,
};
const struct scmi_desc scmi_smc_desc = {
......@@ -195,4 +231,14 @@ const struct scmi_desc scmi_smc_desc = {
.max_rx_timeout_ms = 30,
.max_msg = 20,
.max_msg_size = 128,
/*
* Setting .sync_cmds_atomic_replies to true for SMC assumes that,
* once the SMC instruction has completed successfully, the issued
* SCMI command would have been already fully processed by the SCMI
* platform firmware and so any possible response value expected
* for the issued command will be immmediately ready to be fetched
* from the shared memory area.
*/
.sync_cmds_completed_on_ret = true,
.atomic_enabled = IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE),
};
This diff is collapsed.
......@@ -43,3 +43,48 @@ bool imx_sc_rm_is_resource_owned(struct imx_sc_ipc *ipc, u16 resource)
return hdr->func;
}
EXPORT_SYMBOL(imx_sc_rm_is_resource_owned);
struct imx_sc_msg_rm_get_resource_owner {
struct imx_sc_rpc_msg hdr;
union {
struct {
u16 resource;
} req;
struct {
u8 val;
} resp;
} data;
} __packed __aligned(4);
/*
* This function get @resource partition number
*
* @param[in] ipc IPC handle
* @param[in] resource resource the control is associated with
* @param[out] pt pointer to return the partition number
*
* @return Returns 0 for success and < 0 for errors.
*/
int imx_sc_rm_get_resource_owner(struct imx_sc_ipc *ipc, u16 resource, u8 *pt)
{
struct imx_sc_msg_rm_get_resource_owner msg;
struct imx_sc_rpc_msg *hdr = &msg.hdr;
int ret;
hdr->ver = IMX_SC_RPC_VERSION;
hdr->svc = IMX_SC_RPC_SVC_RM;
hdr->func = IMX_SC_RM_FUNC_GET_RESOURCE_OWNER;
hdr->size = 2;
msg.data.req.resource = resource;
ret = imx_scu_call_rpc(ipc, &msg, true);
if (ret)
return ret;
if (pt)
*pt = msg.data.resp.val;
return 0;
}
EXPORT_SYMBOL(imx_sc_rm_get_resource_owner);
......@@ -155,6 +155,10 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 },
{ "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 },
{ "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 },
{ "vpu-enc1", IMX_SC_R_VPU_ENC_1, 1, false, 0 },
{ "vpu-mu0", IMX_SC_R_VPU_MU_0, 1, false, 0 },
{ "vpu-mu1", IMX_SC_R_VPU_MU_1, 1, false, 0 },
{ "vpu-mu2", IMX_SC_R_VPU_MU_2, 1, false, 0 },
/* GPU SS */
{ "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 },
......
......@@ -49,26 +49,12 @@ struct qcom_scm_mem_map_info {
__le64 mem_size;
};
#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
struct qcom_scm_wb_entry {
int flag;
void *entry;
/* Each bit configures cold/warm boot address for one of the 4 CPUs */
static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
0, BIT(0), BIT(3), BIT(5)
};
static struct qcom_scm_wb_entry qcom_scm_wb[] = {
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
BIT(2), BIT(1), BIT(4), BIT(6)
};
static const char * const qcom_scm_convention_names[] = {
......@@ -179,9 +165,8 @@ static enum qcom_scm_convention __get_convention(void)
/**
* qcom_scm_call() - Invoke a syscall in the secure world
* @dev: device
* @svc_id: service identifier
* @cmd_id: command identifier
* @desc: Descriptor structure containing arguments and return values
* @res: Structure containing results from SMC/HVC call
*
* Sends a command to the SCM and waits for the command to finish processing.
* This should *only* be called in pre-emptible context.
......@@ -205,8 +190,6 @@ static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc,
/**
* qcom_scm_call_atomic() - atomic variation of qcom_scm_call()
* @dev: device
* @svc_id: service identifier
* @cmd_id: command identifier
* @desc: Descriptor structure containing arguments and return values
* @res: Structure containing results from SMC/HVC call
*
......@@ -260,97 +243,83 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
return ret ? false : !!res.result[0];
}
/**
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
* @entry: Entry point function for the cpus
* @cpus: The cpumask of cpus that will use the entry point
*
* Set the Linux entry point for the SCM to transfer control to when coming
* out of a power down. CPU power down may be executed on cpuidle or hotplug.
*/
int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
static int qcom_scm_set_boot_addr(void *entry, const u8 *cpu_bits)
{
int ret;
int flags = 0;
int cpu;
unsigned int flags = 0;
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_BOOT,
.cmd = QCOM_SCM_BOOT_SET_ADDR,
.arginfo = QCOM_SCM_ARGS(2),
.owner = ARM_SMCCC_OWNER_SIP,
};
/*
* Reassign only if we are switching from hotplug entry point
* to cpuidle entry point or vice versa.
*/
for_each_cpu(cpu, cpus) {
if (entry == qcom_scm_wb[cpu].entry)
continue;
flags |= qcom_scm_wb[cpu].flag;
for_each_present_cpu(cpu) {
if (cpu >= QCOM_SCM_BOOT_MAX_CPUS)
return -EINVAL;
flags |= cpu_bits[cpu];
}
/* No change in entry function */
if (!flags)
return 0;
desc.args[0] = flags;
desc.args[1] = virt_to_phys(entry);
ret = qcom_scm_call(__scm->dev, &desc, NULL);
if (!ret) {
for_each_cpu(cpu, cpus)
qcom_scm_wb[cpu].entry = entry;
}
return ret;
return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
}
EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
/**
* qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
* @entry: Entry point function for the cpus
* @cpus: The cpumask of cpus that will use the entry point
*
* Set the cold boot address of the cpus. Any cpu outside the supported
* range would be removed from the cpu present mask.
*/
int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
static int qcom_scm_set_boot_addr_mc(void *entry, unsigned int flags)
{
int flags = 0;
int cpu;
int scm_cb_flags[] = {
QCOM_SCM_FLAG_COLDBOOT_CPU0,
QCOM_SCM_FLAG_COLDBOOT_CPU1,
QCOM_SCM_FLAG_COLDBOOT_CPU2,
QCOM_SCM_FLAG_COLDBOOT_CPU3,
};
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_BOOT,
.cmd = QCOM_SCM_BOOT_SET_ADDR,
.arginfo = QCOM_SCM_ARGS(2),
.cmd = QCOM_SCM_BOOT_SET_ADDR_MC,
.owner = ARM_SMCCC_OWNER_SIP,
.arginfo = QCOM_SCM_ARGS(6),
.args = {
virt_to_phys(entry),
/* Apply to all CPUs in all affinity levels */
~0ULL, ~0ULL, ~0ULL, ~0ULL,
flags,
},
};
if (!cpus || cpumask_empty(cpus))
return -EINVAL;
/* Need a device for DMA of the additional arguments */
if (!__scm || __get_convention() == SMC_CONVENTION_LEGACY)
return -EOPNOTSUPP;
for_each_cpu(cpu, cpus) {
if (cpu < ARRAY_SIZE(scm_cb_flags))
flags |= scm_cb_flags[cpu];
else
set_cpu_present(cpu, false);
}
return qcom_scm_call(__scm->dev, &desc, NULL);
}
desc.args[0] = flags;
desc.args[1] = virt_to_phys(entry);
/**
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for all cpus
* @entry: Entry point function for the cpus
*
* Set the Linux entry point for the SCM to transfer control to when coming
* out of a power down. CPU power down may be executed on cpuidle or hotplug.
*/
int qcom_scm_set_warm_boot_addr(void *entry)
{
if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_WARMBOOT))
/* Fallback to old SCM call */
return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_warm_bits);
return 0;
}
EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
/**
* qcom_scm_set_cold_boot_addr() - Set the cold boot address for all cpus
* @entry: Entry point function for the cpus
*/
int qcom_scm_set_cold_boot_addr(void *entry)
{
if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_COLDBOOT))
/* Fallback to old SCM call */
return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_cold_bits);
return 0;
}
EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
/**
* qcom_scm_cpu_power_down() - Power down the cpu
* @flags - Flags to flush cache
* @flags: Flags to flush cache
*
* This is an end point to power down cpu. If there was a pending interrupt,
* the control would return from this function, otherwise, the cpu jumps to the
......@@ -435,10 +404,16 @@ static void qcom_scm_set_download_mode(bool enable)
* and optional blob of data used for authenticating the metadata
* and the rest of the firmware
* @size: size of the metadata
* @ctx: optional metadata context
*
* Returns 0 on success.
* Return: 0 on success.
*
* Upon successful return, the PAS metadata context (@ctx) will be used to
* track the metadata allocation, this needs to be released by invoking
* qcom_scm_pas_metadata_release() by the caller.
*/
int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size,
struct qcom_scm_pas_metadata *ctx)
{
dma_addr_t mdata_phys;
void *mdata_buf;
......@@ -467,7 +442,7 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
ret = qcom_scm_clk_enable();
if (ret)
goto free_metadata;
goto out;
desc.args[1] = mdata_phys;
......@@ -475,13 +450,36 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
qcom_scm_clk_disable();
free_metadata:
dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
out:
if (ret < 0 || !ctx) {
dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
} else if (ctx) {
ctx->ptr = mdata_buf;
ctx->phys = mdata_phys;
ctx->size = size;
}
return ret ? : res.result[0];
}
EXPORT_SYMBOL(qcom_scm_pas_init_image);
/**
* qcom_scm_pas_metadata_release() - release metadata context
* @ctx: metadata context
*/
void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx)
{
if (!ctx->ptr)
return;
dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys);
ctx->ptr = NULL;
ctx->phys = 0;
ctx->size = 0;
}
EXPORT_SYMBOL(qcom_scm_pas_metadata_release);
/**
* qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral
* for firmware loading
......@@ -749,12 +747,6 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
};
int ret;
desc.args[0] = addr;
desc.args[1] = size;
desc.args[2] = spare;
desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
QCOM_SCM_VAL);
ret = qcom_scm_call(__scm->dev, &desc, NULL);
/* the pg table has been initialized already, ignore the error */
......@@ -765,6 +757,21 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
}
EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_MP,
.cmd = QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE,
.arginfo = QCOM_SCM_ARGS(2),
.args[0] = size,
.args[1] = spare,
.owner = ARM_SMCCC_OWNER_SIP,
};
return qcom_scm_call(__scm->dev, &desc, NULL);
}
EXPORT_SYMBOL(qcom_scm_iommu_set_cp_pool_size);
int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
u32 cp_nonpixel_start,
u32 cp_nonpixel_size)
......@@ -1131,6 +1138,22 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
}
EXPORT_SYMBOL(qcom_scm_hdcp_req);
int qcom_scm_iommu_set_pt_format(u32 sec_id, u32 ctx_num, u32 pt_fmt)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_SMMU_PROGRAM,
.cmd = QCOM_SCM_SMMU_PT_FORMAT,
.arginfo = QCOM_SCM_ARGS(3),
.args[0] = sec_id,
.args[1] = ctx_num,
.args[2] = pt_fmt, /* 0: LPAE AArch32 - 1: AArch64 */
.owner = ARM_SMCCC_OWNER_SIP,
};
return qcom_scm_call(__scm->dev, &desc, NULL);
}
EXPORT_SYMBOL(qcom_scm_iommu_set_pt_format);
int qcom_scm_qsmmu500_wait_safe_toggle(bool en)
{
struct qcom_scm_desc desc = {
......
This diff is collapsed.
......@@ -3412,7 +3412,7 @@ static int ti_sci_probe(struct platform_device *pdev)
ret = register_restart_handler(&info->nb);
if (ret) {
dev_err(dev, "reboot registration fail(%d)\n", ret);
return ret;
goto out;
}
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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