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

Pull SoC driver updates from Arnd Bergmann:
 "The driver updates again are all over the place with many minor fixes
  going into platform specific code. The most notable changes are:

   - Support for Microchip pic64gx system controllers
   - Work on cleaning up devicetree bindings for SoC drivers, and
     converting them into the new format
   - Lots of smaller changes for Qualcomm SoC drivers, including support
     for a number of newly supported chips
   - reset controller API cleanups and a new driver for Cix Sky1
   - Reworks of the Tegra PMC and CBB drivers, along with a change to
     how individual Tegra SoCs get selected in Kconfig and BPMP firmware
     driver updates including a refresh of the ABI header to match the
     version used by firmware
   - STM32 updates to the firewall bus driver and support for the debug
     bus through OP-TEE
   - SCMI firmware driver improvements for reliability, in particular
     for dealing with broken firmware interrupts
   - Memory driver updates for Tegra, and a patch to remove the unused
     Baikal T1 driver"

* tag 'soc-drivers-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (193 commits)
  firmware: arm_ffa: Use the correct buffer size during RXTX_MAP
  firmware: qcom: scm: Allow QSEECOM on Lenovo IdeaCentre Mini X
  clk: spear: fix resource leak in clk_register_vco_pll()
  reset: rzv2h-usb2phy: Add support for VBUS mux controller registration
  reset: rzv2h-usb2phy: Convert to regmap API
  dt-bindings: reset: renesas,rzv2h-usb2phy: Document RZ/G3E USB2PHY reset
  dt-bindings: reset: renesas,rzv2h-usb2phy: Add '#mux-state-cells' property
  soc: microchip: add mpfs gpio interrupt mux driver
  dt-bindings: soc: microchip: document PolarFire SoC's gpio interrupt mux
  gpio: mpfs: Add interrupt support
  soc: qcom: ubwc: add helpers to get programmable values
  soc: qcom: ubwc: add helper to get min_acc length
  firmware: qcom: scm: Register gunyah watchdog device
  soc: qcom: socinfo: Add SoC ID for SA8650P
  dt-bindings: arm: qcom,ids: Add SoC ID for SA8650P
  firmware: qcom: scm: Allow QSEECOM on Mahua CRD
  soc: qcom: wcnss: simplify allocation of req
  soc: qcom: pd-mapper: Add support for Eliza
  soc: qcom: aoss: compare against normalized cooling state
  soc: qcom: llcc: fix v1 SB syndrome register offset
  ...
This commit is contained in:
Linus Torvalds
2026-04-16 20:34:34 -07:00
148 changed files with 9034 additions and 2647 deletions

View File

@@ -128,6 +128,9 @@ properties:
"#address-cells":
const: 1
access-controllers:
maxItems: 1
patternProperties:
'^trig-conns@([0-9]+)$':
type: object

View File

@@ -78,6 +78,9 @@ properties:
description: Output connection to CoreSight Trace bus
$ref: /schemas/graph.yaml#/properties/port
access-controllers:
maxItems: 1
required:
- compatible
- reg

View File

@@ -118,6 +118,9 @@ properties:
description: Output connection from the ETM to CoreSight Trace bus.
$ref: /schemas/graph.yaml#/properties/port
access-controllers:
maxItems: 1
required:
- compatible
- clocks

View File

@@ -73,6 +73,9 @@ properties:
description: Output connection to the CoreSight Trace bus.
$ref: /schemas/graph.yaml#/properties/port
access-controllers:
maxItems: 1
required:
- compatible
- reg

View File

@@ -128,6 +128,9 @@ properties:
- const: tracedata
- const: metadata
access-controllers:
maxItems: 1
required:
- compatible
- reg

View File

@@ -70,6 +70,9 @@ properties:
description: Input connection from the CoreSight Trace bus.
$ref: /schemas/graph.yaml#/properties/port
access-controllers:
maxItems: 1
required:
- compatible
- reg

View File

@@ -0,0 +1,66 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/atmel,at91rm9200-sdramc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip (Atmel) SDRAM / DDR Controller (RAMC / DDRAMC / UDDRC)
maintainers:
- Nicolas Ferre <nicolas.ferre@microchip.com>
- Claudiu Beznea <claudiu.beznea@tuxon.dev>
description:
The SDRAM/DDR Controller (often called RAMC or DDRAMC) in various
Atmel/Microchip ARM9 and Cortex-A5/A7 SoCs manages external
SDRAM / DDR memory. It is typically exposed as a syscon node for
register access from other drivers (e.g. for initialization or mode
configuration). No interrupts or clocks are usually required in the
binding.
properties:
compatible:
oneOf:
- items:
- const: atmel,at91rm9200-sdramc
- const: syscon
- items:
- const: microchip,sama7d65-uddrc
- const: microchip,sama7g5-uddrc
- enum:
- atmel,at91sam9260-sdramc
- atmel,at91sam9g45-ddramc
- atmel,sama5d3-ddramc
- microchip,sam9x60-ddramc
- microchip,sam9x7-ddramc
- microchip,sama7g5-uddrc
reg:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- const: ddrck
- const: mpddr
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/at91.h>
ramc@ffffe400 {
compatible = "atmel,at91sam9g45-ddramc";
reg = <0xffffe400 0x200>;
clocks = <&pmc PMC_TYPE_SYSTEM 2>;
clock-names = "ddrck";
};
...

View File

@@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/atmel,at91rm9200-st.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atmel System Timer
maintainers:
- Nicolas Ferre <nicolas.ferre@microchip.com>
- Claudiu Beznea <claudiu.beznea@tuxon.dev>
description:
The System Timer (ST) module in AT91RM9200 provides periodic tick and
alarm capabilities. It is exposed as a simple multi-function device
(simple-mfd + syscon) because it shares its register space and interrupt
with other System Controller blocks.
properties:
compatible:
items:
- const: atmel,at91rm9200-st
- const: syscon
- const: simple-mfd
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 1
patternProperties:
"^watchdog@[0-9a-f]+$":
$ref: /schemas/watchdog/atmel,at91rm9200-wdt.yaml#
required:
- compatible
- reg
- interrupts
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
timer@fffffd00 {
compatible = "atmel,at91rm9200-st", "syscon", "simple-mfd";
reg = <0xfffffd00 0x100>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
clocks = <&slow_xtal>;
#address-cells = <1>;
#size-cells = <1>;
watchdog@fffffd40 {
compatible = "atmel,at91rm9200-wdt";
reg = <0xfffffd40 0x40>;
};
};
...

View File

@@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/atmel,at91sam9260-pit.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atmel AT91SAM9260 Periodic Interval Timer (PIT)
maintainers:
- Nicolas Ferre <nicolas.ferre@microchip.com>
- Claudiu Beznea <claudiu.beznea@tuxon.dev>
description:
The Periodic Interval Timer (PIT) is part of the System Controller of
various Microchip 32-bit ARM-based SoCs (formerly Atmel AT91 series).
It is a simple down-counter timer used mainly as the kernel tick source.
The PIT is clocked from the slow clock and shares a single IRQ line with
other System Controller peripherals.
properties:
compatible:
const: atmel,at91sam9260-pit
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
timer@fffffd30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffd30 0x10>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk32k>;
};
...

View File

@@ -1,48 +0,0 @@
Atmel system registers
Chipid required properties:
- compatible: Should be "atmel,sama5d2-chipid" or "microchip,sama7g5-chipid"
"microchip,sama7d65-chipid"
- reg : Should contain registers location and length
PIT Timer required properties:
- compatible: Should be "atmel,at91sam9260-pit"
- reg: Should contain registers location and length
- interrupts: Should contain interrupt for the PIT which is the IRQ line
shared across all System Controller members.
PIT64B Timer required properties:
- compatible: Should be "microchip,sam9x60-pit64b" or
"microchip,sam9x7-pit64b", "microchip,sam9x60-pit64b"
"microchip,sama7d65-pit64b", "microchip,sam9x60-pit64b"
- reg: Should contain registers location and length
- interrupts: Should contain interrupt for PIT64B timer
- clocks: Should contain the available clock sources for PIT64B timer.
System Timer (ST) required properties:
- compatible: Should be "atmel,at91rm9200-st", "syscon", "simple-mfd"
- reg: Should contain registers location and length
- interrupts: Should contain interrupt for the ST which is the IRQ line
shared across all System Controller members.
- clocks: phandle to input clock.
Its subnodes can be:
- watchdog: compatible should be "atmel,at91rm9200-wdt"
RAMC SDRAM/DDR Controller required properties:
- compatible: Should be "atmel,at91rm9200-sdramc", "syscon" or
"atmel,at91sam9260-sdramc" or
"atmel,at91sam9g45-ddramc" or
"atmel,sama5d3-ddramc" or
"microchip,sam9x60-ddramc" or
"microchip,sama7g5-uddrc" or
"microchip,sama7d65-uddrc", "microchip,sama7g5-uddrc" or
"microchip,sam9x7-ddramc", "atmel,sama5d3-ddramc".
- reg: Should contain registers location and length
Examples:
ramc0: ramc@ffffe800 {
compatible = "atmel,at91sam9g45-ddramc";
reg = <0xffffe800 0x200>;
};

View File

@@ -28,6 +28,9 @@ properties:
reg:
maxItems: 1
'#clock-cells':
const: 1
clocks:
maxItems: 2
@@ -39,6 +42,7 @@ properties:
required:
- compatible
- reg
- '#clock-cells'
additionalProperties: false
@@ -47,4 +51,5 @@ examples:
smc1@40410000 {
compatible = "fsl,imx7ulp-smc1";
reg = <0x40410000 0x1000>;
#clock-cells = <1>;
};

View File

@@ -996,6 +996,14 @@ properties:
- const: engicam,icore-mx8mm # i.MX8MM Engicam i.Core MX8M Mini SoM
- const: fsl,imx8mm
- description: Ka-Ro Electronics TX8M-1610 based boards
items:
- enum:
- gocontroll,moduline-iv-306-d
- gocontroll,moduline-mini-111
- const: karo,tx8m-1610
- const: fsl,imx8mm
- description: Kontron BL i.MX8MM (N801X S) Board
items:
- const: kontron,imx8mm-bl
@@ -1041,6 +1049,13 @@ properties:
- const: phytec,imx8mm-phycore-som # phyCORE-i.MX8MM SoM
- const: fsl,imx8mm
- description: SolidRun i.MX8MM SoM based boards
items:
- enum:
- solidrun,imx8mm-hummingboard-ripple # SolidRun i.MX8MM SoM on HummingBoard Ripple
- const: solidrun,imx8mm-sr-som
- const: fsl,imx8mm
- description: Variscite VAR-SOM-MX8MM based boards
items:
- const: variscite,var-som-mx8mm-symphony
@@ -1069,6 +1084,7 @@ properties:
- fsl,imx8mn-ddr4-evk # i.MX8MN DDR4 EVK Board
- fsl,imx8mn-evk # i.MX8MN LPDDR4 EVK Board
- gw,imx8mn-gw7902 # i.MX8MM Gateworks Board
- solidrun,solidsense-n8-compact # SolidRun SolidSense N8 Compact
- const: fsl,imx8mn
- description: ifm i.MX8MN VHIP4 based boards
@@ -1106,6 +1122,7 @@ properties:
- beacon,imx8mp-beacon-kit # i.MX8MP Beacon Development Kit
- dmo,imx8mp-data-modul-edm-sbc # i.MX8MP eDM SBC
- emcraft,imx8mp-navqp # i.MX8MP Emcraft Systems NavQ+ Kit
- fsl,imx8mp-ab2 # i.MX8MP Audio Board V2
- fsl,imx8mp-evk # i.MX8MP EVK Board
- fsl,imx8mp-evk-revb4 # i.MX8MP EVK Rev B4 Board
- fsl,imx8mp-frdm # i.MX8MP Freedom Board
@@ -1225,6 +1242,7 @@ properties:
items:
- enum:
- solidrun,imx8mp-cubox-m # SolidRun i.MX8MP SoM on CuBox-M
- solidrun,imx8mp-hummingboard-iiot # SolidRun i.MX8MP SoM on HummingBoard IIoT
- solidrun,imx8mp-hummingboard-mate # SolidRun i.MX8MP SoM on HummingBoard Mate
- solidrun,imx8mp-hummingboard-pro # SolidRun i.MX8MP SoM on HummingBoard Pro
- solidrun,imx8mp-hummingboard-pulse # SolidRun i.MX8MP SoM on HummingBoard Pulse
@@ -1420,6 +1438,16 @@ properties:
- const: tq,imx8dxp-tqma8xdps # TQ-Systems GmbH TQMa8XDPS SOM
- const: fsl,imx8dxp
- description:
TQMa8x is a series of SOM featuring NXP i.MX8 system-on-chip
variants. It is designed to be clicked on different carrier boards
MBa8x is the starterkit
items:
- enum:
- tq,imx8qm-tqma8qm-mba8x # TQ-Systems GmbH TQMa8QM SOM on MBa8x
- const: tq,imx8qm-tqma8qm # TQ-Systems GmbH TQMa8QM SOM
- const: fsl,imx8qm
- description: i.MX8ULP based Boards
items:
- enum:
@@ -1432,6 +1460,7 @@ properties:
- enum:
- fsl,imx91-11x11-evk # i.MX91 11x11 EVK Board
- fsl,imx91-11x11-frdm # FRDM i.MX91 Development Board
- fsl,imx91-11x11-frdm-s # FRDM i.MX91S Development Board
- const: fsl,imx91
- description: i.MX93 based Boards
@@ -1441,6 +1470,7 @@ properties:
- fsl,imx93-11x11-evk # i.MX93 11x11 EVK Board
- fsl,imx93-11x11-frdm # i.MX93 11x11 FRDM Board
- fsl,imx93-14x14-evk # i.MX93 14x14 EVK Board
- fsl,imx93-wireless-evk # i.MX93 and IW610G WLCSP (Wi-Fi + BLE + 802.15.4) SiP EVK Board
- const: fsl,imx93
- description: i.MX94 based Boards
@@ -1477,6 +1507,36 @@ properties:
- const: toradex,smarc-imx95 # Toradex SMARC iMX95 Module
- const: fsl,imx95
- description: Toradex Boards with Verdin iMX95 Modules
items:
- enum:
- toradex,verdin-imx95-nonwifi-dahlia # Verdin iMX95 Module on Dahlia
- toradex,verdin-imx95-nonwifi-dev # Verdin iMX95 Module on Verdin Development Board
- toradex,verdin-imx95-nonwifi-ivy # Verdin iMX95 Module on Ivy
- toradex,verdin-imx95-nonwifi-mallow # Verdin iMX95 Module on Mallow
- toradex,verdin-imx95-nonwifi-yavia # Verdin iMX95 Module on Yavia
- const: toradex,verdin-imx95-nonwifi # Verdin iMX95 Module without Wi-Fi / BT
- const: toradex,verdin-imx95 # Verdin iMX95 Module
- const: fsl,imx95
- description: Toradex Boards with Verdin iMX95 Wi-Fi / BT Modules
items:
- enum:
- toradex,verdin-imx95-wifi-dahlia # Verdin iMX95 Wi-Fi / BT Module on Dahlia
- toradex,verdin-imx95-wifi-dev # Verdin iMX95 Wi-Fi / BT Module on Verdin Development B.
- toradex,verdin-imx95-wifi-ivy # Verdin iMX95 Wi-Fi / BT Module on Ivy
- toradex,verdin-imx95-wifi-mallow # Verdin iMX95 Wi-Fi / BT Module on Mallow
- toradex,verdin-imx95-wifi-yavia # Verdin iMX95 Wi-Fi / BT Module on Yavia
- const: toradex,verdin-imx95-wifi # Verdin iMX95 Wi-Fi / BT Module
- const: toradex,verdin-imx95 # Verdin iMX95 Module
- const: fsl,imx95
- description: Variscite DART-MX95 based Boards
items:
- const: variscite,var-dart-mx95-sonata # Variscite DART-MX95 SOM on Sonata Development Board
- const: variscite,var-dart-mx95 # Variscite DART-MX95 SOM
- const: fsl,imx95
- description: i.MXRT1050 based Boards
items:
- enum:
@@ -1522,11 +1582,14 @@ properties:
soldered on an adapter board or for the connector variant
MBa93xxLA mainboard is a single board computer using the solderable
SOM variant
MBa93xxLA-MINI mainboard is a single board computer using the solderable
SOM variant
items:
- enum:
- tq,imx93-tqma9352-mba91xxca # TQ-Systems GmbH i.MX93 TQMa93xxCA/LA SOM on MBa91xxCA
- tq,imx93-tqma9352-mba93xxca # TQ-Systems GmbH i.MX93 TQMa93xxCA/LA SOM on MBa93xxCA
- tq,imx93-tqma9352-mba93xxla # TQ-Systems GmbH i.MX93 TQMa93xxLA SOM on MBa93xxLA SBC
- tq,imx93-tqma9352-mba93xxla-mini # TQ-Systems GmbH i.MX93 TQMa93xxLA SOM on MBa93xxLA-MINI SBC
- const: tq,imx93-tqma9352 # TQ-Systems GmbH i.MX93 TQMa93xxCA/LA SOM
- const: fsl,imx93
@@ -1545,6 +1608,12 @@ properties:
- const: phytec,imx93-phycore-som # phyCORE-i.MX93 SoM
- const: fsl,imx93
- description: Variscite DART-MX91 based boards
items:
- const: variscite,var-dart-mx91-sonata # Variscite DART-MX91 on Sonata Development Board
- const: variscite,var-dart-mx91 # Variscite DART-MX91 SOM
- const: fsl,imx91
- description: Variscite VAR-SOM-MX93 based boards
items:
- const: variscite,var-som-mx93-symphony
@@ -1557,6 +1626,17 @@ properties:
- const: kontron,imx93-osm-s # Kontron OSM-S i.MX93 SoM
- const: fsl,imx93
- description:
TQMa95xxLA is a series of SOM featuring NXP i.MX95 SoC variants,
designed to be soldered on different carrier boards.
MBa95xxCA is a carrier reference design / starter kit that allows
to use TQMa95xxLA via an adaper board.
items:
- enum:
- tq,imx95-tqma9596la-mba95xxca # TQ-Systems GmbH i.MX95 TQMa95xxLA SOM on MBa95xxCA
- const: tq,imx95-tqma9596la # TQ-Systems GmbH i.MX95 TQMa95xxLA SOM
- const: fsl,imx95
- description:
TQMa95xxSA is a series of SOM featuring NXP i.MX95 SoC variants.
It has the SMARC form factor and is designed to be placed on
@@ -1827,6 +1907,12 @@ properties:
- fsl,s32v234-evb # S32V234-EVB2 Customer Evaluation Board
- const: fsl,s32v234
- description: S32N79 based Boards
items:
- enum:
- nxp,s32n79-rdb
- const: nxp,s32n79
- description: Traverse LS1088A based Boards
items:
- enum:

View File

@@ -0,0 +1,68 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/microchip,sam9x60-pit64b.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip PIT64B 64-bit Periodic Interval Timer
maintainers:
- Nicolas Ferre <nicolas.ferre@microchip.com>
- Claudiu Beznea <claudiu.beznea@tuxon.dev>
description:
The Microchip PIT64B is a 64-bit periodic interval timer used in
several modern Microchip ARM SoCs including SAM9X60, SAM9X7 and
SAMA7D65 families. It provides extended timing range, flexible
clock selection and supports both periodic and one-shot interrupt
generation modes.
properties:
compatible:
oneOf:
- const: microchip,sam9x60-pit64b
- items:
- enum:
- microchip,sam9x7-pit64b
- microchip,sama7d65-pit64b
- microchip,sama7g5-pit64b
- const: microchip,sam9x60-pit64b
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
maxItems: 2
items:
enum:
- pclk
- gclk
required:
- compatible
- reg
- interrupts
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/at91.h>
timer@f0028000 {
compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b";
reg = <0xf0028000 0x100>;
interrupts = <37 IRQ_TYPE_LEVEL_HIGH 7>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 37>, <&pmc PMC_TYPE_GCK 37>;
clock-names = "pclk", "gclk";
};
...

View File

@@ -0,0 +1,41 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/microchip,sama7g5-chipid.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atmel/Microchip RAMC SDRAM/DDR Controller
maintainers:
- Nicolas Ferre <nicolas.ferre@microchip.com>
- Claudiu Beznea <claudiu.beznea@tuxon.dev>
description:
This binding describes the Atmel/Microchip Chip ID register block used
for SoC identification and revision information. It requires compatible
strings matching specific SoC families and a reg property defining the
register address and size.
properties:
compatible:
enum:
- atmel,sama5d2-chipid
- microchip,sama7d65-chipid
- microchip,sama7g5-chipid
reg:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
chipid@fc069000 {
compatible = "atmel,sama5d2-chipid";
reg = <0xfc069000 0x8>;
};
...

View File

@@ -22,5 +22,27 @@ properties:
- phytec,phy3250
- const: nxp,lpc3250
- items:
- enum:
- ea,lpc4357-developers-kit
- const: nxp,lpc4357
- const: nxp,lpc4350
- items:
- enum:
- ciaa,lpc4337
- const: nxp,lpc4337
- const: nxp,lpc4350
- items:
- enum:
- hitex,lpc4350-eval-board
- const: nxp,lpc4350
- items:
- enum:
- myir,myd-lpc4357
- const: nxp,lpc4357
additionalProperties: true
...

View File

@@ -131,6 +131,33 @@ properties:
- const: toradex,apalis-tk1-v1.2
- const: toradex,apalis-tk1
- const: nvidia,tegra124
- items:
- const: google,nyan-big-rev7
- const: google,nyan-big-rev6
- const: google,nyan-big-rev5
- const: google,nyan-big-rev4
- const: google,nyan-big-rev3
- const: google,nyan-big-rev2
- const: google,nyan-big-rev1
- const: google,nyan-big-rev0
- const: google,nyan-big
- const: google,nyan
- const: nvidia,tegra124
- items:
- const: google,nyan-blaze-rev10
- const: google,nyan-blaze-rev9
- const: google,nyan-blaze-rev8
- const: google,nyan-blaze-rev7
- const: google,nyan-blaze-rev6
- const: google,nyan-blaze-rev5
- const: google,nyan-blaze-rev4
- const: google,nyan-blaze-rev3
- const: google,nyan-blaze-rev2
- const: google,nyan-blaze-rev1
- const: google,nyan-blaze-rev0
- const: google,nyan-blaze
- const: google,nyan
- const: nvidia,tegra124
- items:
- enum:
- nvidia,norrin
@@ -184,17 +211,35 @@ properties:
- const: nvidia,tegra124
- items:
- enum:
- nvidia,darcy
- nvidia,p2371-0000
- nvidia,p2371-2180
- nvidia,p2571
- nvidia,p2894-0050-a08
- nvidia,p3450-0000
- const: nvidia,tegra210
- items:
- const: nvidia,p3541-0000
- const: nvidia,p3450-0000
- const: nvidia,tegra210
- description: NVIDIA Jetson Nano
items:
- const: nvidia,p3450-0000
- const: nvidia,tegra210
- description: NVIDIA Shield TV
items:
- const: nvidia,p2894-0050-a08
- const: nvidia,darcy
- const: nvidia,tegra210
- description: Google Pixel C
items:
- const: google,smaug-rev8
- const: google,smaug-rev7
- const: google,smaug-rev6
- const: google,smaug-rev5
- const: google,smaug-rev4
- const: google,smaug-rev3
- const: google,smaug-rev2
- const: google,smaug-rev1
- const: google,smaug
- const: nvidia,tegra210
- description: Jetson TX2 Developer Kit
items:
- const: nvidia,p2771-0000
@@ -268,5 +313,10 @@ properties:
- const: nvidia,p3971-0089+p3834-0008
- const: nvidia,p3834-0008
- const: nvidia,tegra264
- description: Jetson AGX Thor Developer Kit
items:
- const: nvidia,p4071-0000+p3834-0008
- const: nvidia,p3834-0008
- const: nvidia,tegra264
additionalProperties: true

View File

@@ -48,6 +48,10 @@ properties:
- nvidia,tegra234-dce-fabric
- nvidia,tegra234-rce-fabric
- nvidia,tegra234-sce-fabric
- nvidia,tegra238-ape-fabric
- nvidia,tegra238-aon-fabric
- nvidia,tegra238-bpmp-fabric
- nvidia,tegra238-cbb-fabric
reg:
maxItems: 1

View File

@@ -0,0 +1,76 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/bus/st,stm32mp131-dbg-bus.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STM32 Coresight bus
maintainers:
- Gatien Chevallier <gatien.chevallier@foss.st.com>
description:
The STM32 debug bus is in charge of checking the debug configuration
of the platform before probing the peripheral drivers that rely on the debug
domain.
properties:
compatible:
items:
- enum:
- st,stm32mp131-dbg-bus
- st,stm32mp151-dbg-bus
"#address-cells":
const: 1
"#size-cells":
const: 1
ranges:
minItems: 1
maxItems: 2
"#access-controller-cells":
const: 1
description:
Contains the debug profile necessary to access the peripheral.
patternProperties:
"@[0-9a-f]+$":
description: Debug related peripherals
type: object
additionalProperties: true
required:
- access-controllers
required:
- "#access-controller-cells"
- "#address-cells"
- "#size-cells"
- compatible
- ranges
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/stm32mp1-clks.h>
dbg_bus: bus@50080000 {
compatible = "st,stm32mp131-dbg-bus";
#address-cells = <1>;
#size-cells = <1>;
#access-controller-cells = <1>;
ranges = <0x50080000 0x50080000 0x3f80000>;
cti@50094000 {
compatible = "arm,coresight-cti", "arm,primecell";
reg = <0x50094000 0x1000>;
clocks = <&rcc CK_DBG>;
clock-names = "apb_pclk";
access-controllers = <&dbg_bus 0>;
};
};

View File

@@ -1,63 +0,0 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
%YAML 1.2
---
$id: http://devicetree.org/schemas/cache/baikal,bt1-l2-ctl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Baikal-T1 L2-cache Control Block
maintainers:
- Serge Semin <fancer.lancer@gmail.com>
description: |
By means of the System Controller Baikal-T1 SoC exposes a few settings to
tune the MIPS P5600 CM2 L2 cache performance up. In particular it's possible
to change the Tag, Data and Way-select RAM access latencies. Baikal-T1
L2-cache controller block is responsible for the tuning. Its DT node is
supposed to be a child of the system controller.
properties:
compatible:
const: baikal,bt1-l2-ctl
reg:
maxItems: 1
baikal,l2-ws-latency:
$ref: /schemas/types.yaml#/definitions/uint32
description: Cycles of latency for Way-select RAM accesses
default: 0
minimum: 0
maximum: 3
baikal,l2-tag-latency:
$ref: /schemas/types.yaml#/definitions/uint32
description: Cycles of latency for Tag RAM accesses
default: 0
minimum: 0
maximum: 3
baikal,l2-data-latency:
$ref: /schemas/types.yaml#/definitions/uint32
description: Cycles of latency for Data RAM accesses
default: 1
minimum: 0
maximum: 3
additionalProperties: false
required:
- compatible
examples:
- |
l2@1f04d028 {
compatible = "baikal,bt1-l2-ctl";
reg = <0x1f04d028 0x004>;
baikal,l2-ws-latency = <1>;
baikal,l2-tag-latency = <1>;
baikal,l2-data-latency = <2>;
};
...

View File

@@ -33,6 +33,7 @@ properties:
- qcom,sc7280-llcc
- qcom,sc8180x-llcc
- qcom,sc8280xp-llcc
- qcom,sdm670-llcc
- qcom,sdm845-llcc
- qcom,sm6350-llcc
- qcom,sm7150-llcc
@@ -204,6 +205,7 @@ allOf:
contains:
enum:
- qcom,sc7280-llcc
- qcom,sdm670-llcc
then:
properties:
reg:

View File

@@ -1,155 +0,0 @@
NVIDIA Tegra124 DFLL FCPU clocksource
This binding uses the common clock binding:
Documentation/devicetree/bindings/clock/clock-bindings.txt
The DFLL IP block on Tegra is a root clocksource designed for clocking
the fast CPU cluster. It consists of a free-running voltage controlled
oscillator connected to the CPU voltage rail (VDD_CPU), and a closed loop
control module that will automatically adjust the VDD_CPU voltage by
communicating with an off-chip PMIC either via an I2C bus or via PWM signals.
Required properties:
- compatible : should be one of:
- "nvidia,tegra124-dfll": for Tegra124
- "nvidia,tegra210-dfll": for Tegra210
- reg : Defines the following set of registers, in the order listed:
- registers for the DFLL control logic.
- registers for the I2C output logic.
- registers for the integrated I2C master controller.
- look-up table RAM for voltage register values.
- interrupts: Should contain the DFLL block interrupt.
- clocks: Must contain an entry for each entry in clock-names.
See clock-bindings.txt for details.
- clock-names: Must include the following entries:
- soc: Clock source for the DFLL control logic.
- ref: The closed loop reference clock
- i2c: Clock source for the integrated I2C master.
- resets: Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names: Must include the following entries:
- dvco: Reset control for the DFLL DVCO.
- #clock-cells: Must be 0.
- clock-output-names: Name of the clock output.
- vdd-cpu-supply: Regulator for the CPU voltage rail that the DFLL
hardware will start controlling. The regulator will be queried for
the I2C register, control values and supported voltages.
Required properties for the control loop parameters:
- nvidia,sample-rate: Sample rate of the DFLL control loop.
- nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM.
- nvidia,force-mode: See the field DFLL_PARAMS_FORCE_MODE in the TRM.
- nvidia,cf: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM.
- nvidia,ci: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM.
- nvidia,cg: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM.
Optional properties for the control loop parameters:
- nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM.
Optional properties for mode selection:
- nvidia,pwm-to-pmic: Use PWM to control regulator rather then I2C.
Required properties for I2C mode:
- nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode.
Required properties for PWM mode:
- nvidia,pwm-period-nanoseconds: period of PWM square wave in nanoseconds.
- nvidia,pwm-tristate-microvolts: Regulator voltage in micro volts when PWM
control is disabled and the PWM output is tristated. Note that this voltage is
configured in hardware, typically via a resistor divider.
- nvidia,pwm-min-microvolts: Regulator voltage in micro volts when PWM control
is enabled and PWM output is low. Hence, this is the minimum output voltage
that the regulator supports when PWM control is enabled.
- nvidia,pwm-voltage-step-microvolts: Voltage increase in micro volts
corresponding to a 1/33th increase in duty cycle. Eg the voltage for 2/33th
duty cycle would be: nvidia,pwm-min-microvolts +
nvidia,pwm-voltage-step-microvolts * 2.
- pinctrl-0: I/O pad configuration when PWM control is enabled.
- pinctrl-1: I/O pad configuration when PWM control is disabled.
- pinctrl-names: must include the following entries:
- dvfs_pwm_enable: I/O pad configuration when PWM control is enabled.
- dvfs_pwm_disable: I/O pad configuration when PWM control is disabled.
Example for I2C:
clock@70110000 {
compatible = "nvidia,tegra124-dfll";
reg = <0 0x70110000 0 0x100>, /* DFLL control */
<0 0x70110000 0 0x100>, /* I2C output control */
<0 0x70110100 0 0x100>, /* Integrated I2C controller */
<0 0x70110200 0 0x100>; /* Look-up table RAM */
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>,
<&tegra_car TEGRA124_CLK_DFLL_REF>,
<&tegra_car TEGRA124_CLK_I2C5>;
clock-names = "soc", "ref", "i2c";
resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
reset-names = "dvco";
#clock-cells = <0>;
clock-output-names = "dfllCPU_out";
vdd-cpu-supply = <&vdd_cpu>;
nvidia,sample-rate = <12500>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,cf = <10>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,i2c-fs-rate = <400000>;
};
Example for PWM:
clock@70110000 {
compatible = "nvidia,tegra124-dfll";
reg = <0 0x70110000 0 0x100>, /* DFLL control */
<0 0x70110000 0 0x100>, /* I2C output control */
<0 0x70110100 0 0x100>, /* Integrated I2C controller */
<0 0x70110200 0 0x100>; /* Look-up table RAM */
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA210_CLK_DFLL_SOC>,
<&tegra_car TEGRA210_CLK_DFLL_REF>,
<&tegra_car TEGRA124_CLK_I2C5>;;
clock-names = "soc", "ref", "i2c";
resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
reset-names = "dvco";
#clock-cells = <0>;
clock-output-names = "dfllCPU_out";
nvidia,sample-rate = <25000>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,cf = <6>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,pwm-min-microvolts = <708000>; /* 708mV */
nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */
nvidia,pwm-to-pmic;
nvidia,pwm-tristate-microvolts = <1000000>;
nvidia,pwm-voltage-step-microvolts = <19200>; /* 19.2mV */
pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
pinctrl-0 = <&dvfs_pwm_active_state>;
pinctrl-1 = <&dvfs_pwm_inactive_state>;
};
/* pinmux nodes added for completeness. Binding doc can be found in:
* Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml
*/
pinmux: pinmux@700008d4 {
dvfs_pwm_active_state: dvfs_pwm_active {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
};
dvfs_pwm_inactive_state: dvfs_pwm_inactive {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_ENABLE>;
};
};
};

View File

@@ -0,0 +1,290 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/nvidia,tegra124-dfll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra124 (and later) DFLL FCPU clocksource
maintainers:
- Thierry Reding <thierry.reding@gmail.com>
- Jon Hunter <jonathanh@nvidia.com>
description:
The DFLL IP block on Tegra is a root clocksource designed for clocking
the fast CPU cluster. It consists of a free-running voltage controlled
oscillator connected to the CPU voltage rail (VDD_CPU), and a closed
loop control module that will automatically adjust the VDD_CPU voltage
by communicating with an off-chip PMIC either via an I2C bus or via
PWM signals.
properties:
compatible:
enum:
- nvidia,tegra124-dfll
- nvidia,tegra210-dfll
reg:
items:
- description: DFLL control logic
- description: I2C output logic
- description: Integrated I2C controller
- description: Look-up table RAM for voltage register values
interrupts:
maxItems: 1
"#clock-cells":
const: 0
clocks:
items:
- description: Clock source for the DFLL control logic
- description: Closed loop reference clock
- description: Clock source for the integrated I2C controller
clock-names:
items:
- const: soc
- const: ref
- const: i2c
clock-output-names:
description: Name of the clock output
items:
- const: dfllCPU_out
resets:
minItems: 1
maxItems: 2
reset-names:
minItems: 1
items:
- const: dvco
- const: dfll
vdd-cpu-supply:
description: Regulator for the CPU voltage rail that the DFLL
hardware will start controlling. The regulator will be queried for
the I2C register, control values and supported voltages.
nvidia,sample-rate:
description: Sample rate of the DFLL control loop
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 12500
maximum: 25000
nvidia,droop-ctrl:
description: Droop control parameter (CL_DVFS_DROOP_CTRL) in the TRM
$ref: /schemas/types.yaml#/definitions/uint32
nvidia,force-mode:
description: See the field DFLL_PARAMS_FORCE_MODE in the TRM
$ref: /schemas/types.yaml#/definitions/uint32
oneOf:
- description: disabled
const: 0
- description: fixed delay mode
const: 1
- description: auto mode
const: 2
nvidia,cf:
description: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 63
nvidia,ci:
description: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
nvidia,cg:
description: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 255
# optional properties
nvidia,cg-scale:
description: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM
$ref: /schemas/types.yaml#/definitions/flag
nvidia,pwm-to-pmic:
description: Use PWM to control regulator rather than I2C
$ref: /schemas/types.yaml#/definitions/flag
nvidia,i2c-fs-rate:
description: I2C transfer rate, if using full speed mode
$ref: /schemas/types.yaml#/definitions/uint32
enum: [100000, 400000]
# required properties for PWM mode
nvidia,pwm-period-nanoseconds:
description: Period of PWM square wave in nanoseconds
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1000
maximum: 1000000000
nvidia,pwm-tristate-microvolts:
description: Regulator voltage in microvolts when PWM control is disabled
and the PWM output is tristated. Note that this voltage is configured in
hardware, typically via a resistor divider.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 3300000
nvidia,pwm-min-microvolts:
description: Regulator voltage in microvolts when PWM control is enabled
and PWM output is low. Hence, this is the minimum output voltage that
the regulator supports when PWM control is enabled.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 3300000
nvidia,pwm-voltage-step-microvolts:
description: |
Voltage increase in micro volts corresponding to a 1/33th increase
in duty cycle. For example, the voltage for 2/33th duty cycle would be:
nvidia,pwm-min-microvolts + nvidia,pwm-voltage-step-microvolts * 2
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 100000
pinctrl-0:
description: I/O pad configuration when PWM control is enabled
pinctrl-1:
description: I/O pad configuration when PWM control is disabled
pinctrl-names:
items:
- const: dvfs_pwm_enable
- const: dvfs_pwm_disable
required:
- compatible
- reg
- interrupts
- "#clock-cells"
- clocks
- clock-names
- clock-output-names
- resets
- reset-names
- nvidia,sample-rate
- nvidia,droop-ctrl
- nvidia,force-mode
- nvidia,cf
- nvidia,ci
- nvidia,cg
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
const: nvidia,tegra124-dfll
then:
properties:
resets:
maxItems: 1
reset-names:
maxItems: 1
else:
properties:
resets:
minItems: 2
reset-names:
minItems: 2
- if:
required:
- nvidia,pwm-to-pmic
then:
required:
- nvidia,pwm-min-microvolts
- nvidia,pwm-period-nanoseconds
- nvidia,pwm-tristate-microvolts
- nvidia,pwm-voltage-step-microvolts
else:
required:
- vdd-cpu-supply
examples:
- |
#include <dt-bindings/clock/tegra124-car.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/tegra124-car.h>
clock@70110000 {
compatible = "nvidia,tegra124-dfll";
reg = <0x70110000 0x100>, /* DFLL control */
<0x70110000 0x100>, /* I2C output control */
<0x70110100 0x100>, /* Integrated I2C controller */
<0x70110200 0x100>; /* Look-up table RAM */
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>,
<&tegra_car TEGRA124_CLK_DFLL_REF>,
<&tegra_car TEGRA124_CLK_I2C5>;
clock-names = "soc", "ref", "i2c";
resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
reset-names = "dvco";
#clock-cells = <0>;
clock-output-names = "dfllCPU_out";
vdd-cpu-supply = <&vdd_cpu>;
nvidia,sample-rate = <12500>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,cf = <10>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,i2c-fs-rate = <400000>;
};
- |
#include <dt-bindings/clock/tegra210-car.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/tegra210-car.h>
clock@70110000 {
compatible = "nvidia,tegra210-dfll";
reg = <0x70110000 0x100>, /* DFLL control */
<0x70110000 0x100>, /* I2C output control */
<0x70110100 0x100>, /* Integrated I2C controller */
<0x70110200 0x100>; /* Look-up table RAM */
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA210_CLK_DFLL_SOC>,
<&tegra_car TEGRA210_CLK_DFLL_REF>,
<&tegra_car TEGRA210_CLK_I2C5>;
clock-names = "soc", "ref", "i2c";
resets = <&tegra_car TEGRA210_RST_DFLL_DVCO>,
<&tegra_car 155>;
reset-names = "dvco", "dfll";
#clock-cells = <0>;
clock-output-names = "dfllCPU_out";
vdd-cpu-supply = <&vdd_cpu>;
nvidia,sample-rate = <25000>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,cf = <6>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,pwm-min-microvolts = <708000>; /* 708mV */
nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */
nvidia,pwm-to-pmic;
nvidia,pwm-tristate-microvolts = <1000000>;
nvidia,pwm-voltage-step-microvolts = <19200>; /* 19.2mV */
};

View File

@@ -82,6 +82,10 @@ properties:
description: phandle of a display panel
$ref: /schemas/types.yaml#/definitions/phandle
port:
description: HDMI output port for connection to HDMI connector or bridge
$ref: /schemas/graph.yaml#/properties/port
"#sound-dai-cells":
const: 0
@@ -97,8 +101,13 @@ required:
- reset-names
- pll-supply
- vdd-supply
anyOf:
- required:
- nvidia,ddc-i2c-bus
- nvidia,hpd-gpio
- required:
- port
examples:
- |

View File

@@ -146,6 +146,13 @@ properties:
this platform. If set, the value should be non-zero.
minimum: 1
arm,no-completion-irq:
type: boolean
description:
This optional property is intended for hardware that does not generate
completion interrupts and can be used to unconditionally enable forced
polling mode of operation.
arm,smc-id:
$ref: /schemas/types.yaml#/definitions/uint32
description:
@@ -379,6 +386,9 @@ then:
- shmem
else:
properties:
arm,no-completion-irq: false
if:
properties:
compatible:

View File

@@ -37,6 +37,7 @@ properties:
maxItems: 1
pmic:
deprecated: true
description: Child node describing the main PMIC.
type: object
additionalProperties: true
@@ -45,6 +46,24 @@ properties:
compatible:
const: samsung,s2mpg10-pmic
pmic-1:
description: Child node describing the main PMIC.
type: object
additionalProperties: true
properties:
compatible:
const: samsung,s2mpg10-pmic
pmic-2:
description: Child node describing the sub PMIC.
type: object
additionalProperties: true
properties:
compatible:
const: samsung,s2mpg11-pmic
shmem:
description:
List of phandle pointing to the shared memory (SHM) area. The memory
@@ -62,7 +81,9 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/regulator/samsung,s2mpg10-regulator.h>
power-management {
compatible = "google,gs101-acpm-ipc";
@@ -70,10 +91,12 @@ examples:
mboxes = <&ap2apm_mailbox>;
shmem = <&apm_sram>;
pmic {
pmic-1 {
compatible = "samsung,s2mpg10-pmic";
interrupts-extended = <&gpa0 6 IRQ_TYPE_LEVEL_LOW>;
vinl3m-supply = <&buck8m>;
regulators {
ldo1m {
regulator-name = "vdd_ldo1";
@@ -82,7 +105,13 @@ examples:
regulator-always-on;
};
// ...
ldo20m {
regulator-name = "vdd_dmics";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
samsung,ext-control = <S2MPG10_EXTCTRL_LDO20M_EN2>;
};
buck8m {
regulator-name = "vdd_mif";
@@ -93,4 +122,21 @@ examples:
};
};
};
pmic-2 {
compatible = "samsung,s2mpg11-pmic";
interrupts-extended = <&gpa0 7 IRQ_TYPE_LEVEL_LOW>;
vinl1s-supply = <&buck8m>;
vinl2s-supply = <&buck6s>;
regulators {
buckd {
regulator-name = "vcc_ufs";
regulator-ramp-delay = <6250>;
enable-gpios = <&gpp0 1 GPIO_ACTIVE_HIGH>;
samsung,ext-control = <S2MPG11_EXTCTRL_UFS_EN>;
};
};
};
};

View File

@@ -23,15 +23,18 @@ properties:
- enum:
- qcom,scm-apq8064
- qcom,scm-apq8084
- qcom,scm-eliza
- qcom,scm-glymur
- qcom,scm-ipq4019
- qcom,scm-ipq5018
- qcom,scm-ipq5210
- qcom,scm-ipq5332
- qcom,scm-ipq5424
- qcom,scm-ipq6018
- qcom,scm-ipq806x
- qcom,scm-ipq8074
- qcom,scm-ipq9574
- qcom,scm-ipq9650
- qcom,scm-kaanapali
- qcom,scm-mdm9607
- qcom,scm-milos
@@ -204,6 +207,7 @@ allOf:
compatible:
contains:
enum:
- qcom,scm-eliza
- qcom,scm-kaanapali
- qcom,scm-milos
- qcom,scm-sm8450

View File

@@ -12,7 +12,9 @@ maintainers:
properties:
compatible:
oneOf:
- const: fsl,imx-irqsteer
- enum:
- fsl,imx-irqsteer
- nxp,s32n79-irqsteer
- items:
- enum:
- fsl,imx8m-irqsteer

View File

@@ -35,11 +35,12 @@ properties:
- enum:
- nvidia,tegra20-ictlr
- nvidia,tegra30-ictlr
- nvidia,tegra210-ictlr
reg:
description: Each entry is a block of 32 interrupts
minItems: 4
maxItems: 5
maxItems: 6
interrupt-controller: true
@@ -64,10 +65,28 @@ allOf:
properties:
reg:
maxItems: 4
else:
- if:
properties:
compatible:
contains:
const: nvidia,tegra30-ictlr
then:
properties:
reg:
minItems: 5
maxItems: 5
- if:
properties:
compatible:
contains:
const: nvidia,tegra210-ictlr
then:
properties:
reg:
minItems: 6
maxItems: 6
examples:
- |

View File

@@ -52,6 +52,9 @@ properties:
Should contain freqs and voltages and opp-supported-hw property, which
is a bitfield indicating SoC speedo ID mask.
allOf:
- $ref: /schemas/thermal/thermal-cooling-devices.yaml
required:
- compatible
- reg
@@ -59,7 +62,7 @@ required:
- clock-names
- nvidia,memory-controller
additionalProperties: false
unevaluatedProperties: false
examples:
- |
@@ -90,4 +93,5 @@ examples:
operating-points-v2 = <&dvfs_opp_table>;
#interconnect-cells = <0>;
#cooling-cells = <2>;
};

View File

@@ -0,0 +1,77 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-mc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra210 SoC Memory Controller
maintainers:
- Thierry Reding <thierry.reding@gmail.com>
- Jon Hunter <jonathanh@nvidia.com>
description: |
The NVIDIA Tegra210 SoC features a 64 bit memory controller that is split
into two 32 bit channels to support LPDDR3 and LPDDR4 with x16 subpartitions.
The MC handles memory requests for 34-bit virtual addresses from internal
clients and arbitrates among them to allocate memory bandwidth.
Up to 8 GiB of physical memory can be supported. Security features such as
encryption of traffic to and from DRAM via general security apertures are
available for video and other secure applications.
properties:
$nodename:
pattern: "^memory-controller@[0-9a-f]+$"
compatible:
items:
- enum:
- nvidia,tegra210-mc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: module clock
clock-names:
items:
- const: mc
"#iommu-cells":
const: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- "#iommu-cells"
- "#reset-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/tegra210-car.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
memory-controller@70019000 {
compatible = "nvidia,tegra210-mc";
reg = <0x70019000 0x1000>;
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA210_CLK_MC>;
clock-names = "mc";
#iommu-cells = <1>;
#reset-cells = <1>;
};

View File

@@ -230,6 +230,10 @@ properties:
connector:
type: object
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
mode:
description: A string that determines the mode in which to
run the port.
@@ -256,7 +260,12 @@ properties:
voltage.
dependencies:
usb-role-switch: [ connector ]
usb-role-switch:
oneOf:
- required:
- connector
- required:
- port
usb2-1:
type: object
@@ -268,6 +277,10 @@ properties:
connector:
type: object
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
mode:
description: A string that determines the mode in which to
run the port.
@@ -306,6 +319,10 @@ properties:
connector:
type: object
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
mode:
description: A string that determines the mode in which to
run the port.
@@ -344,6 +361,10 @@ properties:
connector:
type: object
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
mode:
description: A string that determines the mode in which to
run the port.
@@ -405,6 +426,10 @@ properties:
description: A phandle to the regulator supplying the VBUS
voltage.
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
usb3-1:
type: object
additionalProperties: false
@@ -438,6 +463,10 @@ properties:
description: A phandle to the regulator supplying the VBUS
voltage.
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
usb3-2:
type: object
additionalProperties: false
@@ -471,6 +500,10 @@ properties:
description: A phandle to the regulator supplying the VBUS
voltage.
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
usb3-3:
type: object
additionalProperties: false
@@ -504,6 +537,10 @@ properties:
description: A phandle to the regulator supplying the VBUS
voltage.
port:
description: connection to a USB Type C controller
$ref: /schemas/graph.yaml#/properties/port
additionalProperties: false
required:

View File

@@ -16,6 +16,7 @@ properties:
oneOf:
- items:
- enum:
- nvidia,tegra210-usb-phy
- nvidia,tegra124-usb-phy
- nvidia,tegra114-usb-phy
- enum:

View File

@@ -27,6 +27,12 @@ properties:
clocks:
maxItems: 1
access-controllers:
minItems: 1
items:
- description: debug configuration access controller
- description: access controller that manages the HDP as a peripheral
patternProperties:
"^hdp[0-7]-pins$":
type: object

View File

@@ -17,7 +17,9 @@ properties:
compatible:
oneOf:
- items:
- const: renesas,r9a09g056-usb2phy-reset # RZ/V2N
- enum:
- renesas,r9a09g047-usb2phy-reset # RZ/G3E
- renesas,r9a09g056-usb2phy-reset # RZ/V2N
- const: renesas,r9a09g057-usb2phy-reset
- const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
@@ -37,6 +39,9 @@ properties:
'#reset-cells':
const: 0
'#mux-state-cells':
const: 1
required:
- compatible
- reg
@@ -44,6 +49,7 @@ required:
- resets
- power-domains
- '#reset-cells'
- '#mux-state-cells'
additionalProperties: false
@@ -58,4 +64,5 @@ examples:
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
};

View File

@@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/cix/cix,sky1-system-control.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cix Sky1 SoC system control register region
maintainers:
- Gary Yang <gary.yang@cixtech.com>
description:
An wide assortment of registers of the system controller on Sky1 SoC,
including resets, usb, wakeup sources and so on.
properties:
compatible:
items:
- enum:
- cix,sky1-system-control
- cix,sky1-s5-system-control
- const: syscon
reg:
maxItems: 1
'#reset-cells':
const: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
syscon@4160000 {
compatible = "cix,sky1-system-control", "syscon";
reg = <0x4160000 0x100>;
#reset-cells = <1>;
};

View File

@@ -40,6 +40,58 @@ properties:
minItems: 8
maxItems: 10
dpi-bridge:
type: object
additionalProperties: false
properties:
compatible:
enum:
- nxp,imx91-pdfc
- nxp,imx93-pdfc
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: Input port node to receive pixel data.
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: Output port node to downstream pixel data receivers.
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
bus-width:
enum: [ 16, 18, 24 ]
description:
Specify the physical parallel bus width.
This property is optional if the display bus-width
matches the SoC bus-width, e.g. a 18-bit RGB666 (display)
is connected and all 18-bit data lines are muxed to the
parallel-output pads.
This property must be set to 18 to cut only the LSBs
instead of the MSBs in case a 24-bit RGB888 display is
connected and only the lower 18-bit data lanes are muxed
to the parallel-output pads.
required:
- port@0
- port@1
required:
- compatible
- ports
allOf:
- if:
properties:
@@ -112,4 +164,30 @@ examples:
clock-names = "apb", "axi", "nic", "disp", "cam",
"pxp", "lcdif", "isi", "csi", "dsi";
#power-domain-cells = <1>;
dpi-bridge {
compatible = "nxp,imx93-pdfc";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
pdfc_from_lcdif: endpoint {
remote-endpoint = <&lcdif_to_pdfc>;
};
};
port@1 {
reg = <1>;
pdfc_to_panel: endpoint {
remote-endpoint = <&panel_from_pdfc>;
bus-width = <18>;
};
};
};
};
};

View File

@@ -0,0 +1,103 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/microchip/microchip,mpfs-irqmux.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip Polarfire SoC GPIO Interrupt Mux
maintainers:
- Conor Dooley <conor.dooley@microchip.com>
description: |
There are 3 GPIO controllers on this SoC, of which:
- GPIO controller 0 has 14 GPIOs
- GPIO controller 1 has 24 GPIOs
- GPIO controller 2 has 32 GPIOs
All GPIOs are capable of generating interrupts, for a total of 70.
There are only 41 IRQs available however, so a configurable mux is used to
ensure all GPIOs can be used for interrupt generation.
38 of the 41 interrupts are in what the documentation calls "direct mode",
as they provide an exclusive connection from a GPIO to the PLIC.
Lines 18 to 23 on GPIO controller 1 are always in "direct mode".
The 3 remaining interrupts are used to mux the interrupts which do not have
a exclusive connection, one for each GPIO controller.
properties:
compatible:
const: microchip,mpfs-irqmux
reg:
maxItems: 1
"#address-cells":
const: 0
"#interrupt-cells":
const: 1
interrupt-map-mask:
items:
- const: 0x7f
interrupt-map:
description: |
Specifies the mapping from GPIO interrupt lines to plic interrupts.
The child interrupt number set in arrays items is computed using the
following formula:
gpio_bank * 32 + gpio_number
with:
- gpio_bank: The GPIO bank number
- 0 for GPIO0,
- 1 for GPIO1,
- 2 for GPIO2
- gpio_number: Number of the gpio in the bank (0..31)
maxItems: 70
required:
- compatible
- reg
- "#address-cells"
- "#interrupt-cells"
- interrupt-map-mask
- interrupt-map
additionalProperties: false
examples:
- |
interrupt-controller@54 {
compatible = "microchip,mpfs-irqmux";
reg = <0x54 0x4>;
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map-mask = <0x7f>;
interrupt-map = <0 &plic 13>, <1 &plic 14>, <2 &plic 15>,
<3 &plic 16>, <4 &plic 17>, <5 &plic 18>,
<6 &plic 19>, <7 &plic 20>, <8 &plic 21>,
<9 &plic 22>, <10 &plic 23>, <11 &plic 24>,
<12 &plic 25>, <13 &plic 26>,
<32 &plic 27>, <33 &plic 28>, <34 &plic 29>,
<35 &plic 30>, <36 &plic 31>, <37 &plic 32>,
<38 &plic 33>, <39 &plic 34>, <40 &plic 35>,
<41 &plic 36>, <42 &plic 37>, <43 &plic 38>,
<44 &plic 39>, <45 &plic 40>, <46 &plic 41>,
<47 &plic 42>, <48 &plic 43>, <49 &plic 44>,
<50 &plic 45>, <51 &plic 46>, <52 &plic 47>,
<53 &plic 48>, <54 &plic 49>, <55 &plic 50>,
<64 &plic 53>, <65 &plic 53>, <66 &plic 53>,
<67 &plic 53>, <68 &plic 53>, <69 &plic 53>,
<70 &plic 53>, <71 &plic 53>, <72 &plic 53>,
<73 &plic 53>, <74 &plic 53>, <75 &plic 53>,
<76 &plic 53>, <77 &plic 53>, <78 &plic 53>,
<79 &plic 53>, <80 &plic 53>, <81 &plic 53>,
<82 &plic 53>, <83 &plic 53>, <84 &plic 53>,
<85 &plic 53>, <86 &plic 53>, <87 &plic 53>,
<88 &plic 53>, <89 &plic 53>, <90 &plic 53>,
<91 &plic 53>, <92 &plic 53>, <93 &plic 53>,
<94 &plic 53>, <95 &plic 53>;
};

View File

@@ -15,7 +15,13 @@ description:
properties:
compatible:
items:
oneOf:
- items:
- const: microchip,mpfs-mss-top-sysreg
- const: syscon
- const: simple-mfd
- items:
- const: microchip,pic64gx-mss-top-sysreg
- const: microchip,mpfs-mss-top-sysreg
- const: syscon
- const: simple-mfd
@@ -38,6 +44,10 @@ properties:
of PolarFire clock/reset IDs.
const: 1
interrupt-controller@54:
type: object
$ref: /schemas/soc/microchip/microchip,mpfs-irqmux.yaml
pinctrl@200:
type: object
$ref: /schemas/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml

View File

@@ -24,7 +24,9 @@ properties:
maxItems: 1
compatible:
const: microchip,mpfs-sys-controller
enum:
- microchip,mpfs-sys-controller
- microchip,pic64gx-sys-controller
microchip,bitstream-flash:
$ref: /schemas/types.yaml#/definitions/phandle

View File

@@ -23,6 +23,8 @@ properties:
oneOf:
- items:
- enum:
- qcom,glymur-pmic-glink
- qcom,kaanapali-pmic-glink
- qcom,qcm6490-pmic-glink
- qcom,sc8180x-pmic-glink
- qcom,sc8280xp-pmic-glink

View File

@@ -24,6 +24,7 @@ properties:
- renesas,r9a07g044-sysc # RZ/G2{L,LC}
- renesas,r9a07g054-sysc # RZ/V2L
- renesas,r9a08g045-sysc # RZ/G3S
- renesas,r9a08g046-sysc # RZ/G3L
reg:
maxItems: 1

View File

@@ -548,6 +548,19 @@ properties:
- const: renesas,r9a08g045s33 # PCIe support
- const: renesas,r9a08g045
- description: RZ/G3L (R9A08G046)
items:
- enum:
- renesas,smarc2-evk # RZ SMARC Carrier-II EVK
- enum:
- renesas,rzg3l-smarcm # RZ/G3L SMARC Module (SoM)
- enum:
- renesas,r9a08g046l26 # Dual Cortex-A55 + Cortex-M33 + GE3D/VCP (14mm LFBGA)
- renesas,r9a08g046l28 # Dual Cortex-A55 + Cortex-M33 + GE3D/VCP (17mm LFBGA)
- renesas,r9a08g046l46 # Quad Cortex-A55 + Cortex-M33 + GE3D/VCP (14mm LFBGA)
- renesas,r9a08g046l48 # Quad Cortex-A55 + Cortex-M33 + GE3D/VCP (17mm LFBGA)
- const: renesas,r9a08g046
- description: RZ/V2M (R9A09G011)
items:
- enum:

View File

@@ -198,7 +198,6 @@ query the reset line status using reset_control_status().
reset_control_rearm
reset_control_put
of_reset_control_get_count
of_reset_control_array_get
devm_reset_control_array_get
reset_control_get_count

View File

@@ -2803,8 +2803,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/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/arm/boot/dts/nxp/
F: arch/arm64/boot/dts/freescale/
X: Documentation/devicetree/bindings/media/i2c/
X: arch/arm64/boot/dts/freescale/fsl-*
@@ -8678,7 +8677,7 @@ F: drivers/phy/mediatek/phy-mtk-hdmi*
F: drivers/phy/mediatek/phy-mtk-mipi*
DRM DRIVERS FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
M: Mikko Perttunen <mperttunen@nvidia.com>
L: dri-devel@lists.freedesktop.org
L: linux-tegra@vger.kernel.org
@@ -20382,7 +20381,7 @@ S: Maintained
F: drivers/pci/controller/*mvebu*
PCI DRIVER FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
L: linux-tegra@vger.kernel.org
L: linux-pci@vger.kernel.org
S: Supported
@@ -22902,7 +22901,7 @@ F: Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-mssio.yaml
F: Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml
F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
F: Documentation/devicetree/bindings/riscv/microchip.yaml
F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml
F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs*.yaml
F: Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
F: Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
F: arch/riscv/boot/dts/microchip/
@@ -25210,6 +25209,7 @@ F: drivers/hwmon/pmbus/stef48h28.c
ST STM32 FIREWALL
M: Gatien Chevallier <gatien.chevallier@foss.st.com>
S: Maintained
F: drivers/bus/stm32_dbg_bus.c
F: drivers/bus/stm32_etzpc.c
F: drivers/bus/stm32_firewall.c
F: drivers/bus/stm32_rifsc.c
@@ -26144,7 +26144,7 @@ F: include/linux/tee_drv.h
F: include/uapi/linux/tee.h
TEGRA ARCHITECTURE SUPPORT
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
M: Jonathan Hunter <jonathanh@nvidia.com>
L: linux-tegra@vger.kernel.org
S: Supported
@@ -26176,7 +26176,7 @@ S: Supported
F: drivers/i2c/busses/i2c-tegra.c
TEGRA IOMMU DRIVERS
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
R: Krishna Reddy <vdumpa@nvidia.com>
L: linux-tegra@vger.kernel.org
S: Supported
@@ -26197,12 +26197,12 @@ F: Documentation/devicetree/bindings/mtd/nvidia,tegra20-nand.yaml
F: drivers/mtd/nand/raw/tegra_nand.c
TEGRA PWM DRIVER
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
S: Supported
F: drivers/pwm/pwm-tegra.c
TEGRA QUAD SPI DRIVER
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
M: Jonathan Hunter <jonathanh@nvidia.com>
M: Sowjanya Komatineni <skomatineni@nvidia.com>
L: linux-tegra@vger.kernel.org
@@ -26220,7 +26220,7 @@ S: Supported
F: drivers/spi/spi-tegra*
TEGRA VIDEO DRIVER
M: Thierry Reding <thierry.reding@gmail.com>
M: Thierry Reding <thierry.reding@kernel.org>
M: Jonathan Hunter <jonathanh@nvidia.com>
M: Sowjanya Komatineni <skomatineni@nvidia.com>
M: Luca Ceresoli <luca.ceresoli@bootlin.com>

View File

@@ -169,6 +169,16 @@ config QCOM_SSC_BLOCK_BUS
i2c/spi/uart controllers, a hexagon core, and a clock controller
which provides clocks for the above.
config STM32_DBG_BUS
tristate "OP-TEE based debug access bus"
depends on OPTEE && STM32_FIREWALL
depends on ARCH_STM32 || COMPILE_TEST
help
Select this to get the support for the OP-TEE based STM32 debug bus
driver that is used to handle debug-related peripherals on STM32
platforms when the debug configuration is not accessible by the
normal world.
config STM32_FIREWALL
bool "STM32 Firewall framework"
depends on (ARCH_STM32 || COMPILE_TEST) && OF

View File

@@ -27,6 +27,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
obj-$(CONFIG_QCOM_SSC_BLOCK_BUS) += qcom-ssc-block-bus.o
obj-$(CONFIG_STM32_DBG_BUS) += stm32_dbg_bus.o
obj-$(CONFIG_STM32_FIREWALL) += stm32_firewall.o stm32_rifsc.o stm32_etzpc.o
obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o

View File

@@ -11,9 +11,19 @@
#include <linux/regmap.h>
#define IMX_AIPSTZ_MPR0 0x0
#define IMX_AIPSTZ_OPACR0 0x40
#define IMX_AIPSTZ_OPACR1 0x44
#define IMX_AIPSTZ_OPACR2 0x48
#define IMX_AIPSTZ_OPACR3 0x4c
#define IMX_AIPSTZ_OPACR4 0x50
struct imx_aipstz_config {
u32 mpr0;
u32 opacr0;
u32 opacr1;
u32 opacr2;
u32 opacr3;
u32 opacr4;
};
struct imx_aipstz_data {
@@ -24,6 +34,11 @@ struct imx_aipstz_data {
static void imx_aipstz_apply_default(struct imx_aipstz_data *data)
{
writel(data->default_cfg->mpr0, data->base + IMX_AIPSTZ_MPR0);
writel(data->default_cfg->opacr0, data->base + IMX_AIPSTZ_OPACR0);
writel(data->default_cfg->opacr1, data->base + IMX_AIPSTZ_OPACR1);
writel(data->default_cfg->opacr2, data->base + IMX_AIPSTZ_OPACR2);
writel(data->default_cfg->opacr3, data->base + IMX_AIPSTZ_OPACR3);
writel(data->default_cfg->opacr4, data->base + IMX_AIPSTZ_OPACR4);
}
static const struct of_device_id imx_aipstz_match_table[] = {

250
drivers/bus/stm32_dbg_bus.c Normal file
View File

@@ -0,0 +1,250 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2026, STMicroelectronics - All Rights Reserved
*/
#include <linux/bus/stm32_firewall.h>
#include <linux/bus/stm32_firewall_device.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
#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/tee_drv.h>
#include <linux/types.h>
enum stm32_dbg_profile {
PERIPHERAL_DBG_PROFILE = 0,
HDP_DBG_PROFILE = 1,
};
enum stm32_dbg_pta_command {
/*
* PTA_CMD_GRANT_DBG_ACCESS - Verify the debug configuration against the given debug profile
* and grant access or not
*
* [in] value[0].a Debug profile to grant access to.
*/
PTA_CMD_GRANT_DBG_ACCESS,
};
/**
* struct stm32_dbg_bus - OP-TEE based STM32 debug bus private data
* @dev: STM32 debug bus device.
* @ctx: OP-TEE context handler.
*/
struct stm32_dbg_bus {
struct device *dev;
struct tee_context *ctx;
};
/* Expect at most 1 instance of this driver */
static struct stm32_dbg_bus *stm32_dbg_bus_priv;
static int stm32_dbg_pta_open_session(u32 *id)
{
struct tee_client_device *dbg_bus_dev = to_tee_client_device(stm32_dbg_bus_priv->dev);
struct tee_ioctl_open_session_arg sess_arg;
int ret;
memset(&sess_arg, 0, sizeof(sess_arg));
export_uuid(sess_arg.uuid, &dbg_bus_dev->id.uuid);
sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
ret = tee_client_open_session(stm32_dbg_bus_priv->ctx, &sess_arg, NULL);
if (ret < 0 || sess_arg.ret) {
dev_err(stm32_dbg_bus_priv->dev, "Failed opening tee session, err: %#x\n",
sess_arg.ret);
return -EOPNOTSUPP;
}
*id = sess_arg.session;
return 0;
}
static void stm32_dbg_pta_close_session(u32 id)
{
tee_client_close_session(stm32_dbg_bus_priv->ctx, id);
}
static int stm32_dbg_bus_grant_access(struct stm32_firewall_controller *ctrl, u32 dbg_profile)
{
struct tee_ioctl_invoke_arg inv_arg = {0};
struct tee_param param[1] = {0};
u32 session_id;
int ret;
if (dbg_profile != PERIPHERAL_DBG_PROFILE && dbg_profile != HDP_DBG_PROFILE)
return -EOPNOTSUPP;
ret = stm32_dbg_pta_open_session(&session_id);
if (ret)
return ret;
inv_arg.func = PTA_CMD_GRANT_DBG_ACCESS;
inv_arg.session = session_id;
inv_arg.num_params = 1;
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
param[0].u.value.a = dbg_profile;
ret = tee_client_invoke_func(stm32_dbg_bus_priv->ctx, &inv_arg, param);
if (ret < 0 || inv_arg.ret != 0) {
dev_dbg(stm32_dbg_bus_priv->dev,
"When invoking function, err %x, TEE returns: %x\n", ret, inv_arg.ret);
if (!ret)
ret = -EACCES;
}
stm32_dbg_pta_close_session(session_id);
return ret;
}
/* Implement mandatory release_access ops even if it does nothing*/
static void stm32_dbg_bus_release_access(struct stm32_firewall_controller *ctrl, u32 dbg_profile)
{
}
static int stm32_dbg_bus_plat_probe(struct platform_device *pdev)
{
struct stm32_firewall_controller *dbg_controller;
int ret;
/* Defer if OP-TEE service is not yet available */
if (!stm32_dbg_bus_priv)
return -EPROBE_DEFER;
dbg_controller = devm_kzalloc(&pdev->dev, sizeof(*dbg_controller), GFP_KERNEL);
if (!dbg_controller)
return dev_err_probe(&pdev->dev, -ENOMEM, "Couldn't allocate debug controller\n");
dbg_controller->dev = &pdev->dev;
dbg_controller->mmio = NULL;
dbg_controller->name = dev_driver_string(dbg_controller->dev);
dbg_controller->type = STM32_PERIPHERAL_FIREWALL;
dbg_controller->grant_access = stm32_dbg_bus_grant_access;
dbg_controller->release_access = stm32_dbg_bus_release_access;
ret = stm32_firewall_controller_register(dbg_controller);
if (ret) {
dev_err(dbg_controller->dev, "Couldn't register as a firewall controller: %d", ret);
return ret;
}
ret = stm32_firewall_populate_bus(dbg_controller);
if (ret) {
dev_err(dbg_controller->dev, "Couldn't populate debug bus: %d", ret);
stm32_firewall_controller_unregister(dbg_controller);
return ret;
}
pm_runtime_enable(&pdev->dev);
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
if (ret) {
dev_err(dbg_controller->dev, "Couldn't populate the node: %d", ret);
stm32_firewall_controller_unregister(dbg_controller);
return ret;
}
return 0;
}
static const struct of_device_id stm32_dbg_bus_of_match[] = {
{ .compatible = "st,stm32mp131-dbg-bus", },
{ .compatible = "st,stm32mp151-dbg-bus", },
{ },
};
MODULE_DEVICE_TABLE(of, stm32_dbg_bus_of_match);
static struct platform_driver stm32_dbg_bus_driver = {
.probe = stm32_dbg_bus_plat_probe,
.driver = {
.name = "stm32-dbg-bus",
.of_match_table = stm32_dbg_bus_of_match,
},
};
static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
return (ver->impl_id == TEE_IMPL_ID_OPTEE);
}
static void stm32_dbg_bus_remove(struct tee_client_device *tee_dev)
{
tee_client_close_context(stm32_dbg_bus_priv->ctx);
stm32_dbg_bus_priv = NULL;
of_platform_depopulate(&tee_dev->dev);
}
static int stm32_dbg_bus_probe(struct tee_client_device *tee_dev)
{
struct device *dev = &tee_dev->dev;
struct stm32_dbg_bus *priv;
int ret = 0;
if (stm32_dbg_bus_priv)
return dev_err_probe(dev, -EBUSY,
"A STM32 debug bus device is already initialized\n");
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* Open context with TEE driver */
priv->ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
if (IS_ERR_OR_NULL(priv->ctx))
return dev_err_probe(dev, PTR_ERR_OR_ZERO(priv->ctx), "Cannot open TEE context\n");
stm32_dbg_bus_priv = priv;
stm32_dbg_bus_priv->dev = dev;
return ret;
}
static const struct tee_client_device_id optee_dbg_bus_id_table[] = {
{UUID_INIT(0xdd05bc8b, 0x9f3b, 0x49f0,
0xb6, 0x49, 0x01, 0xaa, 0x10, 0xc1, 0xc2, 0x10)},
{}
};
static struct tee_client_driver stm32_optee_dbg_bus_driver = {
.id_table = optee_dbg_bus_id_table,
.probe = stm32_dbg_bus_probe,
.remove = stm32_dbg_bus_remove,
.driver = {
.name = "optee_dbg_bus",
},
};
static void __exit stm32_optee_dbg_bus_driver_exit(void)
{
platform_driver_unregister(&stm32_dbg_bus_driver);
tee_client_driver_unregister(&stm32_optee_dbg_bus_driver);
}
module_exit(stm32_optee_dbg_bus_driver_exit);
static int __init stm32_optee_dbg_bus_driver_init(void)
{
int err;
err = tee_client_driver_register(&stm32_optee_dbg_bus_driver);
if (err)
return err;
err = platform_driver_register(&stm32_dbg_bus_driver);
if (err)
tee_client_driver_unregister(&stm32_optee_dbg_bus_driver);
return err;
}
module_init(stm32_optee_dbg_bus_driver_init);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gatien Chevallier <gatien.chevallier@foss.st.com>");
MODULE_DESCRIPTION("OP-TEE based STM32 debug access bus driver");

View File

@@ -5,6 +5,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/bus/stm32_firewall.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -16,8 +17,6 @@
#include <linux/platform_device.h>
#include <linux/types.h>
#include "stm32_firewall.h"
/*
* ETZPC registers
*/

View File

@@ -5,6 +5,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/bus/stm32_firewall.h>
#include <linux/bus/stm32_firewall_device.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -18,8 +19,6 @@
#include <linux/types.h>
#include <linux/slab.h>
#include "stm32_firewall.h"
/* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
#define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
@@ -185,6 +184,48 @@ void stm32_firewall_release_access_by_id(struct stm32_firewall *firewall, u32 su
}
EXPORT_SYMBOL_GPL(stm32_firewall_release_access_by_id);
int stm32_firewall_get_grant_all_access(struct device *dev, struct stm32_firewall **firewall,
int *nb_firewall)
{
struct stm32_firewall *loc_firewall;
int err;
int i;
*nb_firewall = of_count_phandle_with_args(dev->of_node, "access-controllers",
"#access-controller-cells");
if (*nb_firewall < 0)
return *nb_firewall;
if (!*nb_firewall) {
*firewall = NULL;
return 0;
}
loc_firewall = devm_kcalloc(dev, *nb_firewall, sizeof(*loc_firewall), GFP_KERNEL);
if (!loc_firewall)
return -ENOMEM;
/* Get stm32 firewall information */
err = stm32_firewall_get_firewall(dev->of_node, loc_firewall, *nb_firewall);
if (err)
return err;
for (i = 0; i < *nb_firewall; i++) {
err = stm32_firewall_grant_access(&loc_firewall[i]);
if (err) {
while (i--)
stm32_firewall_release_access(&loc_firewall[i]);
return err;
}
}
*firewall = loc_firewall;
return 0;
}
EXPORT_SYMBOL_GPL(stm32_firewall_get_grant_all_access);
/* Firewall controller API */
int stm32_firewall_controller_register(struct stm32_firewall_controller *firewall_controller)
@@ -241,7 +282,6 @@ EXPORT_SYMBOL_GPL(stm32_firewall_controller_unregister);
int stm32_firewall_populate_bus(struct stm32_firewall_controller *firewall_controller)
{
struct stm32_firewall *firewalls;
struct device_node *child;
struct device *parent;
unsigned int i;
int len;
@@ -251,30 +291,25 @@ int stm32_firewall_populate_bus(struct stm32_firewall_controller *firewall_contr
dev_dbg(parent, "Populating %s system bus\n", dev_name(firewall_controller->dev));
for_each_available_child_of_node(dev_of_node(parent), child) {
for_each_available_child_of_node_scoped(dev_of_node(parent), child) {
/* The access-controllers property is mandatory for firewall bus devices */
len = of_count_phandle_with_args(child, "access-controllers",
"#access-controller-cells");
if (len <= 0) {
of_node_put(child);
if (len <= 0)
return -EINVAL;
}
firewalls = kzalloc_objs(*firewalls, len);
if (!firewalls) {
of_node_put(child);
if (!firewalls)
return -ENOMEM;
}
err = stm32_firewall_get_firewall(child, firewalls, (unsigned int)len);
if (err) {
kfree(firewalls);
of_node_put(child);
return err;
}
for (i = 0; i < len; i++) {
if (firewall_controller->grant_access(firewall_controller,
if (firewall_controller->grant_access(firewalls[i].firewall_ctrl,
firewalls[i].firewall_id)) {
/*
* Peripheral access not allowed or not defined.

View File

@@ -5,6 +5,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/bus/stm32_firewall.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -15,10 +16,9 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/types.h>
#include "stm32_firewall.h"
/*
* RIFSC offset register
*/
@@ -450,7 +450,7 @@ static void stm32_rifsc_fill_rimu_dbg_entry(struct rifsc_dbg_private *rifsc,
const struct stm32_rifsc_resources_names *dbg_names = rifsc->res_names;
u32 rimc_attr = readl_relaxed(rifsc->mmio + RIFSC_RIMC_ATTR0 + 0x4 * i);
snprintf(dbg_entry->m_name, sizeof(dbg_entry->m_name), "%s", dbg_names->initiator_names[i]);
strscpy(dbg_entry->m_name, dbg_names->initiator_names[i]);
dbg_entry->m_cid = FIELD_GET(RIFSC_RIMC_MCID_MASK, rimc_attr);
dbg_entry->cidsel = rimc_attr & RIFSC_RIMC_CIDSEL;
dbg_entry->m_sec = rimc_attr & RIFSC_RIMC_MSEC;
@@ -469,8 +469,7 @@ static void stm32_rifsc_fill_dev_dbg_entry(struct rifsc_dbg_private *rifsc,
sec_cfgr = readl_relaxed(rifsc->mmio + RIFSC_RISC_SECCFGR0 + 0x4 * reg_id);
priv_cfgr = readl_relaxed(rifsc->mmio + RIFSC_RISC_PRIVCFGR0 + 0x4 * reg_id);
snprintf(dbg_entry->dev_name, sizeof(dbg_entry->dev_name), "%s",
dbg_names->device_names[i]);
strscpy(dbg_entry->dev_name, dbg_names->device_names[i]);
dbg_entry->dev_id = i;
dbg_entry->dev_cid_filt_en = cid_cfgr & CIDCFGR_CFEN;
dbg_entry->dev_sem_en = cid_cfgr & CIDCFGR_SEMEN;
@@ -688,34 +687,6 @@ static int stm32_rifsc_grant_access(struct stm32_firewall_controller *ctrl, u32
sec_reg_value = readl(rifsc_controller->mmio + RIFSC_RISC_SECCFGR0 + 0x4 * reg_id);
cid_reg_value = readl(rifsc_controller->mmio + RIFSC_RISC_PER0_CIDCFGR + 0x8 * firewall_id);
/* First check conditions for semaphore mode, which doesn't take into account static CID. */
if ((cid_reg_value & CIDCFGR_SEMEN) && (cid_reg_value & CIDCFGR_CFEN)) {
if (cid_reg_value & BIT(RIF_CID1 + SEMWL_SHIFT)) {
/* Static CID is irrelevant if semaphore mode */
goto skip_cid_check;
} else {
dev_dbg(rifsc_controller->dev,
"Invalid bus semaphore configuration: index %d\n", firewall_id);
return -EACCES;
}
}
/*
* Skip CID check if CID filtering isn't enabled or filtering is enabled on CID0, which
* corresponds to whatever CID.
*/
if (!(cid_reg_value & CIDCFGR_CFEN) ||
FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) == RIF_CID0)
goto skip_cid_check;
/* Coherency check with the CID configuration */
if (FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) != RIF_CID1) {
dev_dbg(rifsc_controller->dev, "Invalid CID configuration for peripheral: %d\n",
firewall_id);
return -EACCES;
}
skip_cid_check:
/* Check security configuration */
if (sec_reg_value & BIT(reg_offset)) {
dev_dbg(rifsc_controller->dev,
@@ -723,19 +694,31 @@ skip_cid_check:
return -EACCES;
}
/*
* If the peripheral is in semaphore mode, take the semaphore so that
* the CID1 has the ownership.
*/
if ((cid_reg_value & CIDCFGR_SEMEN) && (cid_reg_value & CIDCFGR_CFEN)) {
/* Skip CID check if CID filtering isn't enabled */
if (!(cid_reg_value & CIDCFGR_CFEN))
goto skip_cid_check;
/* First check conditions for semaphore mode, which doesn't take into account static CID. */
if (cid_reg_value & CIDCFGR_SEMEN) {
if (!(cid_reg_value & BIT(RIF_CID1 + SEMWL_SHIFT))) {
dev_dbg(rifsc_controller->dev,
"Invalid bus semaphore configuration: index %d\n", firewall_id);
return -EACCES;
}
rc = stm32_rif_acquire_semaphore(rifsc_controller, firewall_id);
if (rc) {
dev_err(rifsc_controller->dev,
dev_dbg(rifsc_controller->dev,
"Couldn't acquire semaphore for peripheral: %d\n", firewall_id);
return rc;
}
} else if (FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) != RIF_CID1) {
dev_dbg(rifsc_controller->dev, "Invalid CID configuration for peripheral: %d\n",
firewall_id);
return -EACCES;
}
skip_cid_check:
return 0;
}

View File

@@ -20,7 +20,7 @@ struct acpm_clk {
u32 id;
struct clk_hw hw;
unsigned int mbox_chan_id;
const struct acpm_handle *handle;
struct acpm_handle *handle;
};
struct acpm_clk_variant {
@@ -113,7 +113,7 @@ static int acpm_clk_register(struct device *dev, struct acpm_clk *aclk,
static int acpm_clk_probe(struct platform_device *pdev)
{
const struct acpm_handle *acpm_handle;
struct acpm_handle *acpm_handle;
struct clk_hw_onecell_data *clk_data;
struct clk_hw **hws;
struct device *dev = &pdev->dev;

View File

@@ -343,13 +343,15 @@ struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
tpll_clk = clk_register(NULL, &pll->hw);
if (IS_ERR_OR_NULL(tpll_clk))
goto free_pll;
goto unregister_clk;
if (pll_clk)
*pll_clk = tpll_clk;
return vco_clk;
unregister_clk:
clk_unregister(vco_clk);
free_pll:
kfree(pll);
free_vco:

View File

@@ -2078,7 +2078,7 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
rxtx_bufsz / FFA_PAGE_SIZE);
PAGE_ALIGN(rxtx_bufsz) / FFA_PAGE_SIZE);
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;

View File

@@ -7,6 +7,7 @@
#define pr_fmt(fmt) "SCMI Notifications BASE - " fmt
#include <linux/math.h>
#include <linux/module.h>
#include <linux/scmi_protocol.h>
@@ -219,8 +220,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
}
real_list_sz = t->rx.len - sizeof(u32);
calc_list_sz = (1 + (loop_num_ret - 1) / sizeof(u32)) *
sizeof(u32);
calc_list_sz = round_up(loop_num_ret, sizeof(u32));
if (calc_list_sz != real_list_sz) {
dev_warn(dev,
"Malformed reply - real_sz:%zd calc_sz:%u (loop_num_ret:%d)\n",

View File

@@ -235,6 +235,9 @@ struct scmi_transport_ops {
* to have an execution latency lesser-equal to the threshold
* should be considered for atomic mode operation: such
* decision is finally left up to the SCMI drivers.
* @no_completion_irq: Flag to indicate that this transport has no completion
* interrupt and has to be polled. This is similar to the
* force_polling below, except this is set via DT property.
* @force_polling: Flag to force this whole transport to use SCMI core polling
* mechanism instead of completion interrupts even if available.
* @sync_cmds_completed_on_ret: Flag to indicate that the transport assures
@@ -254,6 +257,7 @@ struct scmi_desc {
int max_msg;
int max_msg_size;
unsigned int atomic_threshold;
bool no_completion_irq;
const bool force_polling;
const bool sync_cmds_completed_on_ret;
const bool atomic_enabled;

View File

@@ -2735,6 +2735,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
cinfo->is_p2a = !tx;
cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms;
cinfo->max_msg_size = info->desc->max_msg_size;
cinfo->no_completion_irq = info->desc->no_completion_irq;
/* Create a unique name for this transport device */
snprintf(name, 32, "__scmi_transport_device_%s_%02X",
@@ -3150,6 +3151,9 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
if (ret && ret != -EINVAL)
dev_err(dev, "Malformed arm,max-msg DT property.\n");
trans->desc.no_completion_irq = of_property_read_bool(dev->of_node,
"arm,no-completion-irq");
dev_info(dev,
"SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n",
trans->desc.max_rx_timeout_ms, trans->desc.max_msg_size,

View File

@@ -20,10 +20,10 @@
* named as _qn.
*/
#define SCMI_QUIRK(_qn, _blk) \
do { \
({ \
if (static_branch_unlikely(&(scmi_quirk_ ## _qn))) \
(_blk); \
} while (0)
})
void scmi_quirks_initialize(void);
void scmi_quirks_enable(struct device *dev, const char *vend,
@@ -34,10 +34,10 @@ void scmi_quirks_enable(struct device *dev, const char *vend,
#define DECLARE_SCMI_QUIRK(_qn)
/* Force quirks compilation even when SCMI Quirks are disabled */
#define SCMI_QUIRK(_qn, _blk) \
do { \
({ \
if (0) \
(_blk); \
} while (0)
})
static inline void scmi_quirks_initialize(void) { }
static inline void scmi_quirks_enable(struct device *dev, const char *vend,

View File

@@ -699,20 +699,18 @@ static DEFINE_MUTEX(__qcuefi_lock);
static int qcuefi_set_reference(struct qcuefi_client *qcuefi)
{
mutex_lock(&__qcuefi_lock);
guard(mutex)(&__qcuefi_lock);
if (qcuefi && __qcuefi) {
mutex_unlock(&__qcuefi_lock);
if (qcuefi && __qcuefi)
return -EEXIST;
}
__qcuefi = qcuefi;
mutex_unlock(&__qcuefi_lock);
return 0;
}
static struct qcuefi_client *qcuefi_acquire(void)
__acquires(__qcuefi_lock)
{
mutex_lock(&__qcuefi_lock);
if (!__qcuefi) {
@@ -723,6 +721,7 @@ static struct qcuefi_client *qcuefi_acquire(void)
}
static void qcuefi_release(void)
__releases(__qcuefi_lock)
{
mutex_unlock(&__qcuefi_lock);
}

View File

@@ -199,19 +199,18 @@ static int qcom_scm_bw_enable(void)
if (!__scm->path)
return 0;
mutex_lock(&__scm->scm_bw_lock);
guard(mutex)(&__scm->scm_bw_lock);
if (!__scm->scm_vote_count) {
ret = icc_set_bw(__scm->path, 0, UINT_MAX);
if (ret < 0) {
dev_err(__scm->dev, "failed to set bandwidth request\n");
goto err_bw;
return ret;
}
}
__scm->scm_vote_count++;
err_bw:
mutex_unlock(&__scm->scm_bw_lock);
return ret;
return 0;
}
static void qcom_scm_bw_disable(void)
@@ -923,14 +922,13 @@ struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *c
goto free_input_rt;
}
tbl_ptr = kzalloc(size, GFP_KERNEL);
tbl_ptr = kmemdup(output_rt_tzm, size, GFP_KERNEL);
if (!tbl_ptr) {
qcom_tzmem_free(output_rt_tzm);
ret = -ENOMEM;
goto free_input_rt;
}
memcpy(tbl_ptr, output_rt_tzm, size);
*output_rt_size = size;
qcom_tzmem_free(output_rt_tzm);
@@ -2290,15 +2288,18 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
*/
static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "asus,vivobook-s15" },
{ .compatible = "asus,vivobook-s15-x1p4" },
{ .compatible = "asus,zenbook-a14-ux3407qa" },
{ .compatible = "asus,zenbook-a14-ux3407ra" },
{ .compatible = "dell,inspiron-14-plus-7441" },
{ .compatible = "dell,latitude-7455" },
{ .compatible = "dell,xps13-9345" },
{ .compatible = "ecs,liva-qc710" },
{ .compatible = "hp,elitebook-ultra-g1q" },
{ .compatible = "hp,omnibook-x14" },
{ .compatible = "huawei,gaokun3" },
{ .compatible = "lenovo,flex-5g" },
{ .compatible = "lenovo,ideacentre-mini-01q8x10" },
{ .compatible = "lenovo,thinkbook-16" },
{ .compatible = "lenovo,thinkpad-t14s" },
{ .compatible = "lenovo,thinkpad-x13s", },
@@ -2309,7 +2310,10 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "microsoft,denali", },
{ .compatible = "microsoft,romulus13", },
{ .compatible = "microsoft,romulus15", },
{ .compatible = "qcom,glymur-crd" },
{ .compatible = "qcom,hamoa-iot-evk" },
{ .compatible = "qcom,mahua-crd" },
{ .compatible = "qcom,purwa-iot-evk" },
{ .compatible = "qcom,sc8180x-primus" },
{ .compatible = "qcom,x1e001de-devkit" },
{ .compatible = "qcom,x1e80100-crd" },
@@ -2467,6 +2471,56 @@ int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size,
}
EXPORT_SYMBOL(qcom_scm_qtee_callback_response);
static void qcom_scm_gunyah_wdt_free(void *data)
{
struct platform_device *gunyah_wdt_dev = data;
platform_device_unregister(gunyah_wdt_dev);
}
static void qcom_scm_gunyah_wdt_init(struct qcom_scm *scm)
{
struct platform_device *gunyah_wdt_dev;
struct device_node *np;
bool of_wdt_available;
int i;
static const uuid_t gunyah_uuid = UUID_INIT(0xc1d58fcd, 0xa453, 0x5fdb,
0x92, 0x65, 0xce, 0x36,
0x67, 0x3d, 0x5f, 0x14);
static const char * const of_wdt_compatible[] = {
"qcom,kpss-wdt",
"arm,sbsa-gwdt",
};
/* Bail out if we are not running under Gunyah */
if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) ||
!arm_smccc_hypervisor_has_uuid(&gunyah_uuid))
return;
/*
* Gunyah emulates either of Qualcomm watchdog or ARM SBSA watchdog on
* newer platforms. Bail out if we find them in the devicetree.
*/
for (i = 0; i < ARRAY_SIZE(of_wdt_compatible); i++) {
np = of_find_compatible_node(NULL, NULL, of_wdt_compatible[i]);
of_wdt_available = of_device_is_available(np);
of_node_put(np);
if (of_wdt_available)
return;
}
gunyah_wdt_dev = platform_device_register_simple("gunyah-wdt", -1,
NULL, 0);
if (IS_ERR(gunyah_wdt_dev)) {
dev_err(scm->dev, "Failed to register Gunyah watchdog device: %ld\n",
PTR_ERR(gunyah_wdt_dev));
return;
}
devm_add_action_or_reset(scm->dev, qcom_scm_gunyah_wdt_free,
gunyah_wdt_dev);
}
static void qcom_scm_qtee_free(void *data)
{
struct platform_device *qtee_dev = data;
@@ -2811,6 +2865,9 @@ static int qcom_scm_probe(struct platform_device *pdev)
/* Initialize the QTEE object interface. */
qcom_scm_qtee_init(scm);
/* Initialize the Gunyah watchdog platform device. */
qcom_scm_gunyah_wdt_init(scm);
return 0;
}

View File

@@ -5,6 +5,7 @@
* Copyright 2025 Linaro Ltd.
*/
#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/ktime.h>
@@ -24,12 +25,12 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
unsigned int acpm_chan_id, bool response)
{
xfer->acpm_chan_id = acpm_chan_id;
xfer->txcnt = cmdlen;
xfer->txd = cmd;
xfer->txlen = cmdlen;
if (response) {
xfer->rxcnt = cmdlen;
xfer->rxd = cmd;
xfer->rxlen = cmdlen;
}
}
@@ -42,7 +43,7 @@ static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id,
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
int acpm_dvfs_set_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id,
unsigned long rate)
{
@@ -50,7 +51,7 @@ int acpm_dvfs_set_rate(const struct acpm_handle *handle,
u32 cmd[4];
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false);
acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, false);
return acpm_do_xfer(handle, &xfer);
}
@@ -62,7 +63,7 @@ static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id)
cmd[3] = ktime_to_ms(ktime_get());
}
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id)
{
struct acpm_xfer xfer;
@@ -70,7 +71,7 @@ unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
int ret;
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true);
acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, true);
ret = acpm_do_xfer(handle, &xfer);
if (ret)

View File

@@ -11,10 +11,10 @@
struct acpm_handle;
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
int acpm_dvfs_set_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int id,
unsigned long rate);
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id,
unsigned int clk_id);

View File

@@ -41,7 +41,7 @@ static const int acpm_pmic_linux_errmap[] = {
[2] = -EACCES, /* Write register can't be accessed or issues to access it. */
};
static int acpm_pmic_to_linux_err(int err)
static int acpm_pmic_to_linux_err(unsigned int err)
{
if (err >= 0 && err < ARRAY_SIZE(acpm_pmic_linux_errmap))
return acpm_pmic_linux_errmap[err];
@@ -63,8 +63,8 @@ static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
{
xfer->txd = cmd;
xfer->rxd = cmd;
xfer->txlen = cmdlen;
xfer->rxlen = cmdlen;
xfer->txcnt = cmdlen;
xfer->rxcnt = cmdlen;
xfer->acpm_chan_id = acpm_chan_id;
}
@@ -77,7 +77,7 @@ static void acpm_pmic_init_read_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan)
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_pmic_read_reg(const struct acpm_handle *handle,
int acpm_pmic_read_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 *buf)
{
@@ -86,7 +86,7 @@ int acpm_pmic_read_reg(const struct acpm_handle *handle,
int ret;
acpm_pmic_init_read_cmd(cmd, type, reg, chan);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -107,7 +107,7 @@ static void acpm_pmic_init_bulk_read_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
FIELD_PREP(ACPM_PMIC_VALUE, count);
}
int acpm_pmic_bulk_read(const struct acpm_handle *handle,
int acpm_pmic_bulk_read(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, u8 *buf)
{
@@ -119,7 +119,7 @@ int acpm_pmic_bulk_read(const struct acpm_handle *handle,
return -EINVAL;
acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -150,7 +150,7 @@ static void acpm_pmic_init_write_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_pmic_write_reg(const struct acpm_handle *handle,
int acpm_pmic_write_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value)
{
@@ -159,7 +159,7 @@ int acpm_pmic_write_reg(const struct acpm_handle *handle,
int ret;
acpm_pmic_init_write_cmd(cmd, type, reg, chan, value);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -187,7 +187,7 @@ static void acpm_pmic_init_bulk_write_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
}
}
int acpm_pmic_bulk_write(const struct acpm_handle *handle,
int acpm_pmic_bulk_write(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, const u8 *buf)
{
@@ -199,7 +199,7 @@ int acpm_pmic_bulk_write(const struct acpm_handle *handle,
return -EINVAL;
acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -220,7 +220,7 @@ static void acpm_pmic_init_update_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_pmic_update_reg(const struct acpm_handle *handle,
int acpm_pmic_update_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value, u8 mask)
{
@@ -229,7 +229,7 @@ int acpm_pmic_update_reg(const struct acpm_handle *handle,
int ret;
acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)

View File

@@ -11,19 +11,19 @@
struct acpm_handle;
int acpm_pmic_read_reg(const struct acpm_handle *handle,
int acpm_pmic_read_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 *buf);
int acpm_pmic_bulk_read(const struct acpm_handle *handle,
int acpm_pmic_bulk_read(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, u8 *buf);
int acpm_pmic_write_reg(const struct acpm_handle *handle,
int acpm_pmic_write_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value);
int acpm_pmic_bulk_write(const struct acpm_handle *handle,
int acpm_pmic_bulk_write(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, const u8 *buf);
int acpm_pmic_update_reg(const struct acpm_handle *handle,
int acpm_pmic_update_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value, u8 mask);
#endif /* __EXYNOS_ACPM_PMIC_H__ */

View File

@@ -205,7 +205,7 @@ static void acpm_get_saved_rx(struct acpm_chan *achan,
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
if (rx_seqnum == tx_seqnum) {
memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
}
}
@@ -258,8 +258,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
if (rx_data->response) {
if (rx_seqnum == tx_seqnum) {
__ioread32_copy(xfer->rxd, addr,
xfer->rxlen / 4);
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
rx_set = true;
clear_bit(seqnum, achan->bitmap_seqnum);
} else {
@@ -269,8 +268,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
* clear yet the bitmap. It will be cleared
* after the response is copied to the request.
*/
__ioread32_copy(rx_data->cmd, addr,
xfer->rxlen / 4);
__ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
}
} else {
clear_bit(seqnum, achan->bitmap_seqnum);
@@ -412,7 +410,7 @@ static int acpm_wait_for_message_response(struct acpm_chan *achan,
*
* Return: 0 on success, -errno otherwise.
*/
int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer)
int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer)
{
struct acpm_info *acpm = handle_to_acpm_info(handle);
struct exynos_mbox_msg msg;
@@ -425,7 +423,9 @@ int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer)
achan = &acpm->chans[xfer->acpm_chan_id];
if (!xfer->txd || xfer->txlen > achan->mlen || xfer->rxlen > achan->mlen)
if (!xfer->txd ||
(xfer->txcnt * sizeof(*xfer->txd) > achan->mlen) ||
(xfer->rxcnt * sizeof(*xfer->rxd) > achan->mlen))
return -EINVAL;
if (!achan->poll_completion) {
@@ -448,7 +448,7 @@ int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer)
/* Write TX command. */
__iowrite32_copy(achan->tx.base + achan->mlen * tx_front,
xfer->txd, xfer->txlen / 4);
xfer->txd, xfer->txcnt);
/* Advance TX front. */
writel(idx, achan->tx.front);
@@ -674,7 +674,7 @@ static int acpm_probe(struct platform_device *pdev)
* acpm_handle_put() - release the handle acquired by acpm_get_by_phandle.
* @handle: Handle acquired by acpm_get_by_phandle.
*/
static void acpm_handle_put(const struct acpm_handle *handle)
static void acpm_handle_put(struct acpm_handle *handle)
{
struct acpm_info *acpm = handle_to_acpm_info(handle);
struct device *dev = acpm->dev;
@@ -700,8 +700,10 @@ static void devm_acpm_release(struct device *dev, void *res)
* @np: ACPM device tree node.
*
* Return: pointer to handle on success, ERR_PTR(-errno) otherwise.
*
* Note: handle CANNOT be pointer to const
*/
static const struct acpm_handle *acpm_get_by_node(struct device *dev,
static struct acpm_handle *acpm_get_by_node(struct device *dev,
struct device_node *np)
{
struct platform_device *pdev;
@@ -743,10 +745,10 @@ static const struct acpm_handle *acpm_get_by_node(struct device *dev,
*
* Return: pointer to handle on success, ERR_PTR(-errno) otherwise.
*/
const struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
struct device_node *np)
{
const struct acpm_handle **ptr, *handle;
struct acpm_handle **ptr, *handle;
ptr = devres_alloc(devm_acpm_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)

View File

@@ -8,16 +8,16 @@
#define __EXYNOS_ACPM_H__
struct acpm_xfer {
const u32 *txd;
u32 *rxd;
size_t txlen;
size_t rxlen;
const u32 *txd __counted_by_ptr(txcnt);
u32 *rxd __counted_by_ptr(rxcnt);
size_t txcnt;
size_t rxcnt;
unsigned int acpm_chan_id;
};
struct acpm_handle;
int acpm_do_xfer(const struct acpm_handle *handle,
int acpm_do_xfer(struct acpm_handle *handle,
const struct acpm_xfer *xfer);
#endif /* __EXYNOS_ACPM_H__ */

View File

@@ -32,6 +32,40 @@ channel_to_ops(struct tegra_bpmp_channel *channel)
return bpmp->soc->ops;
}
struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, unsigned int *id)
{
struct platform_device *pdev;
struct of_phandle_args args;
struct tegra_bpmp *bpmp;
int err;
err = __of_parse_phandle_with_args(dev->of_node, "nvidia,bpmp", NULL,
1, 0, &args);
if (err < 0)
return ERR_PTR(err);
pdev = of_find_device_by_node(args.np);
if (!pdev) {
bpmp = ERR_PTR(-ENODEV);
goto put;
}
bpmp = platform_get_drvdata(pdev);
if (!bpmp) {
bpmp = ERR_PTR(-EPROBE_DEFER);
put_device(&pdev->dev);
goto put;
}
if (id)
*id = args.args[0];
put:
of_node_put(args.np);
return bpmp;
}
EXPORT_SYMBOL_GPL(tegra_bpmp_get_with_id);
struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
{
struct platform_device *pdev;

View File

@@ -580,6 +580,7 @@ config GPIO_PL061
config GPIO_POLARFIRE_SOC
bool "Microchip FPGA GPIO support"
select REGMAP_MMIO
select GPIOLIB_IRQCHIP
help
Say yes here to support the GPIO controllers on Microchip FPGAs.

View File

@@ -9,8 +9,9 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mod_devicetable.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
@@ -18,7 +19,7 @@
#define MPFS_GPIO_CTRL(i) (0x4 * (i))
#define MPFS_MAX_NUM_GPIO 32
#define MPFS_GPIO_EN_INT 3
#define MPFS_GPIO_EN_INT BIT(3)
#define MPFS_GPIO_EN_OUT_BUF BIT(2)
#define MPFS_GPIO_EN_IN BIT(1)
#define MPFS_GPIO_EN_OUT BIT(0)
@@ -52,6 +53,7 @@ static const struct regmap_config mpfs_gpio_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.use_raw_spinlock = true,
};
static int mpfs_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio_index)
@@ -114,13 +116,98 @@ static int mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int valu
return ret;
}
static int mpfs_gpio_irq_set_type(struct irq_data *data, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
int gpio_index = irqd_to_hwirq(data) % 32;
u32 interrupt_type;
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_BOTH;
break;
case IRQ_TYPE_EDGE_FALLING:
interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_NEG;
break;
case IRQ_TYPE_EDGE_RISING:
interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_POS;
break;
case IRQ_TYPE_LEVEL_HIGH:
interrupt_type = MPFS_GPIO_TYPE_INT_LEVEL_HIGH;
break;
case IRQ_TYPE_LEVEL_LOW:
interrupt_type = MPFS_GPIO_TYPE_INT_LEVEL_LOW;
break;
}
regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
MPFS_GPIO_TYPE_INT_MASK, interrupt_type);
return 0;
}
static void mpfs_gpio_irq_unmask(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
int gpio_index = irqd_to_hwirq(data) % 32;
gpiochip_enable_irq(gc, gpio_index);
mpfs_gpio_direction_input(gc, gpio_index);
regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
MPFS_GPIO_EN_INT, MPFS_GPIO_EN_INT);
}
static void mpfs_gpio_irq_mask(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
int gpio_index = irqd_to_hwirq(data) % 32;
regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
MPFS_GPIO_EN_INT, 0);
gpiochip_disable_irq(gc, gpio_index);
}
static const struct irq_chip mpfs_gpio_irqchip = {
.name = "MPFS GPIO",
.irq_set_type = mpfs_gpio_irq_set_type,
.irq_mask = mpfs_gpio_irq_mask,
.irq_unmask = mpfs_gpio_irq_unmask,
.flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static void mpfs_gpio_irq_handler(struct irq_desc *desc)
{
struct irq_chip *irqchip = irq_desc_get_chip(desc);
struct mpfs_gpio_chip *mpfs_gpio = irq_desc_get_handler_data(desc);
unsigned long status;
u32 val;
int i;
chained_irq_enter(irqchip, desc);
regmap_read(mpfs_gpio->regs, MPFS_IRQ_REG, &val);
status = val;
for_each_set_bit(i, &status, MPFS_MAX_NUM_GPIO) {
regmap_write(mpfs_gpio->regs, MPFS_IRQ_REG, BIT(i));
generic_handle_domain_irq(mpfs_gpio->gc.irq.domain, i);
}
chained_irq_exit(irqchip, desc);
}
static int mpfs_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct mpfs_gpio_chip *mpfs_gpio;
struct gpio_irq_chip *girq;
struct clk *clk;
void __iomem *base;
int ngpios;
int ngpios, nirqs, ret;
mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL);
if (!mpfs_gpio)
@@ -157,6 +244,35 @@ static int mpfs_gpio_probe(struct platform_device *pdev)
mpfs_gpio->gc.parent = dev;
mpfs_gpio->gc.owner = THIS_MODULE;
nirqs = of_irq_count(node);
if (nirqs > MPFS_MAX_NUM_GPIO)
return -ENXIO;
if (nirqs) {
girq = &mpfs_gpio->gc.irq;
gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip);
girq->num_parents = nirqs;
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
sizeof(*girq->parents), GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
for (int i = 0; i < nirqs; i++) {
ret = platform_get_irq(pdev, i);
if (ret < 0)
return ret;
girq->parents[i] = ret;
girq->parent_handler_data = mpfs_gpio;
girq->parent_handler = mpfs_gpio_irq_handler;
}
girq->handler = handle_level_irq;
girq->default_type = IRQ_TYPE_NONE;
}
return devm_gpiochip_add_data(dev, &mpfs_gpio->gc, mpfs_gpio);
}

View File

@@ -64,17 +64,6 @@ config BRCMSTB_MEMC
controller and specifically control the Self Refresh Power Down
(SRPD) inactivity timeout.
config BT1_L2_CTL
bool "Baikal-T1 CM2 L2-RAM Cache Control Block"
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
select MFD_SYSCON
help
Baikal-T1 CPU is based on the MIPS P5600 Warrior IP-core. The CPU
resides Coherency Manager v2 with embedded 1MB L2-cache. It's
possible to tune the L2 cache performance up by setting the data,
tags and way-select latencies of RAM access. This driver provides a
dt properties-based and sysfs interface for it.
config TI_AEMIF
tristate "Texas Instruments AEMIF driver"
depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST

View File

@@ -11,7 +11,6 @@ obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o
obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
obj-$(CONFIG_TI_EMIF) += emif.o
obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o

View File

@@ -14,6 +14,7 @@
#define REG_MEMC_CNTRLR_CONFIG 0x00
#define CNTRLR_CONFIG_LPDDR4_SHIFT 5
#define CNTRLR_CONFIG_LPDDR5_SHIFT 6
#define CNTRLR_CONFIG_MASK 0xf
#define REG_MEMC_SRPD_CFG_21 0x20
#define REG_MEMC_SRPD_CFG_20 0x34
@@ -34,14 +35,15 @@ struct brcmstb_memc {
u32 srpd_offset;
};
static int brcmstb_memc_uses_lpddr4(struct brcmstb_memc *memc)
static int brcmstb_memc_uses_lpddr45(struct brcmstb_memc *memc)
{
void __iomem *config = memc->ddr_ctrl + REG_MEMC_CNTRLR_CONFIG;
u32 reg;
reg = readl_relaxed(config) & CNTRLR_CONFIG_MASK;
return reg == CNTRLR_CONFIG_LPDDR4_SHIFT;
return reg == CNTRLR_CONFIG_LPDDR4_SHIFT ||
reg == CNTRLR_CONFIG_LPDDR5_SHIFT;
}
static int brcmstb_memc_srpd_config(struct brcmstb_memc *memc,
@@ -95,7 +97,7 @@ static ssize_t srpd_store(struct device *dev, struct device_attribute *attr,
* dynamic tuning process will also get affected by the inactivity
* timeout, thus making it non functional.
*/
if (brcmstb_memc_uses_lpddr4(memc))
if (brcmstb_memc_uses_lpddr45(memc))
return -EOPNOTSUPP;
ret = kstrtouint(buf, 10, &val);

View File

@@ -1,323 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Authors:
* Serge Semin <Sergey.Semin@baikalelectronics.ru>
*
* Baikal-T1 CM2 L2-cache Control Block driver.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/bitfield.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/sysfs.h>
#include <linux/of.h>
#define L2_CTL_REG 0x028
#define L2_CTL_DATA_STALL_FLD 0
#define L2_CTL_DATA_STALL_MASK GENMASK(1, L2_CTL_DATA_STALL_FLD)
#define L2_CTL_TAG_STALL_FLD 2
#define L2_CTL_TAG_STALL_MASK GENMASK(3, L2_CTL_TAG_STALL_FLD)
#define L2_CTL_WS_STALL_FLD 4
#define L2_CTL_WS_STALL_MASK GENMASK(5, L2_CTL_WS_STALL_FLD)
#define L2_CTL_SET_CLKRATIO BIT(13)
#define L2_CTL_CLKRATIO_LOCK BIT(31)
#define L2_CTL_STALL_MIN 0
#define L2_CTL_STALL_MAX 3
#define L2_CTL_STALL_SET_DELAY_US 1
#define L2_CTL_STALL_SET_TOUT_US 1000
/*
* struct l2_ctl - Baikal-T1 L2 Control block private data.
* @dev: Pointer to the device structure.
* @sys_regs: Baikal-T1 System Controller registers map.
*/
struct l2_ctl {
struct device *dev;
struct regmap *sys_regs;
};
/*
* enum l2_ctl_stall - Baikal-T1 L2-cache-RAM stall identifier.
* @L2_WSSTALL: Way-select latency.
* @L2_TAGSTALL: Tag latency.
* @L2_DATASTALL: Data latency.
*/
enum l2_ctl_stall {
L2_WS_STALL,
L2_TAG_STALL,
L2_DATA_STALL
};
/*
* struct l2_ctl_device_attribute - Baikal-T1 L2-cache device attribute.
* @dev_attr: Actual sysfs device attribute.
* @id: L2-cache stall field identifier.
*/
struct l2_ctl_device_attribute {
struct device_attribute dev_attr;
enum l2_ctl_stall id;
};
#define to_l2_ctl_dev_attr(_dev_attr) \
container_of(_dev_attr, struct l2_ctl_device_attribute, dev_attr)
#define L2_CTL_ATTR_RW(_name, _prefix, _id) \
struct l2_ctl_device_attribute l2_ctl_attr_##_name = \
{ __ATTR(_name, 0644, _prefix##_show, _prefix##_store), _id }
static int l2_ctl_get_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 *val)
{
u32 data = 0;
int ret;
ret = regmap_read(l2->sys_regs, L2_CTL_REG, &data);
if (ret)
return ret;
switch (id) {
case L2_WS_STALL:
*val = FIELD_GET(L2_CTL_WS_STALL_MASK, data);
break;
case L2_TAG_STALL:
*val = FIELD_GET(L2_CTL_TAG_STALL_MASK, data);
break;
case L2_DATA_STALL:
*val = FIELD_GET(L2_CTL_DATA_STALL_MASK, data);
break;
default:
return -EINVAL;
}
return 0;
}
static int l2_ctl_set_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 val)
{
u32 mask = 0, data = 0;
int ret;
val = clamp_val(val, L2_CTL_STALL_MIN, L2_CTL_STALL_MAX);
switch (id) {
case L2_WS_STALL:
data = FIELD_PREP(L2_CTL_WS_STALL_MASK, val);
mask = L2_CTL_WS_STALL_MASK;
break;
case L2_TAG_STALL:
data = FIELD_PREP(L2_CTL_TAG_STALL_MASK, val);
mask = L2_CTL_TAG_STALL_MASK;
break;
case L2_DATA_STALL:
data = FIELD_PREP(L2_CTL_DATA_STALL_MASK, val);
mask = L2_CTL_DATA_STALL_MASK;
break;
default:
return -EINVAL;
}
data |= L2_CTL_SET_CLKRATIO;
mask |= L2_CTL_SET_CLKRATIO;
ret = regmap_update_bits(l2->sys_regs, L2_CTL_REG, mask, data);
if (ret)
return ret;
return regmap_read_poll_timeout(l2->sys_regs, L2_CTL_REG, data,
data & L2_CTL_CLKRATIO_LOCK,
L2_CTL_STALL_SET_DELAY_US,
L2_CTL_STALL_SET_TOUT_US);
}
static void l2_ctl_clear_data(void *data)
{
struct l2_ctl *l2 = data;
struct platform_device *pdev = to_platform_device(l2->dev);
platform_set_drvdata(pdev, NULL);
}
static struct l2_ctl *l2_ctl_create_data(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct l2_ctl *l2;
int ret;
l2 = devm_kzalloc(dev, sizeof(*l2), GFP_KERNEL);
if (!l2)
return ERR_PTR(-ENOMEM);
ret = devm_add_action(dev, l2_ctl_clear_data, l2);
if (ret) {
dev_err(dev, "Can't add L2 CTL data clear action\n");
return ERR_PTR(ret);
}
l2->dev = dev;
platform_set_drvdata(pdev, l2);
return l2;
}
static int l2_ctl_find_sys_regs(struct l2_ctl *l2)
{
l2->sys_regs = syscon_node_to_regmap(l2->dev->of_node->parent);
if (IS_ERR(l2->sys_regs)) {
dev_err(l2->dev, "Couldn't get L2 CTL register map\n");
return PTR_ERR(l2->sys_regs);
}
return 0;
}
static int l2_ctl_of_parse_property(struct l2_ctl *l2, enum l2_ctl_stall id,
const char *propname)
{
int ret = 0;
u32 data;
if (!of_property_read_u32(l2->dev->of_node, propname, &data)) {
ret = l2_ctl_set_latency(l2, id, data);
if (ret)
dev_err(l2->dev, "Invalid value of '%s'\n", propname);
}
return ret;
}
static int l2_ctl_of_parse(struct l2_ctl *l2)
{
int ret;
ret = l2_ctl_of_parse_property(l2, L2_WS_STALL, "baikal,l2-ws-latency");
if (ret)
return ret;
ret = l2_ctl_of_parse_property(l2, L2_TAG_STALL, "baikal,l2-tag-latency");
if (ret)
return ret;
return l2_ctl_of_parse_property(l2, L2_DATA_STALL,
"baikal,l2-data-latency");
}
static ssize_t l2_ctl_latency_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr);
struct l2_ctl *l2 = dev_get_drvdata(dev);
u32 data;
int ret;
ret = l2_ctl_get_latency(l2, devattr->id, &data);
if (ret)
return ret;
return sysfs_emit(buf, "%u\n", data);
}
static ssize_t l2_ctl_latency_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr);
struct l2_ctl *l2 = dev_get_drvdata(dev);
u32 data;
int ret;
if (kstrtouint(buf, 0, &data) < 0)
return -EINVAL;
ret = l2_ctl_set_latency(l2, devattr->id, data);
if (ret)
return ret;
return count;
}
static L2_CTL_ATTR_RW(l2_ws_latency, l2_ctl_latency, L2_WS_STALL);
static L2_CTL_ATTR_RW(l2_tag_latency, l2_ctl_latency, L2_TAG_STALL);
static L2_CTL_ATTR_RW(l2_data_latency, l2_ctl_latency, L2_DATA_STALL);
static struct attribute *l2_ctl_sysfs_attrs[] = {
&l2_ctl_attr_l2_ws_latency.dev_attr.attr,
&l2_ctl_attr_l2_tag_latency.dev_attr.attr,
&l2_ctl_attr_l2_data_latency.dev_attr.attr,
NULL
};
ATTRIBUTE_GROUPS(l2_ctl_sysfs);
static void l2_ctl_remove_sysfs(void *data)
{
struct l2_ctl *l2 = data;
device_remove_groups(l2->dev, l2_ctl_sysfs_groups);
}
static int l2_ctl_init_sysfs(struct l2_ctl *l2)
{
int ret;
ret = device_add_groups(l2->dev, l2_ctl_sysfs_groups);
if (ret) {
dev_err(l2->dev, "Failed to create L2 CTL sysfs nodes\n");
return ret;
}
ret = devm_add_action_or_reset(l2->dev, l2_ctl_remove_sysfs, l2);
if (ret)
dev_err(l2->dev, "Can't add L2 CTL sysfs remove action\n");
return ret;
}
static int l2_ctl_probe(struct platform_device *pdev)
{
struct l2_ctl *l2;
int ret;
l2 = l2_ctl_create_data(pdev);
if (IS_ERR(l2))
return PTR_ERR(l2);
ret = l2_ctl_find_sys_regs(l2);
if (ret)
return ret;
ret = l2_ctl_of_parse(l2);
if (ret)
return ret;
ret = l2_ctl_init_sysfs(l2);
if (ret)
return ret;
return 0;
}
static const struct of_device_id l2_ctl_of_match[] = {
{ .compatible = "baikal,bt1-l2-ctl" },
{ }
};
MODULE_DEVICE_TABLE(of, l2_ctl_of_match);
static struct platform_driver l2_ctl_driver = {
.probe = l2_ctl_probe,
.driver = {
.name = "bt1-l2-ctl",
.of_match_table = l2_ctl_of_match
}
};
module_platform_driver(l2_ctl_driver);
MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
MODULE_DESCRIPTION("Baikal-T1 L2-cache driver");

View File

@@ -1005,11 +1005,9 @@ static int rpcif_probe(struct platform_device *pdev)
return PTR_ERR(rpc->base);
rpc->info = of_device_get_match_data(dev);
rpc->regmap = devm_regmap_init(dev, NULL, rpc, rpc->info->regmap_config);
if (IS_ERR(rpc->regmap)) {
dev_err(dev, "failed to init regmap for rpcif, error %ld\n",
PTR_ERR(rpc->regmap));
return PTR_ERR(rpc->regmap);
}
if (IS_ERR(rpc->regmap))
return dev_err_probe(dev, PTR_ERR(rpc->regmap),
"failed to init regmap for rpcif\n");
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
rpc->dirmap = devm_ioremap_resource(dev, res);

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/clk.h>
@@ -56,6 +56,23 @@ static const struct of_device_id tegra_mc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
const struct tegra_mc_regs tegra20_mc_regs = {
.cfg_channel_enable = 0xdf8,
.err_status = 0x08,
.err_add = 0x0c,
.err_add_hi = 0x11fc,
.err_vpr_status = 0x654,
.err_vpr_add = 0x658,
.err_sec_status = 0x67c,
.err_sec_add = 0x680,
.err_mts_status = 0x9b0,
.err_mts_add = 0x9b4,
.err_gen_co_status = 0xc00,
.err_gen_co_add = 0xc04,
.err_route_status = 0x9c0,
.err_route_add = 0x9c4,
};
static void tegra_mc_devm_action_put_device(void *data)
{
struct tegra_mc *mc = data;
@@ -381,12 +398,16 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc)
}
EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count);
const irq_handler_t tegra30_mc_irq_handlers[] = {
tegra30_mc_handle_irq
};
#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
defined(CONFIG_ARCH_TEGRA_114_SOC) || \
defined(CONFIG_ARCH_TEGRA_124_SOC) || \
defined(CONFIG_ARCH_TEGRA_132_SOC) || \
defined(CONFIG_ARCH_TEGRA_210_SOC)
static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
static void tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
{
unsigned long long tick;
unsigned int i;
@@ -414,8 +435,6 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
/* latch new values */
mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL);
return 0;
}
static int load_one_timing(struct tegra_mc *mc,
@@ -509,32 +528,24 @@ int tegra30_mc_probe(struct tegra_mc *mc)
int err;
mc->clk = devm_clk_get_optional(mc->dev, "mc");
if (IS_ERR(mc->clk)) {
dev_err(mc->dev, "failed to get MC clock: %ld\n", PTR_ERR(mc->clk));
return PTR_ERR(mc->clk);
}
if (IS_ERR(mc->clk))
return dev_err_probe(mc->dev, PTR_ERR(mc->clk),
"failed to get MC clock\n");
/* ensure that debug features are disabled */
mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG);
err = tegra_mc_setup_latency_allowance(mc);
if (err < 0) {
dev_err(mc->dev, "failed to setup latency allowance: %d\n", err);
return err;
}
tegra_mc_setup_latency_allowance(mc);
err = tegra_mc_setup_timings(mc);
if (err < 0) {
dev_err(mc->dev, "failed to setup timings: %d\n", err);
return err;
}
if (err < 0)
return dev_err_probe(mc->dev, err, "failed to setup timings\n");
return 0;
}
const struct tegra_mc_ops tegra30_mc_ops = {
.probe = tegra30_mc_probe,
.handle_irq = tegra30_mc_handle_irq,
};
#endif
@@ -575,9 +586,9 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
}
/* mask all interrupts to avoid flooding */
status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask;
status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
} else {
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
}
if (!status)
@@ -600,37 +611,37 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
switch (intmask) {
case MC_INT_DECERR_VPR:
status_reg = MC_ERR_VPR_STATUS;
addr_reg = MC_ERR_VPR_ADR;
status_reg = mc->soc->regs->err_vpr_status;
addr_reg = mc->soc->regs->err_vpr_add;
break;
case MC_INT_SECERR_SEC:
status_reg = MC_ERR_SEC_STATUS;
addr_reg = MC_ERR_SEC_ADR;
status_reg = mc->soc->regs->err_sec_status;
addr_reg = mc->soc->regs->err_sec_add;
break;
case MC_INT_DECERR_MTS:
status_reg = MC_ERR_MTS_STATUS;
addr_reg = MC_ERR_MTS_ADR;
status_reg = mc->soc->regs->err_mts_status;
addr_reg = mc->soc->regs->err_mts_add;
break;
case MC_INT_DECERR_GENERALIZED_CARVEOUT:
status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS;
addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR;
status_reg = mc->soc->regs->err_gen_co_status;
addr_reg = mc->soc->regs->err_gen_co_add;
break;
case MC_INT_DECERR_ROUTE_SANITY:
status_reg = MC_ERR_ROUTE_SANITY_STATUS;
addr_reg = MC_ERR_ROUTE_SANITY_ADR;
status_reg = mc->soc->regs->err_route_status;
addr_reg = mc->soc->regs->err_route_add;
break;
default:
status_reg = MC_ERR_STATUS;
addr_reg = MC_ERR_ADR;
status_reg = mc->soc->regs->err_status;
addr_reg = mc->soc->regs->err_add;
#ifdef CONFIG_PHYS_ADDR_T_64BIT
if (mc->soc->has_addr_hi_reg)
addr_hi_reg = MC_ERR_ADR_HI;
addr_hi_reg = mc->soc->regs->err_add_hi;
#endif
break;
}
@@ -647,9 +658,12 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
addr = mc_ch_readl(mc, channel, addr_hi_reg);
else
addr = mc_readl(mc, addr_hi_reg);
} else {
} else if (mc->soc->mc_addr_hi_mask) {
addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
MC_ERR_STATUS_ADR_HI_MASK);
mc->soc->mc_addr_hi_mask);
} else {
dev_err_ratelimited(mc->dev, "Unable to determine high address!");
return IRQ_NONE;
}
addr <<= 32;
}
@@ -674,11 +688,11 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
}
}
type = (value & MC_ERR_STATUS_TYPE_MASK) >>
type = (value & mc->soc->mc_err_status_type_mask) >>
MC_ERR_STATUS_TYPE_SHIFT;
desc = tegra_mc_error_names[type];
desc = tegra20_mc_error_names[type];
switch (value & MC_ERR_STATUS_TYPE_MASK) {
switch (value & mc->soc->mc_err_status_type_mask) {
case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE:
perm[0] = ' ';
perm[1] = '[';
@@ -744,9 +758,10 @@ const char *const tegra_mc_status_names[32] = {
[16] = "MTS carveout violation",
[17] = "Generalized carveout violation",
[20] = "Route Sanity error",
[21] = "GIC_MSI error",
};
const char *const tegra_mc_error_names[8] = {
const char *const tegra20_mc_error_names[8] = {
[2] = "EMEM decode error",
[3] = "TrustZone violation",
[4] = "Carveout violation",
@@ -883,7 +898,7 @@ static void tegra_mc_num_channel_enabled(struct tegra_mc *mc)
unsigned int i;
u32 value;
value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE);
value = mc_ch_readl(mc, 0, mc->soc->regs->cfg_channel_enable);
if (value <= 0) {
mc->num_channels = mc->soc->num_channels;
return;
@@ -935,28 +950,35 @@ static int tegra_mc_probe(struct platform_device *pdev)
tegra_mc_num_channel_enabled(mc);
if (mc->soc->ops && mc->soc->ops->handle_irq) {
mc->irq = platform_get_irq(pdev, 0);
if (mc->irq < 0)
return mc->irq;
if (mc->soc->handle_irq) {
unsigned int i;
WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
if (mc->soc->num_channels)
mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask,
MC_INTMASK);
else
mc_writel(mc, mc->soc->intmask, MC_INTMASK);
for (i = 0; i < mc->soc->num_interrupts; i++) {
int irq;
err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0,
irq = platform_get_irq(pdev, i);
if (irq < 0)
return irq;
err = devm_request_irq(&pdev->dev, irq, mc->soc->handle_irq[i], 0,
dev_name(&pdev->dev), mc);
if (err < 0) {
dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
err);
dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err);
return err;
}
}
for (i = 0; i < mc->soc->num_intmasks; i++) {
if (mc->soc->num_channels)
mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmasks[i].mask,
mc->soc->intmasks[i].reg);
else
mc_writel(mc, mc->soc->intmasks[i].mask, mc->soc->intmasks[i].reg);
}
}
if (mc->soc->reset_ops) {
err = tegra_mc_reset_setup(mc);
if (err < 0)
@@ -971,8 +993,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU) && mc->soc->smmu) {
mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
if (IS_ERR(mc->smmu)) {
dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
PTR_ERR(mc->smmu));
dev_err(&pdev->dev, "failed to probe SMMU: %pe\n", mc->smmu);
mc->smmu = NULL;
}
}

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
*/
#ifndef MEMORY_TEGRA_MC_H
@@ -13,15 +13,36 @@
#include <soc/tegra/mc.h>
#define MC_INTSTATUS 0x00
/* Bit field of MC_INTSTATUS register */
#define MC_INT_DECERR_EMEM BIT(6)
#define MC_INT_INVALID_GART_PAGE BIT(7)
#define MC_INT_SECURITY_VIOLATION BIT(8)
#define MC_INT_ARBITRATION_EMEM BIT(9)
#define MC_INT_INVALID_SMMU_PAGE BIT(10)
#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11)
#define MC_INT_DECERR_VPR BIT(12)
#define MC_INT_SECERR_SEC BIT(13)
#define MC_INT_DECERR_MTS BIT(16)
#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17)
#define MC_INT_DECERR_ROUTE_SANITY BIT(20)
#define MC_INT_DECERR_ROUTE_SANITY_GIC_MSI BIT(21)
#define MC_INTMASK 0x04
#define MC_ERR_STATUS 0x08
#define MC_ERR_ADR 0x0c
#define MC_GART_ERROR_REQ 0x30
#define MC_EMEM_ADR_CFG 0x54
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
#define MC_SECURITY_VIOLATION_STATUS 0x74
#define MC_EMEM_ARB_CFG 0x90
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30)
#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31)
#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff
#define MC_EMEM_ARB_TIMING_RCD 0x98
#define MC_EMEM_ARB_TIMING_RP 0x9c
#define MC_EMEM_ARB_TIMING_RC 0xa0
@@ -41,60 +62,97 @@
#define MC_EMEM_ARB_MISC1 0xdc
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
#define MC_EMEM_ARB_OVERRIDE 0xe8
#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3
#define MC_TIMING_CONTROL_DBG 0xf8
#define MC_TIMING_CONTROL 0xfc
#define MC_ERR_VPR_STATUS 0x654
#define MC_ERR_VPR_ADR 0x658
#define MC_ERR_SEC_STATUS 0x67c
#define MC_ERR_SEC_ADR 0x680
#define MC_ERR_MTS_STATUS 0x9b0
#define MC_ERR_MTS_ADR 0x9b4
#define MC_ERR_ROUTE_SANITY_STATUS 0x9c0
#define MC_ERR_ROUTE_SANITY_ADR 0x9c4
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8
#define MC_GLOBAL_INTSTATUS 0xf24
#define MC_ERR_ADR_HI 0x11fc
#define MC_TIMING_UPDATE BIT(0)
#define MC_INT_DECERR_ROUTE_SANITY BIT(20)
#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17)
#define MC_INT_DECERR_MTS BIT(16)
#define MC_INT_SECERR_SEC BIT(13)
#define MC_INT_DECERR_VPR BIT(12)
#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11)
#define MC_INT_INVALID_SMMU_PAGE BIT(10)
#define MC_INT_ARBITRATION_EMEM BIT(9)
#define MC_INT_SECURITY_VIOLATION BIT(8)
#define MC_INT_INVALID_GART_PAGE BIT(7)
#define MC_INT_DECERR_EMEM BIT(6)
#define MC_GLOBAL_INTSTATUS 0xf24
/* Bit field of MC_ERR_STATUS_0 register */
#define MC_ERR_STATUS_RW BIT(16)
#define MC_ERR_STATUS_SECURITY BIT(17)
#define MC_ERR_STATUS_NONSECURE BIT(25)
#define MC_ERR_STATUS_WRITABLE BIT(26)
#define MC_ERR_STATUS_READABLE BIT(27)
#define MC_ERR_STATUS_GSC_ADR_HI_MASK 0xffff
#define MC_ERR_STATUS_GSC_ADR_HI_SHIFT 16
#define MC_ERR_STATUS_RT_ADR_HI_SHIFT 15
#define MC_ERR_STATUS_TYPE_SHIFT 28
#define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28)
#define MC_ERR_STATUS_TYPE_MASK (0x7 << 28)
#define MC_ERR_STATUS_READABLE BIT(27)
#define MC_ERR_STATUS_WRITABLE BIT(26)
#define MC_ERR_STATUS_NONSECURE BIT(25)
#define MC_ERR_STATUS_RT_TYPE_MASK (0xf << 28)
#define MC_ERR_STATUS_RT_TYPE_SHIFT 28
#define MC_ERR_STATUS_ADR_HI_SHIFT 20
#define MC_ERR_STATUS_ADR_HI_MASK 0x3
#define MC_ERR_STATUS_SECURITY BIT(17)
#define MC_ERR_STATUS_RW BIT(16)
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff
#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30)
#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31)
#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3
#define MC_TIMING_UPDATE BIT(0)
#define MC_BROADCAST_CHANNEL ~0
/* Tegra264 specific registers */
/* Registers for MSS HUB */
#define MSS_HUB_GLOBAL_INTSTATUS_0 0x6000
#define MSS_HUBC_INTR BIT(0)
#define MSS_HUB_GLOBAL_MASK 0x7F00
#define MSS_HUB_GLOBAL_SHIFT 8
#define MSS_HUB_HUBC_INTSTATUS_0 0x6008
#define MSS_HUB_INTRSTATUS_0 0x600c
#define MSS_HUB_HUBC_INTMASK_0 0x6010
#define MSS_HUB_HUBC_SCRUB_DONE_INTMASK BIT(0)
#define MSS_HUB_HUBC_INTPRIORITY_0 0x6014
#define MSS_HUB_INTRMASK_0 0x6018
#define MSS_HUB_COALESCER_ERR_INTMASK BIT(0)
#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK BIT(1)
#define MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK BIT(2)
#define MSS_HUB_MSI_ERR_INTMASK BIT(3)
#define MSS_HUB_POISON_RSP_INTMASK BIT(4)
#define MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK BIT(5)
#define MSS_HUB_RESERVED_PA_ERR_INTMASK BIT(6)
#define MSS_HUB_INTRPRIORITY_0 0x601c
#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0 0x6020
#define MSS_HUB_MSI_ERR_STATUS_0 0x6024
#define MSS_HUB_POISON_RSP_STATUS_0 0x6028
#define MSS_HUB_COALESCE_ERR_STATUS_0 0x60e0
#define MSS_HUB_COALESCE_ERR_ADR_HI_0 0x60e4
#define MSS_HUB_COALESCE_ERR_ADR_0 0x60e8
#define MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0 0x638c
#define MSS_HUB_RESERVED_PA_ERR_STATUS_0 0x6390
#define MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0 0x63b0
/* Registers for channels */
#define MC_CH_INTSTATUS_0 0x82d4
#define MC_CH_INTMASK_0 0x82d8
#define WCAM_ERR_INTMASK BIT(19)
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0 0xbc74
/* Registers for MCF */
#define MCF_COMMON_INTSTATUS0_0_0 0xce04
#define MCF_INTSTATUS_0 0xce2c
#define MCF_INTMASK_0 0xce30
#define MCF_INTPRIORITY_0 0xce34
/* Registers for SBS */
#define MSS_SBS_INTSTATUS_0 0xec08
#define MSS_SBS_INTMASK_0 0xec0c
#define MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK BIT(0)
#define MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK BIT(1)
#define MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK BIT(2)
/* Bit field of MC_ERR_ROUTE_SANITY_STATUS_0 register */
#define MC_ERR_ROUTE_SANITY_RW BIT(12)
#define MC_ERR_ROUTE_SANITY_SEC BIT(13)
#define ERR_GENERALIZED_APERTURE_ID_SHIFT 0
#define ERR_GENERALIZED_APERTURE_ID_MASK 0x1F
#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT 5
#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK 0x1F
static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents)
{
val = val * percents;
@@ -203,8 +261,9 @@ extern const struct tegra_mc_ops tegra186_mc_ops;
#endif
irqreturn_t tegra30_mc_handle_irq(int irq, void *data);
extern const irq_handler_t tegra30_mc_irq_handlers[1];
extern const char * const tegra_mc_status_names[32];
extern const char * const tegra_mc_error_names[8];
extern const char * const tegra20_mc_error_names[8];
/*
* These IDs are for internal use of Tegra ICC drivers. The ID numbers are

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/of.h>
@@ -1101,6 +1101,14 @@ static const struct tegra_mc_reset tegra114_mc_resets[] = {
TEGRA114_MC_RESET(VI, 0x200, 0x204, 17),
};
static const struct tegra_mc_intmask tegra114_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
MC_INT_DECERR_EMEM,
},
};
const struct tegra_mc_soc tegra114_mc_soc = {
.clients = tegra114_mc_clients,
.num_clients = ARRAY_SIZE(tegra114_mc_clients),
@@ -1108,10 +1116,14 @@ const struct tegra_mc_soc tegra114_mc_soc = {
.atom_size = 32,
.client_id_mask = 0x7f,
.smmu = &tegra114_smmu_soc,
.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
MC_INT_DECERR_EMEM,
.intmasks = tegra114_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra114_mc_intmasks),
.reset_ops = &tegra_mc_reset_ops_common,
.resets = tegra114_mc_resets,
.num_resets = ARRAY_SIZE(tegra114_mc_resets),
.ops = &tegra30_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_err_status_type_mask = (0x7 << 28),
};

View File

@@ -608,7 +608,7 @@ static int tegra124_emc_prepare_timing_change(struct tegra_emc *emc,
if ((last->emc_mode_1 & 0x1) == (timing->emc_mode_1 & 0x1))
dll_change = DLL_CHANGE_NONE;
else if (timing->emc_mode_1 & 0x1)
else if (!(timing->emc_mode_1 & 0x1))
dll_change = DLL_CHANGE_ON;
else
dll_change = DLL_CHANGE_OFF;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/of.h>
@@ -1258,6 +1258,15 @@ static const struct tegra_smmu_soc tegra124_smmu_soc = {
.num_asids = 128,
};
static const struct tegra_mc_intmask tegra124_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
},
};
const struct tegra_mc_soc tegra124_mc_soc = {
.clients = tegra124_mc_clients,
.num_clients = ARRAY_SIZE(tegra124_mc_clients),
@@ -1267,14 +1276,18 @@ const struct tegra_mc_soc tegra124_mc_soc = {
.smmu = &tegra124_smmu_soc,
.emem_regs = tegra124_mc_emem_regs,
.num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs),
.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.intmasks = tegra124_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra124_mc_intmasks),
.reset_ops = &tegra_mc_reset_ops_common,
.resets = tegra124_mc_resets,
.num_resets = ARRAY_SIZE(tegra124_mc_resets),
.icc_ops = &tegra124_mc_icc_ops,
.ops = &tegra30_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_addr_hi_mask = 0x3,
.mc_err_status_type_mask = (0x7 << 28),
};
#endif /* CONFIG_ARCH_TEGRA_124_SOC */
@@ -1292,6 +1305,15 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = {
.num_asids = 128,
};
static const struct tegra_mc_intmask tegra132_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
},
};
const struct tegra_mc_soc tegra132_mc_soc = {
.clients = tegra124_mc_clients,
.num_clients = ARRAY_SIZE(tegra124_mc_clients),
@@ -1299,13 +1321,17 @@ const struct tegra_mc_soc tegra132_mc_soc = {
.atom_size = 32,
.client_id_mask = 0x7f,
.smmu = &tegra132_smmu_soc,
.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.intmasks = tegra132_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra132_mc_intmasks),
.reset_ops = &tegra_mc_reset_ops_common,
.resets = tegra124_mc_resets,
.num_resets = ARRAY_SIZE(tegra124_mc_resets),
.icc_ops = &tegra124_mc_icc_ops,
.ops = &tegra30_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_addr_hi_mask = 0x3,
.mc_err_status_type_mask = (0x7 << 28),
};
#endif /* CONFIG_ARCH_TEGRA_132_SOC */

View File

@@ -22,6 +22,7 @@ struct tegra186_emc {
struct tegra_bpmp *bpmp;
struct device *dev;
struct clk *clk;
struct clk *clk_dbb;
struct tegra186_emc_dvfs *dvfs;
unsigned int num_dvfs;
@@ -328,6 +329,13 @@ static int tegra186_emc_probe(struct platform_device *pdev)
goto put_bpmp;
}
emc->clk_dbb = devm_clk_get_optional_enabled(&pdev->dev, "dbb");
if (IS_ERR(emc->clk_dbb)) {
err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk_dbb),
"failed to get DBB clock\n");
goto put_bpmp;
}
platform_set_drvdata(pdev, emc);
emc->dev = &pdev->dev;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017-2025 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/io.h>
@@ -174,7 +174,6 @@ const struct tegra_mc_ops tegra186_mc_ops = {
.remove = tegra186_mc_remove,
.resume = tegra186_mc_resume,
.probe_device = tegra186_mc_probe_device,
.handle_irq = tegra30_mc_handle_irq,
};
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
@@ -902,17 +901,30 @@ static const struct tegra_mc_client tegra186_mc_clients[] = {
},
};
static const struct tegra_mc_intmask tegra186_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = 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,
},
};
const struct tegra_mc_soc tegra186_mc_soc = {
.num_clients = ARRAY_SIZE(tegra186_mc_clients),
.clients = tegra186_mc_clients,
.num_address_bits = 40,
.num_channels = 4,
.client_id_mask = 0xff,
.intmask = 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,
.intmasks = tegra186_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks),
.ops = &tegra186_mc_ops,
.ch_intmask = 0x0000000f,
.global_intstatus_channel_shift = 0,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_addr_hi_mask = 0x3,
.mc_err_status_type_mask = (0x7 << 28),
};
#endif

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-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <soc/tegra/mc.h>
@@ -1343,19 +1343,31 @@ static const struct tegra_mc_client tegra194_mc_clients[] = {
},
};
static const struct tegra_mc_intmask tegra194_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = 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,
},
};
const struct tegra_mc_soc tegra194_mc_soc = {
.num_clients = ARRAY_SIZE(tegra194_mc_clients),
.clients = tegra194_mc_clients,
.num_address_bits = 40,
.num_channels = 16,
.client_id_mask = 0xff,
.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,
.intmasks = tegra194_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra194_mc_intmasks),
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
.icc_ops = &tegra_mc_icc_ops,
.ch_intmask = 0x00000f00,
.global_intstatus_channel_shift = 8,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_addr_hi_mask = 0x3,
.mc_err_status_type_mask = (0x7 << 28),
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2012-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/bitfield.h>
@@ -695,7 +695,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
unsigned int bit;
/* mask all interrupts to avoid flooding */
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
if (!status)
return IRQ_NONE;
@@ -713,7 +713,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
value = mc_readl(mc, reg);
id = value & mc->soc->client_id_mask;
desc = tegra_mc_error_names[2];
desc = tegra20_mc_error_names[2];
if (value & BIT(31))
direction = "write";
@@ -724,7 +724,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
value = mc_readl(mc, reg);
id = (value >> 1) & mc->soc->client_id_mask;
desc = tegra_mc_error_names[2];
desc = tegra20_mc_error_names[2];
if (value & BIT(0))
direction = "write";
@@ -736,7 +736,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
id = value & mc->soc->client_id_mask;
type = (value & BIT(30)) ? 4 : 3;
desc = tegra_mc_error_names[type];
desc = tegra20_mc_error_names[type];
secure = "secure ";
if (value & BIT(31))
@@ -761,9 +761,20 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
return IRQ_HANDLED;
}
static const irq_handler_t tegra20_mc_irq_handlers[] = {
tegra20_mc_handle_irq
};
static const struct tegra_mc_ops tegra20_mc_ops = {
.probe = tegra20_mc_probe,
.handle_irq = tegra20_mc_handle_irq,
};
static const struct tegra_mc_intmask tegra20_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
MC_INT_DECERR_EMEM,
},
};
const struct tegra_mc_soc tegra20_mc_soc = {
@@ -771,11 +782,15 @@ const struct tegra_mc_soc tegra20_mc_soc = {
.num_clients = ARRAY_SIZE(tegra20_mc_clients),
.num_address_bits = 32,
.client_id_mask = 0x3f,
.intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
MC_INT_DECERR_EMEM,
.intmasks = tegra20_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra20_mc_intmasks),
.reset_ops = &tegra20_mc_reset_ops,
.resets = tegra20_mc_resets,
.num_resets = ARRAY_SIZE(tegra20_mc_resets),
.icc_ops = &tegra20_mc_icc_ops,
.ops = &tegra20_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra20_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers),
.mc_err_status_type_mask = (0x7 << 28),
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2015-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <dt-bindings/memory/tegra210-mc.h>
@@ -1273,6 +1273,15 @@ static const struct tegra_mc_reset tegra210_mc_resets[] = {
TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13),
};
static const struct tegra_mc_intmask tegra210_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
},
};
const struct tegra_mc_soc tegra210_mc_soc = {
.clients = tegra210_mc_clients,
.num_clients = ARRAY_SIZE(tegra210_mc_clients),
@@ -1280,11 +1289,15 @@ const struct tegra_mc_soc tegra210_mc_soc = {
.atom_size = 64,
.client_id_mask = 0xff,
.smmu = &tegra210_smmu_soc,
.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.intmasks = tegra210_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra210_mc_intmasks),
.reset_ops = &tegra_mc_reset_ops_common,
.resets = tegra210_mc_resets,
.num_resets = ARRAY_SIZE(tegra210_mc_resets),
.ops = &tegra30_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_addr_hi_mask = 0x3,
.mc_err_status_type_mask = (0x7 << 28),
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2022-2026, NVIDIA CORPORATION. All rights reserved.
*/
#include <soc/tegra/mc.h>
@@ -1132,16 +1132,23 @@ static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
.set = tegra234_mc_icc_set,
};
static const struct tegra_mc_intmask tegra234_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = 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,
},
};
const struct tegra_mc_soc tegra234_mc_soc = {
.num_clients = ARRAY_SIZE(tegra234_mc_clients),
.clients = tegra234_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,
.intmasks = tegra234_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra234_mc_intmasks),
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
.icc_ops = &tegra234_mc_icc_ops,
@@ -1152,4 +1159,9 @@ const struct tegra_mc_soc tegra234_mc_soc = {
* supported.
*/
.num_carveouts = 32,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_addr_hi_mask = 0x3,
.mc_err_status_type_mask = (0x7 << 28),
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2025, NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2025-2026, NVIDIA CORPORATION. All rights reserved.
*/
#include <dt-bindings/memory/nvidia,tegra264.h>
@@ -188,6 +188,41 @@ static const struct tegra_mc_client tegra264_mc_clients[] = {
},
};
static const char *const tegra264_hub_error_names[32] = {
[0] = "coalescer error",
[1] = "SMMU BYPASS ALLOW error",
[2] = "Illegal tbugrp_id error",
[3] = "Malformed MSI request error",
[4] = "Read response with poison bit error",
[5] = "Restricted access violation error",
[6] = "Reserved PA error",
};
static const char *const tegra264_mc_error_names[4] = {
[1] = "EMEM decode error",
[2] = "TrustZone violation",
[3] = "Carveout violation",
};
static const char *const tegra264_rt_error_names[16] = {
[1] = "DECERR_PARTIAL_POPULATED",
[2] = "DECERR_SMMU_BYPASS",
[3] = "DECERR_INVALID_MMIO",
[4] = "DECERR_INVALID_GIC_MSI",
[5] = "DECERR_ATOMIC_SYSRAM",
[9] = "DECERR_REMOTE_REQ_PRE_BOOT",
[10] = "DECERR_ISO_OVER_C2C",
[11] = "DECERR_UNSUPPORTED_SBS_OPCODE",
[12] = "DECERR_SBS_REQ_OVER_SISO_LL",
};
/*
* MC instance aperture mapping for hubc registers
*/
static const int mc_hubc_aperture_number[5] = {
7, 8, 9, 10, 11
};
/*
* tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW
* @src: ICC node for Memory Controller's (MC) Client
@@ -283,6 +318,312 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
return 0;
}
static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus)
{
unsigned int bit;
for_each_set_bit(bit, &mcf_ch_intstatus, 32) {
const char *client = "unknown", *desc = "NA";
u32 status_reg, status1_reg = 0, addr_reg, addr_hi_reg = 0, err_type_mask = 0;
u32 value, client_id, i, addr_hi_shift = 0, addr_hi_mask = 0, status1;
u32 mc_rw_bit = MC_ERR_STATUS_RW, mc_sec_bit = MC_ERR_STATUS_SECURITY;
phys_addr_t addr = 0;
u8 type;
switch (BIT(bit)) {
case MC_INT_DECERR_EMEM:
case MC_INT_SECURITY_VIOLATION:
status_reg = mc->soc->regs->err_status;
addr_reg = mc->soc->regs->err_add;
addr_hi_reg = mc->soc->regs->err_add_hi;
err_type_mask = mc->soc->mc_err_status_type_mask;
break;
case MC_INT_DECERR_VPR:
status_reg = mc->soc->regs->err_vpr_status;
addr_reg = mc->soc->regs->err_vpr_add;
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
addr_hi_mask = mc->soc->mc_addr_hi_mask;
break;
case MC_INT_SECERR_SEC:
status_reg = mc->soc->regs->err_sec_status;
addr_reg = mc->soc->regs->err_sec_add;
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
addr_hi_mask = mc->soc->mc_addr_hi_mask;
break;
case MC_INT_DECERR_MTS:
status_reg = mc->soc->regs->err_mts_status;
addr_reg = mc->soc->regs->err_mts_add;
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
addr_hi_mask = mc->soc->mc_addr_hi_mask;
break;
case MC_INT_DECERR_GENERALIZED_CARVEOUT:
status_reg = mc->soc->regs->err_gen_co_status;
status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0;
addr_reg = mc->soc->regs->err_gen_co_add;
addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT;
addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK;
break;
case MC_INT_DECERR_ROUTE_SANITY:
case MC_INT_DECERR_ROUTE_SANITY_GIC_MSI:
status_reg = mc->soc->regs->err_route_status;
addr_reg = mc->soc->regs->err_route_add;
addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT;
addr_hi_mask = mc->soc->mc_addr_hi_mask;
mc_sec_bit = MC_ERR_ROUTE_SANITY_SEC;
mc_rw_bit = MC_ERR_ROUTE_SANITY_RW;
err_type_mask = MC_ERR_STATUS_RT_TYPE_MASK;
break;
default:
dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n");
return;
}
value = mc_ch_readl(mc, channel, status_reg);
if (addr_hi_reg) {
addr = mc_ch_readl(mc, channel, addr_hi_reg);
} else {
if (!status1_reg) {
addr = ((value >> addr_hi_shift) & addr_hi_mask);
} else {
status1 = mc_ch_readl(mc, channel, status1_reg);
addr = ((status1 >> addr_hi_shift) & addr_hi_mask);
}
}
addr <<= 32;
addr |= mc_ch_readl(mc, channel, addr_reg);
client_id = value & mc->soc->client_id_mask;
for (i = 0; i < mc->soc->num_clients; i++) {
if (mc->soc->clients[i].id == client_id) {
client = mc->soc->clients[i].name;
break;
}
}
if (err_type_mask == MC_ERR_STATUS_RT_TYPE_MASK) {
type = (value & err_type_mask) >>
MC_ERR_STATUS_RT_TYPE_SHIFT;
desc = tegra264_rt_error_names[type];
} else if (err_type_mask) {
type = (value & err_type_mask) >>
MC_ERR_STATUS_TYPE_SHIFT;
desc = tegra264_mc_error_names[type];
}
dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n",
client, value & mc_sec_bit ? "secure" : "non-secure",
value & mc_rw_bit ? "write" : "read", &addr,
tegra_mc_status_names[bit] ?: "unknown", desc);
if (status1_reg)
dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n",
((status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT)
& ERR_GENERALIZED_APERTURE_ID_MASK),
((status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT)
& ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK));
}
/* clear interrupts */
mc_ch_writel(mc, channel, mcf_ch_intstatus, MCF_INTSTATUS_0);
}
static irqreturn_t handle_mcf_irq(int irq, void *data)
{
struct tegra_mc *mc = data;
unsigned long common_intstat, intstatus;
u32 slice;
/* Read MCF_COMMON_INTSTATUS0_0_0 from MCB block */
common_intstat = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, MCF_COMMON_INTSTATUS0_0_0);
if (common_intstat == 0) {
dev_warn(mc->dev, "No interrupt in MCF\n");
return IRQ_NONE;
}
for_each_set_bit(slice, &common_intstat, 32) {
/* Find out the slice number on which interrupt occurred */
if (slice > 4) {
dev_err(mc->dev, "Slice index out of bounds: %u\n", slice);
return IRQ_NONE;
}
intstatus = mc_ch_readl(mc, slice, MCF_INTSTATUS_0);
if (intstatus != 0)
mcf_log_fault(mc, slice, intstatus);
}
return IRQ_HANDLED;
}
static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat)
{
unsigned int bit;
for_each_set_bit(bit, &hub_intstat, 32) {
const char *client = "unknown";
u32 client_id, status_reg, value, i;
phys_addr_t addr = 0;
switch (BIT(bit)) {
case MSS_HUB_COALESCER_ERR_INTMASK:
status_reg = MSS_HUB_COALESCE_ERR_STATUS_0;
addr = mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_HI_0);
addr <<= 32;
addr |= mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_0);
break;
case MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK:
status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0;
break;
case MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK:
status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0;
break;
case MSS_HUB_MSI_ERR_INTMASK:
status_reg = MSS_HUB_MSI_ERR_STATUS_0;
break;
case MSS_HUB_POISON_RSP_INTMASK:
status_reg = MSS_HUB_POISON_RSP_STATUS_0;
break;
case MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK:
status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0;
break;
case MSS_HUB_RESERVED_PA_ERR_INTMASK:
status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0;
break;
default:
dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n");
return;
}
value = mc_ch_readl(mc, hub, status_reg);
client_id = value & mc->soc->client_id_mask;
for (i = 0; i < mc->soc->num_clients; i++) {
if (mc->soc->clients[i].id == client_id) {
client = mc->soc->clients[i].name;
break;
}
}
dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n",
client, &addr, tegra264_hub_error_names[bit] ?: "unknown",
value);
}
/* clear interrupts */
mc_ch_writel(mc, hub, hub_intstat, MSS_HUB_INTRSTATUS_0);
}
static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_number)
{
struct tegra_mc *mc = data;
u32 global_intstat;
unsigned long hub_interrupt, intstat, hub;
/* Read MSS_HUB_GLOBAL_INTSTATUS_0 from mc_hubc_aperture_number block */
global_intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_GLOBAL_INTSTATUS_0);
if (global_intstat == 0) {
dev_warn(mc->dev, "No interrupt in HUB/HUBC\n");
return IRQ_NONE;
}
/* Handle interrupt from hubc */
if (global_intstat & MSS_HUBC_INTR) {
/* Read MSS_HUB_HUBC_INTSTATUS_0 from block mc_hubc_aperture_number */
intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_HUBC_INTSTATUS_0);
if (intstat != 0) {
dev_err_ratelimited(mc->dev, "Scrubber operation status: 0x%lx\n",
intstat);
/* Clear hubc interrupt */
mc_ch_writel(mc, mc_hubc_aperture_number, intstat,
MSS_HUB_HUBC_INTSTATUS_0);
}
}
hub_interrupt = (global_intstat & MSS_HUB_GLOBAL_MASK) >> MSS_HUB_GLOBAL_SHIFT;
/* Handle interrupt from hub */
for_each_set_bit(hub, &hub_interrupt, 32) {
/* Read MSS_HUB_INTRSTATUS_0 from block MCi */
intstat = mc_ch_readl(mc, hub, MSS_HUB_INTRSTATUS_0);
if (intstat != 0)
hub_log_fault(mc, hub, intstat);
}
/* Clear global interrupt status register */
mc_ch_writel(mc, mc_hubc_aperture_number, global_intstat, MSS_HUB_GLOBAL_INTSTATUS_0);
return IRQ_HANDLED;
}
static irqreturn_t handle_disp_hub_irq(int irq, void *data)
{
return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]);
}
static irqreturn_t handle_system_hub_irq(int irq, void *data)
{
return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]);
}
static irqreturn_t handle_vision_hub_irq(int irq, void *data)
{
return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]);
}
static irqreturn_t handle_uphy_hub_irq(int irq, void *data)
{
return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]);
}
static irqreturn_t handle_top_hub_irq(int irq, void *data)
{
return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]);
}
static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg)
{
u32 intstat, i;
/* Iterate over all MC blocks to read INTSTATUS */
for (i = 0; i < mc->num_channels; i++) {
intstat = mc_ch_readl(mc, i, intstat_reg);
if (intstat) {
dev_err_ratelimited(mc->dev, "channel: %i status: 0x%x\n", i, intstat);
/* Clear interrupt */
mc_ch_writel(mc, i, intstat, intstat_reg);
}
}
return IRQ_HANDLED;
}
static irqreturn_t handle_sbs_irq(int irq, void *data)
{
return handle_generic_irq((struct tegra_mc *)data, MSS_SBS_INTSTATUS_0);
}
static irqreturn_t handle_channel_irq(int irq, void *data)
{
return handle_generic_irq((struct tegra_mc *)data, MC_CH_INTSTATUS_0);
}
static const irq_handler_t tegra264_mc_irq_handlers[8] = {
handle_mcf_irq, handle_disp_hub_irq, handle_vision_hub_irq,
handle_system_hub_irq, handle_uphy_hub_irq, handle_top_hub_irq,
handle_sbs_irq, handle_channel_irq
};
static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = {
.xlate = tegra_mc_icc_xlate,
.aggregate = tegra264_mc_icc_aggregate,
@@ -290,16 +631,80 @@ static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = {
.set = tegra264_mc_icc_set,
};
static const struct tegra_mc_regs tegra264_mc_regs = {
.cfg_channel_enable = 0x8870,
.err_status = 0xbc00,
.err_add = 0xbc04,
.err_add_hi = 0xbc08,
.err_vpr_status = 0xbc20,
.err_vpr_add = 0xbc24,
.err_sec_status = 0xbc3c,
.err_sec_add = 0xbc40,
.err_mts_status = 0xbc5c,
.err_mts_add = 0xbc60,
.err_gen_co_status = 0xbc78,
.err_gen_co_add = 0xbc7c,
.err_route_status = 0xbc64,
.err_route_add = 0xbc68,
};
static const struct tegra_mc_intmask tegra264_mc_intmasks[] = {
{
.reg = MCF_INTMASK_0,
.mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | 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,
},
{
.reg = MCF_INTPRIORITY_0,
.mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | 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,
},
{
.reg = MSS_HUB_INTRMASK_0,
.mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK |
MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK |
MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK |
MSS_HUB_RESERVED_PA_ERR_INTMASK,
},
{
.reg = MSS_HUB_INTRPRIORITY_0,
.mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK |
MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK |
MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK |
MSS_HUB_RESERVED_PA_ERR_INTMASK,
},
{
.reg = MSS_HUB_HUBC_INTMASK_0,
.mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK,
},
{
.reg = MSS_HUB_HUBC_INTPRIORITY_0,
.mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK,
},
{
.reg = MSS_SBS_INTMASK_0,
.mask = MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK |
MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK |
MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK,
},
{
.reg = MC_CH_INTMASK_0,
.mask = WCAM_ERR_INTMASK,
}
};
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,
.intmasks = tegra264_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra264_mc_intmasks),
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
.icc_ops = &tegra264_mc_icc_ops,
@@ -310,4 +715,9 @@ const struct tegra_mc_soc tegra264_mc_soc = {
* supported.
*/
.num_carveouts = 32,
.mc_addr_hi_mask = 0xff,
.mc_err_status_type_mask = (0x3 << 28),
.regs = &tegra264_mc_regs,
.handle_irq = tegra264_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra264_mc_irq_handlers),
};

