Commit cc0f7c3f authored by Linus Torvalds's avatar Linus Torvalds

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

Pull SoC driver updates from Arnd Bergmann:
 "The updates to the mediatek, allwinner, ti, tegra, microchip, stm32,
  samsung, imx, zynq and amlogic platoforms are fairly small maintenance
  changes, either addressing minor mistakes or enabling additional
  hardware.

  The qualcomm platform changes add a number of features and are larger
  than the other ones combined, introducing the use of linux/cleanup.h
  across several drivers, adding support for Snapdragon X1E and other
  SoCs in platform drivers, a new "protection domain mapper" driver, and
  a "shared memory bridge" driver.

  The cznic "turris omnia" router based on Marvell Armada gets a
  platform driver that talks to the board specific microcontroller.

  The reset and cache subsystems get a few minor updates to SoC specific
  drivers, while the ff-a, scmi and optee firmware drivers get some code
  refactoring and new features"

* tag 'soc-drivers-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (122 commits)
  firmware: turris-mox-rwtm: Initialize completion before mailbox
  firmware: turris-mox-rwtm: Fix checking return value of wait_for_completion_timeout()
  firmware: turris-mox-rwtm: Do not complete if there are no waiters
  MAINTAINERS: drop riscv list from cache controllers
  platform: cznic: turris-omnia-mcu: fix Kconfig dependencies
  bus: sunxi-rsb: Constify struct regmap_bus
  soc: sunxi: sram: Constify struct regmap_config
  platform: cznic: turris-omnia-mcu: Depend on WATCHDOG
  platform: cznic: turris-omnia-mcu: Depend on OF
  soc: samsung: exynos-pmu: add support for PMU_ALIVE non atomic registers
  arm64: stm32: enable scmi regulator for stm32
  firmware: qcom: tzmem: blacklist more platforms for SHM Bridge
  soc: qcom: wcnss: simplify with cleanup.h
  soc: qcom: pdr: simplify with cleanup.h
  soc: qcom: ocmem: simplify with cleanup.h
  soc: qcom: mdt_loader: simplify with cleanup.h
  soc: qcom: llcc: simplify with cleanup.h
  firmware: qcom: tzmem: simplify returning pointer without cleanup
  soc: qcom: socinfo: Add PM6350 PMIC
  arm64: dts: renesas: rz-smarc: Replace fixed regulator for USB VBUS
  ...
