2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

soc: driver updates for 6.17

Changes are all over the place, but very little sticks out as
 noteworthy.
 
 There is a new misc driver for the Raspberry Pi 5's RP1 multifunction
 I/O chip, along with hooking it up to the pinctrl and clk frameworks.
 
 The reset controller and memory subsystems have mainly small updates,
 but there are two new reset drivers for the K230 and VC1800B SoCs,
 and new memory driver support for Tegra264.
 
 The ARM SMCCC and SCMI firmware drivers gain a few more features that
 should help them be supported across more environments. Similarly,
 the SoC specific firmware on Tegra and Qualcomm get minor enhancements
 and chip support.
 
 In the drivers/soc/ directory, the ASPEED LPC snoop driver gets an
 overhaul for code robustness, the Tegra and Qualcomm and NXP drivers
 grow to support more chips, while the Hisilicon, Mediatek and Renesas
 drivers see mostly janitorial fixes.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmiEmIcACgkQmmx57+YA
 GNkE4g/6A2OKti+qtIsLt10zS7paGP38ftu9ad27WC54AOGgVk4ZXt8mVGRmqOf+
 BICIM+wc4gehdvRJTRnq3gZg3e1puuYdcMuBOh4qsghRMjdYUKfNairtn/iX7d+f
 e5auzz5/gV7MWNM7jiQNydCqZSeV6u2/cqD5iRCrRgaB5FOG4yY1BkAsah1UzZjk
 MycudqjkK4IX5zp5oqXB/PoesULAbB2unjvfw194LATYSqmcRLQRWFdv4aM0R6ba
 TDP5x0d95nhMTNWif3495zc2WxdSYzbD4lNv44RPpKDywqBj+qFBI/EpMFkxQ5Hy
 cqv60Dm+/tx+DBO/Ma0zJzsV4ChRIEBNkTUh36OxmYxq70x1T4FEynZ6IT8a8dXD
 ltjHwOcTHp1M0OpNj+PIFBD+ohWFWKOo+T9GRtTInLjUGBlJA6LK9i4Lb0DaIyRt
 DmmvbZCwh0PI/nZiyQzw7rsXWwqDcqeF8FScw+9ooBk7Z7Jr1gMc52ya0qrRWQ8w
 Tr3D+lNE0aDfErnx4RrNsjD8lpX4nOfRFvuWSTlWqkBjGhoDP/tnNi2RCWmbXo2Z
 PDDWLnECo6o1aIxYO/tHjbFKVJB38p4e/LLP89htu8dFxSZKnVzxosnOvEVWS8+Y
 a0oZb9j1tAOYHmMWDm+zaQ7BlK9CMURNTdUcnqNqIvZpHnHz9M8=
 =7T40
 -----END PGP SIGNATURE-----

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

Pull SoC driver updates from Arnd Bergmann:
 "Changes are all over the place, but very little sticks out as
  noteworthy.

  There is a new misc driver for the Raspberry Pi 5's RP1 multifunction
  I/O chip, along with hooking it up to the pinctrl and clk frameworks.

  The reset controller and memory subsystems have mainly small updates,
  but there are two new reset drivers for the K230 and VC1800B SoCs, and
  new memory driver support for Tegra264.

  The ARM SMCCC and SCMI firmware drivers gain a few more features that
  should help them be supported across more environments. Similarly, the
  SoC specific firmware on Tegra and Qualcomm get minor enhancements and
  chip support.

  In the drivers/soc/ directory, the ASPEED LPC snoop driver gets an
  overhaul for code robustness, the Tegra and Qualcomm and NXP drivers
  grow to support more chips, while the Hisilicon, Mediatek and Renesas
  drivers see mostly janitorial fixes"

* tag 'soc-drivers-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (100 commits)
  bus: del unnecessary init var
  soc: fsl: qe: convert set_multiple() to returning an integer
  pinctrl: rp1: use new GPIO line value setter callbacks
  soc: hisilicon: kunpeng_hccs: Fix incorrect log information
  dt-bindings: soc: qcom: qcom,pmic-glink: document Milos compatible
  dt-bindings: soc: qcom,aoss-qmp: document the Milos Always-On Subsystem side channel
  dt-bindings: firmware: qcom,scm: document Milos SCM Firmware Interface
  soc: qcom: socinfo: Add support to retrieve APPSBL build details
  soc: qcom: pmic_glink: fix OF node leak
  soc: qcom: spmi-pmic: add more PMIC SUBTYPE IDs
  soc: qcom: socinfo: Add PM7550 & PMIV0108 PMICs
  soc: qcom: socinfo: Add SoC IDs for SM7635 family
  dt-bindings: arm: qcom,ids: Add SoC IDs for SM7635 family
  firmware: qcom: scm: request the waitqueue irq *after* initializing SCM
  firmware: qcom: scm: initialize tzmem before marking SCM as available
  firmware: qcom: scm: take struct device as argument in SHM bridge enable
  firmware: qcom: scm: remove unused arguments from SHM bridge routines
  soc: qcom: rpmh-rsc: Add RSC version 4 support
  memory: tegra: Add Tegra264 MC and EMC support
  firmware: tegra: bpmp: Fix build failure for tegra264-only config
  ...
This commit is contained in:
Linus Torvalds 2025-07-29 11:13:27 -07:00
commit 0f46f50845
94 changed files with 6805 additions and 1083 deletions

View File

@ -200,6 +200,7 @@ properties:
- qcom,kryo385
- qcom,kryo465
- qcom,kryo468
- qcom,kryo470
- qcom,kryo485
- qcom,kryo560
- qcom,kryo570

View File

@ -32,6 +32,7 @@ properties:
- qcom,scm-ipq8074
- qcom,scm-ipq9574
- qcom,scm-mdm9607
- qcom,scm-milos
- qcom,scm-msm8226
- qcom,scm-msm8660
- qcom,scm-msm8916
@ -198,6 +199,7 @@ allOf:
compatible:
contains:
enum:
- qcom,scm-milos
- qcom,scm-sm8450
- qcom,scm-sm8550
- qcom,scm-sm8650

View File

@ -1,127 +0,0 @@
* Device tree bindings for ARM PL172/PL175/PL176 MultiPort Memory Controller
Required properties:
- compatible: Must be "arm,primecell" and exactly one from
"arm,pl172", "arm,pl175" or "arm,pl176".
- reg: Must contains offset/length value for controller.
- #address-cells: Must be 2. The partition number has to be encoded in the
first address cell and it may accept values 0..N-1
(N - total number of partitions). The second cell is the
offset into the partition.
- #size-cells: Must be set to 1.
- ranges: Must contain one or more chip select memory regions.
- clocks: Must contain references to controller clocks.
- clock-names: Must contain "mpmcclk" and "apb_pclk".
- clock-ranges: Empty property indicating that child nodes can inherit
named clocks. Required only if clock tree data present
in device tree.
See clock-bindings.txt
Child chip-select (cs) nodes contain the memory devices nodes connected to
such as NOR (e.g. cfi-flash) and NAND.
Required child cs node properties:
- #address-cells: Must be 2.
- #size-cells: Must be 1.
- ranges: Empty property indicating that child nodes can inherit
memory layout.
- clock-ranges: Empty property indicating that child nodes can inherit
named clocks. Required only if clock tree data present
in device tree.
- mpmc,cs: Chip select number. Indicates to the pl0172 driver
which chipselect is used for accessing the memory.
- mpmc,memory-width: Width of the chip select memory. Must be equal to
either 8, 16 or 32.
Optional child cs node config properties:
- mpmc,async-page-mode: Enable asynchronous page mode.
- mpmc,cs-active-high: Set chip select polarity to active high.
- mpmc,byte-lane-low: Set byte lane state to low.
- mpmc,extended-wait: Enable extended wait.
- mpmc,buffer-enable: Enable write buffer, option is not supported by
PL175 and PL176 controllers.
- mpmc,write-protect: Enable write protect.
Optional child cs node timing properties:
- mpmc,write-enable-delay: Delay from chip select assertion to write
enable (WE signal) in nano seconds.
- mpmc,output-enable-delay: Delay from chip select assertion to output
enable (OE signal) in nano seconds.
- mpmc,write-access-delay: Delay from chip select assertion to write
access in nano seconds.
- mpmc,read-access-delay: Delay from chip select assertion to read
access in nano seconds.
- mpmc,page-mode-read-delay: Delay for asynchronous page mode sequential
accesses in nano seconds.
- mpmc,turn-round-delay: Delay between access to memory banks in nano
seconds.
If any of the above timing parameters are absent, current parameter value will
be taken from the corresponding HW reg.
Example for pl172 with nor flash on chip select 0 shown below.
emc: memory-controller@40005000 {
compatible = "arm,pl172", "arm,primecell";
reg = <0x40005000 0x1000>;
clocks = <&ccu1 CLK_CPU_EMCDIV>, <&ccu1 CLK_CPU_EMC>;
clock-names = "mpmcclk", "apb_pclk";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x1c000000 0x1000000
1 0 0x1d000000 0x1000000
2 0 0x1e000000 0x1000000
3 0 0x1f000000 0x1000000>;
cs0 {
#address-cells = <2>;
#size-cells = <1>;
ranges;
mpmc,cs = <0>;
mpmc,memory-width = <16>;
mpmc,byte-lane-low;
mpmc,write-enable-delay = <0>;
mpmc,output-enable-delay = <0>;
mpmc,read-enable-delay = <70>;
mpmc,page-mode-read-delay = <70>;
flash@0,0 {
compatible = "sst,sst39vf320", "cfi-flash";
reg = <0 0 0x400000>;
bank-width = <2>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "data";
reg = <0 0x400000>;
};
};
};
};

View File

@ -0,0 +1,222 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/arm,pl172.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM PL172/PL175/PL176 MultiPort Memory Controller
maintainers:
- Frank Li <Frank.Li@nxp.com>
# We need a select here so we don't match all nodes with 'arm,primecell'
select:
properties:
compatible:
contains:
enum:
- arm,pl172
- arm,pl175
- arm,pl176
required:
- compatible
properties:
compatible:
items:
- enum:
- arm,pl172
- arm,pl175
- arm,pl176
- const: arm,primecell
reg:
maxItems: 1
'#address-cells':
const: 2
'#size-cells':
const: 1
ranges: true
clocks:
maxItems: 2
clock-names:
items:
- const: mpmcclk
- const: apb_pclk
clock-ranges: true
resets:
maxItems: 1
patternProperties:
"^cs[0-9]$":
type: object
additionalProperties: false
patternProperties:
"^flash@[0-9],[0-9a-f]+$":
type: object
$ref: /schemas/mtd/mtd-physmap.yaml#
unevaluatedProperties: false
"^(gpio|sram)@[0-9],[0-9a-f]+$":
type: object
additionalProperties: true
properties:
'#address-cells':
const: 2
'#size-cells':
const: 1
ranges: true
clocks:
maxItems: 2
clock-ranges: true
mpmc,cs:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Chip select number. Indicates to the pl0172 driver
which chipselect is used for accessing the memory.
mpmc,memory-width:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [8, 16, 32]
description:
Width of the chip select memory. Must be equal to either 8, 16 or 32.
mpmc,async-page-mode:
$ref: /schemas/types.yaml#/definitions/flag
description:
Enable asynchronous page mode.
mpmc,cs-active-high:
$ref: /schemas/types.yaml#/definitions/flag
description:
Set chip select polarity to active high.
mpmc,byte-lane-low:
$ref: /schemas/types.yaml#/definitions/flag
description:
Set byte lane state to low.
mpmc,extended-wait:
$ref: /schemas/types.yaml#/definitions/flag
description:
Enable extended wait.
mpmc,buffer-enable:
$ref: /schemas/types.yaml#/definitions/flag
description:
Enable write buffer, option is not supported by
PL175 and PL176 controllers.
mpmc,write-protect:
$ref: /schemas/types.yaml#/definitions/flag
description:
Enable write protect.
mpmc,read-enable-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay from chip select assertion to read
enable (RE signal) in nano seconds.
mpmc,write-enable-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay from chip select assertion to write
enable (WE signal) in nano seconds.
mpmc,output-enable-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay from chip select assertion to output
enable (OE signal) in nano seconds.
mpmc,write-access-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay from chip select assertion to write
access in nano seconds.
mpmc,read-access-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay from chip select assertion to read
access in nano seconds.
mpmc,page-mode-read-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay for asynchronous page mode sequential
accesses in nano seconds.
mpmc,turn-round-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay between access to memory banks in nano
seconds.
required:
- compatible
- reg
- '#address-cells'
- '#size-cells'
- ranges
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/lpc18xx-ccu.h>
memory-controller@40005000 {
compatible = "arm,pl172", "arm,primecell";
reg = <0x40005000 0x1000>;
clocks = <&ccu1 CLK_CPU_EMCDIV>, <&ccu1 CLK_CPU_EMC>;
clock-names = "mpmcclk", "apb_pclk";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x1c000000 0x1000000
1 0 0x1d000000 0x1000000
2 0 0x1e000000 0x1000000
3 0 0x1f000000 0x1000000>;
cs0 {
#address-cells = <2>;
#size-cells = <1>;
ranges;
mpmc,cs = <0>;
mpmc,memory-width = <16>;
mpmc,byte-lane-low;
mpmc,write-enable-delay = <0>;
mpmc,output-enable-delay = <0>;
mpmc,read-enable-delay = <70>;
mpmc,page-mode-read-delay = <70>;
flash@0,0 {
compatible = "sst,sst39vf320", "cfi-flash";
reg = <0 0 0x400000>;
bank-width = <2>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "data";
reg = <0 0x400000>;
};
};
};
};

View File

@ -11,11 +11,10 @@ maintainers:
properties:
compatible:
oneOf:
- description: Revision > 2.1 controllers
items:
- enum:
- brcm,brcmstb-memc-ddr-rev-b.1.x
- brcm,brcmstb-memc-ddr-rev-b.2.0
- brcm,brcmstb-memc-ddr-rev-b.2.1
- brcm,brcmstb-memc-ddr-rev-b.2.2
- brcm,brcmstb-memc-ddr-rev-b.2.3
- brcm,brcmstb-memc-ddr-rev-b.2.5
@ -29,6 +28,19 @@ properties:
- brcm,brcmstb-memc-ddr-rev-c.1.2
- brcm,brcmstb-memc-ddr-rev-c.1.3
- brcm,brcmstb-memc-ddr-rev-c.1.4
- const: brcm,brcmstb-memc-ddr-rev-b.2.1
- const: brcm,brcmstb-memc-ddr
- description: Revision 2.1 controllers
items:
- const: brcm,brcmstb-memc-ddr-rev-b.2.1
- const: brcm,brcmstb-memc-ddr
- description: Revision 2.0 controllers
items:
- const: brcm,brcmstb-memc-ddr-rev-b.2.0
- const: brcm,brcmstb-memc-ddr
- description: Revision 1.x controllers
items:
- const: brcm,brcmstb-memc-ddr-rev-b.1.x
- const: brcm,brcmstb-memc-ddr
reg:
@ -46,7 +58,9 @@ additionalProperties: false
examples:
- |
memory-controller@9902000 {
compatible = "brcm,brcmstb-memc-ddr-rev-c.1.1", "brcm,brcmstb-memc-ddr";
compatible = "brcm,brcmstb-memc-ddr-rev-c.1.1",
"brcm,brcmstb-memc-ddr-rev-b.2.1",
"brcm,brcmstb-memc-ddr";
reg = <0x9902000 0x600>;
clock-frequency = <2133000000>;
};

View File

@ -23,7 +23,14 @@ allOf:
properties:
compatible:
const: renesas,r9a09g047-xspi # RZ/G3E
oneOf:
- const: renesas,r9a09g047-xspi # RZ/G3E
- items:
- enum:
- renesas,r9a09g056-xspi # RZ/V2N
- renesas,r9a09g057-xspi # RZ/V2H(P)
- const: renesas,r9a09g047-xspi
reg:
items:

View File

@ -0,0 +1,39 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/canaan,k230-rst.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Canaan Kendryte K230 Reset Controller
maintainers:
- Junhui Liu <junhui.liu@pigmoral.tech>
description:
The Canaan Kendryte K230 reset controller is part of the SoC's system
controller and controls the reset registers for CPUs and various peripherals.
properties:
compatible:
const: canaan,k230-rst
reg:
maxItems: 1
'#reset-cells':
const: 1
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
reset-controller@91101000 {
compatible = "canaan,k230-rst";
reg = <0x91101000 0x1000>;
#reset-cells = <1>;
};

View File

@ -1,83 +0,0 @@
NXP LPC1850 Reset Generation Unit (RGU)
========================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: Should be "nxp,lpc1850-rgu"
- reg: register base and length
- clocks: phandle and clock specifier to RGU clocks
- clock-names: should contain "delay" and "reg"
- #reset-cells: should be 1
See table below for valid peripheral reset numbers. Numbers not
in the table below are either reserved or not applicable for
normal operation.
Reset Peripheral
9 System control unit (SCU)
12 ARM Cortex-M0 subsystem core (LPC43xx only)
13 CPU core
16 LCD controller
17 USB0
18 USB1
19 DMA
20 SDIO
21 External memory controller (EMC)
22 Ethernet
25 Flash bank A
27 EEPROM
28 GPIO
29 Flash bank B
32 Timer0
33 Timer1
34 Timer2
35 Timer3
36 Repetitive Interrupt timer (RIT)
37 State Configurable Timer (SCT)
38 Motor control PWM (MCPWM)
39 QEI
40 ADC0
41 ADC1
42 DAC
44 USART0
45 UART1
46 USART2
47 USART3
48 I2C0
49 I2C1
50 SSP0
51 SSP1
52 I2S0 and I2S1
53 Serial Flash Interface (SPIFI)
54 C_CAN1
55 C_CAN0
56 ARM Cortex-M0 application core (LPC4370 only)
57 SGPIO (LPC43xx only)
58 SPI (LPC43xx only)
60 ADCHS (12-bit ADC) (LPC4370 only)
Refer to NXP LPC18xx or LPC43xx user manual for more details about
the reset signals and the connected block/peripheral.
Reset provider example:
rgu: reset-controller@40053000 {
compatible = "nxp,lpc1850-rgu";
reg = <0x40053000 0x1000>;
clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_BUS>;
clock-names = "delay", "reg";
#reset-cells = <1>;
};
Reset consumer example:
mac: ethernet@40010000 {
compatible = "nxp,lpc1850-dwmac", "snps,dwmac-3.611", "snps,dwmac";
reg = <0x40010000 0x2000>;
interrupts = <5>;
interrupt-names = "macirq";
clocks = <&ccu1 CLK_CPU_ETHERNET>;
clock-names = "stmmaceth";
resets = <&rgu 22>;
reset-names = "stmmaceth";
};

View File

@ -0,0 +1,101 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/nxp,lpc1850-rgu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP LPC1850 Reset Generation Unit (RGU)
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
const: nxp,lpc1850-rgu
reg:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: delay
- const: reg
'#reset-cells':
const: 1
description: |
See table below for valid peripheral reset numbers. Numbers not
in the table below are either reserved or not applicable for
normal operation.
Reset Peripheral
9 System control unit (SCU)
12 ARM Cortex-M0 subsystem core (LPC43xx only)
13 CPU core
16 LCD controller
17 USB0
18 USB1
19 DMA
20 SDIO
21 External memory controller (EMC)
22 Ethernet
25 Flash bank A
27 EEPROM
28 GPIO
29 Flash bank B
32 Timer0
33 Timer1
34 Timer2
35 Timer3
36 Repetitive Interrupt timer (RIT)
37 State Configurable Timer (SCT)
38 Motor control PWM (MCPWM)
39 QEI
40 ADC0
41 ADC1
42 DAC
44 USART0
45 UART1
46 USART2
47 USART3
48 I2C0
49 I2C1
50 SSP0
51 SSP1
52 I2S0 and I2S1
53 Serial Flash Interface (SPIFI)
54 C_CAN1
55 C_CAN0
56 ARM Cortex-M0 application core (LPC4370 only)
57 SGPIO (LPC43xx only)
58 SPI (LPC43xx only)
60 ADCHS (12-bit ADC) (LPC4370 only)
Refer to NXP LPC18xx or LPC43xx user manual for more details about
the reset signals and the connected block/peripheral.
required:
- compatible
- reg
- clocks
- clock-names
- '#reset-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/lpc18xx-ccu.h>
#include <dt-bindings/clock/lpc18xx-cgu.h>
reset-controller@40053000 {
compatible = "nxp,lpc1850-rgu";
reg = <0x40053000 0x1000>;
clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_BUS>;
clock-names = "delay", "reg";
#reset-cells = <1>;
};

View File

@ -15,7 +15,12 @@ description:
properties:
compatible:
const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
oneOf:
- items:
- const: renesas,r9a09g056-usb2phy-reset # RZ/V2N
- const: renesas,r9a09g057-usb2phy-reset
- const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
reg:
maxItems: 1

View File

@ -1,30 +0,0 @@
Synopsys DesignWare Reset controller
=======================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: should be one of the following.
"snps,dw-high-reset" - for active high configuration
"snps,dw-low-reset" - for active low configuration
- reg: physical base address of the controller and length of memory mapped
region.
- #reset-cells: must be 1.
example:
dw_rst_1: reset-controller@0000 {
compatible = "snps,dw-high-reset";
reg = <0x0000 0x4>;
#reset-cells = <1>;
};
dw_rst_2: reset-controller@1000 {
compatible = "snps,dw-low-reset";
reg = <0x1000 0x8>;
#reset-cells = <1>;
};

View File

@ -0,0 +1,39 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/snps,dw-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare Reset controller
maintainers:
- Philipp Zabel <p.zabel@pengutronix.de>
properties:
compatible:
enum:
- snps,dw-high-reset
- snps,dw-low-reset
reg:
maxItems: 1
'#reset-cells':
const: 1
reset-controller: true
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
reset-controller@0 {
compatible = "snps,dw-high-reset";
reg = <0x0000 0x4>;
#reset-cells = <1>;
};

View File

@ -16,7 +16,9 @@ properties:
- enum:
- sophgo,sg2044-reset
- const: sophgo,sg2042-reset
- const: sophgo,sg2042-reset
- enum:
- sophgo,cv1800b-reset
- sophgo,sg2042-reset
reg:
maxItems: 1

View File

@ -25,6 +25,7 @@ properties:
compatible:
items:
- enum:
- qcom,milos-aoss-qmp
- qcom,qcs615-aoss-qmp
- qcom,qcs8300-aoss-qmp
- qcom,qdu1000-aoss-qmp
@ -38,6 +39,7 @@ properties:
- qcom,sdx75-aoss-qmp
- qcom,sdm845-aoss-qmp
- qcom,sm6350-aoss-qmp
- qcom,sm7150-aoss-qmp
- qcom,sm8150-aoss-qmp
- qcom,sm8250-aoss-qmp
- qcom,sm8350-aoss-qmp

View File

@ -18,6 +18,7 @@ properties:
compatible:
items:
- enum:
- qcom,sm7150-dcc
- qcom,sm8150-dcc
- qcom,sc7280-dcc
- qcom,sc7180-dcc

View File

@ -37,6 +37,7 @@ properties:
- const: qcom,pmic-glink
- items:
- enum:
- qcom,milos-pmic-glink
- qcom,sm8650-pmic-glink
- qcom,sm8750-pmic-glink
- qcom,x1e80100-pmic-glink

View File

@ -22,17 +22,32 @@ properties:
- qcom,msm8974-imem
- qcom,msm8976-imem
- qcom,qcs404-imem
- qcom,qcs615-imem
- qcom,qcs8300-imem
- qcom,qdu1000-imem
- qcom,sa8775p-imem
- qcom,sar2130p-imem
- qcom,sc7180-imem
- qcom,sc7280-imem
- qcom,sc8280xp-imem
- qcom,sdm630-imem
- qcom,sdm845-imem
- qcom,sdx55-imem
- qcom,sdx65-imem
- qcom,sdx75-imem
- qcom,sm6115-imem
- qcom,sm6125-imem
- qcom,sm6350-imem
- qcom,sm6375-imem
- qcom,sm7150-imem
- qcom,sm8150-imem
- qcom,sm8250-imem
- qcom,sm8350-imem
- qcom,sm8450-imem
- qcom,sm8550-imem
- qcom,sm8650-imem
- qcom,sm8750-imem
- qcom,x1e80100-imem
- const: syscon
- const: simple-mfd

View File

@ -2620,6 +2620,8 @@ L: imx@lists.linux.dev
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
F: Documentation/devicetree/bindings/firmware/fsl*
F: Documentation/devicetree/bindings/firmware/nxp*
F: arch/arm/boot/dts/nxp/imx/
F: arch/arm/boot/dts/nxp/mxs/
F: arch/arm64/boot/dts/freescale/
@ -3035,8 +3037,10 @@ R: Ghennadi Procopciuc <ghennadi.procopciuc@oss.nxp.com>
R: NXP S32 Linux Team <s32@nxp.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/rtc/nxp,s32g-rtc.yaml
F: arch/arm64/boot/dts/freescale/s32g*.dts*
F: drivers/pinctrl/nxp/
F: drivers/rtc/rtc-s32g.c
ARM/NXP S32G/S32R DWMAC ETHERNET DRIVER
M: Jan Petrous <jan.petrous@oss.nxp.com>
@ -20819,6 +20823,14 @@ S: Maintained
F: Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml
F: drivers/media/platform/raspberrypi/rp1-cfe/
RASPBERRY PI RP1 PCI DRIVER
M: Andrea della Porta <andrea.porta@suse.com>
S: Maintained
F: arch/arm64/boot/dts/broadcom/rp1*.dts*
F: drivers/clk/clk-rp1.c
F: drivers/misc/rp1/
F: drivers/pinctrl/pinctrl-rp1.c
RC-CORE / LIRC FRAMEWORK
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org

View File

@ -87,6 +87,12 @@ config HISILICON_LPC
Driver to enable I/O access to devices attached to the Low Pin
Count bus on the HiSilicon Hip06/7 SoC.
config IMX_AIPSTZ
tristate "Support for IMX Secure AHB to IP Slave bus (AIPSTZ) bridge"
depends on ARCH_MXC
help
Enable support for IMX AIPSTZ bridge.
config IMX_WEIM
bool "Freescale EIM DRIVER"
depends on ARCH_MXC || COMPILE_TEST

View File

@ -15,6 +15,7 @@ obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_BT1_APB) += bt1-apb.o
obj-$(CONFIG_BT1_AXI) += bt1-axi.o
obj-$(CONFIG_IMX_AIPSTZ) += imx-aipstz.o
obj-$(CONFIG_IMX_WEIM) += imx-weim.o
obj-$(CONFIG_INTEL_IXP4XX_EB) += intel-ixp4xx-eb.o
obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o

108
drivers/bus/imx-aipstz.c Normal file
View File

@ -0,0 +1,108 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2025 NXP
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#define IMX_AIPSTZ_MPR0 0x0
struct imx_aipstz_config {
u32 mpr0;
};
struct imx_aipstz_data {
void __iomem *base;
const struct imx_aipstz_config *default_cfg;
};
static void imx_aipstz_apply_default(struct imx_aipstz_data *data)
{
writel(data->default_cfg->mpr0, data->base + IMX_AIPSTZ_MPR0);
}
static const struct of_device_id imx_aipstz_match_table[] = {
{ .compatible = "simple-bus", },
{ }
};
static int imx_aipstz_probe(struct platform_device *pdev)
{
struct imx_aipstz_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return dev_err_probe(&pdev->dev, -ENOMEM,
"failed to allocate data memory\n");
data->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(data->base))
return dev_err_probe(&pdev->dev, -ENOMEM,
"failed to get/ioremap AC memory\n");
data->default_cfg = of_device_get_match_data(&pdev->dev);
imx_aipstz_apply_default(data);
dev_set_drvdata(&pdev->dev, data);
pm_runtime_set_active(&pdev->dev);
devm_pm_runtime_enable(&pdev->dev);
return of_platform_populate(pdev->dev.of_node, imx_aipstz_match_table,
NULL, &pdev->dev);
}
static void imx_aipstz_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
}
static int imx_aipstz_runtime_resume(struct device *dev)
{
struct imx_aipstz_data *data = dev_get_drvdata(dev);
/* restore potentially lost configuration during domain power-off */
imx_aipstz_apply_default(data);
return 0;
}
static const struct dev_pm_ops imx_aipstz_pm_ops = {
RUNTIME_PM_OPS(NULL, imx_aipstz_runtime_resume, NULL)
SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
/*
* following configuration is equivalent to:
* masters 0-7 => trusted for R/W + use AHB's HPROT[1] to det. privilege
*/
static const struct imx_aipstz_config imx8mp_aipstz_default_cfg = {
.mpr0 = 0x77777777,
};
static const struct of_device_id imx_aipstz_of_ids[] = {
{ .compatible = "fsl,imx8mp-aipstz", .data = &imx8mp_aipstz_default_cfg },
{ }
};
MODULE_DEVICE_TABLE(of, imx_aipstz_of_ids);
static struct platform_driver imx_aipstz_of_driver = {
.probe = imx_aipstz_probe,
.remove = imx_aipstz_remove,
.driver = {
.name = "imx-aipstz",
.of_match_table = imx_aipstz_of_ids,
.pm = pm_ptr(&imx_aipstz_pm_ops),
},
};
module_platform_driver(imx_aipstz_of_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IMX secure AHB to IP Slave bus (AIPSTZ) bridge driver");
MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>");

View File

@ -2170,9 +2170,8 @@ static int sysc_reset(struct sysc *ddata)
static int sysc_init_module(struct sysc *ddata)
{
bool rstctrl_deasserted = false;
int error = 0;
int error = sysc_clockdomain_init(ddata);
error = sysc_clockdomain_init(ddata);
if (error)
return error;

View File

@ -88,6 +88,15 @@ config COMMON_CLK_RK808
These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
Clkout1 is always on, Clkout2 can off by control register.
config COMMON_CLK_RP1
tristate "Raspberry Pi RP1-based clock support"
depends on MISC_RP1 || COMPILE_TEST
default MISC_RP1
help
Enable common clock framework support for Raspberry Pi RP1.
This multi-function device has 3 main PLLs and several clock
generators to drive the internal sub-peripherals.
config COMMON_CLK_HI655X
tristate "Clock driver for Hi655x" if EXPERT
depends on (MFD_HI655X_PMIC || COMPILE_TEST)

View File

@ -84,6 +84,7 @@ obj-$(CONFIG_CLK_LS1028A_PLLDIG) += clk-plldig.o
obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_RP1) += clk-rp1.o
obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o

1494
drivers/clk/clk-rp1.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -323,6 +323,31 @@ static struct attribute *scmi_device_attributes_attrs[] = {
};
ATTRIBUTE_GROUPS(scmi_device_attributes);
static int scmi_pm_suspend(struct device *dev)
{
const struct device_driver *drv = dev->driver;
if (drv && drv->pm && drv->pm->suspend)
return drv->pm->suspend(dev);
return 0;
}
static int scmi_pm_resume(struct device *dev)
{
const struct device_driver *drv = dev->driver;
if (drv && drv->pm && drv->pm->resume)
return drv->pm->resume(dev);
return 0;
}
static const struct dev_pm_ops scmi_dev_pm_ops = {
.suspend = pm_sleep_ptr(scmi_pm_suspend),
.resume = pm_sleep_ptr(scmi_pm_resume),
};
const struct bus_type scmi_bus_type = {
.name = "scmi_protocol",
.match = scmi_dev_match,
@ -330,6 +355,7 @@ const struct bus_type scmi_bus_type = {
.remove = scmi_dev_remove,
.uevent = scmi_device_uevent,
.dev_groups = scmi_device_attributes_groups,
.pm = &scmi_dev_pm_ops,
};
EXPORT_SYMBOL_GPL(scmi_bus_type);

View File

@ -305,6 +305,7 @@ enum debug_counters {
ERR_MSG_INVALID,
ERR_MSG_NOMEM,
ERR_PROTOCOL,
XFERS_INFLIGHT,
SCMI_DEBUG_COUNTERS_LAST
};
@ -314,6 +315,12 @@ static inline void scmi_inc_count(atomic_t *arr, int stat)
atomic_inc(&arr[stat]);
}
static inline void scmi_dec_count(atomic_t *arr, int stat)
{
if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS))
atomic_dec(&arr[stat]);
}
enum scmi_bad_msg {
MSG_UNEXPECTED = -1,
MSG_INVALID = -2,
@ -498,4 +505,5 @@ static struct platform_driver __drv = { \
void scmi_notification_instance_data_set(const struct scmi_handle *handle,
void *priv);
void *scmi_notification_instance_data_get(const struct scmi_handle *handle);
int scmi_inflight_count(const struct scmi_handle *handle);
#endif /* _SCMI_COMMON_H */

View File

@ -190,6 +190,7 @@ struct scmi_info {
};
#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)
#define tx_minfo_to_scmi_info(h) container_of(h, struct scmi_info, tx_minfo)
#define bus_nb_to_scmi_info(nb) container_of(nb, struct scmi_info, bus_nb)
#define req_nb_to_scmi_info(nb) container_of(nb, struct scmi_info, dev_req_nb)
@ -603,9 +604,14 @@ static inline void
scmi_xfer_inflight_register_unlocked(struct scmi_xfer *xfer,
struct scmi_xfers_info *minfo)
{
/* In this context minfo will be tx_minfo due to the xfer pending */
struct scmi_info *info = tx_minfo_to_scmi_info(minfo);
/* Set in-flight */
set_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
hash_add(minfo->pending_xfers, &xfer->node, xfer->hdr.seq);
scmi_inc_count(info->dbg->counters, XFERS_INFLIGHT);
xfer->pending = true;
}
@ -807,9 +813,13 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)
spin_lock_irqsave(&minfo->xfer_lock, flags);
if (refcount_dec_and_test(&xfer->users)) {
if (xfer->pending) {
struct scmi_info *info = tx_minfo_to_scmi_info(minfo);
scmi_xfer_token_clear(minfo, xfer);
hash_del(&xfer->node);
xfer->pending = false;
scmi_dec_count(info->dbg->counters, XFERS_INFLIGHT);
}
hlist_add_head(&xfer->node, &minfo->free_xfers);
}
@ -1433,7 +1443,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq,
xfer->hdr.poll_completion);
xfer->hdr.poll_completion,
scmi_inflight_count(&info->handle));
/* Clear any stale status */
xfer->hdr.status = SCMI_SUCCESS;
@ -1469,7 +1480,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
info->desc->ops->mark_txdone(cinfo, ret, xfer);
trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq, ret);
xfer->hdr.protocol_id, xfer->hdr.seq, ret,
scmi_inflight_count(&info->handle));
return ret;
}
@ -2912,6 +2924,7 @@ static const char * const dbg_counter_strs[] = {
"err_msg_invalid",
"err_msg_nomem",
"err_protocol",
"xfers_inflight",
};
static ssize_t reset_all_on_write(struct file *filp, const char __user *buf,
@ -3405,6 +3418,17 @@ static struct dentry *scmi_debugfs_init(void)
return d;
}
int scmi_inflight_count(const struct scmi_handle *handle)
{
if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) {
struct scmi_info *info = handle_to_scmi_info(handle);
return atomic_read(&info->dbg->counters[XFERS_INFLIGHT]);
} else {
return 0;
}
}
static int __init scmi_driver_init(void)
{
scmi_quirks_initialize();

View File

@ -318,6 +318,9 @@ struct scmi_registered_events_desc {
* customized event report
* @num_sources: The number of possible sources for this event as stated at
* events' registration time
* @not_supported_by_platform: A flag to indicate that not even one source was
* found to be supported by the platform for this
* event
* @sources: A reference to a dynamically allocated array used to refcount the
* events' enable requests for all the existing sources
* @sources_mtx: A mutex to serialize the access to @sources
@ -334,6 +337,7 @@ struct scmi_registered_event {
const struct scmi_event *evt;
void *report;
u32 num_sources;
bool not_supported_by_platform;
refcount_t *sources;
/* locking to serialize the access to sources */
struct mutex sources_mtx;
@ -811,10 +815,19 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
if (!r_evt->report)
return -ENOMEM;
for (id = 0; id < r_evt->num_sources; id++)
if (ee->ops->is_notify_supported &&
!ee->ops->is_notify_supported(ph, r_evt->evt->id, id))
if (ee->ops->is_notify_supported) {
int supported = 0;
for (id = 0; id < r_evt->num_sources; id++) {
if (!ee->ops->is_notify_supported(ph, r_evt->evt->id, id))
refcount_set(&r_evt->sources[id], NOTIF_UNSUPP);
else
supported++;
}
/* Not even one source has been found to be supported */
r_evt->not_supported_by_platform = !supported;
}
pd->registered_events[i] = r_evt;
/* Ensure events are updated */
@ -936,6 +949,11 @@ static inline int scmi_bind_event_handler(struct scmi_notify_instance *ni,
* of protocol instance.
*/
hash_del(&hndl->hash);
/* Bailout if event is not supported at all */
if (r_evt->not_supported_by_platform)
return -EOPNOTSUPP;
/*
* Acquire protocols only for NON pending handlers, so as NOT to trigger
* protocol initialization when a notifier is registered against a still
@ -1060,6 +1078,9 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni,
r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(evt_key),
KEY_XTRACT_EVT_ID(evt_key));
if (r_evt && r_evt->not_supported_by_platform)
return ERR_PTR(-EOPNOTSUPP);
mutex_lock(&ni->pending_mtx);
/* Search registered events at first ... if possible at all */
if (r_evt) {
@ -1087,7 +1108,7 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni,
hndl->key);
/* this hndl can be only a pending one */
scmi_put_handler_unlocked(ni, hndl);
hndl = NULL;
hndl = ERR_PTR(-EINVAL);
}
}
mutex_unlock(&ni->pending_mtx);
@ -1370,8 +1391,8 @@ static int scmi_notifier_register(const struct scmi_handle *handle,
evt_key = MAKE_HASH_KEY(proto_id, evt_id,
src_id ? *src_id : SRC_ID_MASK);
hndl = scmi_get_or_create_handler(ni, evt_key);
if (!hndl)
return -EINVAL;
if (IS_ERR(hndl))
return PTR_ERR(hndl);
blocking_notifier_chain_register(&hndl->chain, nb);
@ -1416,8 +1437,8 @@ static int scmi_notifier_unregister(const struct scmi_handle *handle,
evt_key = MAKE_HASH_KEY(proto_id, evt_id,
src_id ? *src_id : SRC_ID_MASK);
hndl = scmi_get_handler(ni, evt_key);
if (!hndl)
return -EINVAL;
if (IS_ERR(hndl))
return PTR_ERR(hndl);
/*
* Note that this chain unregistration call is safe on its own

View File

@ -892,7 +892,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
freq = dom->opp[idx].indicative_freq * dom->mult_factor;
/* All OPPs above the sustained frequency are treated as turbo */
data.turbo = freq > dom->sustained_freq_khz * 1000;
data.turbo = freq > dom->sustained_freq_khz * 1000UL;
data.level = dom->opp[idx].perf;
data.freq = freq;

View File

@ -475,7 +475,8 @@ static void scmi_xfer_raw_worker(struct work_struct *work)
raw->desc->ops->mark_txdone(rw->cinfo, ret, xfer);
trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq, ret);
xfer->hdr.protocol_id, xfer->hdr.seq,
ret, scmi_inflight_count(raw->handle));
/* Wait also for an async delayed response if needed */
if (!ret && xfer->async_done) {
@ -642,7 +643,8 @@ static int scmi_do_xfer_raw_start(struct scmi_raw_mode_info *raw,
trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq,
xfer->hdr.poll_completion);
xfer->hdr.poll_completion,
scmi_inflight_count(raw->handle));
ret = raw->desc->ops->send_message(rw->cinfo, xfer);
if (ret) {

View File

@ -46,6 +46,7 @@
#include <linux/math.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/printk.h>
#include <linux/reboot.h>
#include <linux/scmi_protocol.h>
@ -324,12 +325,7 @@ static int scmi_userspace_notifier(struct notifier_block *nb,
static void scmi_suspend_work_func(struct work_struct *work)
{
struct scmi_syspower_conf *sc =
container_of(work, struct scmi_syspower_conf, suspend_work);
pm_suspend(PM_SUSPEND_MEM);
sc->state = SCMI_SYSPOWER_IDLE;
}
static int scmi_syspower_probe(struct scmi_device *sdev)
@ -354,6 +350,7 @@ static int scmi_syspower_probe(struct scmi_device *sdev)
sc->required_transition = SCMI_SYSTEM_MAX;
sc->userspace_nb.notifier_call = &scmi_userspace_notifier;
sc->dev = &sdev->dev;
dev_set_drvdata(&sdev->dev, sc);
INIT_WORK(&sc->suspend_work, scmi_suspend_work_func);
@ -363,6 +360,18 @@ static int scmi_syspower_probe(struct scmi_device *sdev)
NULL, &sc->userspace_nb);
}
static int scmi_system_power_resume(struct device *dev)
{
struct scmi_syspower_conf *sc = dev_get_drvdata(dev);
sc->state = SCMI_SYSPOWER_IDLE;
return 0;
}
static const struct dev_pm_ops scmi_system_power_pmops = {
SYSTEM_SLEEP_PM_OPS(NULL, scmi_system_power_resume)
};
static const struct scmi_device_id scmi_id_table[] = {
{ SCMI_PROTOCOL_SYSTEM, "syspower" },
{ },
@ -370,6 +379,9 @@ static const struct scmi_device_id scmi_id_table[] = {
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
static struct scmi_driver scmi_system_power_driver = {
.driver = {
.pm = pm_sleep_ptr(&scmi_system_power_pmops),
},
.name = "scmi-system-power",
.probe = scmi_syspower_probe,
.id_table = scmi_id_table,

View File

@ -1603,7 +1603,13 @@ bool qcom_scm_lmh_dcvsh_available(void)
}
EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available);
int qcom_scm_shm_bridge_enable(void)
/*
* This is only supposed to be called once by the TZMem module. It takes the
* SCM struct device as argument and uses it to pass the call as at the time
* the SHM Bridge is enabled, the SCM is not yet fully set up and doesn't
* accept global user calls. Don't try to use the __scm pointer here.
*/
int qcom_scm_shm_bridge_enable(struct device *scm_dev)
{
int ret;
@ -1615,11 +1621,11 @@ int qcom_scm_shm_bridge_enable(void)
struct qcom_scm_res res;
if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP,
if (!__qcom_scm_is_call_available(scm_dev, QCOM_SCM_SVC_MP,
QCOM_SCM_MP_SHM_BRIDGE_ENABLE))
return -EOPNOTSUPP;
ret = qcom_scm_call(__scm->dev, &desc, &res);
ret = qcom_scm_call(scm_dev, &desc, &res);
if (ret)
return ret;
@ -1631,7 +1637,7 @@ int qcom_scm_shm_bridge_enable(void)
}
EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_enable);
int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags,
int qcom_scm_shm_bridge_create(u64 pfn_and_ns_perm_flags,
u64 ipfn_and_s_perm_flags, u64 size_and_flags,
u64 ns_vmids, u64 *handle)
{
@ -1659,7 +1665,7 @@ int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags,
}
EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_create);
int qcom_scm_shm_bridge_delete(struct device *dev, u64 handle)
int qcom_scm_shm_bridge_delete(u64 handle)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_MP,
@ -2250,24 +2256,47 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (ret)
return ret;
/* Paired with smp_load_acquire() in qcom_scm_is_available(). */
smp_store_release(&__scm, scm);
ret = of_reserved_mem_device_init(scm->dev);
if (ret && ret != -ENODEV)
return dev_err_probe(scm->dev, ret,
"Failed to setup the reserved memory region for TZ mem\n");
ret = qcom_tzmem_enable(scm->dev);
if (ret)
return dev_err_probe(scm->dev, ret,
"Failed to enable the TrustZone memory allocator\n");
memset(&pool_config, 0, sizeof(pool_config));
pool_config.initial_size = 0;
pool_config.policy = QCOM_TZMEM_POLICY_ON_DEMAND;
pool_config.max_size = SZ_256K;
scm->mempool = devm_qcom_tzmem_pool_new(scm->dev, &pool_config);
if (IS_ERR(scm->mempool))
return dev_err_probe(scm->dev, PTR_ERR(scm->mempool),
"Failed to create the SCM memory pool\n");
irq = platform_get_irq_optional(pdev, 0);
if (irq < 0) {
if (irq != -ENXIO) {
ret = irq;
goto err;
}
if (irq != -ENXIO)
return irq;
} else {
ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler,
IRQF_ONESHOT, "qcom-scm", __scm);
if (ret < 0) {
dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n");
goto err;
}
ret = devm_request_threaded_irq(scm->dev, irq, NULL, qcom_scm_irq_handler,
IRQF_ONESHOT, "qcom-scm", scm);
if (ret < 0)
return dev_err_probe(scm->dev, ret,
"Failed to request qcom-scm irq\n");
}
/*
* Paired with smp_load_acquire() in qcom_scm_is_available().
*
* This marks the SCM API as ready to accept user calls and can only
* be called after the TrustZone memory pool is initialized and the
* waitqueue interrupt requested.
*/
smp_store_release(&__scm, scm);
__get_convention();
/*
@ -2283,32 +2312,6 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled") || !download_mode)
qcom_scm_disable_sdi();
ret = of_reserved_mem_device_init(__scm->dev);
if (ret && ret != -ENODEV) {
dev_err_probe(__scm->dev, ret,
"Failed to setup the reserved memory region for TZ mem\n");
goto err;
}
ret = qcom_tzmem_enable(__scm->dev);
if (ret) {
dev_err_probe(__scm->dev, ret,
"Failed to enable the TrustZone memory allocator\n");
goto err;
}
memset(&pool_config, 0, sizeof(pool_config));
pool_config.initial_size = 0;
pool_config.policy = QCOM_TZMEM_POLICY_ON_DEMAND;
pool_config.max_size = SZ_256K;
__scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config);
if (IS_ERR(__scm->mempool)) {
ret = dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool),
"Failed to create the SCM memory pool\n");
goto err;
}
/*
* Initialize the QSEECOM interface.
*
@ -2323,12 +2326,6 @@ static int qcom_scm_probe(struct platform_device *pdev)
WARN(ret < 0, "failed to initialize qseecom: %d\n", ret);
return 0;
err:
/* Paired with smp_load_acquire() in qcom_scm_is_available(). */
smp_store_release(&__scm, NULL);
return ret;
}
static void qcom_scm_shutdown(struct platform_device *pdev)

View File

@ -83,6 +83,7 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
struct qcom_scm_res *res);
struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
int qcom_scm_shm_bridge_enable(struct device *scm_dev);
#define QCOM_SCM_SVC_BOOT 0x01
#define QCOM_SCM_BOOT_SET_ADDR 0x01

View File

@ -20,6 +20,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include "qcom_scm.h"
#include "qcom_tzmem.h"
struct qcom_tzmem_area {
@ -94,7 +95,7 @@ static int qcom_tzmem_init(void)
goto notsupp;
}
ret = qcom_scm_shm_bridge_enable();
ret = qcom_scm_shm_bridge_enable(qcom_tzmem_dev);
if (ret == -EOPNOTSUPP)
goto notsupp;
@ -124,9 +125,9 @@ static int qcom_tzmem_init_area(struct qcom_tzmem_area *area)
if (!handle)
return -ENOMEM;
ret = qcom_scm_shm_bridge_create(qcom_tzmem_dev, pfn_and_ns_perm,
ipfn_and_s_perm, size_and_flags,
QCOM_SCM_VMID_HLOS, handle);
ret = qcom_scm_shm_bridge_create(pfn_and_ns_perm, ipfn_and_s_perm,
size_and_flags, QCOM_SCM_VMID_HLOS,
handle);
if (ret)
return ret;
@ -142,7 +143,7 @@ static void qcom_tzmem_cleanup_area(struct qcom_tzmem_area *area)
if (!qcom_tzmem_using_shm_bridge)
return;
qcom_scm_shm_bridge_delete(qcom_tzmem_dev, *handle);
qcom_scm_shm_bridge_delete(*handle);
kfree(handle);
}

View File

@ -72,10 +72,7 @@ bool arm_smccc_hypervisor_has_uuid(const uuid_t *hyp_uuid)
struct arm_smccc_res res = {};
uuid_t uuid;
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
return false;
arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
return false;

View File

@ -2,7 +2,7 @@
menu "Tegra firmware driver"
config TEGRA_IVC
bool "Tegra IVC protocol"
bool "Tegra IVC protocol" if COMPILE_TEST
depends on ARCH_TEGRA
help
IVC (Inter-VM Communication) protocol is part of the IPC
@ -13,8 +13,9 @@ config TEGRA_IVC
config TEGRA_BPMP
bool "Tegra BPMP driver"
depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC
depends on ARCH_TEGRA && TEGRA_HSP_MBOX
depends on !CPU_BIG_ENDIAN
select TEGRA_IVC
help
BPMP (Boot and Power Management Processor) is designed to off-loading
the PM functions which include clock/DVFS/thermal/power from the CPU.

View File

@ -4,6 +4,7 @@ tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC) += bpmp-tegra210.o
tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o
tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC) += bpmp-tegra186.o
tegra-bpmp-$(CONFIG_ARCH_TEGRA_234_SOC) += bpmp-tegra186.o
tegra-bpmp-$(CONFIG_ARCH_TEGRA_264_SOC) += bpmp-tegra186.o
tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o
obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o
obj-$(CONFIG_TEGRA_IVC) += ivc.o

View File

@ -23,13 +23,7 @@ struct tegra_bpmp_ops {
int (*resume)(struct tegra_bpmp *bpmp);
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
extern const struct tegra_bpmp_ops tegra210_bpmp_ops;
#endif
#endif

View File

@ -6,7 +6,7 @@
#include <linux/genalloc.h>
#include <linux/io.h>
#include <linux/mailbox_client.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <soc/tegra/bpmp.h>
@ -192,16 +192,11 @@ static void tegra186_bpmp_teardown_channels(struct tegra_bpmp *bpmp)
static int tegra186_bpmp_dram_init(struct tegra_bpmp *bpmp)
{
struct tegra186_bpmp *priv = bpmp->priv;
struct device_node *np;
struct resource res;
size_t size;
int err;
np = of_parse_phandle(bpmp->dev->of_node, "memory-region", 0);
if (!np)
return -ENODEV;
err = of_address_to_resource(np, 0, &res);
err = of_reserved_mem_region_to_resource(bpmp->dev->of_node, 0, &res);
if (err < 0) {
dev_warn(bpmp->dev, "failed to parse memory region: %d\n", err);
return err;

View File

@ -836,7 +836,8 @@ static const struct dev_pm_ops tegra_bpmp_pm_ops = {
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_264_SOC)
static const struct tegra_bpmp_soc tegra186_soc = {
.channels = {
.cpu_tx = {
@ -884,7 +885,8 @@ static const struct tegra_bpmp_soc tegra210_soc = {
static const struct of_device_id tegra_bpmp_match[] = {
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_264_SOC)
{ .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)

View File

@ -184,62 +184,10 @@ static const struct of_device_id brcmstb_memc_of_match[] = {
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.5",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.6",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.7",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.8",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.0",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.1",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.2",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.3",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.4",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
/* default to the original offset */
/* default to the V21 offset */
{
.compatible = "brcm,brcmstb-memc-ddr",
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V1X]
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
},
{}
};

View File

@ -39,6 +39,7 @@
* are two devices attached to this EMIF, this
* value is the maximum of the two temperature
* levels.
* @lpmode: Chosen low power mode
* @node: node in the device list
* @base: base address of memory-mapped IO registers.
* @dev: device pointer.

View File

@ -320,6 +320,38 @@ static const u8 mtk_smi_larb_mt6893_ostd[][SMI_LARB_PORT_NR_MAX] = {
[20] = {0x9, 0x9, 0x5, 0x5, 0x1, 0x1},
};
static const u8 mtk_smi_larb_mt8186_ostd[][SMI_LARB_PORT_NR_MAX] = {
[0] = {0x2, 0x1, 0x8, 0x1,},
[1] = {0x1, 0x3, 0x1, 0x1,},
[2] = {0x6, 0x1, 0x4, 0x1,},
[3] = {},
[4] = {0xf, 0x1, 0x5, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
0x1, 0x1, 0x1,},
[5] = {},
[6] = {},
[7] = {0x1, 0x3, 0x1, 0x1, 0x1, 0x3, 0x2, 0xd, 0x7, 0x5, 0x3,
0x1, 0x5,},
[8] = {0x1, 0x2, 0x2,},
[9] = {0x9, 0x7, 0xf, 0x8, 0x1, 0x8, 0x9, 0x3, 0x3, 0xb, 0x7, 0x4,
0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
0x1, 0x1, 0x1, 0x1, 0x1,},
[10] = {},
[11] = {0x9, 0x7, 0xf, 0x8, 0x1, 0x8, 0x9, 0x3, 0x3, 0xb, 0x7, 0x4,
0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8, 0x7, 0x7, 0x1, 0x6, 0x2,
0xf, 0x8, 0x1, 0x1, 0x1,},
[12] = {},
[13] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x6, 0x6, 0x6, 0x1, 0x1, 0x1,},
[14] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1,},
[15] = {},
[16] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x1, 0x14, 0x1, 0x4, 0x4, 0x4,
0x2, 0x4, 0x2, 0x8, 0x4, 0x4,},
[17] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x1, 0x14, 0x1, 0x4, 0x4, 0x4,
0x2, 0x4, 0x2, 0x8, 0x4, 0x4,},
[18] = {},
[19] = {0x1, 0x1, 0x1, 0x1,},
[20] = {0x2, 0x2, 0x2, 0x2, 0x1, 0x1,},
};
static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = {
[0] = {0x02, 0x18, 0x22, 0x22, 0x01, 0x02, 0x0a,},
[1] = {0x12, 0x02, 0x14, 0x14, 0x01, 0x18, 0x0a,},
@ -491,6 +523,7 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = {
.config_port = mtk_smi_larb_config_port_gen2_general,
.flags_general = MTK_SMI_FLAG_SLEEP_CTL,
.ostd = mtk_smi_larb_mt8186_ostd,
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {

View File

@ -1455,8 +1455,8 @@ static int gpmc_setup_irq(struct gpmc_device *gpmc)
gpmc->irq_chip.irq_unmask = gpmc_irq_unmask;
gpmc->irq_chip.irq_set_type = gpmc_irq_set_type;
gpmc_irq_domain = irq_domain_create_linear(of_fwnode_handle(gpmc->dev->of_node),
gpmc->nirqs, &gpmc_irq_domain_ops, gpmc);
gpmc_irq_domain = irq_domain_create_linear(dev_fwnode(gpmc->dev), gpmc->nirqs,
&gpmc_irq_domain_ops, gpmc);
if (!gpmc_irq_domain) {
dev_err(gpmc->dev, "IRQ domain add failed\n");
return -ENODEV;

View File

@ -46,7 +46,7 @@ static int stm32_omm_set_amcr(struct device *dev, bool set)
struct regmap *syscfg_regmap;
struct device_node *node;
struct resource res, res1;
u32 amcr_base, amcr_mask;
unsigned int syscon_args[2];
int ret, idx;
unsigned int i, amcr, read_amcr;
@ -98,29 +98,20 @@ static int stm32_omm_set_amcr(struct device *dev, bool set)
of_node_put(node);
}
syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
syscfg_regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node, "st,syscfg-amcr",
2, syscon_args);
if (IS_ERR(syscfg_regmap))
return dev_err_probe(dev, PTR_ERR(syscfg_regmap),
"Failed to get st,syscfg-amcr property\n");
ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
&amcr_base);
if (ret)
return ret;
ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
&amcr_mask);
if (ret)
return ret;
amcr = mm_ospi2_size / SZ_64M;
if (set)
regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
regmap_update_bits(syscfg_regmap, syscon_args[0], syscon_args[1], amcr);
/* read AMCR and check coherency with memory-map areas defined in DT */
regmap_read(syscfg_regmap, amcr_base, &read_amcr);
read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
regmap_read(syscfg_regmap, syscon_args[0], &read_amcr);
read_amcr = read_amcr >> (ffs(syscon_args[1]) - 1);
if (amcr != read_amcr) {
dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");

View File

@ -10,6 +10,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
tegra-mc-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
tegra-mc-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186.o tegra194.o
tegra-mc-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186.o tegra234.o
tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
@ -21,5 +22,6 @@ obj-$(CONFIG_TEGRA210_EMC) += tegra210-emc.o
obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-emc.o
obj-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186-emc.o
obj-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186-emc.o
obj-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186-emc.o
tegra210-emc-y := tegra210-emc-core.o tegra210-emc-cc-r21021.o

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/clk.h>
@ -48,6 +48,9 @@ static const struct of_device_id tegra_mc_of_match[] = {
#endif
#ifdef CONFIG_ARCH_TEGRA_234_SOC
{ .compatible = "nvidia,tegra234-mc", .data = &tegra234_mc_soc },
#endif
#ifdef CONFIG_ARCH_TEGRA_264_SOC
{ .compatible = "nvidia,tegra264-mc", .data = &tegra264_mc_soc },
#endif
{ /* sentinel */ }
};

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved.
*/
#ifndef MEMORY_TEGRA_MC_H
@ -182,6 +182,10 @@ extern const struct tegra_mc_soc tegra194_mc_soc;
extern const struct tegra_mc_soc tegra234_mc_soc;
#endif
#ifdef CONFIG_ARCH_TEGRA_264_SOC
extern const struct tegra_mc_soc tegra264_mc_soc;
#endif
#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
defined(CONFIG_ARCH_TEGRA_114_SOC) || \
defined(CONFIG_ARCH_TEGRA_124_SOC) || \
@ -193,7 +197,8 @@ extern const struct tegra_mc_ops tegra30_mc_ops;
#if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
defined(CONFIG_ARCH_TEGRA_194_SOC) || \
defined(CONFIG_ARCH_TEGRA_234_SOC)
defined(CONFIG_ARCH_TEGRA_234_SOC) || \
defined(CONFIG_ARCH_TEGRA_264_SOC)
extern const struct tegra_mc_ops tegra186_mc_ops;
#endif

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2019 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2019-2025 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/clk.h>
@ -393,6 +393,9 @@ static const struct of_device_id tegra186_emc_of_match[] = {
#endif
#if defined(CONFIG_ARCH_TEGRA_234_SOC)
{ .compatible = "nvidia,tegra234-emc" },
#endif
#if defined(CONFIG_ARCH_TEGRA_264_SOC)
{ .compatible = "nvidia,tegra264-emc" },
#endif
{ /* sentinel */ }
};

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017-2021 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2017-2025 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/io.h>
@ -26,11 +26,24 @@
static int tegra186_mc_probe(struct tegra_mc *mc)
{
struct platform_device *pdev = to_platform_device(mc->dev);
struct resource *res;
unsigned int i;
char name[8];
int err;
/*
* From Tegra264, the SID region is not present in MC node and BROADCAST is first.
* The common function 'tegra_mc_probe()' already maps first region entry from DT.
* Check if the SID region is present in DT then map BROADCAST. Otherwise, consider
* the first entry mapped in mc probe as the BROADCAST region. This is done to avoid
* mapping the region twice when SID is not present and keep backward compatibility.
*/
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sid");
if (res)
mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast");
else
mc->bcast_ch_regs = mc->regs;
if (IS_ERR(mc->bcast_ch_regs)) {
if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) {
dev_warn(&pdev->dev,

View File

@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2025 NVIDIA CORPORATION. All rights reserved. */
#ifndef MEMORY_TEGRA_TEGRA264_BWMGR_H
#define MEMORY_TEGRA_TEGRA264_BWMGR_H
#define TEGRA264_BWMGR_ICC_PRIMARY 1
#define TEGRA264_BWMGR_DEBUG 2
#define TEGRA264_BWMGR_CPU_CLUSTER0 3
#define TEGRA264_BWMGR_CPU_CLUSTER1 4
#define TEGRA264_BWMGR_CPU_CLUSTER2 5
#define TEGRA264_BWMGR_CPU_CLUSTER3 6
#define TEGRA264_BWMGR_CPU_CLUSTER4 7
#define TEGRA264_BWMGR_CPU_CLUSTER5 8
#define TEGRA264_BWMGR_CPU_CLUSTER6 9
#define TEGRA264_BWMGR_CACTMON 10
#define TEGRA264_BWMGR_DISPLAY 11
#define TEGRA264_BWMGR_VI 12
#define TEGRA264_BWMGR_APE 13
#define TEGRA264_BWMGR_VIFAL 14
#define TEGRA264_BWMGR_GPU 15
#define TEGRA264_BWMGR_EQOS 16
#define TEGRA264_BWMGR_PCIE_0 17
#define TEGRA264_BWMGR_PCIE_1 18
#define TEGRA264_BWMGR_PCIE_2 19
#define TEGRA264_BWMGR_PCIE_3 20
#define TEGRA264_BWMGR_PCIE_4 21
#define TEGRA264_BWMGR_PCIE_5 22
#define TEGRA264_BWMGR_SDMMC_1 23
#define TEGRA264_BWMGR_SDMMC_2 24
#define TEGRA264_BWMGR_NVDEC 25
#define TEGRA264_BWMGR_NVENC 26
#define TEGRA264_BWMGR_NVJPG_0 27
#define TEGRA264_BWMGR_NVJPG_1 28
#define TEGRA264_BWMGR_OFAA 29
#define TEGRA264_BWMGR_XUSB_HOST 30
#define TEGRA264_BWMGR_XUSB_DEV 31
#define TEGRA264_BWMGR_TSEC 32
#define TEGRA264_BWMGR_VIC 33
#define TEGRA264_BWMGR_APEDMA 34
#define TEGRA264_BWMGR_SE 35
#define TEGRA264_BWMGR_ISP 36
#define TEGRA264_BWMGR_HDA 37
#define TEGRA264_BWMGR_VI2FAL 38
#define TEGRA264_BWMGR_VI2 39
#define TEGRA264_BWMGR_RCE 40
#define TEGRA264_BWMGR_PVA 41
#define TEGRA264_BWMGR_NVPMODEL 42
#endif

View File

@ -0,0 +1,313 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include <dt-bindings/memory/nvidia,tegra264.h>
#include <linux/interconnect.h>
#include <linux/of_device.h>
#include <linux/tegra-icc.h>
#include <soc/tegra/bpmp.h>
#include <soc/tegra/mc.h>
#include "mc.h"
#include "tegra264-bwmgr.h"
/*
* MC Client entries are sorted in the increasing order of the
* override and security register offsets.
*/
static const struct tegra_mc_client tegra264_mc_clients[] = {
{
.id = TEGRA264_MEMORY_CLIENT_HDAR,
.name = "hdar",
.bpmp_id = TEGRA264_BWMGR_HDA,
.type = TEGRA_ICC_ISO_AUDIO,
}, {
.id = TEGRA264_MEMORY_CLIENT_HDAW,
.name = "hdaw",
.bpmp_id = TEGRA264_BWMGR_HDA,
.type = TEGRA_ICC_ISO_AUDIO,
}, {
.id = TEGRA264_MEMORY_CLIENT_MGBE0R,
.name = "mgbe0r",
.bpmp_id = TEGRA264_BWMGR_EQOS,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_MGBE0W,
.name = "mgbe0w",
.bpmp_id = TEGRA264_BWMGR_EQOS,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_MGBE1R,
.name = "mgbe1r",
.bpmp_id = TEGRA264_BWMGR_EQOS,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_MGBE1W,
.name = "mgbe1w",
.bpmp_id = TEGRA264_BWMGR_EQOS,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_SDMMC0R,
.name = "sdmmc0r",
.bpmp_id = TEGRA264_BWMGR_SDMMC_1,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_SDMMC0W,
.name = "sdmmc0w",
.bpmp_id = TEGRA264_BWMGR_SDMMC_1,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_VICR,
.name = "vicr",
.bpmp_id = TEGRA264_BWMGR_VIC,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_VICW,
.name = "vicw",
.bpmp_id = TEGRA264_BWMGR_VIC,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_APER,
.name = "aper",
.bpmp_id = TEGRA264_BWMGR_APE,
.type = TEGRA_ICC_ISO_AUDIO,
}, {
.id = TEGRA264_MEMORY_CLIENT_APEW,
.name = "apew",
.bpmp_id = TEGRA264_BWMGR_APE,
.type = TEGRA_ICC_ISO_AUDIO,
}, {
.id = TEGRA264_MEMORY_CLIENT_APEDMAR,
.name = "apedmar",
.bpmp_id = TEGRA264_BWMGR_APEDMA,
.type = TEGRA_ICC_ISO_AUDIO,
}, {
.id = TEGRA264_MEMORY_CLIENT_APEDMAW,
.name = "apedmaw",
.bpmp_id = TEGRA264_BWMGR_APEDMA,
.type = TEGRA_ICC_ISO_AUDIO,
}, {
.id = TEGRA264_MEMORY_CLIENT_VIFALCONR,
.name = "vifalconr",
.bpmp_id = TEGRA264_BWMGR_VIFAL,
.type = TEGRA_ICC_ISO_VIFAL,
}, {
.id = TEGRA264_MEMORY_CLIENT_VIFALCONW,
.name = "vifalconw",
.bpmp_id = TEGRA264_BWMGR_VIFAL,
.type = TEGRA_ICC_ISO_VIFAL,
}, {
.id = TEGRA264_MEMORY_CLIENT_RCER,
.name = "rcer",
.bpmp_id = TEGRA264_BWMGR_RCE,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_RCEW,
.name = "rcew",
.bpmp_id = TEGRA264_BWMGR_RCE,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE0W,
.name = "pcie0w",
.bpmp_id = TEGRA264_BWMGR_PCIE_0,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE1R,
.name = "pcie1r",
.bpmp_id = TEGRA264_BWMGR_PCIE_1,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE1W,
.name = "pcie1w",
.bpmp_id = TEGRA264_BWMGR_PCIE_1,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE2AR,
.name = "pcie2ar",
.bpmp_id = TEGRA264_BWMGR_PCIE_2,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE2AW,
.name = "pcie2aw",
.bpmp_id = TEGRA264_BWMGR_PCIE_2,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE3R,
.name = "pcie3r",
.bpmp_id = TEGRA264_BWMGR_PCIE_3,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE3W,
.name = "pcie3w",
.bpmp_id = TEGRA264_BWMGR_PCIE_3,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE4R,
.name = "pcie4r",
.bpmp_id = TEGRA264_BWMGR_PCIE_4,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE4W,
.name = "pcie4w",
.bpmp_id = TEGRA264_BWMGR_PCIE_4,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE5R,
.name = "pcie5r",
.bpmp_id = TEGRA264_BWMGR_PCIE_5,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_PCIE5W,
.name = "pcie5w",
.bpmp_id = TEGRA264_BWMGR_PCIE_5,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_GPUR02MC,
.name = "gpur02mc",
.bpmp_id = TEGRA264_BWMGR_GPU,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_GPUW02MC,
.name = "gpuw02mc",
.bpmp_id = TEGRA264_BWMGR_GPU,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_NVDECSRD2MC,
.name = "nvdecsrd2mc",
.bpmp_id = TEGRA264_BWMGR_NVDEC,
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA264_MEMORY_CLIENT_NVDECSWR2MC,
.name = "nvdecswr2mc",
.bpmp_id = TEGRA264_BWMGR_NVDEC,
.type = TEGRA_ICC_NISO,
},
};
/*
* tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW
* @src: ICC node for Memory Controller's (MC) Client
* @dst: ICC node for Memory Controller (MC)
*
* Passing the current request info from the MC to the BPMP-FW where
* LA and PTSA registers are accessed and the final EMC freq is set
* based on client_id, type, latency and bandwidth.
* icc_set_bw() makes set_bw calls for both MC and EMC providers in
* sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'.
* So, the data passed won't be updated by concurrent set calls from
* other clients.
*/
static int tegra264_mc_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider);
struct mrq_bwmgr_int_request bwmgr_req = { 0 };
struct mrq_bwmgr_int_response bwmgr_resp = { 0 };
const struct tegra_mc_client *pclient = src->data;
struct tegra_bpmp_message msg;
int ret;
/*
* Same Src and Dst node will happen during boot from icc_node_add().
* This can be used to pre-initialize and set bandwidth for all clients
* before their drivers are loaded. We are skipping this case as for us,
* the pre-initialization already happened in Bootloader(MB2) and BPMP-FW.
*/
if (src->id == dst->id)
return 0;
if (!mc->bwmgr_mrq_supported)
return 0;
if (!mc->bpmp) {
dev_err(mc->dev, "BPMP reference NULL\n");
return -ENOENT;
}
if (pclient->type == TEGRA_ICC_NISO)
bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw;
else
bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw;
bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id;
bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET;
bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw;
bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS;
memset(&msg, 0, sizeof(msg));
msg.mrq = MRQ_BWMGR_INT;
msg.tx.data = &bwmgr_req;
msg.tx.size = sizeof(bwmgr_req);
msg.rx.data = &bwmgr_resp;
msg.rx.size = sizeof(bwmgr_resp);
ret = tegra_bpmp_transfer(mc->bpmp, &msg);
if (ret < 0) {
dev_err(mc->dev, "BPMP transfer failed: %d\n", ret);
goto error;
}
if (msg.rx.ret < 0) {
pr_err("failed to set bandwidth for %u: %d\n",
bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret);
ret = -EINVAL;
}
error:
return ret;
}
static int tegra264_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
struct icc_provider *p = node->provider;
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
if (!mc->bwmgr_mrq_supported)
return 0;
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
{
*avg = 0;
*peak = 0;
return 0;
}
static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = {
.xlate = tegra_mc_icc_xlate,
.aggregate = tegra264_mc_icc_aggregate,
.get_bw = tegra264_mc_icc_get_init_bw,
.set = tegra264_mc_icc_set,
};
const struct tegra_mc_soc tegra264_mc_soc = {
.num_clients = ARRAY_SIZE(tegra264_mc_clients),
.clients = tegra264_mc_clients,
.num_address_bits = 40,
.num_channels = 16,
.client_id_mask = 0x1ff,
.intmask = MC_INT_DECERR_ROUTE_SANITY |
MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
.icc_ops = &tegra264_mc_icc_ops,
.ch_intmask = 0x0000ff00,
.global_intstatus_channel_shift = 8,
/*
* Additionally, there are lite carveouts but those are not currently
* supported.
*/
.num_carveouts = 32,
};

View File

@ -660,4 +660,5 @@ source "drivers/misc/pvpanic/Kconfig"
source "drivers/misc/mchp_pci1xxxx/Kconfig"
source "drivers/misc/keba/Kconfig"
source "drivers/misc/amd-sbi/Kconfig"
source "drivers/misc/rp1/Kconfig"
endmenu

View File

@ -75,3 +75,4 @@ lan966x-pci-objs += lan966x_pci.dtbo.o
obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o
obj-y += keba/
obj-y += amd-sbi/
obj-$(CONFIG_MISC_RP1) += rp1/

20
drivers/misc/rp1/Kconfig Normal file
View File

@ -0,0 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# RaspberryPi RP1 misc device
#
config MISC_RP1
tristate "RaspberryPi RP1 misc device"
depends on OF_IRQ && OF_OVERLAY && PCI_MSI && PCI_QUIRKS
select PCI_DYNAMIC_OF_NODES
help
Support the RP1 peripheral chip found on Raspberry Pi 5 board.
This device supports several sub-devices including e.g. Ethernet
controller, USB controller, I2C, SPI and UART.
The driver is responsible for enabling the DT node once the PCIe
endpoint has been configured, and handling interrupts.
This driver uses an overlay to load other drivers to support for
RP1 internal sub-devices.

View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_MISC_RP1) += rp1-pci.o
rp1-pci-objs := rp1_pci.o rp1-pci.dtbo.o

View File

@ -0,0 +1,25 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* The dts overlay is included from the dts directory so
* it can be possible to check it with CHECK_DTBS while
* also compile it from the driver source directory.
*/
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target-path="";
__overlay__ {
compatible = "pci1de4,1";
#address-cells = <3>;
#size-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
#include "arm64/broadcom/rp1-common.dtsi"
};
};
};

333
drivers/misc/rp1/rp1_pci.c Normal file
View File

@ -0,0 +1,333 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2025 Raspberry Pi Ltd.
*
* All rights reserved.
*/
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#define RP1_HW_IRQ_MASK GENMASK(5, 0)
#define REG_SET 0x800
#define REG_CLR 0xc00
/* MSI-X CFG registers start at 0x8 */
#define MSIX_CFG(x) (0x8 + (4 * (x)))
#define MSIX_CFG_IACK_EN BIT(3)
#define MSIX_CFG_IACK BIT(2)
#define MSIX_CFG_ENABLE BIT(0)
/* Address map */
#define RP1_PCIE_APBS_BASE 0x108000
/* Interrupts */
#define RP1_INT_END 61
/* Embedded dtbo symbols created by cmd_wrap_S_dtb in scripts/Makefile.lib */
extern char __dtbo_rp1_pci_begin[];
extern char __dtbo_rp1_pci_end[];
struct rp1_dev {
struct pci_dev *pdev;
struct irq_domain *domain;
struct irq_data *pcie_irqds[64];
void __iomem *bar1;
int ovcs_id; /* overlay changeset id */
bool level_triggered_irq[RP1_INT_END];
};
static void msix_cfg_set(struct rp1_dev *rp1, unsigned int hwirq, u32 value)
{
iowrite32(value, rp1->bar1 + RP1_PCIE_APBS_BASE + REG_SET + MSIX_CFG(hwirq));
}
static void msix_cfg_clr(struct rp1_dev *rp1, unsigned int hwirq, u32 value)
{
iowrite32(value, rp1->bar1 + RP1_PCIE_APBS_BASE + REG_CLR + MSIX_CFG(hwirq));
}
static void rp1_mask_irq(struct irq_data *irqd)
{
struct rp1_dev *rp1 = irqd->domain->host_data;
struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
pci_msi_mask_irq(pcie_irqd);
}
static void rp1_unmask_irq(struct irq_data *irqd)
{
struct rp1_dev *rp1 = irqd->domain->host_data;
struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
pci_msi_unmask_irq(pcie_irqd);
}
static int rp1_irq_set_type(struct irq_data *irqd, unsigned int type)
{
struct rp1_dev *rp1 = irqd->domain->host_data;
unsigned int hwirq = (unsigned int)irqd->hwirq;
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
dev_dbg(&rp1->pdev->dev, "MSIX IACK EN for IRQ %u\n", hwirq);
msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
rp1->level_triggered_irq[hwirq] = true;
break;
case IRQ_TYPE_EDGE_RISING:
msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN);
rp1->level_triggered_irq[hwirq] = false;
break;
default:
return -EINVAL;
}
return 0;
}
static struct irq_chip rp1_irq_chip = {
.name = "rp1_irq_chip",
.irq_mask = rp1_mask_irq,
.irq_unmask = rp1_unmask_irq,
.irq_set_type = rp1_irq_set_type,
};
static void rp1_chained_handle_irq(struct irq_desc *desc)
{
unsigned int hwirq = desc->irq_data.hwirq & RP1_HW_IRQ_MASK;
struct rp1_dev *rp1 = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned int virq;
chained_irq_enter(chip, desc);
virq = irq_find_mapping(rp1->domain, hwirq);
generic_handle_irq(virq);
if (rp1->level_triggered_irq[hwirq])
msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK);
chained_irq_exit(chip, desc);
}
static int rp1_irq_xlate(struct irq_domain *d, struct device_node *node,
const u32 *intspec, unsigned int intsize,
unsigned long *out_hwirq, unsigned int *out_type)
{
struct rp1_dev *rp1 = d->host_data;
struct irq_data *pcie_irqd;
unsigned long hwirq;
int pcie_irq;
int ret;
ret = irq_domain_xlate_twocell(d, node, intspec, intsize,
&hwirq, out_type);
if (ret)
return ret;
pcie_irq = pci_irq_vector(rp1->pdev, hwirq);
pcie_irqd = irq_get_irq_data(pcie_irq);
rp1->pcie_irqds[hwirq] = pcie_irqd;
*out_hwirq = hwirq;
return 0;
}
static int rp1_irq_activate(struct irq_domain *d, struct irq_data *irqd,
bool reserve)
{
struct rp1_dev *rp1 = d->host_data;
msix_cfg_set(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE);
return 0;
}
static void rp1_irq_deactivate(struct irq_domain *d, struct irq_data *irqd)
{
struct rp1_dev *rp1 = d->host_data;
msix_cfg_clr(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE);
}
static const struct irq_domain_ops rp1_domain_ops = {
.xlate = rp1_irq_xlate,
.activate = rp1_irq_activate,
.deactivate = rp1_irq_deactivate,
};
static void rp1_unregister_interrupts(struct pci_dev *pdev)
{
struct rp1_dev *rp1 = pci_get_drvdata(pdev);
int irq, i;
if (rp1->domain) {
for (i = 0; i < RP1_INT_END; i++) {
irq = irq_find_mapping(rp1->domain, i);
irq_dispose_mapping(irq);
}
irq_domain_remove(rp1->domain);
}
pci_free_irq_vectors(pdev);
}
static int rp1_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
u32 dtbo_size = __dtbo_rp1_pci_end - __dtbo_rp1_pci_begin;
void *dtbo_start = __dtbo_rp1_pci_begin;
struct device *dev = &pdev->dev;
struct device_node *rp1_node;
bool skip_ovl = true;
struct rp1_dev *rp1;
int err = 0;
int i;
/*
* Either use rp1_nexus node if already present in DT, or
* set a flag to load it from overlay at runtime
*/
rp1_node = of_find_node_by_name(NULL, "rp1_nexus");
if (!rp1_node) {
rp1_node = dev_of_node(dev);
skip_ovl = false;
}
if (!rp1_node) {
dev_err(dev, "Missing of_node for device\n");
err = -EINVAL;
goto err_put_node;
}
rp1 = devm_kzalloc(&pdev->dev, sizeof(*rp1), GFP_KERNEL);
if (!rp1) {
err = -ENOMEM;
goto err_put_node;
}
rp1->pdev = pdev;
if (pci_resource_len(pdev, 1) <= 0x10000) {
dev_err(&pdev->dev,
"Not initialized - is the firmware running?\n");
err = -EINVAL;
goto err_put_node;
}
err = pcim_enable_device(pdev);
if (err < 0) {
err = dev_err_probe(&pdev->dev, err,
"Enabling PCI device has failed");
goto err_put_node;
}
rp1->bar1 = pcim_iomap(pdev, 1, 0);
if (!rp1->bar1) {
dev_err(&pdev->dev, "Cannot map PCI BAR\n");
err = -EIO;
goto err_put_node;
}
pci_set_master(pdev);
err = pci_alloc_irq_vectors(pdev, RP1_INT_END, RP1_INT_END,
PCI_IRQ_MSIX);
if (err < 0) {
err = dev_err_probe(&pdev->dev, err,
"Failed to allocate MSI-X vectors\n");
goto err_put_node;
} else if (err != RP1_INT_END) {
dev_err(&pdev->dev, "Cannot allocate enough interrupts\n");
err = -EINVAL;
goto err_put_node;
}
pci_set_drvdata(pdev, rp1);
rp1->domain = irq_domain_add_linear(rp1_node, RP1_INT_END,
&rp1_domain_ops, rp1);
if (!rp1->domain) {
dev_err(&pdev->dev, "Error creating IRQ domain\n");
err = -ENOMEM;
goto err_unregister_interrupts;
}
for (i = 0; i < RP1_INT_END; i++) {
unsigned int irq = irq_create_mapping(rp1->domain, i);
if (!irq) {
dev_err(&pdev->dev, "Failed to create IRQ mapping\n");
err = -EINVAL;
goto err_unregister_interrupts;
}
irq_set_chip_and_handler(irq, &rp1_irq_chip, handle_level_irq);
irq_set_probe(irq);
irq_set_chained_handler_and_data(pci_irq_vector(pdev, i),
rp1_chained_handle_irq, rp1);
}
if (!skip_ovl) {
err = of_overlay_fdt_apply(dtbo_start, dtbo_size, &rp1->ovcs_id,
rp1_node);
if (err)
goto err_unregister_interrupts;
}
err = of_platform_default_populate(rp1_node, NULL, dev);
if (err) {
dev_err_probe(&pdev->dev, err, "Error populating devicetree\n");
goto err_unload_overlay;
}
return 0;
err_unload_overlay:
of_overlay_remove(&rp1->ovcs_id);
err_unregister_interrupts:
rp1_unregister_interrupts(pdev);
err_put_node:
if (skip_ovl)
of_node_put(rp1_node);
return err;
}
static void rp1_remove(struct pci_dev *pdev)
{
struct rp1_dev *rp1 = pci_get_drvdata(pdev);
struct device *dev = &pdev->dev;
of_platform_depopulate(dev);
of_overlay_remove(&rp1->ovcs_id);
rp1_unregister_interrupts(pdev);
}
static const struct pci_device_id dev_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0), },
{ }
};
MODULE_DEVICE_TABLE(pci, dev_id_table);
static struct pci_driver rp1_driver = {
.name = KBUILD_MODNAME,
.id_table = dev_id_table,
.probe = rp1_probe,
.remove = rp1_remove,
};
module_pci_driver(rp1_driver);
MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
MODULE_AUTHOR("Andrea della Porta <andrea.porta@suse.com>");
MODULE_DESCRIPTION("RaspberryPi RP1 misc device");
MODULE_LICENSE("GPL");

View File

@ -6303,6 +6303,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, 0x9660, of_pci_make_dev_node);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0, of_pci_make_dev_node);
/*
* Devices known to require a longer delay before first config space access

View File

@ -624,6 +624,17 @@ config PINCTRL_MLXBF3
each pin. This driver can also be built as a module called
pinctrl-mlxbf3.
config PINCTRL_RP1
tristate "Pinctrl driver for RP1"
depends on MISC_RP1
default MISC_RP1
select PINMUX
select PINCONF
select GENERIC_PINCONF
help
Enable the gpio and pinctrl/mux driver for RaspberryPi RP1
multi function device.
source "drivers/pinctrl/actions/Kconfig"
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"

View File

@ -49,6 +49,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o
obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o

File diff suppressed because it is too large Load Diff

View File

@ -51,8 +51,8 @@ config RESET_BERLIN
config RESET_BRCMSTB
tristate "Broadcom STB reset controller"
depends on ARCH_BRCMSTB || COMPILE_TEST
default ARCH_BRCMSTB
depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
default ARCH_BRCMSTB || ARCH_BCM2835
help
This enables the reset controller driver for Broadcom STB SoCs using
a SUN_TOP_CTRL_SW_INIT style controller.
@ -60,11 +60,11 @@ config RESET_BRCMSTB
config RESET_BRCMSTB_RESCAL
tristate "Broadcom STB RESCAL reset controller"
depends on HAS_IOMEM
depends on ARCH_BRCMSTB || COMPILE_TEST
default ARCH_BRCMSTB
depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
default ARCH_BRCMSTB || ARCH_BCM2835
help
This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
BCM7216.
BCM7216 or the BCM2712.
config RESET_EYEQ
bool "Mobileye EyeQ reset controller"
@ -140,6 +140,15 @@ config RESET_K210
Say Y if you want to control reset signals provided by this
controller.
config RESET_K230
tristate "Reset controller driver for Canaan Kendryte K230 SoC"
depends on ARCH_CANAAN || COMPILE_TEST
depends on OF
help
Support for the Canaan Kendryte K230 RISC-V SoC reset controller.
Say Y if you want to control reset signals provided by this
controller.
config RESET_LANTIQ
bool "Lantiq XWAY Reset Driver" if COMPILE_TEST
default SOC_TYPE_XWAY
@ -287,7 +296,7 @@ config RESET_SUNXI
This enables the reset driver for Allwinner SoCs.
config RESET_TH1520
tristate "T-HEAD 1520 reset controller"
tristate "T-HEAD TH1520 reset controller"
depends on ARCH_THEAD || COMPILE_TEST
select REGMAP_MMIO
help

View File

@ -20,6 +20,7 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_IMX8MP_AUDIOMIX) += reset-imx8mp-audiomix.o
obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
obj-$(CONFIG_RESET_K210) += reset-k210.o
obj-$(CONFIG_RESET_K230) += reset-k230.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o

371
drivers/reset/reset-k230.c Normal file
View File

@ -0,0 +1,371 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022-2024 Canaan Bright Sight Co., Ltd
* Copyright (C) 2024-2025 Junhui Liu <junhui.liu@pigmoral.tech>
*
* The reset management module in the K230 SoC provides reset time control
* registers. For RST_TYPE_CPU0, RST_TYPE_CPU1 and RST_TYPE_SW_DONE, the period
* during which reset is applied or removed while the clock is stopped can be
* set up to 15 * 0.25 = 3.75 µs. For RST_TYPE_HW_DONE, that period can be set
* up to 255 * 0.25 = 63.75 µs. For RST_TYPE_FLUSH, the reset bit is
* automatically cleared by hardware when flush completes.
*
* Although this driver does not configure the reset time registers, delays have
* been added to the assert, deassert, and reset operations to cover the maximum
* reset time. Some reset types include done bits whose toggle does not
* unambiguously signal whether hardware reset removal or clock-stop period
* expiration occurred first. Delays are therefore retained for types with done
* bits to ensure safe timing.
*
* Reference: K230 Technical Reference Manual V0.3.1
* https://kendryte-download.canaan-creative.com/developer/k230/HDK/K230%E7%A1%AC%E4%BB%B6%E6%96%87%E6%A1%A3/K230_Technical_Reference_Manual_V0.3.1_20241118.pdf
*/
#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include <dt-bindings/reset/canaan,k230-rst.h>
/**
* enum k230_rst_type - K230 reset types
* @RST_TYPE_CPU0: Reset type for CPU0
* Automatically clears, has write enable and done bit, active high
* @RST_TYPE_CPU1: Reset type for CPU1
* Manually clears, has write enable and done bit, active high
* @RST_TYPE_FLUSH: Reset type for CPU L2 cache flush
* Automatically clears, has write enable, no done bit, active high
* @RST_TYPE_HW_DONE: Reset type for hardware auto clear
* Automatically clears, no write enable, has done bit, active high
* @RST_TYPE_SW_DONE: Reset type for software manual clear
* Manually clears, no write enable and done bit,
* active high if ID is RST_SPI2AXI, otherwise active low
*/
enum k230_rst_type {
RST_TYPE_CPU0,
RST_TYPE_CPU1,
RST_TYPE_FLUSH,
RST_TYPE_HW_DONE,
RST_TYPE_SW_DONE,
};
struct k230_rst_map {
u32 offset;
enum k230_rst_type type;
u32 done;
u32 reset;
};
struct k230_rst {
struct reset_controller_dev rcdev;
void __iomem *base;
/* protect register read-modify-write */
spinlock_t lock;
};
static const struct k230_rst_map k230_resets[] = {
[RST_CPU0] = { 0x4, RST_TYPE_CPU0, BIT(12), BIT(0) },
[RST_CPU1] = { 0xc, RST_TYPE_CPU1, BIT(12), BIT(0) },
[RST_CPU0_FLUSH] = { 0x4, RST_TYPE_FLUSH, 0, BIT(4) },
[RST_CPU1_FLUSH] = { 0xc, RST_TYPE_FLUSH, 0, BIT(4) },
[RST_AI] = { 0x14, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_VPU] = { 0x1c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_HISYS] = { 0x2c, RST_TYPE_HW_DONE, BIT(4), BIT(0) },
[RST_HISYS_AHB] = { 0x2c, RST_TYPE_HW_DONE, BIT(5), BIT(1) },
[RST_SDIO0] = { 0x34, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SDIO1] = { 0x34, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_SDIO_AXI] = { 0x34, RST_TYPE_HW_DONE, BIT(30), BIT(2) },
[RST_USB0] = { 0x3c, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_USB1] = { 0x3c, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_USB0_AHB] = { 0x3c, RST_TYPE_HW_DONE, BIT(30), BIT(0) },
[RST_USB1_AHB] = { 0x3c, RST_TYPE_HW_DONE, BIT(31), BIT(1) },
[RST_SPI0] = { 0x44, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SPI1] = { 0x44, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_SPI2] = { 0x44, RST_TYPE_HW_DONE, BIT(30), BIT(2) },
[RST_SEC] = { 0x4c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_PDMA] = { 0x54, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SDMA] = { 0x54, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_DECOMPRESS] = { 0x5c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_SRAM] = { 0x64, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SHRM_AXIM] = { 0x64, RST_TYPE_HW_DONE, BIT(30), BIT(2) },
[RST_SHRM_AXIS] = { 0x64, RST_TYPE_HW_DONE, BIT(31), BIT(3) },
[RST_NONAI2D] = { 0x6c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_MCTL] = { 0x74, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_ISP] = { 0x80, RST_TYPE_HW_DONE, BIT(29), BIT(6) },
[RST_ISP_DW] = { 0x80, RST_TYPE_HW_DONE, BIT(28), BIT(5) },
[RST_DPU] = { 0x88, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_DISP] = { 0x90, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_GPU] = { 0x98, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_AUDIO] = { 0xa4, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_TIMER0] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(0) },
[RST_TIMER1] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_TIMER2] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(2) },
[RST_TIMER3] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(3) },
[RST_TIMER4] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(4) },
[RST_TIMER5] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(5) },
[RST_TIMER_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(6) },
[RST_HDI] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(7) },
[RST_WDT0] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(12) },
[RST_WDT1] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(13) },
[RST_WDT0_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(14) },
[RST_WDT1_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(15) },
[RST_TS_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(16) },
[RST_MAILBOX] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(17) },
[RST_STC] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(18) },
[RST_PMU] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(19) },
[RST_LOSYS_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(0) },
[RST_UART0] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_UART1] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(2) },
[RST_UART2] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(3) },
[RST_UART3] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(4) },
[RST_UART4] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(5) },
[RST_I2C0] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(6) },
[RST_I2C1] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(7) },
[RST_I2C2] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(8) },
[RST_I2C3] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(9) },
[RST_I2C4] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(10) },
[RST_JAMLINK0_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(11) },
[RST_JAMLINK1_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(12) },
[RST_JAMLINK2_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(13) },
[RST_JAMLINK3_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(14) },
[RST_CODEC_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(17) },
[RST_GPIO_DB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(18) },
[RST_GPIO_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(19) },
[RST_ADC] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(20) },
[RST_ADC_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(21) },
[RST_PWM_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(22) },
[RST_SHRM_APB] = { 0x64, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_CSI0] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(0) },
[RST_CSI1] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_CSI2] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(2) },
[RST_CSI_DPHY] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(3) },
[RST_ISP_AHB] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(4) },
[RST_M0] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(7) },
[RST_M1] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(8) },
[RST_M2] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(9) },
[RST_SPI2AXI] = { 0xa8, RST_TYPE_SW_DONE, 0, BIT(0) }
};
static inline struct k230_rst *to_k230_rst(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct k230_rst, rcdev);
}
static void k230_rst_clear_done(struct k230_rst *rstc, unsigned long id,
bool write_en)
{
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
guard(spinlock_irqsave)(&rstc->lock);
reg = readl(rstc->base + rmap->offset);
reg |= rmap->done; /* write 1 to clear */
if (write_en)
reg |= rmap->done << 16;
writel(reg, rstc->base + rmap->offset);
}
static int k230_rst_wait_and_clear_done(struct k230_rst *rstc, unsigned long id,
bool write_en)
{
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
int ret;
ret = readl_poll_timeout(rstc->base + rmap->offset, reg,
reg & rmap->done, 10, 1000);
if (ret) {
dev_err(rstc->rcdev.dev, "Wait for reset done timeout\n");
return ret;
}
k230_rst_clear_done(rstc, id, write_en);
return 0;
}
static void k230_rst_update(struct k230_rst *rstc, unsigned long id,
bool assert, bool write_en, bool active_low)
{
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
guard(spinlock_irqsave)(&rstc->lock);
reg = readl(rstc->base + rmap->offset);
if (assert ^ active_low)
reg |= rmap->reset;
else
reg &= ~rmap->reset;
if (write_en)
reg |= rmap->reset << 16;
writel(reg, rstc->base + rmap->offset);
}
static int k230_rst_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
struct k230_rst *rstc = to_k230_rst(rcdev);
switch (k230_resets[id].type) {
case RST_TYPE_CPU1:
k230_rst_update(rstc, id, true, true, false);
break;
case RST_TYPE_SW_DONE:
k230_rst_update(rstc, id, true, false,
id == RST_SPI2AXI ? false : true);
break;
case RST_TYPE_CPU0:
case RST_TYPE_FLUSH:
case RST_TYPE_HW_DONE:
return -EOPNOTSUPP;
}
/*
* The time period when reset is applied but the clock is stopped for
* RST_TYPE_CPU1 and RST_TYPE_SW_DONE can be set up to 3.75us. Delay
* 10us to ensure proper reset timing.
*/
udelay(10);
return 0;
}
static int k230_rst_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct k230_rst *rstc = to_k230_rst(rcdev);
int ret = 0;
switch (k230_resets[id].type) {
case RST_TYPE_CPU1:
k230_rst_update(rstc, id, false, true, false);
ret = k230_rst_wait_and_clear_done(rstc, id, true);
break;
case RST_TYPE_SW_DONE:
k230_rst_update(rstc, id, false, false,
id == RST_SPI2AXI ? false : true);
break;
case RST_TYPE_CPU0:
case RST_TYPE_FLUSH:
case RST_TYPE_HW_DONE:
return -EOPNOTSUPP;
}
/*
* The time period when reset is removed but the clock is stopped for
* RST_TYPE_CPU1 and RST_TYPE_SW_DONE can be set up to 3.75us. Delay
* 10us to ensure proper reset timing.
*/
udelay(10);
return ret;
}
static int k230_rst_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
struct k230_rst *rstc = to_k230_rst(rcdev);
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
int ret = 0;
switch (rmap->type) {
case RST_TYPE_CPU0:
k230_rst_clear_done(rstc, id, true);
k230_rst_update(rstc, id, true, true, false);
ret = k230_rst_wait_and_clear_done(rstc, id, true);
/*
* The time period when reset is applied and removed but the
* clock is stopped for RST_TYPE_CPU0 can be set up to 7.5us.
* Delay 10us to ensure proper reset timing.
*/
udelay(10);
break;
case RST_TYPE_FLUSH:
k230_rst_update(rstc, id, true, true, false);
/* Wait flush request bit auto cleared by hardware */
ret = readl_poll_timeout(rstc->base + rmap->offset, reg,
!(reg & rmap->reset), 10, 1000);
if (ret)
dev_err(rcdev->dev, "Wait for flush done timeout\n");
break;
case RST_TYPE_HW_DONE:
k230_rst_clear_done(rstc, id, false);
k230_rst_update(rstc, id, true, false, false);
ret = k230_rst_wait_and_clear_done(rstc, id, false);
/*
* The time period when reset is applied and removed but the
* clock is stopped for RST_TYPE_HW_DONE can be set up to
* 127.5us. Delay 200us to ensure proper reset timing.
*/
fsleep(200);
break;
case RST_TYPE_CPU1:
case RST_TYPE_SW_DONE:
k230_rst_assert(rcdev, id);
ret = k230_rst_deassert(rcdev, id);
break;
}
return ret;
}
static const struct reset_control_ops k230_rst_ops = {
.reset = k230_rst_reset,
.assert = k230_rst_assert,
.deassert = k230_rst_deassert,
};
static int k230_rst_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct k230_rst *rstc;
rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
if (!rstc)
return -ENOMEM;
rstc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rstc->base))
return PTR_ERR(rstc->base);
spin_lock_init(&rstc->lock);
rstc->rcdev.dev = dev;
rstc->rcdev.owner = THIS_MODULE;
rstc->rcdev.ops = &k230_rst_ops;
rstc->rcdev.nr_resets = ARRAY_SIZE(k230_resets);
rstc->rcdev.of_node = dev->of_node;
return devm_reset_controller_register(dev, &rstc->rcdev);
}
static const struct of_device_id k230_rst_match[] = {
{ .compatible = "canaan,k230-rst", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, k230_rst_match);
static struct platform_driver k230_rst_driver = {
.probe = k230_rst_probe,
.driver = {
.name = "k230-rst",
.of_match_table = k230_rst_match,
}
};
module_platform_driver(k230_rst_driver);
MODULE_AUTHOR("Junhui Liu <junhui.liu@pigmoral.tech>");
MODULE_DESCRIPTION("Canaan K230 reset driver");
MODULE_LICENSE("GPL");

View File

@ -155,62 +155,16 @@ static int mpfs_reset_probe(struct auxiliary_device *adev,
return devm_reset_controller_register(dev, rcdev);
}
static void mpfs_reset_unregister_adev(void *_adev)
{
struct auxiliary_device *adev = _adev;
auxiliary_device_delete(adev);
auxiliary_device_uninit(adev);
}
static void mpfs_reset_adev_release(struct device *dev)
{
struct auxiliary_device *adev = to_auxiliary_dev(dev);
kfree(adev);
}
static struct auxiliary_device *mpfs_reset_adev_alloc(struct device *clk_dev)
{
struct auxiliary_device *adev;
int ret;
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
if (!adev)
return ERR_PTR(-ENOMEM);
adev->name = "reset-mpfs";
adev->dev.parent = clk_dev;
adev->dev.release = mpfs_reset_adev_release;
adev->id = 666u;
ret = auxiliary_device_init(adev);
if (ret) {
kfree(adev);
return ERR_PTR(ret);
}
return adev;
}
int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base)
{
struct auxiliary_device *adev;
int ret;
adev = mpfs_reset_adev_alloc(clk_dev);
if (IS_ERR(adev))
return PTR_ERR(adev);
adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs",
(__force void *)base);
if (!adev)
return -ENODEV;
ret = auxiliary_device_add(adev);
if (ret) {
auxiliary_device_uninit(adev);
return ret;
}
adev->dev.platform_data = (__force void *)base;
return devm_add_action_or_reset(clk_dev, mpfs_reset_unregister_adev, adev);
return 0;
}
EXPORT_SYMBOL_NS_GPL(mpfs_reset_controller_register, "MCHP_CLK_MPFS");

View File

@ -151,6 +151,8 @@ static const struct of_device_id reset_simple_dt_ids[] = {
{ .compatible = "snps,dw-high-reset" },
{ .compatible = "snps,dw-low-reset",
.data = &reset_simple_active_low },
{ .compatible = "sophgo,cv1800b-reset",
.data = &reset_simple_active_low },
{ .compatible = "sophgo,sg2042-reset",
.data = &reset_simple_active_low },
{ /* sentinel */ },

View File

@ -12,6 +12,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/dev_printk.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/kfifo.h>
@ -25,7 +26,6 @@
#define DEVICE_NAME "aspeed-lpc-snoop"
#define NUM_SNOOP_CHANNELS 2
#define SNOOP_FIFO_SIZE 2048
#define HICR5 0x80
@ -57,7 +57,22 @@ struct aspeed_lpc_snoop_model_data {
unsigned int has_hicrb_ensnp;
};
enum aspeed_lpc_snoop_index {
ASPEED_LPC_SNOOP_INDEX_0 = 0,
ASPEED_LPC_SNOOP_INDEX_1 = 1,
ASPEED_LPC_SNOOP_INDEX_MAX = ASPEED_LPC_SNOOP_INDEX_1,
};
struct aspeed_lpc_snoop_channel_cfg {
enum aspeed_lpc_snoop_index index;
u32 hicr5_en;
u32 snpwadr_mask;
u32 snpwadr_shift;
u32 hicrb_en;
};
struct aspeed_lpc_snoop_channel {
const struct aspeed_lpc_snoop_channel_cfg *cfg;
bool enabled;
struct kfifo fifo;
wait_queue_head_t wq;
@ -68,7 +83,24 @@ struct aspeed_lpc_snoop {
struct regmap *regmap;
int irq;
struct clk *clk;
struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS];
struct aspeed_lpc_snoop_channel chan[ASPEED_LPC_SNOOP_INDEX_MAX + 1];
};
static const struct aspeed_lpc_snoop_channel_cfg channel_cfgs[ASPEED_LPC_SNOOP_INDEX_MAX + 1] = {
{
.index = ASPEED_LPC_SNOOP_INDEX_0,
.hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W,
.snpwadr_mask = SNPWADR_CH0_MASK,
.snpwadr_shift = SNPWADR_CH0_SHIFT,
.hicrb_en = HICRB_ENSNP0D,
},
{
.index = ASPEED_LPC_SNOOP_INDEX_1,
.hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W,
.snpwadr_mask = SNPWADR_CH1_MASK,
.snpwadr_shift = SNPWADR_CH1_SHIFT,
.hicrb_en = HICRB_ENSNP1D,
},
};
static struct aspeed_lpc_snoop_channel *snoop_file_to_chan(struct file *file)
@ -182,108 +214,88 @@ static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop,
return 0;
}
static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
struct device *dev,
int channel, u16 lpc_port)
__attribute__((nonnull))
static int aspeed_lpc_enable_snoop(struct device *dev,
struct aspeed_lpc_snoop *lpc_snoop,
struct aspeed_lpc_snoop_channel *channel,
const struct aspeed_lpc_snoop_channel_cfg *cfg,
u16 lpc_port)
{
const struct aspeed_lpc_snoop_model_data *model_data;
int rc = 0;
u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en;
const struct aspeed_lpc_snoop_model_data *model_data =
of_device_get_match_data(dev);
if (WARN_ON(lpc_snoop->chan[channel].enabled))
if (WARN_ON(channel->enabled))
return -EBUSY;
init_waitqueue_head(&lpc_snoop->chan[channel].wq);
/* Create FIFO datastructure */
rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo,
SNOOP_FIFO_SIZE, GFP_KERNEL);
init_waitqueue_head(&channel->wq);
channel->cfg = cfg;
channel->miscdev.minor = MISC_DYNAMIC_MINOR;
channel->miscdev.fops = &snoop_fops;
channel->miscdev.parent = dev;
channel->miscdev.name =
devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, cfg->index);
if (!channel->miscdev.name)
return -ENOMEM;
rc = kfifo_alloc(&channel->fifo, SNOOP_FIFO_SIZE, GFP_KERNEL);
if (rc)
return rc;
lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR;
lpc_snoop->chan[channel].miscdev.name =
devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel);
if (!lpc_snoop->chan[channel].miscdev.name) {
rc = -ENOMEM;
goto err_free_fifo;
}
lpc_snoop->chan[channel].miscdev.fops = &snoop_fops;
lpc_snoop->chan[channel].miscdev.parent = dev;
rc = misc_register(&lpc_snoop->chan[channel].miscdev);
rc = misc_register(&channel->miscdev);
if (rc)
goto err_free_fifo;
/* Enable LPC snoop channel at requested port */
switch (channel) {
case 0:
hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W;
snpwadr_mask = SNPWADR_CH0_MASK;
snpwadr_shift = SNPWADR_CH0_SHIFT;
hicrb_en = HICRB_ENSNP0D;
break;
case 1:
hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W;
snpwadr_mask = SNPWADR_CH1_MASK;
snpwadr_shift = SNPWADR_CH1_SHIFT;
hicrb_en = HICRB_ENSNP1D;
break;
default:
rc = -EINVAL;
goto err_misc_deregister;
}
regmap_set_bits(lpc_snoop->regmap, HICR5, cfg->hicr5_en);
regmap_update_bits(lpc_snoop->regmap, SNPWADR, cfg->snpwadr_mask,
lpc_port << cfg->snpwadr_shift);
regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en);
regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask,
lpc_port << snpwadr_shift);
if (model_data->has_hicrb_ensnp)
regmap_update_bits(lpc_snoop->regmap, HICRB,
hicrb_en, hicrb_en);
model_data = of_device_get_match_data(dev);
if (model_data && model_data->has_hicrb_ensnp)
regmap_set_bits(lpc_snoop->regmap, HICRB, cfg->hicrb_en);
lpc_snoop->chan[channel].enabled = true;
channel->enabled = true;
return 0;
err_misc_deregister:
misc_deregister(&lpc_snoop->chan[channel].miscdev);
err_free_fifo:
kfifo_free(&lpc_snoop->chan[channel].fifo);
kfifo_free(&channel->fifo);
return rc;
}
__attribute__((nonnull))
static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
int channel)
struct aspeed_lpc_snoop_channel *channel)
{
if (!lpc_snoop->chan[channel].enabled)
if (!channel->enabled)
return;
switch (channel) {
case 0:
regmap_update_bits(lpc_snoop->regmap, HICR5,
HICR5_EN_SNP0W | HICR5_ENINT_SNP0W,
0);
break;
case 1:
regmap_update_bits(lpc_snoop->regmap, HICR5,
HICR5_EN_SNP1W | HICR5_ENINT_SNP1W,
0);
break;
default:
return;
/* Disable interrupts along with the device */
regmap_clear_bits(lpc_snoop->regmap, HICR5, channel->cfg->hicr5_en);
channel->enabled = false;
/* Consider improving safety wrt concurrent reader(s) */
misc_deregister(&channel->miscdev);
kfifo_free(&channel->fifo);
}
lpc_snoop->chan[channel].enabled = false;
/* Consider improving safety wrt concurrent reader(s) */
misc_deregister(&lpc_snoop->chan[channel].miscdev);
kfifo_free(&lpc_snoop->chan[channel].fifo);
static void aspeed_lpc_snoop_remove(struct platform_device *pdev)
{
struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev);
/* Disable both snoop channels */
aspeed_lpc_disable_snoop(lpc_snoop, &lpc_snoop->chan[0]);
aspeed_lpc_disable_snoop(lpc_snoop, &lpc_snoop->chan[1]);
}
static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
{
struct aspeed_lpc_snoop *lpc_snoop;
struct device *dev;
struct device_node *np;
u32 port;
struct device *dev;
int idx;
int rc;
dev = &pdev->dev;
@ -301,69 +313,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
}
lpc_snoop->regmap = syscon_node_to_regmap(np);
if (IS_ERR(lpc_snoop->regmap)) {
dev_err(dev, "Couldn't get regmap\n");
return -ENODEV;
}
if (IS_ERR(lpc_snoop->regmap))
return dev_err_probe(dev, PTR_ERR(lpc_snoop->regmap), "Couldn't get regmap\n");
dev_set_drvdata(&pdev->dev, lpc_snoop);
rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port);
if (rc) {
dev_err(dev, "no snoop ports configured\n");
return -ENODEV;
}
lpc_snoop->clk = devm_clk_get(dev, NULL);
if (IS_ERR(lpc_snoop->clk)) {
rc = PTR_ERR(lpc_snoop->clk);
if (rc != -EPROBE_DEFER)
dev_err(dev, "couldn't get clock\n");
return rc;
}
rc = clk_prepare_enable(lpc_snoop->clk);
if (rc) {
dev_err(dev, "couldn't enable clock\n");
return rc;
}
lpc_snoop->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(lpc_snoop->clk))
return dev_err_probe(dev, PTR_ERR(lpc_snoop->clk), "couldn't get clock");
rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev);
if (rc)
goto err;
return rc;
rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port);
static_assert(ARRAY_SIZE(channel_cfgs) == ARRAY_SIZE(lpc_snoop->chan),
"Broken implementation assumption regarding cfg count");
for (idx = ASPEED_LPC_SNOOP_INDEX_0; idx <= ASPEED_LPC_SNOOP_INDEX_MAX; idx++) {
u32 port;
rc = of_property_read_u32_index(dev->of_node, "snoop-ports", idx, &port);
if (rc)
goto err;
break;
/* Configuration of 2nd snoop channel port is optional */
if (of_property_read_u32_index(dev->of_node, "snoop-ports",
1, &port) == 0) {
rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port);
if (rc) {
aspeed_lpc_disable_snoop(lpc_snoop, 0);
goto err;
}
rc = aspeed_lpc_enable_snoop(dev, lpc_snoop, &lpc_snoop->chan[idx],
&channel_cfgs[idx], port);
if (rc)
goto cleanup_channels;
}
return 0;
return idx == ASPEED_LPC_SNOOP_INDEX_0 ? -ENODEV : 0;
err:
clk_disable_unprepare(lpc_snoop->clk);
cleanup_channels:
aspeed_lpc_snoop_remove(pdev);
return rc;
}
static void aspeed_lpc_snoop_remove(struct platform_device *pdev)
{
struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev);
/* Disable both snoop channels */
aspeed_lpc_disable_snoop(lpc_snoop, 0);
aspeed_lpc_disable_snoop(lpc_snoop, 1);
clk_disable_unprepare(lpc_snoop->clk);
}
static const struct aspeed_lpc_snoop_model_data ast2400_model_data = {
.has_hicrb_ensnp = 0,
};