View File

@@ -554,14 +554,14 @@ static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
emc->emc_cfg = readl_relaxed(emc->regs + EMC_CFG);
emc_dbg = readl_relaxed(emc->regs + EMC_DBG);
if (emc->dll_on == !!(timing->emc_mode_1 & 0x1))
if (emc->dll_on == !(timing->emc_mode_1 & 0x1))
dll_change = DLL_CHANGE_NONE;
else if (timing->emc_mode_1 & 0x1)
else if (!(timing->emc_mode_1 & 0x1))
dll_change = DLL_CHANGE_ON;
else
dll_change = DLL_CHANGE_OFF;
emc->dll_on = !!(timing->emc_mode_1 & 0x1);
emc->dll_on = !(timing->emc_mode_1 & 0x1);
if (timing->data[80] && !readl_relaxed(emc->regs + EMC_ZCAL_INTERVAL))
emc->zcal_long = true;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/device.h>
@@ -1384,6 +1384,14 @@ static const struct tegra_mc_icc_ops tegra30_mc_icc_ops = {
.set = tegra30_mc_icc_set,
};
static const struct tegra_mc_intmask tegra30_mc_intmasks[] = {
{
.reg = MC_INTMASK,
.mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
MC_INT_DECERR_EMEM,
},
};
const struct tegra_mc_soc tegra30_mc_soc = {
.clients = tegra30_mc_clients,
.num_clients = ARRAY_SIZE(tegra30_mc_clients),
@@ -1393,11 +1401,15 @@ const struct tegra_mc_soc tegra30_mc_soc = {
.smmu = &tegra30_smmu_soc,
.emem_regs = tegra30_mc_emem_regs,
.num_emem_regs = ARRAY_SIZE(tegra30_mc_emem_regs),
.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
MC_INT_DECERR_EMEM,
.intmasks = tegra30_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra30_mc_intmasks),
.reset_ops = &tegra_mc_reset_ops_common,
.resets = tegra30_mc_resets,
.num_resets = ARRAY_SIZE(tegra30_mc_resets),
.icc_ops = &tegra30_mc_icc_ops,
.ops = &tegra30_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
.mc_err_status_type_mask = (0x7 << 28),
};

View File

@@ -367,7 +367,7 @@ static const struct regmap_config s2mpg11_regmap_config_meter = {
};
struct sec_pmic_acpm_shared_bus_context {
const struct acpm_handle *acpm;
struct acpm_handle *acpm;
unsigned int acpm_chan_id;
u8 speedy_channel;
};
@@ -390,7 +390,7 @@ static int sec_pmic_acpm_bus_write(void *context, const void *data,
size_t count)
{
struct sec_pmic_acpm_bus_context *ctx = context;
const struct acpm_handle *acpm = ctx->shared->acpm;
struct acpm_handle *acpm = ctx->shared->acpm;
const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS);
const u8 *d = data;
@@ -410,7 +410,7 @@ static int sec_pmic_acpm_bus_read(void *context, const void *reg_buf, size_t reg
void *val_buf, size_t val_size)
{
struct sec_pmic_acpm_bus_context *ctx = context;
const struct acpm_handle *acpm = ctx->shared->acpm;
struct acpm_handle *acpm = ctx->shared->acpm;
const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
const u8 *r = reg_buf;
u8 reg;
@@ -429,7 +429,7 @@ static int sec_pmic_acpm_bus_reg_update_bits(void *context, unsigned int reg, un
unsigned int val)
{
struct sec_pmic_acpm_bus_context *ctx = context;
const struct acpm_handle *acpm = ctx->shared->acpm;
struct acpm_handle *acpm = ctx->shared->acpm;
const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id, ctx->type, reg & 0xff,
@@ -480,7 +480,7 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
struct regmap *regmap_common, *regmap_pmic, *regmap;
const struct sec_pmic_acpm_platform_data *pdata;
struct sec_pmic_acpm_shared_bus_context *shared_ctx;
const struct acpm_handle *acpm;
struct acpm_handle *acpm;
struct device *dev = &pdev->dev;
int ret, irq;

View File

@@ -4,6 +4,7 @@
* Author: Clément Le Goffic <clement.legoffic@foss.st.com> for STMicroelectronics.
*/
#include <linux/bits.h>
#include <linux/bus/stm32_firewall_device.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/generic.h>
@@ -46,9 +47,11 @@ struct stm32_hdp {
void __iomem *base;
struct clk *clk;
struct pinctrl_dev *pctl_dev;
struct stm32_firewall *firewall;
struct gpio_generic_chip gpio_chip;
u32 mux_conf;
u32 gposet_conf;
int nb_firewall_entries;
const char * const *func_name;
};
@@ -615,6 +618,13 @@ static int stm32_hdp_probe(struct platform_device *pdev)
return -ENOMEM;
hdp->dev = dev;
if (IS_ENABLED(CONFIG_STM32_FIREWALL)) {
err = stm32_firewall_get_grant_all_access(dev, &hdp->firewall,
&hdp->nb_firewall_entries);
if (err)
return err;
}
platform_set_drvdata(pdev, hdp);
hdp->base = devm_platform_ioremap_resource(pdev, 0);
@@ -670,8 +680,12 @@ static int stm32_hdp_probe(struct platform_device *pdev)
static void stm32_hdp_remove(struct platform_device *pdev)
{
struct stm32_hdp *hdp = platform_get_drvdata(pdev);
int i;
writel_relaxed(HDP_CTRL_DISABLE, hdp->base + HDP_CTRL);
for (i = 0; i < hdp->nb_firewall_entries; i++)
stm32_firewall_release_access(&hdp->firewall[i]);
}
static int stm32_hdp_suspend(struct device *dev)

View File

@@ -257,6 +257,8 @@ config RESET_RZG2L_USBPHY_CTRL
config RESET_RZV2H_USB2PHY
tristate "Renesas RZ/V2H(P) (and similar SoCs) USB2PHY Reset driver"
depends on ARCH_RENESAS || COMPILE_TEST
select AUXILIARY_BUS
select REGMAP_MMIO
help
Support for USB2PHY Port reset Control found on the RZ/V2H(P) SoC
(and similar SoCs).
@@ -291,6 +293,13 @@ config RESET_SIMPLE
- SiFive FU740 SoCs
- Sophgo SoCs
config RESET_SKY1
bool "Cix Sky1 reset controller"
depends on ARCH_CIX || COMPILE_TEST
select REGMAP_MMIO
help
This enables the reset controller for Cix Sky1.
config RESET_SOCFPGA
bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)
default ARM && ARCH_INTEL_SOCFPGA

View File

@@ -38,6 +38,7 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
obj-$(CONFIG_RESET_RZV2H_USB2PHY) += reset-rzv2h-usb2phy.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_SKY1) += reset-sky1.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,6 @@
struct ath79_reset {
struct reset_controller_dev rcdev;
struct notifier_block restart_nb;
void __iomem *base;
spinlock_t lock;
};
@@ -72,11 +71,9 @@ static const struct reset_control_ops ath79_reset_ops = {
.status = ath79_reset_status,
};
static int ath79_reset_restart_handler(struct notifier_block *nb,
unsigned long action, void *data)
static int ath79_reset_restart_handler(struct sys_off_data *data)
{
struct ath79_reset *ath79_reset =
container_of(nb, struct ath79_reset, restart_nb);
struct ath79_reset *ath79_reset = data->cb_data;
ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET);
@@ -108,10 +105,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
if (err)
return err;
ath79_reset->restart_nb.notifier_call = ath79_reset_restart_handler;
ath79_reset->restart_nb.priority = 128;
err = register_restart_handler(&ath79_reset->restart_nb);
err = devm_register_restart_handler(&pdev->dev, ath79_reset_restart_handler, ath79_reset);
if (err)
dev_warn(&pdev->dev, "Failed to register restart handler\n");