parents 99298eb6 49e24c80
What: /sys/bus/i2c/devices/<mcu_device>/board_revision
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains board revision number.
Only available if board information is burned in the MCU (older
revisions have board information burned in the ATSHA204-A chip).
Format: %u.
What: /sys/bus/i2c/devices/<mcu_device>/first_mac_address
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains device first MAC address. Each Turris Omnia is
allocated 3 MAC addresses. The two additional addresses are
computed from the first one by incrementing it.
Only available if board information is burned in the MCU (older
revisions have board information burned in the ATSHA204-A chip).
Format: %pM.
What: /sys/bus/i2c/devices/<mcu_device>/front_button_mode
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RW) The front button on the Turris Omnia router can be
configured either to change the intensity of all the LEDs on the
front panel, or to send the press event to the CPU as an
interrupt.
This file switches between these two modes:
- "mcu" makes the button press event be handled by the MCU to
change the LEDs panel intensity.
- "cpu" makes the button press event be handled by the CPU.
Format: %s.
What: /sys/bus/i2c/devices/<mcu_device>/front_button_poweron
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RW) Newer versions of the microcontroller firmware of the
Turris Omnia router support powering off the router into true
low power mode. The router can be powered on by pressing the
front button.
This file configures whether front button power on is enabled.
This file is present only if the power off feature is supported
by the firmware.
Format: %i.
What: /sys/bus/i2c/devices/<mcu_device>/fw_features
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Newer versions of the microcontroller firmware report the
features they support. These can be read from this file. If the
MCU firmware is too old, this file reads 0x0.
Format: 0x%x.
What: /sys/bus/i2c/devices/<mcu_device>/fw_version_hash_application
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains the version hash (commit hash) of the application
part of the microcontroller firmware.
Format: %s.
What: /sys/bus/i2c/devices/<mcu_device>/fw_version_hash_bootloader
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains the version hash (commit hash) of the bootloader
part of the microcontroller firmware.
Format: %s.
What: /sys/bus/i2c/devices/<mcu_device>/mcu_type
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains the microcontroller type (STM32, GD32, MKL).
Format: %s.
What: /sys/bus/i2c/devices/<mcu_device>/reset_selector
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains the selected factory reset level, determined by
how long the rear reset button was held by the user during board
reset.
Format: %i.
What: /sys/bus/i2c/devices/<mcu_device>/serial_number
Date: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains the 64-bit board serial number in hexadecimal
format.
Only available if board information is burned in the MCU (older
revisions have board information burned in the ATSHA204-A chip).
Format: %016X.
......@@ -20,7 +20,7 @@ description: |
initialized early into boot process and provides services to Operating Systems
on multiple processors including ones running Linux.
See http://processors.wiki.ti.com/index.php/TISCI for protocol definition.
See https://software-dl.ti.com/tisci/esd/latest/index.html for protocol definition.
The TI-SCI node describes the Texas Instrument's System Controller entity node.
This parent node may optionally have additional children nodes which describe
......
......@@ -21,6 +21,7 @@ properties:
compatible:
enum:
- qcom,qdu1000-llcc
- qcom,sa8775p-llcc
- qcom,sc7180-llcc
- qcom,sc7280-llcc
- qcom,sc8180x-llcc
......@@ -79,6 +80,33 @@ allOf:
- const: llcc0_base
- const: llcc_broadcast_base
- if:
properties:
compatible:
contains:
enum:
- qcom,sa8775p-llcc
then:
properties:
reg:
items:
- description: LLCC0 base register region
- description: LLCC1 base register region
- description: LLCC2 base register region
- description: LLCC3 base register region
- description: LLCC4 base register region
- description: LLCC5 base register region
- description: LLCC broadcast base register region
reg-names:
items:
- const: llcc0_base
- const: llcc1_base
- const: llcc2_base
- const: llcc3_base
- const: llcc4_base
- const: llcc5_base
- const: llcc_broadcast_base
- if:
properties:
compatible:
......@@ -141,8 +169,31 @@ allOf:
- qcom,sm8150-llcc
- qcom,sm8250-llcc
- qcom,sm8350-llcc
then:
properties:
reg:
items:
- description: LLCC0 base register region
- description: LLCC1 base register region
- description: LLCC2 base register region
- description: LLCC3 base register region
- description: LLCC broadcast base register region
reg-names:
items:
- const: llcc0_base
- const: llcc1_base
- const: llcc2_base
- const: llcc3_base
- const: llcc_broadcast_base
- if:
properties:
compatible:
contains:
enum:
- qcom,sm8450-llcc
- qcom,sm8550-llcc
- qcom,sm8650-llcc
then:
properties:
reg:
......@@ -151,7 +202,8 @@ allOf:
- description: LLCC1 base register region
- description: LLCC2 base register region
- description: LLCC3 base register region
- description: LLCC broadcast base register region
- description: LLCC broadcast OR register region
- description: LLCC broadcast AND register region
reg-names:
items:
- const: llcc0_base
......@@ -159,6 +211,7 @@ allOf:
- const: llcc2_base
- const: llcc3_base
- const: llcc_broadcast_base
- const: llcc_broadcast_and_base
additionalProperties: false
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/cache/starfive,jh8100-starlink-cache.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: StarFive StarLink Cache Controller
maintainers:
- Joshua Yeong <joshua.yeong@starfivetech.com>
description:
StarFive's StarLink Cache Controller manages the L3 cache shared between
clusters of CPU cores. The cache driver enables RISC-V non-standard cache
management as an alternative to instructions in the RISC-V Zicbom extension.
allOf:
- $ref: /schemas/cache-controller.yaml#
# We need a select here so we don't match all nodes with 'cache'
select:
properties:
compatible:
contains:
enum:
- starfive,jh8100-starlink-cache
required:
- compatible
properties:
compatible:
items:
- const: starfive,jh8100-starlink-cache
- const: cache
reg:
maxItems: 1
unevaluatedProperties: false
required:
- compatible
- reg
- cache-block-size
- cache-level
- cache-sets
- cache-size
- cache-unified
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
cache-controller@15000000 {
compatible = "starfive,jh8100-starlink-cache", "cache";
reg = <0x0 0x15000000 0x0 0x278>;
cache-block-size = <64>;
cache-level = <3>;
cache-sets = <8192>;
cache-size = <0x400000>;
cache-unified;
};
};
......@@ -36,7 +36,7 @@ properties:
The second cell should contain the clock ID.
Please see http://processors.wiki.ti.com/index.php/TISCI for
Please see https://software-dl.ti.com/tisci/esd/latest/index.html for
protocol documentation for the values to be used for different devices.
additionalProperties: false
......
......@@ -72,14 +72,17 @@ properties:
- const: tx
- const: tx_reply
- const: rx
- const: rx_reply
minItems: 2
mboxes:
description:
List of phandle and mailbox channel specifiers. It should contain
exactly one, two or three mailboxes; the first one or two for transmitting
messages ("tx") and another optional ("rx") for receiving notifications
and delayed responses, if supported by the platform.
exactly one, two, three or four mailboxes; the first one or two for
transmitting messages ("tx") and another optional ("rx") for receiving
notifications and delayed responses, if supported by the platform.
The optional ("rx_reply") is for notifications completion interrupt,
if supported by the platform.
The number of mailboxes needed for transmitting messages depends on the
type of channels exposed by the specific underlying mailbox controller;
one single channel descriptor is enough if such channel is bidirectional,
......@@ -92,9 +95,10 @@ properties:
2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
4 mbox / 2 shmem => SCMI TX and RX over 4 mailbox unidirectional channels
Any other combination of mboxes and shmem is invalid.
minItems: 1
maxItems: 3
maxItems: 4
shmem:
description:
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/firmware/cznic,turris-omnia-mcu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: CZ.NIC's Turris Omnia MCU
maintainers:
- Marek Behún <kabel@kernel.org>
description:
The MCU on Turris Omnia acts as a system controller providing additional
GPIOs, interrupts, watchdog, system power off and wakeup configuration.
properties:
compatible:
const: cznic,turris-omnia-mcu
reg:
description: MCU I2C slave address
maxItems: 1
interrupts:
maxItems: 1
interrupt-controller: true
'#interrupt-cells':
const: 2
description: |
The first cell specifies the interrupt number (0 to 63), the second cell
specifies interrupt type (which can be one of IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH).
The interrupt numbers correspond sequentially to GPIO numbers, taking the
GPIO banks into account:
IRQ number GPIO bank GPIO pin within bank
0 - 15 0 0 - 15
16 - 47 1 0 - 31
48 - 63 2 0 - 15
There are several exceptions:
IRQ number meaning
11 LED panel brightness changed by button press
13 TRNG entropy ready
14 ECDSA message signature computation done
gpio-controller: true
'#gpio-cells':
const: 3
description:
The first cell is bank number (0, 1 or 2), the second cell is pin number
within the bank (0 to 15 for banks 0 and 2, 0 to 31 for bank 1), and the
third cell specifies consumer flags.
required:
- compatible
- reg
- interrupts
- interrupt-controller
- gpio-controller
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
system-controller@2a {
compatible = "cznic,turris-omnia-mcu";
reg = <0x2a>;
interrupt-parent = <&gpio1>;
interrupts = <11 IRQ_TYPE_NONE>;
gpio-controller;
#gpio-cells = <3>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
......@@ -93,6 +93,11 @@ properties:
protocol to handle sleeping SCM calls.
maxItems: 1
memory-region:
description:
Phandle to the memory region reserved for the shared memory bridge to TZ.
maxItems: 1
qcom,sdi-enabled:
description:
Indicates that the SDI (Secure Debug Image) has been enabled by TZ
......@@ -193,6 +198,16 @@ allOf:
then:
properties:
interrupts: false
- if:
not:
properties:
compatible:
contains:
enum:
- qcom,scm-sa8775p
then:
properties:
memory-region: false
required:
- compatible
......
......@@ -35,6 +35,7 @@ properties:
- qcom,sm8250-cpu-bwmon
- qcom,sm8550-cpu-bwmon
- qcom,sm8650-cpu-bwmon
- qcom,x1e80100-cpu-bwmon
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
- items:
- enum:
......@@ -44,6 +45,7 @@ properties:
- qcom,sm8250-llcc-bwmon
- qcom,sm8550-llcc-bwmon
- qcom,sm8650-llcc-bwmon
- qcom,x1e80100-llcc-bwmon
- const: qcom,sc7280-llcc-bwmon
- const: qcom,sc7280-llcc-bwmon # BWMON v5
- const: qcom,sdm845-llcc-bwmon # BWMON v5
......@@ -72,7 +74,6 @@ required:
- interconnects
- interrupts
- operating-points-v2
- opp-table
- reg
additionalProperties: false
......
......@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: FSL/NXP Integrated Flash Controller
maintainers:
- Li Yang <leoyang.li@nxp.com>
- Shawn Guo <shawnguo@kernel.org>
description: |
NXP's integrated flash controller (IFC) is an advanced version of the
......
......@@ -42,6 +42,12 @@ properties:
0 = Port 1 Phy reset
1 = Port 2 Phy reset
regulator-vbus:
type: object
description: USB VBUS regulator
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
......@@ -49,6 +55,7 @@ required:
- resets
- power-domains
- '#reset-cells'
- regulator-vbus
additionalProperties: false
......@@ -64,4 +71,7 @@ examples:
resets = <&cpg R9A07G044_USB_PRESETN>;
power-domains = <&cpg>;
#reset-cells = <1>;
regulator-vbus {
regulator-name = "vbus";
};
};
......@@ -37,7 +37,7 @@ properties:
The second cell should contain the reset mask corresponding to the device
used by system controller.
Please see http://processors.wiki.ti.com/index.php/TISCI for
Please see https://software-dl.ti.com/tisci/esd/latest/index.html for
protocol documentation for the values to be used for different devices.
......
......@@ -31,6 +31,7 @@ properties:
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp
- qcom,sc8280xp-aoss-qmp
- qcom,sdx75-aoss-qmp
- qcom,sdm845-aoss-qmp
- qcom,sm6350-aoss-qmp
- qcom,sm8150-aoss-qmp
......
......@@ -41,6 +41,7 @@ properties:
description:
Three entries specifying the outgoing ipc bit used for signaling the
remote end of the smp2p edge.
deprecated: true
qcom,local-pid:
$ref: /schemas/types.yaml#/definitions/uint32
......@@ -128,7 +129,7 @@ examples:
compatible = "qcom,smp2p";
qcom,smem = <431>, <451>;
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
qcom,ipc = <&apcs 8 18>;
mboxes = <&apcs 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
......
......@@ -33,6 +33,14 @@ properties:
specifier of the column in the subscription matrix representing the local
processor.
mboxes:
minItems: 1
maxItems: 5
description:
Reference to the mailbox representing the outgoing doorbell in APCS for
this client. Each entry represents the N:th remote processor by index
(0-indexed).
'#size-cells':
const: 0
......@@ -47,6 +55,7 @@ patternProperties:
description:
Three entries specifying the outgoing ipc bit used for signaling the N:th
remote processor.
deprecated: true
"@[0-9a-f]$":
type: object
......@@ -98,15 +107,18 @@ required:
- '#address-cells'
- '#size-cells'
anyOf:
- required:
- qcom,ipc-1
- required:
- qcom,ipc-2
- required:
- qcom,ipc-3
oneOf:
- required:
- qcom,ipc-4
- mboxes
- anyOf:
- required:
- qcom,ipc-1
- required:
- qcom,ipc-2
- required:
- qcom,ipc-3
- required:
- qcom,ipc-4
additionalProperties: false
......@@ -122,7 +134,7 @@ examples:
compatible = "qcom,smsm";
#address-cells = <1>;
#size-cells = <0>;
qcom,ipc-3 = <&apcs 8 19>;
mboxes = <0>, <0>, <0>, <&apcs 19>;
apps_smsm: apps@0 {
reg = <0>;
......
......@@ -40,7 +40,7 @@ properties:
TI_SCI_PD_SHARED - Allows the device to be shared by multiple hosts.
Please refer to dt-bindings/soc/ti,sci_pm_domain.h for the definitions.
Please see http://processors.wiki.ti.com/index.php/TISCI for
Please see https://software-dl.ti.com/tisci/esd/latest/index.html for
protocol documentation for the values to be used for different devices.
additionalProperties: false
......
......@@ -2,7 +2,7 @@
# Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,j721e-system-controller.yaml#
$id: http://devicetree.org/schemas/soc/ti/ti,j721e-system-controller.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI J721e System Controller Registers R/W
......@@ -19,7 +19,7 @@ description: |
and access the registers directly.
maintainers:
- Kishon Vijay Abraham I <kishon@ti.com>
- Kishon Vijay Abraham I <kishon@kernel.org>
- Roger Quadros <rogerq@kernel.org>
properties:
......
......@@ -56,6 +56,9 @@ properties:
ranges: true
patternProperties:
"^regulators@[0-9a-f]+$":
$ref: /schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml#
"^sram@[a-f0-9]+":
$ref: /schemas/sram/sram.yaml#
unevaluatedProperties: false
......@@ -130,3 +133,28 @@ examples:
};
};
};
- |
syscon@3000000 {
compatible = "allwinner,sun20i-d1-system-control";
reg = <0x3000000 0x1000>;
ranges;
#address-cells = <1>;
#size-cells = <1>;
regulators@3000150 {
compatible = "allwinner,sun20i-d1-system-ldos";
reg = <0x3000150 0x4>;
reg_ldoa: ldoa {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
reg_ldob: ldob {
regulator-name = "vcc-dram";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
};
};
};
......@@ -2185,10 +2185,12 @@ M: Marek Behún <kabel@kernel.org>
S: Maintained
W: https://www.turris.cz/
F: Documentation/ABI/testing/debugfs-moxtet
F: Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
F: Documentation/ABI/testing/sysfs-bus-moxtet-devices
F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
F: Documentation/devicetree/bindings/bus/moxtet.txt
F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
F: Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
F: Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
F: Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
......@@ -2197,10 +2199,12 @@ F: drivers/firmware/turris-mox-rwtm.c
F: drivers/gpio/gpio-moxtet.c
F: drivers/leds/leds-turris-omnia.c
F: drivers/mailbox/armada-37xx-rwtm-mailbox.c
F: drivers/platform/cznic/
F: drivers/watchdog/armada_37xx_wdt.c
F: include/dt-bindings/bus/moxtet.h
F: include/linux/armada-37xx-rwtm-mailbox.h
F: include/linux/moxtet.h
F: include/linux/turris-omnia-mcu-interface.h
ARM/FARADAY FA526 PORT
M: Hans Ulli Kroll <ulli.kroll@googlemail.com>
......@@ -14867,6 +14871,7 @@ MICROCHIP SOC DRIVERS
M: Conor Dooley <conor@kernel.org>
S: Supported
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
F: Documentation/devicetree/bindings/soc/microchip/
F: drivers/soc/microchip/
MICROCHIP SPI DRIVER
......@@ -18661,6 +18666,14 @@ F: Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst
F: drivers/net/ethernet/qualcomm/rmnet/
F: include/linux/if_rmnet.h
QUALCOMM TRUST ZONE MEMORY ALLOCATOR
M: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/firmware/qcom/qcom_tzmem.c
F: drivers/firmware/qcom/qcom_tzmem.h
F: include/linux/firmware/qcom/qcom_tzmem.h
QUALCOMM TSENS THERMAL DRIVER
M: Amit Kucheria <amitk@kernel.org>
M: Thara Gopinath <thara.gopinath@gmail.com>
......@@ -21339,9 +21352,9 @@ F: drivers/staging/
STANDALONE CACHE CONTROLLER DRIVERS
M: Conor Dooley <conor@kernel.org>
L: linux-riscv@lists.infradead.org
S: Maintained
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
F: Documentation/devicetree/bindings/cache/
F: drivers/cache
STARFIRE/DURALAN NETWORK DRIVER
......@@ -21854,6 +21867,7 @@ F: drivers/mfd/syscon.c
SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
M: Sudeep Holla <sudeep.holla@arm.com>
R: Cristian Marussi <cristian.marussi@arm.com>
L: arm-scmi@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/firmware/arm,sc[mp]i.yaml
......@@ -22583,6 +22597,7 @@ L: linux-kernel@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
F: Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
F: drivers/pmdomain/ti/omap_prm.c
F: drivers/soc/ti/*
......
......@@ -312,6 +312,8 @@ config ARCH_STM32
select STM32_EXTI
select ARM_SMC_MBOX
select ARM_SCMI_PROTOCOL
select REGULATOR
select REGULATOR_ARM_SCMI
select COMMON_CLK_SCMI
select STM32_FIREWALL
help
......
......@@ -54,14 +54,6 @@ codec_dai: simple-audio-card,codec {
};
};
usb0_vbus_otg: regulator-usb0-vbus-otg {
compatible = "regulator-fixed";
regulator-name = "USB0_VBUS_OTG";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
vccq_sdhi1: regulator-vccq-sdhi1 {
compatible = "regulator-gpio";
regulator-name = "SDHI1 VccQ";
......@@ -139,6 +131,9 @@ &ohci1 {
&phyrst {
status = "okay";
usb0_vbus_otg: regulator-vbus {
regulator-name = "vbus";
};
};
&scif0 {
......
......@@ -457,7 +457,7 @@ static void regmap_sunxi_rsb_free_ctx(void *context)
kfree(ctx);
}
static struct regmap_bus regmap_sunxi_rsb = {
static const struct regmap_bus regmap_sunxi_rsb = {
.reg_write = regmap_sunxi_rsb_reg_write,
.reg_read = regmap_sunxi_rsb_reg_read,
.free_context = regmap_sunxi_rsb_free_ctx,
......
......@@ -14,4 +14,13 @@ config SIFIVE_CCACHE
help
Support for the composable cache controller on SiFive platforms.
config STARFIVE_STARLINK_CACHE
bool "StarFive StarLink Cache controller"
depends on RISCV
depends on ARCH_STARFIVE
select RISCV_DMA_NONCOHERENT
select RISCV_NONSTANDARD_CACHE_OPS
help
Support for the StarLink cache controller IP from StarFive.
endmenu
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
obj-$(CONFIG_STARFIVE_STARLINK_CACHE) += starfive_starlink_cache.o
// SPDX-License-Identifier: GPL-2.0
/*
* Cache Management Operations for StarFive's Starlink cache controller
*
* Copyright (C) 2024 Shanghai StarFive Technology Co., Ltd.
*
* Author: Joshua Yeong <joshua.yeong@starfivetech.com>
*/
#include <linux/bitfield.h>
#include <linux/cacheflush.h>
#include <linux/iopoll.h>
#include <linux/of_address.h>
#include <asm/dma-noncoherent.h>
#define STARLINK_CACHE_FLUSH_START_ADDR 0x0
#define STARLINK_CACHE_FLUSH_END_ADDR 0x8
#define STARLINK_CACHE_FLUSH_CTL 0x10
#define STARLINK_CACHE_ALIGN 0x40
#define STARLINK_CACHE_ADDRESS_RANGE_MASK GENMASK(39, 0)
#define STARLINK_CACHE_FLUSH_CTL_MODE_MASK GENMASK(2, 1)
#define STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK BIT(0)
#define STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE 0
#define STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE 1
#define STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED 2
#define STARLINK_CACHE_FLUSH_POLL_DELAY_US 1
#define STARLINK_CACHE_FLUSH_TIMEOUT_US 5000000
static void __iomem *starlink_cache_base;
static void starlink_cache_flush_complete(void)
{
volatile void __iomem *ctl = starlink_cache_base + STARLINK_CACHE_FLUSH_CTL;
u64 v;
int ret;
ret = readq_poll_timeout_atomic(ctl, v, !(v & STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK),
STARLINK_CACHE_FLUSH_POLL_DELAY_US,
STARLINK_CACHE_FLUSH_TIMEOUT_US);
if (ret)
WARN(1, "StarFive Starlink cache flush operation timeout\n");
}
static void starlink_cache_dma_cache_wback(phys_addr_t paddr, unsigned long size)
{
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
mb();
writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED),
starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
starlink_cache_flush_complete();
}
static void starlink_cache_dma_cache_invalidate(phys_addr_t paddr, unsigned long size)
{
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
mb();
writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE),
starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
starlink_cache_flush_complete();
}
static void starlink_cache_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size)
{
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
mb();
writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE),
starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
starlink_cache_flush_complete();
}
static const struct riscv_nonstd_cache_ops starlink_cache_ops = {
.wback = &starlink_cache_dma_cache_wback,
.inv = &starlink_cache_dma_cache_invalidate,
.wback_inv = &starlink_cache_dma_cache_wback_inv,
};
static const struct of_device_id starlink_cache_ids[] = {
{ .compatible = "starfive,jh8100-starlink-cache" },
{ /* sentinel */ }
};
static int __init starlink_cache_init(void)
{
struct device_node *np;
u32 block_size;
int ret;
np = of_find_matching_node(NULL, starlink_cache_ids);
if (!of_device_is_available(np))
return -ENODEV;
ret = of_property_read_u32(np, "cache-block-size", &block_size);
if (ret)
return ret;
if (block_size % STARLINK_CACHE_ALIGN)
return -EINVAL;
starlink_cache_base = of_iomap(np, 0);
if (!starlink_cache_base)
return -ENOMEM;
riscv_cbom_block_size = block_size;
riscv_noncoherent_supported();
riscv_noncoherent_register_cache_ops(&starlink_cache_ops);
return 0;
}
arch_initcall(starlink_cache_init);
......@@ -191,6 +191,7 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
case QCOM_ID_IPQ5312:
case QCOM_ID_IPQ5302:
case QCOM_ID_IPQ5300:
case QCOM_ID_IPQ5321:
case QCOM_ID_IPQ9514:
case QCOM_ID_IPQ9550:
case QCOM_ID_IPQ9554:
......
......@@ -2,5 +2,7 @@
ffa-bus-y = bus.o
ffa-driver-y = driver.o
ffa-transport-$(CONFIG_ARM_FFA_SMCCC) += smccc.o
ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y) $(ffa-transport-y)
obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-module.o
ffa-core-objs := $(ffa-bus-y)
ffa-module-objs := $(ffa-driver-y) $(ffa-transport-y)
obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-core.o
obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa-module.o
......@@ -30,12 +30,11 @@ static int ffa_device_match(struct device *dev, struct device_driver *drv)
while (!uuid_is_null(&id_table->uuid)) {
/*
* FF-A v1.0 doesn't provide discovery of UUIDs, just the
* partition IDs, so fetch the partitions IDs for this
* id_table UUID and assign the UUID to the device if the
* partition ID matches
* partition IDs, so match it unconditionally here and handle
* it via the installed bus notifier during driver binding.
*/
if (uuid_is_null(&ffa_dev->uuid))
ffa_device_match_uuid(ffa_dev, &id_table->uuid);
return 1;
if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
return 1;
......@@ -50,6 +49,10 @@ static int ffa_device_probe(struct device *dev)
struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
struct ffa_device *ffa_dev = to_ffa_dev(dev);
/* UUID can be still NULL with FF-A v1.0, so just skip probing them */
if (uuid_is_null(&ffa_dev->uuid))
return -ENODEV;
return ffa_drv->probe(ffa_dev);
}
......@@ -232,14 +235,21 @@ void ffa_device_unregister(struct ffa_device *ffa_dev)
}
EXPORT_SYMBOL_GPL(ffa_device_unregister);
int arm_ffa_bus_init(void)
static int __init arm_ffa_bus_init(void)
{
return bus_register(&ffa_bus_type);
}
subsys_initcall(arm_ffa_bus_init);
void arm_ffa_bus_exit(void)
static void __exit arm_ffa_bus_exit(void)
{
ffa_devices_unregister();
bus_unregister(&ffa_bus_type);
ida_destroy(&ffa_bus_id);
}
module_exit(arm_ffa_bus_exit);
MODULE_ALIAS("ffa-core");
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
MODULE_DESCRIPTION("ARM FF-A bus");
MODULE_LICENSE("GPL");
......@@ -14,8 +14,6 @@ typedef struct arm_smccc_1_2_regs ffa_value_t;
typedef void (ffa_fn)(ffa_value_t, ffa_value_t *);
int arm_ffa_bus_init(void);
void arm_ffa_bus_exit(void);
bool ffa_device_is_valid(struct ffa_device *ffa_dev);
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid);
......
......@@ -1224,14 +1224,6 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
int count, idx;
struct ffa_partition_info *pbuf, *tpbuf;
/*
* FF-A v1.1 provides UUID for each partition as part of the discovery
* API, the discovered UUID must be populated in the device's UUID and
* there is no need to copy the same from the driver table.
*/
if (drv_info->version > FFA_VERSION_1_0)
return;
count = ffa_partition_probe(uuid, &pbuf);
if (count <= 0)
return;
......@@ -1242,6 +1234,35 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
kfree(pbuf);
}
static int
ffa_bus_notifier(struct notifier_block *nb, unsigned long action, void *data)
{
struct device *dev = data;
struct ffa_device *fdev = to_ffa_dev(dev);
if (action == BUS_NOTIFY_BIND_DRIVER) {
struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
const struct ffa_device_id *id_table= ffa_drv->id_table;
/*
* FF-A v1.1 provides UUID for each partition as part of the
* discovery API, the discovered UUID must be populated in the
* device's UUID and there is no need to workaround by copying
* the same from the driver table.
*/
if (uuid_is_null(&fdev->uuid))
ffa_device_match_uuid(fdev, &id_table->uuid);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static struct notifier_block ffa_bus_nb = {
.notifier_call = ffa_bus_notifier,
};
static int ffa_setup_partitions(void)
{
int count, idx, ret;
......@@ -1250,6 +1271,12 @@ static int ffa_setup_partitions(void)
struct ffa_dev_part_info *info;
struct ffa_partition_info *pbuf, *tpbuf;
if (drv_info->version == FFA_VERSION_1_0) {
ret = bus_register_notifier(&ffa_bus_type, &ffa_bus_nb);
if (ret)
pr_err("Failed to register FF-A bus notifiers\n");
}
count = ffa_partition_probe(&uuid_null, &pbuf);
if (count <= 0) {
pr_info("%s: No partitions found, error %d\n", __func__, count);
......@@ -1261,7 +1288,7 @@ static int ffa_setup_partitions(void)
import_uuid(&uuid, (u8 *)tpbuf->uuid);
/* Note that if the UUID will be uuid_null, that will require
* ffa_device_match() to find the UUID of this partition id
* ffa_bus_notifier() to find the UUID of this partition id
* with help of ffa_device_match_uuid(). FF-A v1.1 and above
* provides UUID here for each partition as part of the
* discovery API and the same is passed.
......@@ -1581,14 +1608,9 @@ static int __init ffa_init(void)
if (ret)
return ret;
ret = arm_ffa_bus_init();
if (ret)
return ret;
drv_info = kzalloc(sizeof(*drv_info), GFP_KERNEL);
if (!drv_info) {
ret = -ENOMEM;
goto ffa_bus_exit;
return -ENOMEM;
}
ret = ffa_version_check(&drv_info->version);
......@@ -1649,11 +1671,9 @@ static int __init ffa_init(void)
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
free_drv_info:
kfree(drv_info);
ffa_bus_exit:
arm_ffa_bus_exit();
return ret;
}
subsys_initcall(ffa_init);
module_init(ffa_init);
static void __exit ffa_exit(void)
{
......@@ -1663,7 +1683,6 @@ static void __exit ffa_exit(void)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
kfree(drv_info);
arm_ffa_bus_exit();
}
module_exit(ffa_exit);
......
......@@ -326,6 +326,7 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);
bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);
bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem);
bool shmem_channel_intr_enabled(struct scmi_shared_mem __iomem *shmem);
/* declarations for message passing transports */
struct scmi_msg_payld;
......
......@@ -21,6 +21,7 @@
* @cl: Mailbox Client
* @chan: Transmit/Receive mailbox uni/bi-directional channel
* @chan_receiver: Optional Receiver mailbox unidirectional channel
* @chan_platform_receiver: Optional Platform Receiver mailbox unidirectional channel
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
*/
......@@ -28,6 +29,7 @@ struct scmi_mailbox {
struct mbox_client cl;
struct mbox_chan *chan;
struct mbox_chan *chan_receiver;
struct mbox_chan *chan_platform_receiver;
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
};
......@@ -91,6 +93,8 @@ static bool mailbox_chan_available(struct device_node *of_node, int idx)
* for replies on the a2p channel. Set as zero if not present.
* @p2a_chan: A reference to the optional p2a channel.
* Set as zero if not present.
* @p2a_rx_chan: A reference to the optional p2a completion channel.
* Set as zero if not present.
*
* At first, validate the transport configuration as described in terms of
* 'mboxes' and 'shmem', then determin which mailbox channel indexes are
......@@ -98,8 +102,8 @@ static bool mailbox_chan_available(struct device_node *of_node, int idx)
*
* Return: 0 on Success or error
*/
static int mailbox_chan_validate(struct device *cdev,
int *a2p_rx_chan, int *p2a_chan)
static int mailbox_chan_validate(struct device *cdev, int *a2p_rx_chan,
int *p2a_chan, int *p2a_rx_chan)
{
int num_mb, num_sh, ret = 0;
struct device_node *np = cdev->of_node;
......@@ -109,8 +113,9 @@ static int mailbox_chan_validate(struct device *cdev,
dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
/* Bail out if mboxes and shmem descriptors are inconsistent */
if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
(num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 4 ||
(num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2) ||
(num_mb == 4 && num_sh != 2)) {
dev_warn(cdev,
"Invalid channel descriptor for '%s' - mbs:%d shm:%d\n",
of_node_full_name(np), num_mb, num_sh);
......@@ -139,6 +144,7 @@ static int mailbox_chan_validate(struct device *cdev,
case 1:
*a2p_rx_chan = 0;
*p2a_chan = 0;
*p2a_rx_chan = 0;
break;
case 2:
if (num_sh == 2) {
......@@ -148,10 +154,17 @@ static int mailbox_chan_validate(struct device *cdev,
*a2p_rx_chan = 1;
*p2a_chan = 0;
}
*p2a_rx_chan = 0;
break;
case 3:
*a2p_rx_chan = 1;
*p2a_chan = 2;
*p2a_rx_chan = 0;
break;
case 4:
*a2p_rx_chan = 1;
*p2a_chan = 2;
*p2a_rx_chan = 3;
break;
}
}
......@@ -166,12 +179,12 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
struct device *cdev = cinfo->dev;
struct scmi_mailbox *smbox;
struct device_node *shmem;
int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
int ret, a2p_rx_chan, p2a_chan, p2a_rx_chan, idx = tx ? 0 : 1;
struct mbox_client *cl;
resource_size_t size;
struct resource res;
ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan, &p2a_rx_chan);
if (ret)
return ret;
......@@ -229,6 +242,17 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
}
}
if (!tx && p2a_rx_chan) {
smbox->chan_platform_receiver = mbox_request_channel(cl, p2a_rx_chan);
if (IS_ERR(smbox->chan_platform_receiver)) {
ret = PTR_ERR(smbox->chan_platform_receiver);
if (ret != -EPROBE_DEFER)
dev_err(cdev, "failed to request SCMI P2A Receiver mailbox\n");
return ret;
}
}
cinfo->transport_info = smbox;
smbox->cinfo = cinfo;
......@@ -243,9 +267,11 @@ static int mailbox_chan_free(int id, void *p, void *data)
if (smbox && !IS_ERR(smbox->chan)) {
mbox_free_channel(smbox->chan);
mbox_free_channel(smbox->chan_receiver);
mbox_free_channel(smbox->chan_platform_receiver);
cinfo->transport_info = NULL;
smbox->chan = NULL;
smbox->chan_receiver = NULL;
smbox->chan_platform_receiver = NULL;
smbox->cinfo = NULL;
}
......@@ -300,8 +326,27 @@ static void mailbox_fetch_notification(struct scmi_chan_info *cinfo,
static void mailbox_clear_channel(struct scmi_chan_info *cinfo)
{
struct scmi_mailbox *smbox = cinfo->transport_info;
struct mbox_chan *intr_chan;
int ret;
shmem_clear_channel(smbox->shmem);
if (!shmem_channel_intr_enabled(smbox->shmem))
return;
if (smbox->chan_platform_receiver)
intr_chan = smbox->chan_platform_receiver;
else if (smbox->chan)
intr_chan = smbox->chan;
else
return;
ret = mbox_send_message(intr_chan, NULL);
/* mbox_send_message returns non-negative value on success, so reset */
if (ret > 0)
ret = 0;
mbox_client_txdone(intr_chan, ret);
}
static bool
......
......@@ -50,6 +50,7 @@
#include <linux/reboot.h>
#include <linux/scmi_protocol.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/time64.h>
#include <linux/timer.h>
#include <linux/types.h>
......@@ -78,6 +79,7 @@ enum scmi_syspower_state {
* @reboot_nb: A notifier_block optionally used to track reboot progress
* @forceful_work: A worker used to trigger a forceful transition once a
* graceful has timed out.
* @suspend_work: A worker used to trigger system suspend
*/
struct scmi_syspower_conf {
struct device *dev;
......@@ -90,6 +92,7 @@ struct scmi_syspower_conf {
struct notifier_block reboot_nb;
struct delayed_work forceful_work;
struct work_struct suspend_work;
};
#define userspace_nb_to_sconf(x) \
......@@ -249,6 +252,9 @@ static void scmi_request_graceful_transition(struct scmi_syspower_conf *sc,
case SCMI_SYSTEM_WARMRESET:
orderly_reboot();
break;
case SCMI_SYSTEM_SUSPEND:
schedule_work(&sc->suspend_work);
break;
default:
break;
}
......@@ -277,7 +283,8 @@ static int scmi_userspace_notifier(struct notifier_block *nb,
struct scmi_system_power_state_notifier_report *er = data;
struct scmi_syspower_conf *sc = userspace_nb_to_sconf(nb);
if (er->system_state >= SCMI_SYSTEM_POWERUP) {
if (er->system_state >= SCMI_SYSTEM_MAX ||
er->system_state == SCMI_SYSTEM_POWERUP) {
dev_err(sc->dev, "Ignoring unsupported system_state: 0x%X\n",
er->system_state);
return NOTIFY_DONE;
......@@ -315,6 +322,16 @@ static int scmi_userspace_notifier(struct notifier_block *nb,
return NOTIFY_OK;
}
static void scmi_suspend_work_func(struct work_struct *work)
{
struct scmi_syspower_conf *sc =
container_of(work, struct scmi_syspower_conf, suspend_work);
pm_suspend(PM_SUSPEND_MEM);
sc->state = SCMI_SYSPOWER_IDLE;
}
static int scmi_syspower_probe(struct scmi_device *sdev)
{
int ret;
......@@ -338,6 +355,8 @@ static int scmi_syspower_probe(struct scmi_device *sdev)
sc->userspace_nb.notifier_call = &scmi_userspace_notifier;
sc->dev = &sdev->dev;
INIT_WORK(&sc->suspend_work, scmi_suspend_work_func);
return handle->notify_ops->devm_event_notifier_register(sdev,
SCMI_PROTOCOL_SYSTEM,
SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER,
......
......@@ -128,3 +128,8 @@ bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem)
return (ioread32(&shmem->channel_status) &
SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
}
bool shmem_channel_intr_enabled(struct scmi_shared_mem __iomem *shmem)
{
return ioread32(&shmem->flags) & SCMI_SHMEM_FLAG_INTR_ENABLED;
}
......@@ -340,4 +340,5 @@ static struct platform_driver meson_sm_driver = {
},
};
module_platform_driver_probe(meson_sm_driver, meson_sm_probe);
MODULE_DESCRIPTION("Amlogic Secure Monitor driver");
MODULE_LICENSE("GPL v2");
......@@ -9,6 +9,7 @@
*
* Author: Conor Dooley <conor.dooley@microchip.com>
*/
#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/math.h>
......@@ -71,8 +72,9 @@
#define AUTO_UPDATE_UPGRADE_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX)
#define AUTO_UPDATE_BLANK_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX)
#define AUTO_UPDATE_DIRECTORY_SIZE SZ_1K
#define AUTO_UPDATE_RESERVED_SIZE SZ_1M
#define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_RESERVED_SIZE)
#define AUTO_UPDATE_INFO_BASE AUTO_UPDATE_DIRECTORY_SIZE
#define AUTO_UPDATE_INFO_SIZE SZ_1M
#define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
#define AUTO_UPDATE_TIMEOUT_MS 60000
......@@ -86,6 +88,17 @@ struct mpfs_auto_update_priv {
bool cancel_request;
};
static bool mpfs_auto_update_is_bitstream_info(const u8 *data, u32 size)
{
if (size < 4)
return false;
if (data[0] == 0x4d && data[1] == 0x43 && data[2] == 0x48 && data[3] == 0x50)
return true;
return false;
}
static enum fw_upload_err mpfs_auto_update_prepare(struct fw_upload *fw_uploader, const u8 *data,
u32 size)
{
......@@ -162,28 +175,17 @@ static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_up
static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
{
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
struct mpfs_mss_response *response;
struct mpfs_mss_msg *message;
u32 *response_msg;
u32 *response_msg __free(kfree) =
kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
struct mpfs_mss_response *response __free(kfree) =
kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);
struct mpfs_mss_msg *message __free(kfree) =
kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);
int ret;
response_msg = devm_kzalloc(priv->dev, AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg),
GFP_KERNEL);
if (!response_msg)
if (!response_msg || !response || !message)
return -ENOMEM;
response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL);
if (!response) {
ret = -ENOMEM;
goto free_response_msg;
}
message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL);
if (!message) {
ret = -ENOMEM;
goto free_response;
}
/*
* The system controller can verify that an image in the flash is valid.
* Rather than duplicate the check in this driver, call the relevant
......@@ -205,31 +207,25 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
ret = mpfs_blocking_transaction(priv->sys_controller, message);
if (ret | response->resp_status) {
dev_warn(priv->dev, "Verification of Upgrade Image failed!\n");
ret = ret ? ret : -EBADMSG;
goto free_message;
return ret ? ret : -EBADMSG;
}
dev_info(priv->dev, "Verification of Upgrade Image passed!\n");
free_message:
devm_kfree(priv->dev, message);
free_response:
devm_kfree(priv->dev, response);
free_response_msg:
devm_kfree(priv->dev, response_msg);
return ret;
return 0;
}
static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv, char *buffer,
static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv,
u32 image_address, loff_t directory_address)
{
struct erase_info erase;
size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
size_t erase_size = round_up(AUTO_UPDATE_DIRECTORY_SIZE, (u64)priv->flash->erasesize);
size_t bytes_written = 0, bytes_read = 0;
char *buffer __free(kfree) = kzalloc(erase_size, GFP_KERNEL);
int ret;
erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
if (!buffer)
return -ENOMEM;
erase.addr = AUTO_UPDATE_DIRECTORY_BASE;
erase.len = erase_size;
......@@ -275,7 +271,7 @@ static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv
return ret;
if (bytes_written != erase_size)
return ret;
return -EIO;
return 0;
}
......@@ -285,26 +281,36 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
{
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
struct erase_info erase;
char *buffer;
loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY;
size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
size_t bytes_written = 0;
bool is_info = mpfs_auto_update_is_bitstream_info(data, size);
u32 image_address;
int ret;
erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
image_address = AUTO_UPDATE_BITSTREAM_BASE +
AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
buffer = devm_kzalloc(priv->dev, erase_size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
if (is_info)
image_address = AUTO_UPDATE_INFO_BASE;
else
image_address = AUTO_UPDATE_BITSTREAM_BASE +
AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
ret = mpfs_auto_update_set_image_address(priv, buffer, image_address, directory_address);
if (ret) {
dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
goto out;
/*
* For bitstream info, the descriptor is written to a fixed offset,
* so there is no need to set the image address.
*/
if (!is_info) {
ret = mpfs_auto_update_set_image_address(priv, image_address, directory_address);
if (ret) {
dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
return ret;
}
} else {
if (size > AUTO_UPDATE_INFO_SIZE) {
dev_err(priv->dev, "bitstream info exceeds permitted size\n");
return -ENOSPC;
}
}
/*
......@@ -318,7 +324,7 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
dev_info(priv->dev, "Erasing the flash at address (0x%x)\n", image_address);
ret = mtd_erase(priv->flash, &erase);
if (ret)
goto out;
return ret;
/*
* No parsing etc of the bitstream is required. The system controller
......@@ -328,18 +334,15 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
dev_info(priv->dev, "Writing the image to the flash at address (0x%x)\n", image_address);
ret = mtd_write(priv->flash, (loff_t)image_address, size, &bytes_written, data);
if (ret)
goto out;
return ret;
if (bytes_written != size) {
ret = -EIO;
goto out;
}
if (bytes_written != size)
return -EIO;
*written = bytes_written;
dev_info(priv->dev, "Wrote 0x%zx bytes to the flash\n", bytes_written);
out:
devm_kfree(priv->dev, buffer);
return ret;
return 0;
}
static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader, const u8 *data,
......@@ -362,6 +365,9 @@ static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader,
goto out;
}
if (mpfs_auto_update_is_bitstream_info(data, size))
goto out;
ret = mpfs_auto_update_verify_image(fw_uploader);
if (ret)
err = FW_UPLOAD_ERR_FW_INVALID;
......@@ -381,23 +387,15 @@ static const struct fw_upload_ops mpfs_auto_update_ops = {
static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv)
{
struct mpfs_mss_response *response;
struct mpfs_mss_msg *message;
u32 *response_msg;
u32 *response_msg __free(kfree) =
kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
struct mpfs_mss_response *response __free(kfree) =
kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);
struct mpfs_mss_msg *message __free(kfree) =
kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);
int ret;
response_msg = devm_kzalloc(priv->dev,
AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg),
GFP_KERNEL);
if (!response_msg)
return -ENOMEM;
response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL);
if (!response)
return -ENOMEM;
message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL);
if (!message)
if (!response_msg || !response || !message)
return -ENOMEM;
/*
......
......@@ -7,8 +7,39 @@
menu "Qualcomm firmware drivers"
config QCOM_SCM
select QCOM_TZMEM
tristate
config QCOM_TZMEM
tristate
select GENERIC_ALLOCATOR
choice
prompt "TrustZone interface memory allocator mode"
default QCOM_TZMEM_MODE_GENERIC
help
Selects the mode of the memory allocator providing memory buffers of
suitable format for sharing with the TrustZone. If in doubt, select
'Generic'.
config QCOM_TZMEM_MODE_GENERIC
bool "Generic"
help
Use the generic allocator mode. The memory is page-aligned, non-cachable
and physically contiguous.
config QCOM_TZMEM_MODE_SHMBRIDGE
bool "SHM Bridge"
help
Use Qualcomm Shared Memory Bridge. The memory has the same alignment as
in the 'Generic' allocator but is also explicitly marked as an SHM Bridge
buffer.
With this selected, all buffers passed to the TrustZone must be allocated
using the TZMem allocator or else the TrustZone will refuse to use them.
endchoice
config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
bool "Qualcomm download mode enabled by default"
depends on QCOM_SCM
......
......@@ -5,5 +5,6 @@
obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o
obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
......@@ -2,6 +2,7 @@
/* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved.
*/
#include <linux/cleanup.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
......@@ -9,6 +10,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/firmware/qcom/qcom_tzmem.h>
#include <linux/arm-smccc.h>
#include <linux/dma-mapping.h>
......@@ -150,11 +152,10 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
enum qcom_scm_convention qcom_convention,
struct qcom_scm_res *res, bool atomic)
{
struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool();
int arglen = desc->arginfo & 0xf;
int i, ret;
dma_addr_t args_phys = 0;
void *args_virt = NULL;
size_t alloc_len;
void *args_virt __free(qcom_tzmem) = NULL;
gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
u32 qcom_smccc_convention = (qcom_convention == SMC_CONVENTION_ARM_32) ?
......@@ -172,9 +173,9 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i];
if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
alloc_len = SCM_SMC_N_EXT_ARGS * sizeof(u64);
args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag);
args_virt = qcom_tzmem_alloc(mempool,
SCM_SMC_N_EXT_ARGS * sizeof(u64),
flag);
if (!args_virt)
return -ENOMEM;
......@@ -192,25 +193,10 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
SCM_SMC_FIRST_EXT_IDX]);
}
args_phys = dma_map_single(dev, args_virt, alloc_len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, args_phys)) {
kfree(args_virt);
return -ENOMEM;
}
smc.args[SCM_SMC_LAST_REG_IDX] = args_phys;
smc.args[SCM_SMC_LAST_REG_IDX] = qcom_tzmem_to_phys(args_virt);
}
/* ret error check follows after args_virt cleanup*/
ret = __scm_smc_do(dev, &smc, &smc_res, atomic);
if (args_virt) {
dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
kfree(args_virt);
}
if (ret)
return ret;
......
This diff is collapsed.
......@@ -5,6 +5,7 @@
#define __QCOM_SCM_INT_H
struct device;
struct qcom_tzmem_pool;
enum qcom_scm_convention {
SMC_CONVENTION_UNKNOWN,
......@@ -78,6 +79,8 @@ int scm_legacy_call_atomic(struct device *dev, const struct qcom_scm_desc *desc,
int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
struct qcom_scm_res *res);
struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
#define QCOM_SCM_SVC_BOOT 0x01
#define QCOM_SCM_BOOT_SET_ADDR 0x01
#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
......@@ -113,6 +116,9 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#define QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE 0x05
#define QCOM_SCM_MP_VIDEO_VAR 0x08
#define QCOM_SCM_MP_ASSIGN 0x16
#define QCOM_SCM_MP_SHM_BRIDGE_ENABLE 0x1c
#define QCOM_SCM_MP_SHM_BRIDGE_DELETE 0x1d
#define QCOM_SCM_MP_SHM_BRIDGE_CREATE 0x1e
#define QCOM_SCM_SVC_OCMEM 0x0f
#define QCOM_SCM_OCMEM_LOCK_CMD 0x01
......@@ -138,6 +144,9 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#define QCOM_SCM_WAITQ_RESUME 0x02
#define QCOM_SCM_WAITQ_GET_WQ_CTX 0x03
#define QCOM_SCM_SVC_GPU 0x28
#define QCOM_SCM_SVC_GPU_INIT_REGS 0x01
/* common error codes */
#define QCOM_SCM_V2_EBUSY -12
#define QCOM_SCM_ENOMEM -5
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2023-2024 Linaro Ltd.
*/
#ifndef __QCOM_TZMEM_PRIV_H
#define __QCOM_TZMEM_PRIV_H
struct device;
int qcom_tzmem_enable(struct device *dev);
#endif /* __QCOM_TZMEM_PRIV_H */
......@@ -4,7 +4,7 @@
*
* Communication protocol with TI SCI hardware
* The system works in a message response protocol
* See: http://processors.wiki.ti.com/index.php/TISCI for details
* See: https://software-dl.ti.com/tisci/esd/latest/index.html for details
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
*/
......
......@@ -2,7 +2,7 @@
/*
* Turris Mox rWTM firmware driver
*
* Copyright (C) 2019 Marek Behún <kabel@kernel.org>
* Copyright (C) 2019, 2024 Marek Behún <kabel@kernel.org>
*/
#include <linux/armada-37xx-rwtm-mailbox.h>
......@@ -174,6 +174,9 @@ static void mox_rwtm_rx_callback(struct mbox_client *cl, void *data)
struct mox_rwtm *rwtm = dev_get_drvdata(cl->dev);
struct armada_37xx_rwtm_rx_msg *msg = data;
if (completion_done(&rwtm->cmd_done))
return;
rwtm->reply = *msg;
complete(&rwtm->cmd_done);
}
......@@ -199,9 +202,8 @@ static int mox_get_board_info(struct mox_rwtm *rwtm)
if (ret < 0)
return ret;
ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
if (ret < 0)
return ret;
if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
return -ETIMEDOUT;
ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
if (ret == -ENODATA) {
......@@ -235,9 +237,8 @@ static int mox_get_board_info(struct mox_rwtm *rwtm)
if (ret < 0)
return ret;
ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
if (ret < 0)
return ret;
if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
return -ETIMEDOUT;
ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
if (ret == -ENODATA) {
......@@ -274,9 +275,8 @@ static int check_get_random_support(struct mox_rwtm *rwtm)
if (ret < 0)
return ret;
ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
if (ret < 0)
return ret;
if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
return -ETIMEDOUT;
return mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
}
......@@ -499,6 +499,7 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rwtm);
mutex_init(&rwtm->busy);
init_completion(&rwtm->cmd_done);
rwtm->mbox_client.dev = dev;
rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
......@@ -512,8 +513,6 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev)
goto remove_files;
}
init_completion(&rwtm->cmd_done);
ret = mox_get_board_info(rwtm);
if (ret < 0)
dev_warn(dev, "Cannot read board information: %i\n", ret);
......
......@@ -41,9 +41,6 @@
/* IOCTL/QUERY feature payload size */
#define FEATURE_PAYLOAD_SIZE 2
/* Firmware feature check version mask */
#define FIRMWARE_VERSION_MASK GENMASK(15, 0)
static bool feature_check_enabled;
static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
......
......@@ -167,7 +167,7 @@ config FSL_CORENET_CF
represents a coherency violation.
config FSL_IFC
bool "Freescale IFC driver" if COMPILE_TEST
bool "Freescale IFC driver"
depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
depends on HAS_IOMEM
......
......@@ -234,8 +234,7 @@ config MTD_NAND_FSL_IFC
tristate "Freescale IFC NAND controller"
depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
depends on HAS_IOMEM
select FSL_IFC
select MEMORY
depends on FSL_IFC
help
Various Freescale chips e.g P1010, include a NAND Flash machine
with built-in hardware ECC capabilities.
......
......@@ -188,6 +188,9 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
if (ch->soc_no_adp_ctrl) {
if (ch->vbus)
regulator_hardware_enable(ch->vbus, vbus);
vbus_ctrl_reg = USB2_VBCTRL;
vbus_ctrl_val = USB2_VBCTRL_VBOUT;
}
......@@ -718,7 +721,10 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
}
channel->vbus = devm_regulator_get_optional(dev, "vbus");
if (channel->soc_no_adp_ctrl && channel->is_otg_channel)
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
else
channel->vbus = devm_regulator_get_optional(dev, "vbus");
if (IS_ERR(channel->vbus)) {
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
ret = PTR_ERR(channel->vbus);
......
......@@ -7,6 +7,8 @@ source "drivers/platform/goldfish/Kconfig"
source "drivers/platform/chrome/Kconfig"
source "drivers/platform/cznic/Kconfig"
source "drivers/platform/mellanox/Kconfig"
source "drivers/platform/olpc/Kconfig"
......
......@@ -10,5 +10,6 @@ obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC_EC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
obj-$(CONFIG_ARM64) += arm64/
# SPDX-License-Identifier: GPL-2.0-only
#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/kconfig-language.rst.
#
menuconfig CZNIC_PLATFORMS
bool "Platform support for CZ.NIC's Turris hardware"
help
Say Y here to be able to choose driver support for CZ.NIC's Turris
devices. This option alone does not add any kernel code.
if CZNIC_PLATFORMS
config TURRIS_OMNIA_MCU
tristate "Turris Omnia MCU driver"
depends on MACH_ARMADA_38X || COMPILE_TEST
depends on I2C
depends on OF
depends on WATCHDOG
depends on GPIOLIB
depends on HW_RANDOM
depends on RTC_CLASS
depends on WATCHDOG_CORE
select GPIOLIB_IRQCHIP
help
Say Y here to add support for the features implemented by the
microcontroller on the CZ.NIC's Turris Omnia SOHO router.
The features include:
- board poweroff into true low power mode (with voltage regulators
disabled) and the ability to configure wake up from this mode (via
rtcwake)
- true random number generator (if available on the MCU)
- MCU watchdog
- GPIO pins
- to get front button press events (the front button can be
configured either to generate press events to the CPU or to change
front LEDs panel brightness)
- to enable / disable USB port voltage regulators and to detect
USB overcurrent
- to detect MiniPCIe / mSATA card presence in MiniPCIe port 0
- to configure resets of various peripherals on board revisions 32+
- to enable / disable the VHV voltage regulator to the SOC in order
to be able to program SOC's OTP on board revisions 32+
- to get input from the LED output pins of the WAN ethernet PHY, LAN
switch and MiniPCIe ports
To compile this driver as a module, choose M here; the module will be
called turris-omnia-mcu.
endif # CZNIC_PLATFORMS
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o
turris-omnia-mcu-y := turris-omnia-mcu-base.o
turris-omnia-mcu-y += turris-omnia-mcu-gpio.o
turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o
turris-omnia-mcu-y += turris-omnia-mcu-trng.o
turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* CZ.NIC's Turris Omnia MCU system off and RTC wakeup driver
*
* This is not a true RTC driver (in the sense that it does not provide a
* real-time clock), rather the MCU implements a wakeup from powered off state
* at a specified time relative to MCU boot, and we expose this feature via RTC
* alarm, so that it can be used via the rtcwake command, which is the standard
* Linux command for this.
*
* 2024 by Marek Behún <kabel@kernel.org>
*/
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kstrtox.h>
#include <linux/reboot.h>
#include <linux/rtc.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/turris-omnia-mcu-interface.h>
#include "turris-omnia-mcu.h"
static int omnia_get_uptime_wakeup(const struct i2c_client *client, u32 *uptime,
u32 *wakeup)
{
__le32 reply[2];
int err;
err = omnia_cmd_read(client, OMNIA_CMD_GET_UPTIME_AND_WAKEUP, reply,
sizeof(reply));
if (err)
return err;
if (uptime)
*uptime = le32_to_cpu(reply[0]);
if (wakeup)
*wakeup = le32_to_cpu(reply[1]);
return 0;
}
static int omnia_read_time(struct device *dev, struct rtc_time *tm)
{
u32 uptime;
int err;
err = omnia_get_uptime_wakeup(to_i2c_client(dev), &uptime, NULL);
if (err)
return err;
rtc_time64_to_tm(uptime, tm);
return 0;
}
static int omnia_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct i2c_client *client = to_i2c_client(dev);
struct omnia_mcu *mcu = i2c_get_clientdata(client);
u32 wakeup;
int err;
err = omnia_get_uptime_wakeup(client, NULL, &wakeup);
if (err)
return err;
alrm->enabled = !!wakeup;
rtc_time64_to_tm(wakeup ?: mcu->rtc_alarm, &alrm->time);
return 0;
}
static int omnia_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct i2c_client *client = to_i2c_client(dev);
struct omnia_mcu *mcu = i2c_get_clientdata(client);
mcu->rtc_alarm = rtc_tm_to_time64(&alrm->time);
if (alrm->enabled)
return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP,
mcu->rtc_alarm);
return 0;
}
static int omnia_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct i2c_client *client = to_i2c_client(dev);
struct omnia_mcu *mcu = i2c_get_clientdata(client);
return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP,
enabled ? mcu->rtc_alarm : 0);
}
static const struct rtc_class_ops omnia_rtc_ops = {
.read_time = omnia_read_time,
.read_alarm = omnia_read_alarm,
.set_alarm = omnia_set_alarm,
.alarm_irq_enable = omnia_alarm_irq_enable,
};
static int omnia_power_off(struct sys_off_data *data)
{
struct omnia_mcu *mcu = data->cb_data;
__be32 tmp;
u8 cmd[9];
u16 arg;
int err;
if (mcu->front_button_poweron)
arg = OMNIA_CMD_POWER_OFF_POWERON_BUTTON;
else
arg = 0;
cmd[0] = OMNIA_CMD_POWER_OFF;
put_unaligned_le16(OMNIA_CMD_POWER_OFF_MAGIC, &cmd[1]);
put_unaligned_le16(arg, &cmd[3]);
/*
* Although all values from and to MCU are passed in little-endian, the
* MCU's CRC unit uses big-endian CRC32 polynomial (0x04c11db7), so we
* need to use crc32_be() here.
*/
tmp = cpu_to_be32(get_unaligned_le32(&cmd[1]));
put_unaligned_le32(crc32_be(~0, (void *)&tmp, sizeof(tmp)), &cmd[5]);
err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd));
if (err)
dev_err(&mcu->client->dev,
"Unable to send the poweroff command: %d\n", err);
return NOTIFY_DONE;
}
static int omnia_restart(struct sys_off_data *data)
{
struct omnia_mcu *mcu = data->cb_data;
u8 cmd[3];
int err;
cmd[0] = OMNIA_CMD_GENERAL_CONTROL;
if (reboot_mode == REBOOT_HARD)
cmd[1] = cmd[2] = OMNIA_CTL_HARD_RST;
else
cmd[1] = cmd[2] = OMNIA_CTL_LIGHT_RST;
err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd));
if (err)
dev_err(&mcu->client->dev,
"Unable to send the restart command: %d\n", err);
/*
* MCU needs a little bit to process the I2C command, otherwise it will
* do a light reset based on SOC SYSRES_OUT pin.
*/
mdelay(1);
return NOTIFY_DONE;
}
static ssize_t front_button_poweron_show(struct device *dev,
struct device_attribute *a, char *buf)
{
struct omnia_mcu *mcu = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d\n", mcu->front_button_poweron);
}
static ssize_t front_button_poweron_store(struct device *dev,
struct device_attribute *a,
const char *buf, size_t count)
{
struct omnia_mcu *mcu = dev_get_drvdata(dev);
bool val;
int err;
err = kstrtobool(buf, &val);
if (err)
return err;
mcu->front_button_poweron = val;
return count;
}
static DEVICE_ATTR_RW(front_button_poweron);
static struct attribute *omnia_mcu_poweroff_attrs[] = {
&dev_attr_front_button_poweron.attr,
NULL
};
static umode_t poweroff_attrs_visible(struct kobject *kobj, struct attribute *a,
int n)
{
struct device *dev = kobj_to_dev(kobj);
struct omnia_mcu *mcu = dev_get_drvdata(dev);
if (mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP)
return a->mode;
return 0;
}
const struct attribute_group omnia_mcu_poweroff_group = {
.attrs = omnia_mcu_poweroff_attrs,
.is_visible = poweroff_attrs_visible,
};
int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)
{
struct device *dev = &mcu->client->dev;
int err;
/* MCU restart is always available */
err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART,
SYS_OFF_PRIO_FIRMWARE,
omnia_restart, mcu);
if (err)
return dev_err_probe(dev, err,
"Cannot register system restart handler\n");
/*
* Poweroff and wakeup are available only if POWEROFF_WAKEUP feature is
* present.
*/
if (!(mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP))
return 0;
err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_FIRMWARE,
omnia_power_off, mcu);
if (err)
return dev_err_probe(dev, err,
"Cannot register system power off handler\n");
mcu->rtcdev = devm_rtc_allocate_device(dev);
if (IS_ERR(mcu->rtcdev))
return dev_err_probe(dev, PTR_ERR(mcu->rtcdev),
"Cannot allocate RTC device\n");
mcu->rtcdev->ops = &omnia_rtc_ops;
mcu->rtcdev->range_max = U32_MAX;
set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, mcu->rtcdev->features);
err = devm_rtc_register_device(mcu->rtcdev);
if (err)
return dev_err_probe(dev, err, "Cannot register RTC device\n");
mcu->front_button_poweron = true;
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -92,6 +92,14 @@ config RESET_IMX7
help
This enables the reset controller driver for i.MX7 SoCs.
config RESET_IMX8MP_AUDIOMIX
tristate "i.MX8MP AudioMix Reset Driver"
depends on ARCH_MXC || COMPILE_TEST
select AUXILIARY_BUS
default CLK_IMX8MP
help
This enables the reset controller driver for i.MX8MP AudioMix
config RESET_INTEL_GW
bool "Intel Reset Controller Driver"
depends on X86 || COMPILE_TEST
......@@ -329,6 +337,12 @@ config RESET_ZYNQ
help
This enables the reset controller driver for Xilinx Zynq SoCs.
config RESET_ZYNQMP
bool "ZYNQMP Reset Driver" if COMPILE_TEST
default ARCH_ZYNQMP
help
This enables the reset controller driver for Xilinx ZynqMP SoCs.
source "drivers/reset/starfive/Kconfig"
source "drivers/reset/sti/Kconfig"
source "drivers/reset/hisilicon/Kconfig"
......
......@@ -2,8 +2,8 @@
obj-y += core.o
obj-y += hisilicon/
obj-y += starfive/
obj-$(CONFIG_ARCH_STI) += sti/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += sti/
obj-y += tegra/
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
......@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_IMX8MP_AUDIOMIX) += reset-imx8mp-audiomix.o
obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
obj-$(CONFIG_RESET_K210) += reset-k210.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
......@@ -41,4 +42,4 @@ obj-$(CONFIG_RESET_TN48M_CPLD) += reset-tn48m.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# SPDX-License-Identifier: GPL-2.0-only
if ARCH_STI
if ARCH_STI || COMPILE_TEST
config STIH407_RESET
bool
bool "STIH407 Reset Driver" if COMPILE_TEST
endif
# SPDX-License-Identifier: GPL-2.0-only
config RESET_TEGRA_BPMP
def_bool TEGRA_BPMP
bool "Tegra BPMP Reset Driver" if COMPILE_TEST
default TEGRA_BPMP
......@@ -688,4 +688,5 @@ static struct platform_driver meson_msr_driver = {
},
};
module_platform_driver(meson_msr_driver);
MODULE_DESCRIPTION("Amlogic Meson SoC Clock Measure driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
......@@ -252,4 +252,5 @@ static int __init imx8_soc_init(void)
return ret;
}
device_initcall(imx8_soc_init);
MODULE_DESCRIPTION("NXP i.MX8M SoC driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment