mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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:
@@ -128,6 +128,9 @@ properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
access-controllers:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
'^trig-conns@([0-9]+)$':
|
||||
type: object
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -128,6 +128,9 @@ properties:
|
||||
- const: tracedata
|
||||
- const: metadata
|
||||
|
||||
access-controllers:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
...
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -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>;
|
||||
};
|
||||
...
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
...
|
||||
@@ -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>;
|
||||
};
|
||||
...
|
||||
@@ -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
|
||||
...
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
...
|
||||
@@ -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:
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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:
|
||||
- |
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,7 +12,9 @@ maintainers:
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: fsl,imx-irqsteer
|
||||
- enum:
|
||||
- fsl,imx-irqsteer
|
||||
- nxp,s32n79-irqsteer
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx8m-irqsteer
|
||||
|
||||
@@ -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:
|
||||
- |
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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:
|
||||
|
||||
@@ -16,6 +16,7 @@ properties:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- nvidia,tegra210-usb-phy
|
||||
- nvidia,tegra124-usb-phy
|
||||
- nvidia,tegra114-usb-phy
|
||||
- enum:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
20
MAINTAINERS
20
MAINTAINERS
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
250
drivers/bus/stm32_dbg_bus.c
Normal 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");
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ®);
|
||||
|
||||
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
Reference in New Issue
Block a user