View File

@@ -4,7 +4,7 @@
#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/property.h>
#include <linux/reset-controller.h>
struct reset_gpio_priv {
@@ -46,34 +46,22 @@ static const struct reset_control_ops reset_gpio_ops = {
.status = reset_gpio_status,
};
static int reset_gpio_of_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
static int reset_gpio_fwnode_xlate(struct reset_controller_dev *rcdev,
const struct fwnode_reference_args *reset_spec)
{
return reset_spec->args[0];
}
static void reset_gpio_of_node_put(void *data)
{
of_node_put(data);
}
static int reset_gpio_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct device *dev = &adev->dev;
struct of_phandle_args *platdata = dev_get_platdata(dev);
struct reset_gpio_priv *priv;
int ret;
if (!platdata)
return -EINVAL;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
auxiliary_set_drvdata(adev, &priv->rc);
priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(priv->reset))
return dev_err_probe(dev, PTR_ERR(priv->reset),
@@ -82,15 +70,10 @@ static int reset_gpio_probe(struct auxiliary_device *adev,
priv->rc.ops = &reset_gpio_ops;
priv->rc.owner = THIS_MODULE;
priv->rc.dev = dev;
priv->rc.of_args = platdata;
ret = devm_add_action_or_reset(dev, reset_gpio_of_node_put,
priv->rc.of_node);
if (ret)
return ret;
/* Cells to match GPIO specifier, but it's not really used */
priv->rc.of_reset_n_cells = 2;
priv->rc.of_xlate = reset_gpio_of_xlate;
priv->rc.fwnode_reset_n_cells = 2;
priv->rc.fwnode_xlate = reset_gpio_fwnode_xlate;
priv->rc.nr_resets = 1;
return devm_reset_controller_register(dev, &priv->rc);

View File

@@ -28,7 +28,6 @@ struct intel_reset_soc {
struct intel_reset_data {
struct reset_controller_dev rcdev;
struct notifier_block restart_nb;
const struct intel_reset_soc *soc_data;
struct regmap *regmap;
struct device *dev;
@@ -153,12 +152,10 @@ static int intel_reset_xlate(struct reset_controller_dev *rcdev,
return id;
}
static int intel_reset_restart_handler(struct notifier_block *nb,
unsigned long action, void *data)
static int intel_reset_restart_handler(struct sys_off_data *data)
{
struct intel_reset_data *reset_data;
struct intel_reset_data *reset_data = data->cb_data;
reset_data = container_of(nb, struct intel_reset_data, restart_nb);
intel_assert_device(&reset_data->rcdev, reset_data->reboot_id);
return NOTIFY_DONE;
@@ -215,9 +212,7 @@ static int intel_reset_probe(struct platform_device *pdev)
if (data->soc_data->legacy)
data->reboot_id |= FIELD_PREP(STAT_BIT_OFFSET_MASK, rb_id[2]);
data->restart_nb.notifier_call = intel_reset_restart_handler;
data->restart_nb.priority = 128;
register_restart_handler(&data->restart_nb);
devm_register_restart_handler(&pdev->dev, intel_reset_restart_handler, data);
return 0;
}

View File

@@ -31,7 +31,6 @@
struct lpc18xx_rgu_data {
struct reset_controller_dev rcdev;
struct notifier_block restart_nb;
struct clk *clk_delay;
struct clk *clk_reg;
void __iomem *base;
@@ -41,11 +40,9 @@ struct lpc18xx_rgu_data {
#define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode,
void *cmd)
static int lpc18xx_rgu_restart(struct sys_off_data *data)
{
struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data,
restart_nb);
struct lpc18xx_rgu_data *rc = data->cb_data;
writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0);
mdelay(2000);
@@ -178,9 +175,8 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(&pdev->dev, ret, "unable to register device\n");
rc->restart_nb.priority = 192,
rc->restart_nb.notifier_call = lpc18xx_rgu_restart,
ret = register_restart_handler(&rc->restart_nb);
ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, 192,
lpc18xx_rgu_restart, rc);
if (ret)
dev_warn(&pdev->dev, "failed to register restart handler\n");

View File

@@ -19,7 +19,6 @@
struct ma35d1_reset_data {
struct reset_controller_dev rcdev;
struct notifier_block restart_handler;
void __iomem *base;
/* protect registers against concurrent read-modify-write */
spinlock_t lock;
@@ -125,10 +124,9 @@ static const struct {
[MA35D1_RESET_SSPCC] = {0x2C, 31}
};
static int ma35d1_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd)
static int ma35d1_restart_handler(struct sys_off_data *sys_off_data)
{
struct ma35d1_reset_data *data =
container_of(this, struct ma35d1_reset_data, restart_handler);
struct ma35d1_reset_data *data = sys_off_data->cb_data;
u32 id = MA35D1_RESET_CHIP;
writel_relaxed(BIT(ma35d1_reset_map[id].bit),
@@ -213,11 +211,10 @@ static int ma35d1_reset_probe(struct platform_device *pdev)
reset_data->rcdev.nr_resets = MA35D1_RESET_COUNT;
reset_data->rcdev.ops = &ma35d1_reset_ops;
reset_data->rcdev.of_node = dev->of_node;
reset_data->restart_handler.notifier_call = ma35d1_restart_handler;
reset_data->restart_handler.priority = 192;
spin_lock_init(&reset_data->lock);
err = register_restart_handler(&reset_data->restart_handler);
err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, 192,
ma35d1_restart_handler, reset_data);
if (err)
dev_warn(&pdev->dev, "failed to register restart handler\n");

View File

@@ -89,7 +89,6 @@ static const struct npcm_reset_info npxm8xx_reset_info[] = {
struct npcm_rc_data {
struct reset_controller_dev rcdev;
struct notifier_block restart_nb;
const struct npcm_reset_info *info;
struct regmap *gcr_regmap;
u32 sw_reset_number;
@@ -100,11 +99,9 @@ struct npcm_rc_data {
#define to_rc_data(p) container_of(p, struct npcm_rc_data, rcdev)
static int npcm_rc_restart(struct notifier_block *nb, unsigned long mode,
void *cmd)
static int npcm_rc_restart(struct sys_off_data *data)
{
struct npcm_rc_data *rc = container_of(nb, struct npcm_rc_data,
restart_nb);
struct npcm_rc_data *rc = data->cb_data;
writel(NPCM_SWRST << rc->sw_reset_number, rc->base + NPCM_SWRSTR);
mdelay(1000);
@@ -472,9 +469,8 @@ static int npcm_rc_probe(struct platform_device *pdev)
if (!of_property_read_u32(pdev->dev.of_node, "nuvoton,sw-reset-number",
&rc->sw_reset_number)) {
if (rc->sw_reset_number && rc->sw_reset_number < 5) {
rc->restart_nb.priority = 192;
rc->restart_nb.notifier_call = npcm_rc_restart;
ret = register_restart_handler(&rc->restart_nb);
ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, 192,
npcm_rc_restart, rc);
if (ret) {
dev_warn(&pdev->dev, "failed to register restart handler\n");
return ret;

View File

@@ -5,42 +5,39 @@
* Copyright (C) 2025 Renesas Electronics Corporation
*/
#include <linux/cleanup.h>
#include <linux/auxiliary_bus.h>
#include <linux/delay.h>
#include <linux/idr.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
struct rzv2h_usb2phy_regval {
u16 reg;
u16 val;
};
static DEFINE_IDA(auxiliary_ids);
struct rzv2h_usb2phy_reset_of_data {
const struct rzv2h_usb2phy_regval *init_vals;
unsigned int init_val_count;
const struct reg_sequence *init_seq;
unsigned int init_nseq;
const struct reg_sequence *assert_seq;
unsigned int assert_nseq;
const struct reg_sequence *deassert_seq;
unsigned int deassert_nseq;
u16 reset_reg;
u16 reset_assert_val;
u16 reset_deassert_val;
u16 reset_status_bits;
u16 reset_release_val;
u16 reset2_reg;
u16 reset2_acquire_val;
u16 reset2_release_val;
};
struct rzv2h_usb2phy_reset_priv {
const struct rzv2h_usb2phy_reset_of_data *data;
void __iomem *base;
struct regmap *regmap;
struct device *dev;
struct reset_controller_dev rcdev;
spinlock_t lock; /* protects register accesses */
};
static inline struct rzv2h_usb2phy_reset_priv
@@ -49,81 +46,31 @@ static inline struct rzv2h_usb2phy_reset_priv
return container_of(rcdev, struct rzv2h_usb2phy_reset_priv, rcdev);
}
/* This function must be called only after pm_runtime_resume_and_get() has been called */
static void rzv2h_usbphy_assert_helper(struct rzv2h_usb2phy_reset_priv *priv)
{
const struct rzv2h_usb2phy_reset_of_data *data = priv->data;
scoped_guard(spinlock, &priv->lock) {
writel(data->reset2_acquire_val, priv->base + data->reset2_reg);
writel(data->reset_assert_val, priv->base + data->reset_reg);
}
usleep_range(11, 20);
}
static int rzv2h_usbphy_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev);
struct device *dev = priv->dev;
int ret;
ret = pm_runtime_resume_and_get(dev);
if (ret) {
dev_err(dev, "pm_runtime_resume_and_get failed\n");
return ret;
}
rzv2h_usbphy_assert_helper(priv);
pm_runtime_put(dev);
return 0;
return regmap_multi_reg_write(priv->regmap, priv->data->assert_seq,
priv->data->assert_nseq);
}
static int rzv2h_usbphy_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev);
const struct rzv2h_usb2phy_reset_of_data *data = priv->data;
struct device *dev = priv->dev;
int ret;
ret = pm_runtime_resume_and_get(dev);
if (ret) {
dev_err(dev, "pm_runtime_resume_and_get failed\n");
return ret;
}
scoped_guard(spinlock, &priv->lock) {
writel(data->reset_deassert_val, priv->base + data->reset_reg);
writel(data->reset2_release_val, priv->base + data->reset2_reg);
writel(data->reset_release_val, priv->base + data->reset_reg);
}
pm_runtime_put(dev);
return 0;
return regmap_multi_reg_write(priv->regmap, priv->data->deassert_seq,
priv->data->deassert_nseq);
}
static int rzv2h_usbphy_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev);
struct device *dev = priv->dev;
int ret;
u32 reg;
ret = pm_runtime_resume_and_get(dev);
if (ret) {
dev_err(dev, "pm_runtime_resume_and_get failed\n");
return ret;
}
reg = readl(priv->base + priv->data->reset_reg);
pm_runtime_put(dev);
regmap_read(priv->regmap, priv->data->reset_reg, &reg);
return (reg & priv->data->reset_status_bits) == priv->data->reset_status_bits;
}
@@ -141,12 +88,52 @@ static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev,
return 0;
}
static void rzv2h_usb2phy_reset_ida_free(void *data)
{
struct auxiliary_device *adev = data;
ida_free(&auxiliary_ids, adev->id);
}
static int rzv2h_usb2phy_reset_mux_register(struct device *dev,
const char *mux_name)
{
struct auxiliary_device *adev;
int id;
id = ida_alloc(&auxiliary_ids, GFP_KERNEL);
if (id < 0)
return id;
adev = __devm_auxiliary_device_create(dev, dev->driver->name,
mux_name, NULL, id);
if (!adev) {
ida_free(&auxiliary_ids, id);
return -ENOMEM;
}
return devm_add_action_or_reset(dev, rzv2h_usb2phy_reset_ida_free, adev);
}
static const struct regmap_config rzv2h_usb2phy_reset_regconf = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.can_sleep = true,
};
static void rzv2h_usb2phy_reset_pm_runtime_put(void *data)
{
pm_runtime_put(data);
}
static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
{
const struct rzv2h_usb2phy_reset_of_data *data;
struct rzv2h_usb2phy_reset_priv *priv;
struct device *dev = &pdev->dev;
struct reset_control *rstc;
void __iomem *base;
int error;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -156,17 +143,19 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
data = of_device_get_match_data(dev);
priv->data = data;
priv->dev = dev;
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
priv->regmap = devm_regmap_init_mmio(dev, base, &rzv2h_usb2phy_reset_regconf);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
rstc = devm_reset_control_get_shared_deasserted(dev, NULL);
if (IS_ERR(rstc))
return dev_err_probe(dev, PTR_ERR(rstc),
"failed to get deasserted reset\n");
spin_lock_init(&priv->lock);
error = devm_pm_runtime_enable(dev);
if (error)
return dev_err_probe(dev, error, "Failed to enable pm_runtime\n");
@@ -175,13 +164,14 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
if (error)
return dev_err_probe(dev, error, "pm_runtime_resume_and_get failed\n");
for (unsigned int i = 0; i < data->init_val_count; i++)
writel(data->init_vals[i].val, priv->base + data->init_vals[i].reg);
error = devm_add_action_or_reset(dev, rzv2h_usb2phy_reset_pm_runtime_put,
dev);
if (error)
return dev_err_probe(dev, error, "unable to register cleanup action\n");
/* keep usb2phy in asserted state */
rzv2h_usbphy_assert_helper(priv);
pm_runtime_put(dev);
error = regmap_multi_reg_write(priv->regmap, data->init_seq, data->init_nseq);
if (error)
return dev_err_probe(dev, error, "failed to initialize PHY registers\n");
priv->rcdev.ops = &rzv2h_usbphy_reset_ops;
priv->rcdev.of_reset_n_cells = 0;
@@ -190,30 +180,47 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
priv->rcdev.of_node = dev->of_node;
priv->rcdev.dev = dev;
return devm_reset_controller_register(dev, &priv->rcdev);
error = devm_reset_controller_register(dev, &priv->rcdev);
if (error)
return dev_err_probe(dev, error, "could not register reset controller\n");
error = rzv2h_usb2phy_reset_mux_register(dev, "vbenctl");
if (error)
return dev_err_probe(dev, error, "could not register aux mux\n");
return 0;
}
/*
* initialization values required to prepare the PHY to receive
* assert and deassert requests.
*/
static const struct rzv2h_usb2phy_regval rzv2h_init_vals[] = {
{ .reg = 0xc10, .val = 0x67c },
{ .reg = 0xc14, .val = 0x1f },
{ .reg = 0x600, .val = 0x909 },
static const struct reg_sequence rzv2h_init_seq[] = {
{ .reg = 0xc10, .def = 0x67c },
{ .reg = 0xc14, .def = 0x01f },
{ .reg = 0x600, .def = 0x909 },
};
static const struct reg_sequence rzv2h_assert_seq[] = {
{ .reg = 0xb04, .def = 0x303 },
{ .reg = 0x000, .def = 0x206, .delay_us = 11 },
};
static const struct reg_sequence rzv2h_deassert_seq[] = {
{ .reg = 0x000, .def = 0x200 },
{ .reg = 0xb04, .def = 0x003 },
{ .reg = 0x000, .def = 0x000 },
};
static const struct rzv2h_usb2phy_reset_of_data rzv2h_reset_of_data = {
.init_vals = rzv2h_init_vals,
.init_val_count = ARRAY_SIZE(rzv2h_init_vals),
.init_seq = rzv2h_init_seq,
.init_nseq = ARRAY_SIZE(rzv2h_init_seq),
.assert_seq = rzv2h_assert_seq,
.assert_nseq = ARRAY_SIZE(rzv2h_assert_seq),
.deassert_seq = rzv2h_deassert_seq,
.deassert_nseq = ARRAY_SIZE(rzv2h_deassert_seq),
.reset_reg = 0,
.reset_assert_val = 0x206,
.reset_status_bits = BIT(2),
.reset_deassert_val = 0x200,
.reset_release_val = 0x0,
.reset2_reg = 0xb04,
.reset2_acquire_val = 0x303,
.reset2_release_val = 0x3,
};
static const struct of_device_id rzv2h_usb2phy_reset_of_match[] = {

Some files were not shown because too many files have changed in this diff Show More