View File

@ -57,7 +57,7 @@ static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
return !!(ioread32be(&regs->cpdata) & pin_mask);
}
static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
static int qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc);
@ -75,9 +75,11 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
iowrite32be(qe_gc->cpdata, &regs->cpdata);
spin_unlock_irqrestore(&qe_gc->lock, flags);
return 0;
}
static void qe_gpio_set_multiple(struct gpio_chip *gc,
static int qe_gpio_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
@ -102,6 +104,8 @@ static void qe_gpio_set_multiple(struct gpio_chip *gc,
iowrite32be(qe_gc->cpdata, &regs->cpdata);
spin_unlock_irqrestore(&qe_gc->lock, flags);
return 0;
}
static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
@ -317,8 +321,8 @@ static int __init qe_add_gpiochips(void)
gc->direction_input = qe_gpio_dir_in;
gc->direction_output = qe_gpio_dir_out;
gc->get = qe_gpio_get;
gc->set = qe_gpio_set;
gc->set_multiple = qe_gpio_set_multiple;
gc->set_rv = qe_gpio_set;
gc->set_multiple_rv = qe_gpio_set_multiple;
ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc);
if (ret)

View File

@ -407,7 +407,6 @@ static int qe_ic_init(struct platform_device *pdev)
void (*high_handler)(struct irq_desc *desc);
struct qe_ic *qe_ic;
struct resource *res;
struct device_node *node = pdev->dev.of_node;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
@ -441,7 +440,7 @@ static int qe_ic_init(struct platform_device *pdev)
high_handler = NULL;
}
qe_ic->irqhost = irq_domain_create_linear(of_fwnode_handle(node), NR_QE_IC_INTS,
qe_ic->irqhost = irq_domain_create_linear(dev_fwnode(&pdev->dev), NR_QE_IC_INTS,
&qe_ic_host_ops, qe_ic);
if (qe_ic->irqhost == NULL) {
dev_err(dev, "failed to add irq domain\n");

View File

@ -1295,11 +1295,11 @@ static int hccs_get_all_spec_port_idle_sta(struct hccs_dev *hdev, u8 port_type,
if (ret) {
dev_err(hdev->dev,
"hccs%u on chip%u/die%u get idle status failed, ret = %d.\n",
k, i, j, ret);
port->port_id, chip->chip_id, die->die_id, ret);
return ret;
} else if (idle == 0) {
dev_info(hdev->dev, "hccs%u on chip%u/die%u is busy.\n",
k, i, j);
port->port_id, chip->chip_id, die->die_id);
return 0;
}
}

View File

@ -17,16 +17,35 @@
#define MT2701_MUTEX0_MOD0 0x2c
#define MT2701_MUTEX0_SOF0 0x30
#define MT2701_MUTEX0_MOD1 0x34
#define MT8183_MUTEX0_MOD0 0x30
#define MT8183_MUTEX0_MOD1 0x34
#define MT8183_MUTEX0_SOF0 0x2c
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
#define DISP_REG_MUTEX_MOD(mutex_mod_reg, n) (mutex_mod_reg + 0x20 * (n))
#define DISP_REG_MUTEX_MOD1(mutex_mod_reg, n) ((mutex_mod_reg) + 0x20 * (n) + 0x4)
/*
* Some SoCs may have multiple MUTEX_MOD registers as more than 32 mods
* are present, hence requiring multiple 32-bits registers.
*
* The mutex_table_mod fully represents that by defining the number of
* the mod sequentially, later used as a bit number, which can be more
* than 0..31.
*
* In order to retain compatibility with older SoCs, we perform R/W on
* the single 32 bits registers, but this requires us to translate the
* mutex ID bit accordingly.
*/
#define DISP_REG_MUTEX_MOD(mutex, id, n) ({ \
const typeof(mutex) _mutex = (mutex); \
u32 _offset = (id) < 32 ? \
_mutex->data->mutex_mod_reg : \
_mutex->data->mutex_mod1_reg; \
_offset + 0x20 * (n); \
})
#define DISP_REG_MUTEX_SOF(mutex_sof_reg, n) (mutex_sof_reg + 0x20 * (n))
#define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
#define INT_MUTEX BIT(1)
@ -334,6 +353,7 @@ struct mtk_mutex_data {
const u8 *mutex_table_mod;
const u16 *mutex_sof;
const u16 mutex_mod_reg;
const u16 mutex_mod1_reg;
const u16 mutex_sof_reg;
const bool no_clk;
};
@ -714,6 +734,7 @@ static const struct mtk_mutex_data mt2701_mutex_driver_data = {
.mutex_mod = mt2701_mutex_mod,
.mutex_sof = mt2712_mutex_sof,
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
.mutex_mod1_reg = MT2701_MUTEX0_MOD1,
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
};
@ -721,6 +742,7 @@ static const struct mtk_mutex_data mt2712_mutex_driver_data = {
.mutex_mod = mt2712_mutex_mod,
.mutex_sof = mt2712_mutex_sof,
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
.mutex_mod1_reg = MT2701_MUTEX0_MOD1,
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
};
@ -728,6 +750,7 @@ static const struct mtk_mutex_data mt6795_mutex_driver_data = {
.mutex_mod = mt8173_mutex_mod,
.mutex_sof = mt6795_mutex_sof,
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
.mutex_mod1_reg = MT2701_MUTEX0_MOD1,
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
};
@ -735,6 +758,7 @@ static const struct mtk_mutex_data mt8167_mutex_driver_data = {
.mutex_mod = mt8167_mutex_mod,
.mutex_sof = mt8167_mutex_sof,
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
.mutex_mod1_reg = MT2701_MUTEX0_MOD1,
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
.no_clk = true,
};
@ -743,6 +767,7 @@ static const struct mtk_mutex_data mt8173_mutex_driver_data = {
.mutex_mod = mt8173_mutex_mod,
.mutex_sof = mt2712_mutex_sof,
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
.mutex_mod1_reg = MT2701_MUTEX0_MOD1,
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
};
@ -750,6 +775,7 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = {
.mutex_mod = mt8183_mutex_mod,
.mutex_sof = mt8183_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.mutex_table_mod = mt8183_mutex_table_mod,
.no_clk = true,
@ -757,6 +783,7 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = {
static const struct mtk_mutex_data mt8186_mdp_mutex_driver_data = {
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.mutex_table_mod = mt8186_mdp_mutex_table_mod,
};
@ -765,6 +792,7 @@ static const struct mtk_mutex_data mt8186_mutex_driver_data = {
.mutex_mod = mt8186_mutex_mod,
.mutex_sof = mt8186_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
};
@ -772,12 +800,14 @@ static const struct mtk_mutex_data mt8188_mutex_driver_data = {
.mutex_mod = mt8188_mutex_mod,
.mutex_sof = mt8188_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
};
static const struct mtk_mutex_data mt8188_vpp_mutex_driver_data = {
.mutex_sof = mt8188_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.mutex_table_mod = mt8188_mdp_mutex_table_mod,
};
@ -786,6 +816,7 @@ static const struct mtk_mutex_data mt8192_mutex_driver_data = {
.mutex_mod = mt8192_mutex_mod,
.mutex_sof = mt8183_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
};
@ -793,12 +824,14 @@ static const struct mtk_mutex_data mt8195_mutex_driver_data = {
.mutex_mod = mt8195_mutex_mod,
.mutex_sof = mt8195_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
};
static const struct mtk_mutex_data mt8195_vpp_mutex_driver_data = {
.mutex_sof = mt8195_mutex_sof,
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
.mutex_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.mutex_table_mod = mt8195_mutex_table_mod,
};
@ -807,6 +840,7 @@ 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_mod1_reg = MT8183_MUTEX0_MOD1,
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
.no_clk = true,
};
@ -859,7 +893,7 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
mutex[mutex->id]);
unsigned int reg;
unsigned int sof_id;
unsigned int sof_id, mod_id;
unsigned int offset;
WARN_ON(&mtx->mutex[mutex->id] != mutex);
@ -890,18 +924,11 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
sof_id = MUTEX_SOF_DP_INTF1;
break;
default:
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
offset = DISP_REG_MUTEX_MOD(mtx, mtx->data->mutex_mod[id], mutex->id);
mod_id = mtx->data->mutex_mod[id] % 32;
reg = readl_relaxed(mtx->regs + offset);
reg |= 1 << mtx->data->mutex_mod[id];
reg |= BIT(mod_id);
writel_relaxed(reg, mtx->regs + offset);
} else {
offset = DISP_REG_MUTEX_MOD2(mutex->id);
reg = readl_relaxed(mtx->regs + offset);
reg |= 1 << (mtx->data->mutex_mod[id] - 32);
writel_relaxed(reg, mtx->regs + offset);
}
return;
}
@ -917,6 +944,7 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
mutex[mutex->id]);
unsigned int reg;
unsigned int mod_id;
unsigned int offset;
WARN_ON(&mtx->mutex[mutex->id] != mutex);
@ -936,18 +964,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
mutex->id));
break;
default:
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
offset = DISP_REG_MUTEX_MOD(mtx, mtx->data->mutex_mod[id], mutex->id);
mod_id = mtx->data->mutex_mod[id] % 32;
reg = readl_relaxed(mtx->regs + offset);
reg &= ~(1 << mtx->data->mutex_mod[id]);
reg &= ~BIT(mod_id);
writel_relaxed(reg, mtx->regs + offset);
} else {
offset = DISP_REG_MUTEX_MOD2(mutex->id);
reg = readl_relaxed(mtx->regs + offset);
reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
writel_relaxed(reg, mtx->regs + offset);
}
break;
}
}
@ -1023,7 +1044,7 @@ int mtk_mutex_write_mod(struct mtk_mutex *mutex,
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
mutex[mutex->id]);
unsigned int reg;
u32 reg_offset, id_offset = 0;
u32 offset, mod_id;
WARN_ON(&mtx->mutex[mutex->id] != mutex);
@ -1033,34 +1054,16 @@ int mtk_mutex_write_mod(struct mtk_mutex *mutex,
return -EINVAL;
}
/*
* Some SoCs may have multiple MUTEX_MOD registers as more than 32 mods
* are present, hence requiring multiple 32-bits registers.
*
* The mutex_table_mod fully represents that by defining the number of
* the mod sequentially, later used as a bit number, which can be more
* than 0..31.
*
* In order to retain compatibility with older SoCs, we perform R/W on
* the single 32 bits registers, but this requires us to translate the
* mutex ID bit accordingly.
*/
if (mtx->data->mutex_table_mod[idx] < 32) {
reg_offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
} else {
reg_offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
mutex->id);
id_offset = 32;
}
offset = DISP_REG_MUTEX_MOD(mtx, mtx->data->mutex_table_mod[idx], mutex->id);
mod_id = mtx->data->mutex_table_mod[idx] % 32;
reg = readl_relaxed(mtx->regs + reg_offset);
reg = readl_relaxed(mtx->regs + offset);
if (clear)
reg &= ~BIT(mtx->data->mutex_table_mod[idx] - id_offset);
reg &= ~BIT(mod_id);
else
reg |= BIT(mtx->data->mutex_table_mod[idx] - id_offset);
reg |= BIT(mod_id);
writel_relaxed(reg, mtx->regs + reg_offset);
writel_relaxed(reg, mtx->regs + offset);
return 0;
}

View File

@ -18,7 +18,38 @@
#include <linux/slab.h>
#include <linux/soc/qcom/mdt_loader.h>
static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
static bool mdt_header_valid(const struct firmware *fw)
{
const struct elf32_hdr *ehdr;
size_t phend;
size_t shend;
if (fw->size < sizeof(*ehdr))
return false;
ehdr = (struct elf32_hdr *)fw->data;
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG))
return false;
if (ehdr->e_phentsize != sizeof(struct elf32_phdr))
return false;
phend = size_add(size_mul(sizeof(struct elf32_phdr), ehdr->e_phnum), ehdr->e_phoff);
if (phend > fw->size)
return false;
if (ehdr->e_shentsize != sizeof(struct elf32_shdr))
return false;
shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff);
if (shend > fw->size)
return false;
return true;
}
static bool mdt_phdr_loadable(const struct elf32_phdr *phdr)
{
if (phdr->p_type != PT_LOAD)
return false;
@ -82,13 +113,16 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
phys_addr_t max_addr = 0;
int i;
if (!mdt_header_valid(fw))
return -EINVAL;
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
if (!mdt_phdr_valid(phdr))
if (!mdt_phdr_loadable(phdr))
continue;
if (phdr->p_paddr < min_addr)
@ -134,8 +168,11 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
ssize_t ret;
void *data;
if (!mdt_header_valid(fw))
return ERR_PTR(-EINVAL);
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
if (ehdr->e_phnum < 2)
return ERR_PTR(-EINVAL);
@ -214,13 +251,16 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
int ret;
int i;
if (!mdt_header_valid(fw))
return -EINVAL;
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
if (!mdt_phdr_valid(phdr))
if (!mdt_phdr_loadable(phdr))
continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
@ -270,7 +310,7 @@ static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_na
int i;
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
/*
@ -310,14 +350,17 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (!fw || !mem_region || !mem_phys || !mem_size)
return -EINVAL;
if (!mdt_header_valid(fw))
return -EINVAL;
is_split = qcom_mdt_bins_are_split(fw, fw_name);
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
if (!mdt_phdr_valid(phdr))
if (!mdt_phdr_loadable(phdr))
continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
@ -344,7 +387,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
if (!mdt_phdr_valid(phdr))
if (!mdt_phdr_loadable(phdr))
continue;
offset = phdr->p_paddr - mem_reloc;

View File

@ -167,7 +167,10 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
return 0;
}
static void pmic_glink_aux_release(struct device *dev) {}
static void pmic_glink_aux_release(struct device *dev)
{
of_node_put(dev->of_node);
}
static int pmic_glink_add_aux_device(struct pmic_glink *pg,
struct auxiliary_device *aux,
@ -181,8 +184,10 @@ static int pmic_glink_add_aux_device(struct pmic_glink *pg,
aux->dev.release = pmic_glink_aux_release;
device_set_of_node_from_dev(&aux->dev, parent);
ret = auxiliary_device_init(aux);
if (ret)
if (ret) {
of_node_put(aux->dev.of_node);
return ret;
}
ret = auxiliary_device_add(aux);
if (ret)

View File

@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2011-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/io.h>
@ -11,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/soc/qcom/qcom_aoss.h>
#include <linux/soc/qcom/smem.h>
#include <clocksource/arm_arch_timer.h>
@ -24,6 +27,19 @@
#define ACCUMULATED_OFFSET 0x18
#define CLIENT_VOTES_OFFSET 0x20
#define DDR_STATS_MAGIC_KEY 0xA1157A75
#define DDR_STATS_MAX_NUM_MODES 20
#define DDR_STATS_MAGIC_KEY_ADDR 0x0
#define DDR_STATS_NUM_MODES_ADDR 0x4
#define DDR_STATS_ENTRY_START_ADDR 0x8
#define DDR_STATS_CP_IDX(data) FIELD_GET(GENMASK(4, 0), data)
#define DDR_STATS_LPM_NAME(data) FIELD_GET(GENMASK(7, 0), data)
#define DDR_STATS_TYPE(data) FIELD_GET(GENMASK(15, 8), data)
#define DDR_STATS_FREQ(data) FIELD_GET(GENMASK(31, 16), data)
static struct qmp *qcom_stats_qmp;
struct subsystem_data {
const char *name;
u32 smem_item;
@ -48,12 +64,19 @@ static const struct subsystem_data subsystems[] = {
struct stats_config {
size_t stats_offset;
size_t ddr_stats_offset;
size_t num_records;
bool appended_stats_avail;
bool dynamic_offset;
bool subsystem_stats_in_smem;
};
struct ddr_stats_entry {
u32 name;
u32 count;
u64 duration;
};
struct stats_data {
bool appended_stats_avail;
void __iomem *base;
@ -122,8 +145,101 @@ static int qcom_soc_sleep_stats_show(struct seq_file *s, void *unused)
return 0;
}
static void qcom_ddr_stats_print(struct seq_file *s, struct ddr_stats_entry *data)
{
u32 cp_idx;
/*
* DDR statistic have two different types of details encoded.
* (1) DDR LPM Stats
* (2) DDR Frequency Stats
*
* The name field have details like which type of DDR stat (bits 8:15)
* along with other details as explained below
*
* In case of DDR LPM stat, name field will be encoded as,
* Bits - Meaning
* 0:7 - DDR LPM name, can be of 0xd4, 0xd3, 0x11 and 0xd0.
* 8:15 - 0x0 (indicates its a LPM stat)
* 16:31 - Unused
*
* In case of DDR FREQ stats, name field will be encoded as,
* Bits - Meaning
* 0:4 - DDR Clock plan index (CP IDX)
* 5:7 - Unused
* 8:15 - 0x1 (indicates its Freq stat)
* 16:31 - Frequency value in Mhz
*/
switch (DDR_STATS_TYPE(data->name)) {
case 0:
seq_printf(s, "DDR LPM Stat Name:0x%lx\tcount:%u\tDuration (ticks):%llu\n",
DDR_STATS_LPM_NAME(data->name), data->count, data->duration);
break;
case 1:
if (!data->count || !DDR_STATS_FREQ(data->name))
return;
cp_idx = DDR_STATS_CP_IDX(data->name);
seq_printf(s, "DDR Freq %luMhz:\tCP IDX:%u\tcount:%u\tDuration (ticks):%llu\n",
DDR_STATS_FREQ(data->name), cp_idx, data->count, data->duration);
break;
}
}
static int qcom_ddr_stats_show(struct seq_file *s, void *d)
{
struct ddr_stats_entry data[DDR_STATS_MAX_NUM_MODES];
void __iomem *reg = (void __iomem *)s->private;
u32 entry_count;
int i, ret;
entry_count = readl_relaxed(reg + DDR_STATS_NUM_MODES_ADDR);
if (entry_count > DDR_STATS_MAX_NUM_MODES)
return -EINVAL;
if (qcom_stats_qmp) {
/*
* Recent SoCs (SM8450 onwards) do not have duration field
* populated from boot up onwards for both DDR LPM Stats
* and DDR Frequency Stats.
*
* Send QMP message to Always on processor which will
* populate duration field into MSG RAM area.
*
* Sent every time to read latest data.
*/
ret = qmp_send(qcom_stats_qmp, "{class: ddr, action: freqsync}");
if (ret)
return ret;
}
reg += DDR_STATS_ENTRY_START_ADDR;
memcpy_fromio(data, reg, sizeof(struct ddr_stats_entry) * entry_count);
for (i = 0; i < entry_count; i++)
qcom_ddr_stats_print(s, &data[i]);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(qcom_soc_sleep_stats);
DEFINE_SHOW_ATTRIBUTE(qcom_subsystem_sleep_stats);
DEFINE_SHOW_ATTRIBUTE(qcom_ddr_stats);
static void qcom_create_ddr_stat_files(struct dentry *root, void __iomem *reg,
const struct stats_config *config)
{
u32 key;
if (!config->ddr_stats_offset)
return;
key = readl_relaxed(reg + config->ddr_stats_offset + DDR_STATS_MAGIC_KEY_ADDR);
if (key == DDR_STATS_MAGIC_KEY)
debugfs_create_file("ddr_stats", 0400, root,
(__force void *)reg + config->ddr_stats_offset,
&qcom_ddr_stats_fops);
}
static void qcom_create_soc_sleep_stat_files(struct dentry *root, void __iomem *reg,
struct stats_data *d,
@ -207,11 +323,27 @@ static int qcom_stats_probe(struct platform_device *pdev)
for (i = 0; i < config->num_records; i++)
d[i].appended_stats_avail = config->appended_stats_avail;
/*
* QMP is used for DDR stats syncing to MSG RAM for recent SoCs (SM8450 onwards).
* The prior SoCs do not need QMP handle as the required stats are already present
* in MSG RAM, provided the DDR_STATS_MAGIC_KEY matches.
*/
qcom_stats_qmp = qmp_get(&pdev->dev);
if (IS_ERR(qcom_stats_qmp)) {
/* We ignore error if QMP is not defined/needed */
if (!of_property_present(pdev->dev.of_node, "qcom,qmp"))
qcom_stats_qmp = NULL;
else if (PTR_ERR(qcom_stats_qmp) == -EPROBE_DEFER)
return -EPROBE_DEFER;
else
return PTR_ERR(qcom_stats_qmp);
}
root = debugfs_create_dir("qcom_stats", NULL);
qcom_create_subsystem_stat_files(root, config);
qcom_create_soc_sleep_stat_files(root, reg, d, config);
qcom_create_ddr_stat_files(root, reg, config);
platform_set_drvdata(pdev, root);
@ -254,6 +386,7 @@ static const struct stats_config rpmh_data_sdm845 = {
static const struct stats_config rpmh_data = {
.stats_offset = 0x48,
.ddr_stats_offset = 0xb8,
.num_records = 3,
.appended_stats_avail = false,
.dynamic_offset = false,

View File

@ -304,6 +304,8 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
const void *buf_src;
int encode_tlv = 0;
int rc;
u8 val8;
u16 val16;
if (!ei_array)
return 0;
@ -338,7 +340,6 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
break;
case QMI_DATA_LEN:
memcpy(&data_len_value, buf_src, temp_ei->elem_size);
data_len_sz = temp_ei->elem_size == sizeof(u8) ?
sizeof(u8) : sizeof(u16);
/* Check to avoid out of range buffer access */
@ -348,8 +349,17 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
__func__);
return -ETOOSMALL;
}
rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
if (data_len_sz == sizeof(u8)) {
val8 = *(u8 *)buf_src;
data_len_value = (u32)val8;
rc = qmi_encode_basic_elem(buf_dst, &val8,
1, data_len_sz);
} else {
val16 = *(u16 *)buf_src;
data_len_value = (u32)le16_to_cpu(val16);
rc = qmi_encode_basic_elem(buf_dst, &val16,
1, data_len_sz);
}
UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
encoded_bytes, tlv_len,
encode_tlv, rc);
@ -523,14 +533,23 @@ static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array,
u32 string_len = 0;
u32 string_len_sz = 0;
const struct qmi_elem_info *temp_ei = ei_array;
u8 val8;
u16 val16;
if (dec_level == 1) {
string_len = tlv_len;
} else {
string_len_sz = temp_ei->elem_len <= U8_MAX ?
sizeof(u8) : sizeof(u16);
rc = qmi_decode_basic_elem(&string_len, buf_src,
if (string_len_sz == sizeof(u8)) {
rc = qmi_decode_basic_elem(&val8, buf_src,
1, string_len_sz);
string_len = (u32)val8;
} else {
rc = qmi_decode_basic_elem(&val16, buf_src,
1, string_len_sz);
string_len = (u32)val16;
}
decoded_bytes += rc;
}
@ -604,6 +623,9 @@ static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
u32 decoded_bytes = 0;
const void *buf_src = in_buf;
int rc;
u8 val8;
u16 val16;
u32 val32;
while (decoded_bytes < in_buf_len) {
if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI)
@ -642,9 +664,17 @@ static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
if (temp_ei->data_type == QMI_DATA_LEN) {
data_len_sz = temp_ei->elem_size == sizeof(u8) ?
sizeof(u8) : sizeof(u16);
rc = qmi_decode_basic_elem(&data_len_value, buf_src,
if (data_len_sz == sizeof(u8)) {
rc = qmi_decode_basic_elem(&val8, buf_src,
1, data_len_sz);
memcpy(buf_dst, &data_len_value, sizeof(u32));
data_len_value = (u32)val8;
} else {
rc = qmi_decode_basic_elem(&val16, buf_src,
1, data_len_sz);
data_len_value = (u32)val16;
}
val32 = cpu_to_le32(data_len_value);
memcpy(buf_dst, &val32, sizeof(u32));
temp_ei = temp_ei + 1;
buf_dst = out_c_struct + temp_ei->offset;
tlv_len -= data_len_sz;
@ -746,9 +776,9 @@ void *qmi_encode_message(int type, unsigned int msg_id, size_t *len,
hdr = msg;
hdr->type = type;
hdr->txn_id = txn_id;
hdr->msg_id = msg_id;
hdr->msg_len = msglen;
hdr->txn_id = cpu_to_le16(txn_id);
hdr->msg_id = cpu_to_le16(msg_id);
hdr->msg_len = cpu_to_le16(msglen);
*len = sizeof(*hdr) + msglen;

View File

@ -400,7 +400,7 @@ static void qmi_invoke_handler(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
for (handler = qmi->handlers; handler->fn; handler++) {
if (handler->type == hdr->type &&
handler->msg_id == hdr->msg_id)
handler->msg_id == le16_to_cpu(hdr->msg_id))
break;
}
@ -488,7 +488,7 @@ static void qmi_handle_message(struct qmi_handle *qmi,
/* If this is a response, find the matching transaction handle */
if (hdr->type == QMI_RESPONSE) {
mutex_lock(&qmi->txn_lock);
txn = idr_find(&qmi->txns, hdr->txn_id);
txn = idr_find(&qmi->txns, le16_to_cpu(hdr->txn_id));
/* Ignore unexpected responses */
if (!txn) {
@ -514,7 +514,7 @@ static void qmi_handle_message(struct qmi_handle *qmi,
} else {
/* Create a txn based on the txn_id of the incoming message */
memset(&tmp_txn, 0, sizeof(tmp_txn));
tmp_txn.id = hdr->txn_id;
tmp_txn.id = le16_to_cpu(hdr->txn_id);
qmi_invoke_handler(qmi, sq, &tmp_txn, buf, len);
}

View File

@ -1072,7 +1072,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT);
drv->ver.minor >>= MINOR_VER_SHIFT;
if (drv->ver.major == 3)
if (drv->ver.major >= 3)
drv->regs = rpmh_rsc_reg_offset_ver_3_0;
else
drv->regs = rpmh_rsc_reg_offset_ver_2_7;

View File

@ -38,6 +38,7 @@
#define SMEM_IMAGE_TABLE_BOOT_INDEX 0
#define SMEM_IMAGE_TABLE_TZ_INDEX 1
#define SMEM_IMAGE_TABLE_RPM_INDEX 3
#define SMEM_IMAGE_TABLE_APPSBL_INDEX 9
#define SMEM_IMAGE_TABLE_APPS_INDEX 10
#define SMEM_IMAGE_TABLE_MPSS_INDEX 11
#define SMEM_IMAGE_TABLE_ADSP_INDEX 12
@ -48,6 +49,7 @@
#define SMEM_IMAGE_TABLE_CDSP1_INDEX 19
#define SMEM_IMAGE_TABLE_GPDSP_INDEX 20
#define SMEM_IMAGE_TABLE_GPDSP1_INDEX 21
#define SMEM_IMAGE_TABLE_TME_INDEX 28
#define SMEM_IMAGE_VERSION_TABLE 469
/*
@ -55,6 +57,7 @@
*/
static const char *const socinfo_image_names[] = {
[SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp",
[SMEM_IMAGE_TABLE_APPSBL_INDEX] = "appsbl",
[SMEM_IMAGE_TABLE_APPS_INDEX] = "apps",
[SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot",
[SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss",
@ -67,6 +70,7 @@ static const char *const socinfo_image_names[] = {
[SMEM_IMAGE_TABLE_CDSP1_INDEX] = "cdsp1",
[SMEM_IMAGE_TABLE_GPDSP_INDEX] = "gpdsp",
[SMEM_IMAGE_TABLE_GPDSP1_INDEX] = "gpdsp1",
[SMEM_IMAGE_TABLE_TME_INDEX] = "tme",
};
static const char *const pmic_models[] = {
@ -126,8 +130,12 @@ static const char *const pmic_models[] = {
[72] = "PMR735D",
[73] = "PM8550",
[74] = "PMK8550",
[78] = "PMM8650AU",
[79] = "PMM8650AU_PSAIL",
[80] = "PM7550",
[82] = "PMC8380",
[83] = "SMB2360",
[91] = "PMIV0108",
};
struct socinfo_params {
@ -446,8 +454,13 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QCM8550) },
{ qcom_board_id(SM8750) },
{ qcom_board_id(IPQ5300) },
{ qcom_board_id(SM7635) },
{ qcom_board_id(SM6650) },
{ qcom_board_id(SM6650P) },
{ qcom_board_id(IPQ5321) },
{ qcom_board_id(IPQ5424) },
{ qcom_board_id(QCM6690) },
{ qcom_board_id(QCS6690) },
{ qcom_board_id(IPQ5404) },
{ qcom_board_id(QCS9100) },
{ qcom_board_id(QCS8300) },

View File

@ -69,79 +69,8 @@ config ARCH_EMEV2
select HAVE_ARM_SCU if SMP
select SYS_SUPPORTS_EM_STI
config ARCH_R8A7794
bool "ARM32 Platform support for R-Car E2"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A7794
config ARCH_R8A7779
bool "ARM32 Platform support for R-Car H1"
default ARCH_RENESAS
select ARCH_RCAR_GEN1
select ARM_ERRATA_754322
select ARM_GLOBAL_TIMER
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select SYSC_R8A7779
config ARCH_R8A7790
bool "ARM32 Platform support for R-Car H2"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
select I2C
select SYSC_R8A7790
config ARCH_R8A7778
bool "ARM32 Platform support for R-Car M1A"
default ARCH_RENESAS
select ARCH_RCAR_GEN1
select ARM_ERRATA_754322
config ARCH_R8A7793
bool "ARM32 Platform support for R-Car M2-N"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select I2C
select SYSC_R8A7791
config ARCH_R8A7791
bool "ARM32 Platform support for R-Car M2-W"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select I2C
select SYSC_R8A7791
config ARCH_R8A7792
bool "ARM32 Platform support for R-Car V2H"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7792
config ARCH_R8A7740
bool "ARM32 Platform support for R-Mobile A1"
default ARCH_RENESAS
select ARCH_RMOBILE
select ARM_ERRATA_754322
select RENESAS_INTC_IRQPIN
config ARCH_R8A73A4
bool "ARM32 Platform support for R-Mobile APE6"
default ARCH_RENESAS
select ARCH_RMOBILE
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
select HAVE_ARM_ARCH_TIMER
select RENESAS_IRQC
config ARCH_R7S72100
bool "ARM32 Platform support for RZ/A1H"
bool "ARM32 Platform support for R7S72100 (RZ/A1H)"
default ARCH_RENESAS
select ARM_ERRATA_754322
select PM
@ -151,29 +80,31 @@ config ARCH_R7S72100
select SYS_SUPPORTS_SH_MTU2
config ARCH_R7S9210
bool "ARM32 Platform support for RZ/A2"
bool "ARM32 Platform support for R7S9210 (RZ/A2)"
default ARCH_RENESAS
select PM
select PM_GENERIC_DOMAINS
select RENESAS_OSTM
select RENESAS_RZA1_IRQC
config ARCH_R8A77470
bool "ARM32 Platform support for RZ/G1C"
config ARCH_R8A73A4
bool "ARM32 Platform support for R8A73A4 (R-Mobile APE6)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARCH_RMOBILE
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
select SYSC_R8A77470
select HAVE_ARM_ARCH_TIMER
select RENESAS_IRQC
config ARCH_R8A7745
bool "ARM32 Platform support for RZ/G1E"
config ARCH_R8A7740
bool "ARM32 Platform support for R8A7740 (R-Mobile A1)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A7745
select ARCH_RMOBILE
select ARM_ERRATA_754322
select RENESAS_INTC_IRQPIN
config ARCH_R8A7742
bool "ARM32 Platform support for RZ/G1H"
bool "ARM32 Platform support for R8A7742 (RZ/G1H)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
@ -181,27 +112,96 @@ config ARCH_R8A7742
select SYSC_R8A7742
config ARCH_R8A7743
bool "ARM32 Platform support for RZ/G1M"
bool "ARM32 Platform support for R8A7743 (RZ/G1M)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7743
config ARCH_R8A7744
bool "ARM32 Platform support for RZ/G1N"
bool "ARM32 Platform support for R8A7744 (RZ/G1N)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7743
config ARCH_R8A7745
bool "ARM32 Platform support for R8A7745 (RZ/G1E)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A7745
config ARCH_R8A77470
bool "ARM32 Platform support for R8A77470 (RZ/G1C)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A77470
config ARCH_R8A7778
bool "ARM32 Platform support for R8A7778 (R-Car M1A)"
default ARCH_RENESAS
select ARCH_RCAR_GEN1
select ARM_ERRATA_754322
config ARCH_R8A7779
bool "ARM32 Platform support for R8A7779 (R-Car H1)"
default ARCH_RENESAS
select ARCH_RCAR_GEN1
select ARM_ERRATA_754322
select ARM_GLOBAL_TIMER
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select SYSC_R8A7779
config ARCH_R8A7790
bool "ARM32 Platform support for R8A7790 (R-Car H2)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
select I2C
select SYSC_R8A7790
config ARCH_R8A7791
bool "ARM32 Platform support for R8A7791 (R-Car M2-W)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select I2C
select SYSC_R8A7791
config ARCH_R8A7792
bool "ARM32 Platform support for R8A7792 (R-Car V2H)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7792
config ARCH_R8A7793
bool "ARM32 Platform support for R8A7793 (R-Car M2-N)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select I2C
select SYSC_R8A7791
config ARCH_R8A7794
bool "ARM32 Platform support for R8A7794 (R-Car E2)"
default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A7794
config ARCH_R9A06G032
bool "ARM32 Platform support for RZ/N1D"
bool "ARM32 Platform support for R9A06G032 (RZ/N1D)"
default ARCH_RENESAS
select ARCH_RZN1
select ARM_ERRATA_814220
config ARCH_SH73A0
bool "ARM32 Platform support for SH-Mobile AG5"
bool "ARM32 Platform support for SH73A0 (SH-Mobile AG5)"
default ARCH_RENESAS
select ARCH_RMOBILE
select ARM_ERRATA_754322
@ -214,26 +214,40 @@ endif # ARM
if ARM64
config ARCH_R8A77995
bool "ARM64 Platform support for R-Car D3"
config ARCH_R8A774A1
bool "ARM64 Platform support for R8A774A1 (RZ/G2M)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77995
select SYSC_R8A774A1
help
This enables support for the Renesas R-Car D3 SoC.
This includes different gradings like R-Car D3e.
This enables support for the Renesas RZ/G2M SoC.
config ARCH_R8A77990
bool "ARM64 Platform support for R-Car E3"
config ARCH_R8A774B1
bool "ARM64 Platform support for R8A774B1 (RZ/G2N)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77990
select SYSC_R8A774B1
help
This enables support for the Renesas R-Car E3 SoC.
This includes different gradings like R-Car E3e.
This enables support for the Renesas RZ/G2N SoC.
config ARCH_R8A774C0
bool "ARM64 Platform support for R8A774C0 (RZ/G2E)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774C0
help
This enables support for the Renesas RZ/G2E SoC.
config ARCH_R8A774E1
bool "ARM64 Platform support for R8A774E1 (RZ/G2H)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774E1
help
This enables support for the Renesas RZ/G2H SoC.
config ARCH_R8A77951
bool "ARM64 Platform support for R-Car H3 ES2.0+"
bool "ARM64 Platform support for R8A77951 (R-Car H3 ES2.0+)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A7795
@ -242,17 +256,8 @@ config ARCH_R8A77951
later).
This includes different gradings like R-Car H3e, H3e-2G, and H3Ne.
config ARCH_R8A77965
bool "ARM64 Platform support for R-Car M3-N"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77965
help
This enables support for the Renesas R-Car M3-N SoC.
This includes different gradings like R-Car M3Ne and M3Ne-2G.
config ARCH_R8A77960
bool "ARM64 Platform support for R-Car M3-W"
bool "ARM64 Platform support for R8A77960 (R-Car M3-W)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77960
@ -260,7 +265,7 @@ config ARCH_R8A77960
This enables support for the Renesas R-Car M3-W SoC.
config ARCH_R8A77961
bool "ARM64 Platform support for R-Car M3-W+"
bool "ARM64 Platform support for R8A77961 (R-Car M3-W+)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77961
@ -268,40 +273,67 @@ config ARCH_R8A77961
This enables support for the Renesas R-Car M3-W+ SoC.
This includes different gradings like R-Car M3e and M3e-2G.
config ARCH_R8A779F0
bool "ARM64 Platform support for R-Car S4-8"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779F0
help
This enables support for the Renesas R-Car S4-8 SoC.
config ARCH_R8A77980
bool "ARM64 Platform support for R-Car V3H"
config ARCH_R8A77965
bool "ARM64 Platform support for R8A77965 (R-Car M3-N)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77980
select SYSC_R8A77965
help
This enables support for the Renesas R-Car V3H SoC.
This enables support for the Renesas R-Car M3-N SoC.
This includes different gradings like R-Car M3Ne and M3Ne-2G.
config ARCH_R8A77970
bool "ARM64 Platform support for R-Car V3M"
bool "ARM64 Platform support for R8A77970 (R-Car V3M)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77970
help
This enables support for the Renesas R-Car V3M SoC.
config ARCH_R8A77980
bool "ARM64 Platform support for R8A77980 (R-Car V3H)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77980
help
This enables support for the Renesas R-Car V3H SoC.
config ARCH_R8A77990
bool "ARM64 Platform support for R8A77990 (R-Car E3)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77990
help
This enables support for the Renesas R-Car E3 SoC.
This includes different gradings like R-Car E3e.
config ARCH_R8A77995
bool "ARM64 Platform support for R8A77995 (R-Car D3)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77995
help
This enables support for the Renesas R-Car D3 SoC.
This includes different gradings like R-Car D3e.
config ARCH_R8A779A0
bool "ARM64 Platform support for R-Car V3U"
bool "ARM64 Platform support for R8A779A0 (R-Car V3U)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779A0
help
This enables support for the Renesas R-Car V3U SoC.
config ARCH_R8A779F0
bool "ARM64 Platform support for R8A779F0 (R-Car S4-8)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779F0
help
This enables support for the Renesas R-Car S4-8 SoC.
config ARCH_R8A779G0
bool "ARM64 Platform support for R-Car V4H"
bool "ARM64 Platform support for R8A779G0 (R-Car V4H)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779G0
@ -309,68 +341,36 @@ config ARCH_R8A779G0
This enables support for the Renesas R-Car V4H SoC.
config ARCH_R8A779H0
bool "ARM64 Platform support for R-Car V4M"
bool "ARM64 Platform support for R8A779H0 (R-Car V4M)"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779H0
help
This enables support for the Renesas R-Car V4M SoC.
config ARCH_R8A774C0
bool "ARM64 Platform support for RZ/G2E"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774C0
help
This enables support for the Renesas RZ/G2E SoC.
config ARCH_R8A774E1
bool "ARM64 Platform support for RZ/G2H"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774E1
help
This enables support for the Renesas RZ/G2H SoC.
config ARCH_R8A774A1
bool "ARM64 Platform support for RZ/G2M"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774A1
help
This enables support for the Renesas RZ/G2M SoC.
config ARCH_R8A774B1
bool "ARM64 Platform support for RZ/G2N"
default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774B1
help
This enables support for the Renesas RZ/G2N SoC.
config ARCH_R9A07G043
bool "ARM64 Platform support for RZ/G2UL"
bool "ARM64 Platform support for R9A07G043U (RZ/G2UL)"
default y if ARCH_RENESAS
select ARCH_RZG2L
help
This enables support for the Renesas RZ/G2UL SoC variants.
config ARCH_R9A07G044
bool "ARM64 Platform support for RZ/G2L"
bool "ARM64 Platform support for R9A07G044 (RZ/G2L)"
default y if ARCH_RENESAS
select ARCH_RZG2L
help
This enables support for the Renesas RZ/G2L SoC variants.
config ARCH_R9A07G054
bool "ARM64 Platform support for RZ/V2L"
bool "ARM64 Platform support for R9A07G054 (RZ/V2L)"
default y if ARCH_RENESAS
select ARCH_RZG2L
help
This enables support for the Renesas RZ/V2L SoC variants.
config ARCH_R9A08G045
bool "ARM64 Platform support for RZ/G3S"
bool "ARM64 Platform support for R9A08G045 (RZ/G3S)"
default y if ARCH_RENESAS
select ARCH_RZG2L
select SYSC_R9A08G045
@ -378,7 +378,7 @@ config ARCH_R9A08G045
This enables support for the Renesas RZ/G3S SoC variants.
config ARCH_R9A09G011
bool "ARM64 Platform support for RZ/V2M"
bool "ARM64 Platform support for R9A09G011 (RZ/V2M)"
default y if ARCH_RENESAS
select PM
select PM_GENERIC_DOMAINS
@ -387,33 +387,45 @@ config ARCH_R9A09G011
This enables support for the Renesas RZ/V2M SoC.
config ARCH_R9A09G047
bool "ARM64 Platform support for RZ/G3E"
bool "ARM64 Platform support for R9A09G047 (RZ/G3E)"
default y if ARCH_RENESAS
select SYS_R9A09G047
help
This enables support for the Renesas RZ/G3E SoC variants.
config ARCH_R9A09G056
bool "ARM64 Platform support for RZ/V2N"
bool "ARM64 Platform support for R9A09G056 (RZ/V2N)"
default y if ARCH_RENESAS
select SYS_R9A09G056
help
This enables support for the Renesas RZ/V2N SoC variants.
config ARCH_R9A09G057
bool "ARM64 Platform support for RZ/V2H(P)"
bool "ARM64 Platform support for R9A09G057 (RZ/V2H(P))"
default y if ARCH_RENESAS
select RENESAS_RZV2H_ICU
select SYS_R9A09G057
help
This enables support for the Renesas RZ/V2H(P) SoC variants.
config ARCH_R9A09G077
bool "ARM64 Platform support for R9A09G077 (RZ/T2H)"
default y if ARCH_RENESAS
help
This enables support for the Renesas RZ/T2H SoC variants.
config ARCH_R9A09G087
bool "ARM64 Platform support for R9A09G087 (RZ/N2H)"
default y if ARCH_RENESAS
help
This enables support for the Renesas RZ/N2H SoC variants.
endif # ARM64
if RISCV
config ARCH_R9A07G043
bool "RISC-V Platform support for RZ/Five"
bool "RISC-V Platform support for R9A07G043F (RZ/Five)"
depends on NONPORTABLE
depends on !DMA_DIRECT_REMAP
depends on RISCV_ALTERNATIVE
@ -439,19 +451,19 @@ config SYSC_RZ
bool "System controller for RZ SoCs" if COMPILE_TEST
config SYSC_R9A08G045
bool "Renesas RZ/G3S System controller support" if COMPILE_TEST
bool "Renesas System controller support for R9A08G045 (RZ/G3S)" if COMPILE_TEST
select SYSC_RZ
config SYS_R9A09G047
bool "Renesas RZ/G3E System controller support" if COMPILE_TEST
bool "Renesas System controller support for R9A09G047 (RZ/G3E)" if COMPILE_TEST
select SYSC_RZ
config SYS_R9A09G056
bool "Renesas RZ/V2N System controller support" if COMPILE_TEST
bool "Renesas System controller support for R9A09G056 (RZ/V2N)" if COMPILE_TEST
select SYSC_RZ
config SYS_R9A09G057
bool "Renesas RZ/V2H System controller support" if COMPILE_TEST
bool "Renesas System controller support for R9A09G057 (RZ/V2H)" if COMPILE_TEST
select SYSC_RZ
endif # SOC_RENESAS

View File

@ -24,7 +24,7 @@ struct rzv2m_pwc_priv {
DECLARE_BITMAP(ch_en_bits, 2);
};
static void rzv2m_pwc_gpio_set(struct gpio_chip *chip, unsigned int offset,
static int rzv2m_pwc_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct rzv2m_pwc_priv *priv = gpiochip_get_data(chip);
@ -38,6 +38,8 @@ static void rzv2m_pwc_gpio_set(struct gpio_chip *chip, unsigned int offset,
writel(reg, priv->base + PWC_GPIO);
assign_bit(offset, priv->ch_en_bits, value);
return 0;
}
static int rzv2m_pwc_gpio_get(struct gpio_chip *chip, unsigned int offset)
@ -62,7 +64,7 @@ static const struct gpio_chip rzv2m_pwc_gc = {
.label = "gpio_rzv2m_pwc",
.owner = THIS_MODULE,
.get = rzv2m_pwc_gpio_get,
.set = rzv2m_pwc_gpio_set,
.set_rv = rzv2m_pwc_gpio_set,
.direction_output = rzv2m_pwc_gpio_direction_output,
.can_sleep = false,
.ngpio = 2,

View File

@ -138,6 +138,14 @@ config ARCH_TEGRA_241_SOC
help
Enable support for the NVIDIA Tegra241 SoC.
config ARCH_TEGRA_264_SOC
bool "NVIDIA Tegra264 SoC"
depends on !CPU_BIG_ENDIAN
select MAILBOX
select SOC_TEGRA_PMC
help
Enable support for the NVIDIA Tegra264 SoC.
endif
endif

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved
* Copyright (c) 2021-2025, NVIDIA CORPORATION. All rights reserved
*
* The driver handles Error's from Control Backbone(CBB) generated due to
* illegal accesses. When an error is reported from a NOC within CBB,
@ -138,7 +138,7 @@ struct tegra194_cbb_userbits {
struct tegra194_cbb_noc_data {
const char *name;
bool erd_mask_inband_err;
const char * const *master_id;
const char * const *initiator_id;
unsigned int max_aperture;
const struct tegra194_cbb_aperture *noc_aperture;
const char * const *routeid_initflow;
@ -216,7 +216,7 @@ static const char * const tegra194_axi2apb_error[] = {
"CH2RFIFOF - Ch2 Request FIFO Full interrupt"
};
static const char * const tegra194_master_id[] = {
static const char * const tegra194_initiator_id[] = {
[0x0] = "CCPLEX",
[0x1] = "CCPLEX_DPMU",
[0x2] = "BPMP",
@ -238,7 +238,7 @@ static const struct tegra_cbb_error tegra194_cbb_errors[] = {
{
.code = "SLV",
.source = "Target",
.desc = "Target error detected by CBB slave"
.desc = "Target error detected by CBB target"
}, {
.code = "DEC",
.source = "Initiator NIU",
@ -1774,8 +1774,8 @@ static void print_errlog5(struct seq_file *file, struct tegra194_cbb *cbb)
tegra_cbb_print_err(file, "\t AXI ID\t\t: %#x\n", userbits.axi_id);
}
tegra_cbb_print_err(file, "\t Master ID\t\t: %s\n",
cbb->noc->master_id[userbits.mstr_id]);
tegra_cbb_print_err(file, "\t Initiator ID\t\t: %s\n",
cbb->noc->initiator_id[userbits.mstr_id]);
tegra_cbb_print_err(file, "\t Security Group(GRPSEC): %#x\n", userbits.grpsec);
tegra_cbb_print_cache(file, userbits.axcache);
tegra_cbb_print_prot(file, userbits.axprot);
@ -1837,14 +1837,14 @@ print_errlog1_2(struct seq_file *file, struct tegra194_cbb *cbb,
/*
* Print transcation type, error code and description from ErrLog0 for all
* errors. For NOC slave errors, all relevant error info is printed using
* errors. For NOC target errors, all relevant error info is printed using
* ErrLog0 only. But additional information is printed for errors from
* APB slaves because for them:
* - All errors are logged as SLV(slave) errors due to APB having only single
* APB targets because for them:
* - All errors are logged as SLV(target) errors due to APB having only single
* bit pslverr to report all errors.
* - Exact cause is printed by reading DMAAPB_X_RAW_INTERRUPT_STATUS register.
* - The driver prints information showing AXI2APB bridge and exact error
* only if there is error in any AXI2APB slave.
* only if there is error in any AXI2APB target.
* - There is still no way to disambiguate a DEC error from SLV error type.
*/
static bool print_errlog0(struct seq_file *file, struct tegra194_cbb *cbb)
@ -1884,8 +1884,8 @@ static bool print_errlog0(struct seq_file *file, struct tegra194_cbb *cbb)
/* For all SLV errors, read DMAAPB_X_RAW_INTERRUPT_STATUS
* register to get error status for all AXI2APB bridges.
* Print bridge details if a bit is set in a bridge's
* status register due to error in a APB slave connected
* to that bridge. For other NOC slaves, none of the status
* status register due to error in a APB target connected
* to that bridge. For other NOC targets, none of the status
* register will be set.
*/
@ -2118,7 +2118,7 @@ static const struct tegra_cbb_ops tegra194_cbb_ops = {
static struct tegra194_cbb_noc_data tegra194_cbb_central_noc_data = {
.name = "cbb-noc",
.erd_mask_inband_err = true,
.master_id = tegra194_master_id,
.initiator_id = tegra194_initiator_id,
.noc_aperture = tegra194_cbbcentralnoc_apert_lookup,
.max_aperture = ARRAY_SIZE(tegra194_cbbcentralnoc_apert_lookup),
.routeid_initflow = tegra194_cbbcentralnoc_routeid_initflow,
@ -2130,7 +2130,7 @@ static struct tegra194_cbb_noc_data tegra194_cbb_central_noc_data = {
static struct tegra194_cbb_noc_data tegra194_aon_noc_data = {
.name = "aon-noc",
.erd_mask_inband_err = false,
.master_id = tegra194_master_id,
.initiator_id = tegra194_initiator_id,
.noc_aperture = tegra194_aonnoc_aperture_lookup,
.max_aperture = ARRAY_SIZE(tegra194_aonnoc_aperture_lookup),
.routeid_initflow = tegra194_aonnoc_routeid_initflow,
@ -2142,7 +2142,7 @@ static struct tegra194_cbb_noc_data tegra194_aon_noc_data = {
static struct tegra194_cbb_noc_data tegra194_bpmp_noc_data = {
.name = "bpmp-noc",
.erd_mask_inband_err = false,
.master_id = tegra194_master_id,
.initiator_id = tegra194_initiator_id,
.noc_aperture = tegra194_bpmpnoc_apert_lookup,
.max_aperture = ARRAY_SIZE(tegra194_bpmpnoc_apert_lookup),
.routeid_initflow = tegra194_bpmpnoc_routeid_initflow,
@ -2154,7 +2154,7 @@ static struct tegra194_cbb_noc_data tegra194_bpmp_noc_data = {
static struct tegra194_cbb_noc_data tegra194_rce_noc_data = {
.name = "rce-noc",
.erd_mask_inband_err = false,
.master_id = tegra194_master_id,
.initiator_id = tegra194_initiator_id,
.noc_aperture = tegra194_scenoc_apert_lookup,
.max_aperture = ARRAY_SIZE(tegra194_scenoc_apert_lookup),
.routeid_initflow = tegra194_scenoc_routeid_initflow,
@ -2166,7 +2166,7 @@ static struct tegra194_cbb_noc_data tegra194_rce_noc_data = {
static struct tegra194_cbb_noc_data tegra194_sce_noc_data = {
.name = "sce-noc",
.erd_mask_inband_err = false,
.master_id = tegra194_master_id,
.initiator_id = tegra194_initiator_id,
.noc_aperture = tegra194_scenoc_apert_lookup,
.max_aperture = ARRAY_SIZE(tegra194_scenoc_apert_lookup),
.routeid_initflow = tegra194_scenoc_routeid_initflow,

File diff suppressed because it is too large Load Diff

View File

@ -128,6 +128,7 @@ static const struct of_device_id apbmisc_match[] __initconst = {
{ .compatible = "nvidia,tegra186-misc", },
{ .compatible = "nvidia,tegra194-misc", },
{ .compatible = "nvidia,tegra234-misc", },
{ .compatible = "nvidia,tegra264-misc", },
{},
};

View File

@ -2500,8 +2500,7 @@ static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
pmc->irq.irq_set_type = pmc->soc->irq_set_type;
pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;
pmc->domain = irq_domain_create_hierarchy(parent, 0, 96,
of_fwnode_handle(pmc->dev->of_node),
pmc->domain = irq_domain_create_hierarchy(parent, 0, 96, dev_fwnode(pmc->dev),
&tegra_pmc_irq_domain_ops, pmc);
if (!pmc->domain) {
dev_err(pmc->dev, "failed to allocate domain\n");
@ -4248,7 +4247,128 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = {
.has_single_mmio_aperture = false,
};
static const struct tegra_pmc_regs tegra264_pmc_regs = {
.scratch0 = 0x684,
.rst_status = 0x4,
.rst_source_shift = 0x2,
.rst_source_mask = 0x1fc,
.rst_level_shift = 0x0,
.rst_level_mask = 0x3,
};
static const char * const tegra264_reset_sources[] = {
"SYS_RESET_N", /* 0x0 */
"CSDC_RTC_XTAL",
"VREFRO_POWER_BAD",
"SCPM_SOC_XTAL",
"SCPM_RTC_XTAL",
"FMON_32K",
"FMON_OSC",
"POD_RTC",
"POD_IO", /* 0x8 */
"POD_PLUS_IO_SPLL",
"POD_PLUS_SOC",
"VMON_PLUS_UV",
"VMON_PLUS_OV",
"FUSECRC_FAULT",
"OSC_FAULT",
"BPMP_BOOT_FAULT",
"SCPM_BPMP_CORE_CLK", /* 0x10 */
"SCPM_PSC_SE_CLK",
"VMON_SOC_MIN",
"VMON_SOC_MAX",
"VMON_MSS_MIN",
"VMON_MSS_MAX",
"POD_PLUS_IO_VMON",
"NVJTAG_SEL_MONITOR",
"NV_THERM_FAULT", /* 0x18 */
"FSI_THERM_FAULT",
"PSC_SW",
"SCPM_OESP_SE_CLK",
"SCPM_SB_SE_CLK",
"POD_CPU",
"POD_GPU",
"DCLS_GPU",
"POD_MSS", /* 0x20 */
"FMON_FSI",
"POD_FSI",
"VMON_FSI_MIN",
"VMON_FSI_MAX",
"VMON_CPU0_MIN",
"VMON_CPU0_MAX",
"BPMP_FMON",
"AO_WDT_POR", /* 0x28 */
"BPMP_WDT_POR",
"AO_TKE_WDT_POR",
"RCE0_WDT_POR",
"RCE1_WDT_POR",
"DCE_WDT_POR",
"FSI_R5_WDT_POR",
"FSI_R52_0_WDT_POR",
"FSI_R52_1_WDT_POR", /* 0x30 */
"FSI_R52_2_WDT_POR",
"FSI_R52_3_WDT_POR",
"TOP_0_WDT_POR",
"TOP_1_WDT_POR",
"TOP_2_WDT_POR",
"APE_C0_WDT_POR",
"APE_C1_WDT_POR",
"GPU_TKE_WDT_POR", /* 0x38 */
"PSC_WDT_POR",
"OESP_WDT_POR",
"SB_WDT_POR",
"SW_MAIN",
"L0L1_RST_OUT_N",
"FSI_HSM",
"CSITE_SW",
"AO_WDT_DBG", /* 0x40 */
"BPMP_WDT_DBG",
"AO_TKE_WDT_DBG",
"RCE0_WDT_DBG",
"RCE1_WDT_DBG",
"DCE_WDT_DBG",
"FSI_R5_WDT_DBG",
"FSI_R52_0_WDT_DBG",
"FSI_R52_1_WDT_DBG", /* 0x48 */
"FSI_R52_2_WDT_DBG",
"FSI_R52_3_WDT_DBG",
"TOP_0_WDT_DBG",
"TOP_1_WDT_DBG",
"TOP_2_WDT_DBG",
"APE_C0_WDT_DBG",
"APE_C1_WDT_DBG",
"PSC_WDT_DBG", /* 0x50 */
"OESP_WDT_DBG",
"SB_WDT_DBG",
"TSC_0_WDT_DBG",
"TSC_1_WDT_DBG",
"L2_RST_OUT_N",
"SC7"
};
static const struct tegra_wake_event tegra264_wake_events[] = {
};
static const struct tegra_pmc_soc tegra264_pmc_soc = {
.has_impl_33v_pwr = true,
.regs = &tegra264_pmc_regs,
.init = tegra186_pmc_init,
.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
.set_wake_filters = tegra186_pmc_set_wake_filters,
.irq_set_wake = tegra186_pmc_irq_set_wake,
.irq_set_type = tegra186_pmc_irq_set_type,
.reset_sources = tegra264_reset_sources,
.num_reset_sources = ARRAY_SIZE(tegra264_reset_sources),
.reset_levels = tegra186_reset_levels,
.num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
.wake_events = tegra264_wake_events,
.num_wake_events = ARRAY_SIZE(tegra264_wake_events),
.max_wake_events = 128,
.max_wake_vectors = 4,
};
static const struct of_device_id tegra_pmc_match[] = {
{ .compatible = "nvidia,tegra264-pmc", .data = &tegra264_pmc_soc },
{ .compatible = "nvidia,tegra234-pmc", .data = &tegra234_pmc_soc },
{ .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc },
{ .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc },

View File

@ -279,8 +279,13 @@
#define QCOM_ID_QCM8550 604
#define QCOM_ID_SM8750 618
#define QCOM_ID_IPQ5300 624
#define QCOM_ID_SM7635 636
#define QCOM_ID_SM6650 640
#define QCOM_ID_SM6650P 641
#define QCOM_ID_IPQ5321 650
#define QCOM_ID_IPQ5424 651
#define QCOM_ID_QCM6690 657
#define QCOM_ID_QCS6690 658
#define QCOM_ID_IPQ5404 671
#define QCOM_ID_QCS9100 667
#define QCOM_ID_QCS8300 674

View File

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (C) 2023-2024 Canaan Bright Sight Co., Ltd
* Copyright (C) 2024-2025 Junhui Liu <junhui.liu@pigmoral.tech>
*/
#ifndef _DT_BINDINGS_CANAAN_K230_RST_H_
#define _DT_BINDINGS_CANAAN_K230_RST_H_
#define RST_CPU0 0
#define RST_CPU1 1
#define RST_CPU0_FLUSH 2
#define RST_CPU1_FLUSH 3
#define RST_AI 4
#define RST_VPU 5
#define RST_HISYS 6
#define RST_HISYS_AHB 7
#define RST_SDIO0 8
#define RST_SDIO1 9
#define RST_SDIO_AXI 10
#define RST_USB0 11
#define RST_USB1 12
#define RST_USB0_AHB 13
#define RST_USB1_AHB 14
#define RST_SPI0 15
#define RST_SPI1 16
#define RST_SPI2 17
#define RST_SEC 18
#define RST_PDMA 19
#define RST_SDMA 20
#define RST_DECOMPRESS 21
#define RST_SRAM 22
#define RST_SHRM_AXIM 23
#define RST_SHRM_AXIS 24
#define RST_NONAI2D 25
#define RST_MCTL 26
#define RST_ISP 27
#define RST_ISP_DW 28
#define RST_DPU 29
#define RST_DISP 30
#define RST_GPU 31
#define RST_AUDIO 32
#define RST_TIMER0 33
#define RST_TIMER1 34
#define RST_TIMER2 35
#define RST_TIMER3 36
#define RST_TIMER4 37
#define RST_TIMER5 38
#define RST_TIMER_APB 39
#define RST_HDI 40
#define RST_WDT0 41
#define RST_WDT1 42
#define RST_WDT0_APB 43
#define RST_WDT1_APB 44
#define RST_TS_APB 45
#define RST_MAILBOX 46
#define RST_STC 47
#define RST_PMU 48
#define RST_LOSYS_APB 49
#define RST_UART0 50
#define RST_UART1 51
#define RST_UART2 52
#define RST_UART3 53
#define RST_UART4 54
#define RST_I2C0 55
#define RST_I2C1 56
#define RST_I2C2 57
#define RST_I2C3 58
#define RST_I2C4 59
#define RST_JAMLINK0_APB 60
#define RST_JAMLINK1_APB 61
#define RST_JAMLINK2_APB 62
#define RST_JAMLINK3_APB 63
#define RST_CODEC_APB 64
#define RST_GPIO_DB 65
#define RST_GPIO_APB 66
#define RST_ADC 67
#define RST_ADC_APB 68
#define RST_PWM_APB 69
#define RST_SHRM_APB 70
#define RST_CSI0 71
#define RST_CSI1 72
#define RST_CSI2 73
#define RST_CSI_DPHY 74
#define RST_ISP_AHB 75
#define RST_M0 76
#define RST_M1 77
#define RST_M2 78
#define RST_SPI2AXI 79
#endif

View File

@ -148,11 +148,10 @@ bool qcom_scm_lmh_dcvsh_available(void);
int qcom_scm_gpu_init_regs(u32 gpu_req);
int qcom_scm_shm_bridge_enable(void);
int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags,
int qcom_scm_shm_bridge_create(u64 pfn_and_ns_perm_flags,
u64 ipfn_and_s_perm_flags, u64 size_and_flags,
u64 ns_vmids, u64 *handle);
int qcom_scm_shm_bridge_delete(struct device *dev, u64 handle);
int qcom_scm_shm_bridge_delete(u64 handle);
#ifdef CONFIG_QCOM_QSEECOM

View File

@ -2624,6 +2624,9 @@
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
#define PCI_VENDOR_ID_RPI 0x1de4
#define PCI_DEVICE_ID_RPI_RP1_C0 0x0001
#define PCI_VENDOR_ID_ALIBABA 0x1ded
#define PCI_VENDOR_ID_CXL 0x1e98

View File

@ -24,9 +24,9 @@ struct socket;
*/
struct qmi_header {
u8 type;
u16 txn_id;
u16 msg_id;
u16 msg_len;
__le16 txn_id;
__le16 msg_id;
__le16 msg_len;
} __packed;
#define QMI_REQUEST 0

View File

@ -50,6 +50,8 @@
#define PMR735B_SUBTYPE 0x34
#define PM6350_SUBTYPE 0x36
#define PM4125_SUBTYPE 0x37
#define PMM8650AU_SUBTYPE 0x4e
#define PMM8650AU_PSAIL_SUBTYPE 0x4f
#define PMI8998_FAB_ID_SMIC 0x11
#define PMI8998_FAB_ID_GF 0x30

View File

@ -36,8 +36,8 @@ TRACE_EVENT(scmi_fc_call,
TRACE_EVENT(scmi_xfer_begin,
TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq,
bool poll),
TP_ARGS(transfer_id, msg_id, protocol_id, seq, poll),
bool poll, int inflight),
TP_ARGS(transfer_id, msg_id, protocol_id, seq, poll, inflight),
TP_STRUCT__entry(
__field(int, transfer_id)
@ -45,6 +45,7 @@ TRACE_EVENT(scmi_xfer_begin,
__field(u8, protocol_id)
__field(u16, seq)
__field(bool, poll)
__field(int, inflight)
),
TP_fast_assign(
@ -53,11 +54,12 @@ TRACE_EVENT(scmi_xfer_begin,
__entry->protocol_id = protocol_id;
__entry->seq = seq;
__entry->poll = poll;
__entry->inflight = inflight;
),
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X poll=%u",
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X poll=%u inflight=%d",
__entry->protocol_id, __entry->msg_id, __entry->seq,
__entry->transfer_id, __entry->poll)
__entry->transfer_id, __entry->poll, __entry->inflight)
);
TRACE_EVENT(scmi_xfer_response_wait,
@ -90,8 +92,8 @@ TRACE_EVENT(scmi_xfer_response_wait,
TRACE_EVENT(scmi_xfer_end,
TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq,
int status),
TP_ARGS(transfer_id, msg_id, protocol_id, seq, status),
int status, int inflight),
TP_ARGS(transfer_id, msg_id, protocol_id, seq, status, inflight),
TP_STRUCT__entry(
__field(int, transfer_id)
@ -99,6 +101,7 @@ TRACE_EVENT(scmi_xfer_end,
__field(u8, protocol_id)
__field(u16, seq)
__field(int, status)
__field(int, inflight)
),
TP_fast_assign(
@ -107,11 +110,12 @@ TRACE_EVENT(scmi_xfer_end,
__entry->protocol_id = protocol_id;
__entry->seq = seq;
__entry->status = status;
__entry->inflight = inflight;
),
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X s=%d",
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X s=%d inflight=%d",
__entry->protocol_id, __entry->msg_id, __entry->seq,
__entry->transfer_id, __entry->status)
__entry->transfer_id, __entry->status, __entry->inflight)
);
TRACE_EVENT(scmi_rx_done,