1
0
mirror of https://git.yoctoproject.org/meta-arm synced 2026-06-06 02:40:18 +00:00

arm-bsp/tc0: Add kernel patches

Add patches for SCMI, MHUv2 and DRM. Also update the kernel config
to enable boot to Android home screen instead of just console.

Change-Id: Ic2af15441667b967ef360d8410de94e83eb73de4
Signed-off-by: Anders Dellien <anders.dellien@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
This commit is contained in:
Anders Dellien
2020-10-21 19:42:56 +01:00
committed by Jon Mason
parent 82ffc86baf
commit 785f8bf4c1
11 changed files with 2208 additions and 138 deletions
@@ -73,7 +73,18 @@ KCONFIG_MODE_sgi575 = "--alldefconfig"
#
# Total Compute KMACHINE
#
SRC_URI_append_tc0 = " file://defconfig"
COMPATIBLE_MACHINE_tc0 = "tc0"
KMACHINE_tc0 = "tc0"
KCONFIG_MODE_tc0 = "--alldefconfig"
SRC_URI_append_tc0 = " \
file://defconfig \
file://0001-drm-Add-component-aware-simple-encoder.patch \
file://0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch \
file://0003-mailbox-arm_mhuv2-add-device-tree-binding-documentat.patch \
file://0004-mailbox-arm_mhuv2-add-arm-mhuv2-driver.patch \
file://0005-mailbox-arm_mhuv2-add-doorbell-transport-protocol-op.patch \
file://0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch \
file://0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch \
file://0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch \
"
@@ -0,0 +1,364 @@
From 7863ac1515009547bae3a66e0808e72b3bdcf8c8 Mon Sep 17 00:00:00 2001
From: Tushar Khandelwal <tushar.khandelwal@arm.com>
Date: Tue, 16 Jun 2020 12:39:06 +0000
Subject: [PATCH 1/9] drm: Add component-aware simple encoder
This is a simple DRM encoder that gets its connector timings information
from a OF subnode in the device tree and exposes that as a "discovered"
panel. It can be used together with component-based DRM drivers in an
emulated environment where no real encoder or connector hardware exists
and the display output is configured outside the kernel.
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Upstream-Status: Backport [https://git.linaro.org/landing-teams/working/arm/kernel-release.git/commit/?h=latest-armlt&id=15283f7be4b1e586702551e85b4caf06531ac2fc]
---
drivers/gpu/drm/Kconfig | 11 +
drivers/gpu/drm/Makefile | 2 +
drivers/gpu/drm/drm_virtual_encoder.c | 299 ++++++++++++++++++++++++++
3 files changed, 312 insertions(+)
create mode 100644 drivers/gpu/drm/drm_virtual_encoder.c
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index e67c194c2aca..c95279cd9341 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -265,6 +265,17 @@ config DRM_VKMS
If M is selected the module will be called vkms.
+config DRM_VIRT_ENCODER
+ tristate "Virtual OF-based encoder"
+ depends on DRM && OF
+ select VIDEOMODE_HELPERS
+ help
+ Choose this option to get a virtual encoder and its associated
+ connector that will use the device tree to read the display
+ timings information. If M is selected the module will be called
+ drm_vencoder.
+
+
config DRM_ATI_PCIGART
bool
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 82ff826b33cc..d2ab6fc64932 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -53,6 +53,8 @@ drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
+drm_vencoder-y := drm_virtual_encoder.o
+obj-$(CONFIG_DRM_VIRT_ENCODER) += drm_vencoder.o
obj-$(CONFIG_DRM) += drm.o
obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
diff --git a/drivers/gpu/drm/drm_virtual_encoder.c b/drivers/gpu/drm/drm_virtual_encoder.c
new file mode 100644
index 000000000000..4fd2098df286
--- /dev/null
+++ b/drivers/gpu/drm/drm_virtual_encoder.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2016 ARM Limited
+ * Author: Liviu Dudau <Liviu.Dudau@arm.com>
+ *
+ * Dummy encoder and connector that use the OF to "discover" the attached
+ * display timings. Can be used in situations where the encoder and connector's
+ * functionality are emulated and no setup steps are needed, or to describe
+ * attached panels for which no driver exists but can be used without
+ * additional hardware setup.
+ *
+ * The encoder also uses the component framework so that it can be a quick
+ * replacement for existing drivers when testing in an emulated environment.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_print.h>
+#include <linux/platform_device.h>
+#include <drm/drm_of.h>
+#include <linux/component.h>
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+struct drm_virt_priv {
+ struct drm_connector connector;
+ struct drm_encoder encoder;
+ struct display_timings *timings;
+};
+
+#define connector_to_drm_virt_priv(x) \
+ container_of(x, struct drm_virt_priv, connector)
+
+#define encoder_to_drm_virt_priv(x) \
+ container_of(x, struct drm_virt_priv, encoder)
+
+static void drm_virtcon_destroy(struct drm_connector *connector)
+{
+ struct drm_virt_priv *conn = connector_to_drm_virt_priv(connector);
+
+ drm_connector_cleanup(connector);
+ display_timings_release(conn->timings);
+}
+
+static enum drm_connector_status
+drm_virtcon_detect(struct drm_connector *connector, bool force)
+{
+ return connector_status_connected;
+}
+
+static const struct drm_connector_funcs drm_virtcon_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .detect = drm_virtcon_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_virtcon_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int drm_virtcon_get_modes(struct drm_connector *connector)
+{
+ struct drm_virt_priv *conn = connector_to_drm_virt_priv(connector);
+ struct display_timings *timings = conn->timings;
+ int i;
+
+ for (i = 0; i < timings->num_timings; i++) {
+ struct drm_display_mode *mode = drm_mode_create(connector->dev);
+ struct videomode vm;
+
+ if (videomode_from_timings(timings, &vm, i))
+ break;
+
+ drm_display_mode_from_videomode(&vm, mode);
+ mode->type = DRM_MODE_TYPE_DRIVER;
+ if (timings->native_mode == i)
+ mode->type = DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+ }
+
+ return i;
+}
+
+static int drm_virtcon_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return MODE_OK;
+}
+
+struct drm_encoder *drm_virtcon_best_encoder(struct drm_connector *connector)
+{
+ struct drm_virt_priv *priv = connector_to_drm_virt_priv(connector);
+
+ return &priv->encoder;
+}
+
+struct drm_encoder *
+drm_virtcon_atomic_best_encoder(struct drm_connector *connector,
+ struct drm_connector_state *connector_state)
+{
+ struct drm_virt_priv *priv = connector_to_drm_virt_priv(connector);
+
+ return &priv->encoder;
+}
+
+static const struct drm_connector_helper_funcs drm_virtcon_helper_funcs = {
+ .get_modes = drm_virtcon_get_modes,
+ .mode_valid = drm_virtcon_mode_valid,
+ .best_encoder = drm_virtcon_best_encoder,
+ .atomic_best_encoder = drm_virtcon_atomic_best_encoder,
+};
+
+static void drm_vencoder_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs drm_vencoder_funcs = {
+ .destroy = drm_vencoder_destroy,
+};
+
+static void drm_vencoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ /* nothing needed */
+}
+
+static bool drm_vencoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ /* nothing needed */
+ return true;
+}
+
+static void drm_vencoder_prepare(struct drm_encoder *encoder)
+{
+ drm_vencoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void drm_vencoder_commit(struct drm_encoder *encoder)
+{
+ drm_vencoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static void drm_vencoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ /* nothing needed */
+}
+
+static const struct drm_encoder_helper_funcs drm_vencoder_helper_funcs = {
+ .dpms = drm_vencoder_dpms,
+ .mode_fixup = drm_vencoder_mode_fixup,
+ .prepare = drm_vencoder_prepare,
+ .commit = drm_vencoder_commit,
+ .mode_set = drm_vencoder_mode_set,
+};
+
+static int drm_vencoder_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_encoder *encoder;
+ struct drm_virt_priv *con;
+ struct drm_connector *connector;
+ struct drm_device *drm = data;
+ u32 crtcs = 0;
+ int ret;
+
+ con = devm_kzalloc(dev, sizeof(*con), GFP_KERNEL);
+ if (!con)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, con);
+ connector = &con->connector;
+ encoder = &con->encoder;
+
+ if (dev->of_node) {
+ struct drm_bridge *bridge;
+ crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+ bridge = of_drm_find_bridge(dev->of_node);
+ if (bridge) {
+ ret = drm_bridge_attach(encoder, bridge, NULL);
+ if (ret) {
+ DRM_ERROR("Failed to initialize bridge\n");
+ return ret;
+ }
+ }
+ con->timings = of_get_display_timings(dev->of_node);
+ if (!con->timings) {
+ dev_err(dev, "failed to get display panel timings\n");
+ return ENXIO;
+ }
+ }
+
+ /* If no CRTCs were found, fall back to the old encoder's behaviour */
+ if (crtcs == 0) {
+ dev_warn(dev, "Falling back to first CRTC\n");
+ crtcs = 1 << 0;
+ }
+
+ encoder->possible_crtcs = crtcs ? crtcs : 1;
+ encoder->possible_clones = 0;
+
+ ret = drm_encoder_init(drm, encoder, &drm_vencoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret)
+ goto encoder_init_err;
+
+ drm_encoder_helper_add(encoder, &drm_vencoder_helper_funcs);
+
+ /* bogus values, pretend we're a 24" screen for DPI calculations */
+ connector->display_info.width_mm = 519;
+ connector->display_info.height_mm = 324;
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+ connector->polled = 0;
+
+ ret = drm_connector_init(drm, connector, &drm_virtcon_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ if (ret)
+ goto connector_init_err;
+
+ drm_connector_helper_add(connector, &drm_virtcon_helper_funcs);
+
+ drm_connector_register(connector);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret)
+ goto attach_err;
+
+ return ret;
+
+attach_err:
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+connector_init_err:
+ drm_encoder_cleanup(encoder);
+encoder_init_err:
+ display_timings_release(con->timings);
+
+ return ret;
+};
+
+static void drm_vencoder_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_virt_priv *con = dev_get_drvdata(dev);
+
+ drm_connector_unregister(&con->connector);
+ drm_connector_cleanup(&con->connector);
+ drm_encoder_cleanup(&con->encoder);
+ display_timings_release(con->timings);
+}
+
+static const struct component_ops drm_vencoder_ops = {
+ .bind = drm_vencoder_bind,
+ .unbind = drm_vencoder_unbind,
+};
+
+static int drm_vencoder_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &drm_vencoder_ops);
+}
+
+static int drm_vencoder_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &drm_vencoder_ops);
+ return 0;
+}
+
+static const struct of_device_id drm_vencoder_of_match[] = {
+ { .compatible = "drm,virtual-encoder", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, drm_vencoder_of_match);
+
+static struct platform_driver drm_vencoder_driver = {
+ .probe = drm_vencoder_probe,
+ .remove = drm_vencoder_remove,
+ .driver = {
+ .name = "drm_vencoder",
+ .of_match_table = drm_vencoder_of_match,
+ },
+};
+
+module_platform_driver(drm_vencoder_driver);
+
+MODULE_AUTHOR("Liviu Dudau");
+MODULE_DESCRIPTION("Virtual DRM Encoder");
+MODULE_LICENSE("GPL v2");
--
2.17.1
@@ -0,0 +1,31 @@
From 190c6354a0d80c31214550553cfbee25571e1942 Mon Sep 17 00:00:00 2001
From: Tushar Khandelwal <tushar.khandelwal@arm.com>
Date: Wed, 17 Jun 2020 10:49:26 +0000
Subject: [PATCH 2/9] drm: arm: komeda: add RENDER capability to the device
node
this is required to make this driver work with android framework
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Upstream-Status: Inappropriate [Product specific configuration]
---
drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index ae274902ff92..238bd8466206 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -56,7 +56,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
}
static struct drm_driver komeda_kms_driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_RENDER,
.lastclose = drm_fb_helper_lastclose,
.gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_vm_ops = &drm_gem_cma_vm_ops,
--
2.17.1
@@ -0,0 +1,134 @@
From bca81c4c54765565651634b6de5edb6a191577a3 Mon Sep 17 00:00:00 2001
From: Usama Arif <usama.arif@arm.com>
Date: Thu, 27 Jun 2019 11:16:22 +0100
Subject: [PATCH 3/9] mailbox: arm_mhuv2: add device tree binding documentation
This patch adds device tree binding for Message Handling Unit
controller version 2 from Arm.
Change-Id: I8c46dd7cd1a48450020c33721ea7cce9f8b8e64f
Signed-off-by: Usama Arif <usama.arif@arm.com>
Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Cc: robh+dt@kernel.org
Cc: mark.rutland@arm.com
Cc: devicetree@vger.kernel.org
Cc: jassisinghbrar@gmail.com
Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
---
.../devicetree/bindings/mailbox/arm,mhuv2.txt | 101 ++++++++++++++++++
1 file changed, 101 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt
diff --git a/Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt
new file mode 100644
index 000000000000..5b8a2ab21ae0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt
@@ -0,0 +1,101 @@
+Arm MHUv2 Mailbox Driver
+========================
+
+The Arm Message-Handling-Unit (MHU) Version 2 is a mailbox controller that has
+between 1 and 124 channel windows to provide unidirectional communication with
+remote processor(s).
+
+Given the unidirectional nature of the device, an MHUv2 mailbox may only be
+written to or read from. If a pair of MHU devices is implemented between two
+processing elements to provide bidirectional communication, these must be
+specified as two separate mailboxes.
+
+If the interrupts property is present in device tree node, then its treated
+as a receiver frame, otherwise a sender frame.
+
+An MHU device must be specified with a transport protocol. The transport
+protocol of an MHU device determines the method of data transmission as well as
+the number of provided mailboxes.
+Following are the possible transport protocol types:
+- Single-word: An MHU device implements as many mailboxes as it
+ provides channel windows. Data is transmitted through
+ the MHU registers.
+- Multi-word: An MHU device implements a single mailbox. All channel windows
+ will be used during transmission. Data is transmitted through
+ the MHU registers.
+- Doorbell: An MHU device implements as many mailboxes as there are flag
+ bits available in its channel windows. Optionally, data may
+ be transmitted through a shared memory region, wherein the MHU
+ is used strictly as an interrupt generation mechanism.
+
+Mailbox Device Node:
+====================
+
+Required properties:
+--------------------
+- compatible: Shall be "arm,mhuv2" & "arm,primecell"
+- reg: Contains the mailbox register address range (base
+ address and length)
+- #mbox-cells Shall be 1 - the index of the channel needed.
+- mhu-protocol Transport protocol of the device. Shall be one of the
+ following: "single-word", "multi-word", "doorbell"
+
+Required properties (receiver frame):
+-------------------------------------
+- interrupts: Contains the interrupt information for the receiver frame
+
+Example:
+--------
+
+ mbox_mw_tx: mhu@10000000 {
+ compatible = "arm,mhuv2","arm,primecell";
+ reg = <0x10000000 0x1000>;
+ clocks = <&refclk100mhz>;
+ clock-names = "apb_pclk";
+ #mbox-cells = <1>;
+ mhu-protocol = "multi-word";
+ };
+
+ mbox_sw_tx: mhu@10000000 {
+ compatible = "arm,mhuv2","arm,primecell";
+ reg = <0x11000000 0x1000>;
+ clocks = <&refclk100mhz>;
+ clock-names = "apb_pclk";
+ #mbox-cells = <1>;
+ mhu-protocol = "single-word";
+ };
+
+ mbox_db_rx: mhu@10000000 {
+ compatible = "arm,mhuv2","arm,primecell";
+ reg = <0x12000000 0x1000>;
+ clocks = <&refclk100mhz>;
+ clock-names = "apb_pclk";
+ #mbox-cells = <1>;
+ interrupts = <0 45 4>;
+ interrupt-names = "mhu_rx";
+ mhu-protocol = "doorbell";
+ };
+
+ mhu_client: scb@2e000000 {
+ compatible = "fujitsu,mb86s70-scb-1.0";
+ reg = <0 0x2e000000 0x4000>;
+ mboxes =
+ // For multi-word frames, client may only instantiate a single
+ // mailbox for a mailbox controller
+ <&mbox_mw_tx 0>,
+
+ // For single-word frames, client may instantiate as many
+ // mailboxes as there are channel windows in the MHU
+ <&mbox_sw_tx 0>,
+ <&mbox_sw_tx 1>,
+ <&mbox_sw_tx 2>,
+ <&mbox_sw_tx 3>,
+
+ // For doorbell frames, client may instantiate as many mailboxes
+ // as there are bits available in the combined number of channel
+ // windows ((channel windows * 32) mailboxes)
+ <mbox_db_rx 0>,
+ <mbox_db_rx 1>,
+ ...
+ <mbox_db_rx 17>;
+ };
\ No newline at end of file
--
2.17.1
@@ -0,0 +1,822 @@
From 364539028799290814a35aa10d32d850486f0b4a Mon Sep 17 00:00:00 2001
From: Usama Arif <usama.arif@arm.com>
Date: Thu, 27 Jun 2019 11:17:14 +0100
Subject: [PATCH 4/9] mailbox: arm_mhuv2: add arm mhuv2 driver
This commit adds a driver for the ARM MHUv2 (Message Handling Unit).
The driver registers itself as a mailbox controller within the common
mailbox framework.
This commit implements the single-word transport protocol;
In single-word mode, the mailbox controller will provide a mailbox for each
channel window available in the MHU device.
Transmitting and receiving data through the mailbox framework in
single-word mode is done through a struct arm_mbox_msg.
Change-Id: I718253ceb902a2d53f7199a746063a36129b0fa6
Signed-off-by: Usama Arif <usama.arif@arm.com>
Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Cc: jassisinghbrar@gmail.com
Cc: devicetree@vger.kernel.org
Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
---
drivers/mailbox/Kconfig | 7 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/arm_mhu_v2.c | 707 +++++++++++++++++++++++
include/linux/mailbox/arm-mbox-message.h | 37 ++
4 files changed, 753 insertions(+)
create mode 100644 drivers/mailbox/arm_mhu_v2.c
create mode 100644 include/linux/mailbox/arm-mbox-message.h
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ab4eb750bbdd..0a0dce01098c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -22,6 +22,13 @@ config IMX_MBOX
help
Mailbox implementation for i.MX Messaging Unit (MU).
+config ARM_MHU_V2
+ tristate "ARM MHUv2 Mailbox"
+ depends on ARM_AMBA
+ help
+ Say Y here if you want to build the ARM MHUv2 controller driver,
+ which provides unidirectional mailboxes between processing elements.
+
config PLATFORM_MHU
tristate "Platform MHU Mailbox"
depends on OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index c22fad6f696b..78377f459421 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
obj-$(CONFIG_ARMADA_37XX_RWTM_MBOX) += armada-37xx-rwtm-mailbox.o
+obj-$(CONFIG_ARM_MHU_V2) += arm_mhu_v2.o
+
obj-$(CONFIG_PLATFORM_MHU) += platform_mhu.o
obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
new file mode 100644
index 000000000000..d809076eb47b
--- /dev/null
+++ b/drivers/mailbox/arm_mhu_v2.c
@@ -0,0 +1,707 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Arm Message Handling Unit Version 2 (MHUv2) driver
+ *
+ * An MHU device may function in one of three transport protocol modes
+ * (single-word, multi-word and doorbell).
+ * This transport protocol should be specified in the device tree entry for the
+ * device. The transport protocol determines how the underlying hardware
+ * resources of the device are utilized when transmitting data.
+ *
+ * The arm MHUv2 driver registers as a mailbox controller with the common
+ * mailbox framework. Each mailbox channel represents a separate virtual
+ * communication channel through the MHU device.
+ * The number of registered mailbox channels is dependent on both the
+ * underlying hardware - mainly the number of channel windows within each MHU
+ * frame, as well as the selected transport protocol.
+ *
+ * Copyright (C) 2019 Arm Ltd.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/amba/bus.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/arm-mbox-message.h>
+#include <linux/of_address.h>
+#include <linux/interrupt.h>
+
+/* Maximum number of channel windows */
+#define MHUV2_CHANNEL_MAX 124
+/* Number of combined interrupt status registers */
+#define MHUV2_CMB_INT_ST_REG_CNT 4
+#define MHUV2_CH_UNKNOWN -1
+
+/* Channel window status register type */
+typedef u32 mhuv2_stat_reg_t;
+#define MHUV2_STAT_BYTES sizeof(mhuv2_stat_reg_t)
+#define MHUV2_STAT_BITS (MHUV2_STAT_BYTES * __CHAR_BIT__)
+
+#define LSB_MASK(n) ((1 << (n)) - 1)
+
+#ifndef PAD
+#define _PADLINE(line) pad##line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif
+
+/* ====== Arm MHUv2 register defines ====== */
+
+/* Register Message Handling Unit Configuration fields */
+struct MHU_CFG_t {
+ u32 NUM_CH : 7;
+ u32 PAD : 25;
+} __packed;
+
+/* Register Implementer Identification fields */
+struct IIDR_t {
+ u32 IMPLEMENTER : 12;
+ u32 REVISION : 4;
+ u32 VARIANT : 4;
+ u32 PRODUCT_ID : 12;
+} __packed;
+
+/* Register Architecture Identification Register fields */
+struct AIDR_t {
+ u32 ARCH_MINOR_REV : 4;
+ u32 ARCH_MAJOR_REV : 4;
+ u32 PAD : 24;
+} __packed;
+
+/* register Interrupt Status fields */
+struct INT_ST_t {
+ u32 NR2R : 1;
+ u32 R2NR : 1;
+ u32 PAD : 30;
+} __packed;
+
+/* Register Interrupt Clear fields */
+struct INT_CLR_t {
+ u32 NR2R : 1;
+ u32 R2NR : 1;
+ u32 PAD : 30;
+} __packed;
+
+/* Register Interrupt Enable fields */
+struct INT_EN_t {
+ u32 R2NR : 1;
+ u32 NR2R : 1;
+ u32 CHCOMB : 1;
+ u32 PAD : 29;
+} __packed;
+
+/* Sender Channel Window fields */
+struct mhu2_send_channel_reg {
+ mhuv2_stat_reg_t STAT;
+ u8 PAD[0xC - 0x4];
+ mhuv2_stat_reg_t STAT_SET;
+ u8 PAD[0x20 - 0x10];
+} __packed;
+
+/* Sender frame register fields */
+struct mhu2_send_frame_reg {
+ struct mhu2_send_channel_reg channel[MHUV2_CHANNEL_MAX];
+ struct MHU_CFG_t MHU_CFG;
+ u32 RESP_CFG;
+ u32 ACCESS_REQUEST;
+ u32 ACCESS_READY;
+ struct INT_ST_t INT_ST;
+ struct INT_CLR_t INT_CLR;
+ struct INT_EN_t INT_EN;
+ u32 RESERVED0;
+ u32 CHCOMB_INT_ST[MHUV2_CMB_INT_ST_REG_CNT];
+ u8 PAD[0xFC8 - 0xFB0];
+ struct IIDR_t IIDR;
+ struct AIDR_t AIDR;
+} __packed;
+
+/* Receiver Channel Window fields */
+struct mhu2_recv_channel_reg {
+ mhuv2_stat_reg_t STAT;
+ mhuv2_stat_reg_t STAT_PEND;
+ mhuv2_stat_reg_t STAT_CLEAR;
+ u8 RESERVED0[0x10 - 0x0C];
+ mhuv2_stat_reg_t MASK;
+ mhuv2_stat_reg_t MASK_SET;
+ mhuv2_stat_reg_t MASK_CLEAR;
+ u8 PAD[0x20 - 0x1C];
+} __packed;
+
+/* Receiver frame register fields */
+struct mhu2_recv_frame_reg {
+ struct mhu2_recv_channel_reg channel[MHUV2_CHANNEL_MAX];
+ struct MHU_CFG_t MHU_CFG;
+ u8 RESERVED0[0xF90 - 0xF84];
+ struct INT_ST_t INT_ST;
+ struct INT_CLR_t INT_CLR;
+ struct INT_EN_t INT_EN;
+ u32 PAD;
+ mhuv2_stat_reg_t CHCOMB_INT_ST[MHUV2_CMB_INT_ST_REG_CNT];
+ u8 RESERVED2[0xFC8 - 0xFB0];
+ struct IIDR_t IIDR;
+ struct AIDR_t AIDR;
+} __packed;
+
+/* ====== Arm MHUv2 device tree property identifiers ====== */
+
+static const char *const mhuv2_protocol_dt_identifiers[] = { "single-word",
+ "multi-word",
+ "doorbell" };
+
+static const char *const mhuv2_frame_dt_identifiers[] = { "receiver",
+ "sender" };
+
+/* ====== Arm MHUv2 data structures ====== */
+
+enum mhuv2_transport_protocol { SINGLE_WORD, MULTI_WORD, DOORBELL };
+
+enum mhuv2_frame { RECEIVER_FRAME, SENDER_FRAME };
+
+/**
+ * Arm MHUv2 operations
+ *
+ * Each transport protocol must provide an implementation of the operations
+ * presented in this structure.
+ * Most operations present a struct mbox_chan* as argument. This channel will
+ * correspond to one of the virtual channels within the MHU device. What
+ * constitutes a channel within the MHU device is dependent on the transport
+ * protocol.
+ */
+struct arm_mhuv2;
+struct mhuv2_ops {
+ int (*read_data)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan,
+ struct arm_mbox_msg *msg);
+ int (*clear_data)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan,
+ struct arm_mbox_msg *msg);
+ int (*send_data)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan,
+ const struct arm_mbox_msg *msg);
+ int (*setup)(struct arm_mhuv2 *mhuv2);
+ int (*last_tx_done)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan);
+ struct mbox_chan *(*get_active_mbox_chan)(struct arm_mhuv2 *mhuv2);
+};
+
+/**
+ * Arm MHUv2 mailbox channel information
+ *
+ * A channel contains a notion of its index within the array of mailbox channels
+ * which a mailbox controller allocates.
+ */
+struct arm_mhuv2_mbox_chan_priv {
+ u32 ch_idx;
+};
+
+#define mhuv2_chan_idx(_chanptr) \
+ (((struct arm_mhuv2_mbox_chan_priv *)(_chanptr)->con_priv)->ch_idx)
+
+/**
+ * Arm MHUv2 mailbox controller data
+ *
+ * @reg: Base address of the register mapping region
+ * @protocol: Transport protocol, derived from device tree
+ * @frame: Frame type, derived from device tree
+ * @irq: Interrupt, only valid for receiver frames
+ * @mbox: Mailbox controller belonging to the MHU frame
+ * @ops: Pointer to transport-protocol specific operations
+ * @dev: Device to which it is attached
+ */
+struct arm_mhuv2 {
+ union {
+ struct mhu2_send_frame_reg __iomem *send;
+ struct mhu2_recv_frame_reg __iomem *recv;
+ } reg;
+ enum mhuv2_frame frame;
+ unsigned int irq;
+ struct mbox_controller mbox;
+ struct mhuv2_ops *ops;
+ struct device *dev;
+};
+
+#define mhu2_from_mbox_ctrl(_mbox) container_of(_mbox, struct arm_mhuv2, mbox)
+#define mhu2_from_mbox_chan(_chan) mhu2_from_mbox_ctrl(_chan->mbox)
+
+/* Macro for reading a bitfield within a physically mapped packed struct */
+#define readl_relaxed_bitfield(_regptr, _field) \
+ ({ \
+ mhuv2_stat_reg_t _regval; \
+ BUILD_BUG_ON(sizeof(*(_regptr)) > sizeof(typeof(_regval))); \
+ _regval = readl_relaxed((_regptr)); \
+ (*(typeof((_regptr)))(&_regval))._field; \
+ })
+
+/* Macro for writing a bitfield within a physically mapped packed struct */
+#define writel_relaxed_bitfield(_value, _regptr, _field) \
+ ({ \
+ mhuv2_stat_reg_t _regval; \
+ BUILD_BUG_ON(sizeof(*_regptr) > sizeof(typeof(_regval))); \
+ _regval = readl_relaxed(_regptr); \
+ (*(typeof(_regptr))(&_regval))._field = _value; \
+ writel_relaxed(_regval, _regptr); \
+ })
+
+static inline int __find_set_bit(uint32_t val)
+{
+ const uint32_t trailing_zeros = __builtin_ctz(val);
+ return trailing_zeros == 32 ? -1 : trailing_zeros;
+}
+
+/**
+ * Get index of a set bit within the combined interrupt status registers
+ *
+ * The function will calculate the index being the offset from the LSB of the
+ * first combined interrupt status register.
+ *
+ */
+static inline int mhuv2_combint_idx(struct arm_mhuv2 *mhuv2)
+{
+ int ch_idx = 0;
+ int set_bit_index, reg_idx;
+
+ for (reg_idx = 0; reg_idx < MHUV2_CMB_INT_ST_REG_CNT; reg_idx++) {
+ mhuv2_stat_reg_t stat_reg;
+
+ stat_reg =
+ readl_relaxed(&mhuv2->reg.recv->CHCOMB_INT_ST[reg_idx]);
+ set_bit_index = __find_set_bit(stat_reg);
+ if (set_bit_index == -1) {
+ ch_idx += MHUV2_STAT_BITS;
+ } else {
+ ch_idx += set_bit_index;
+ break;
+ }
+ }
+ return (ch_idx >= (MHUV2_CMB_INT_ST_REG_CNT * MHUV2_STAT_BITS) ?
+ MHUV2_CH_UNKNOWN :
+ ch_idx);
+}
+
+/* ================ Single word transport protocol operations =============== */
+static inline int mhuv20_get_non_zero_ch_idx(struct arm_mhuv2 *mhuv2)
+{
+ /* Locate a channel window with a non-zero STAT register */
+ int ch_idx;
+ int ch = MHUV2_CH_UNKNOWN;
+
+ for (ch_idx = 0;
+ ch_idx < readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
+ ch_idx++) {
+ if (readl_relaxed(&mhuv2->reg.recv->channel[ch_idx].STAT)) {
+ ch = ch_idx;
+ break;
+ }
+ }
+ return ch;
+}
+
+static inline int mhuv2_get_non_zero_ch_idx(struct arm_mhuv2 *mhuv2)
+{
+ /* Identify index of channel window containing non-zero data */
+ switch (readl_relaxed_bitfield(&mhuv2->reg.recv->AIDR,
+ ARCH_MINOR_REV)) {
+ case 1:
+ return mhuv2_combint_idx(mhuv2);
+ default:
+ return mhuv20_get_non_zero_ch_idx(mhuv2);
+ }
+}
+
+static inline int mhuv2_read_data_single_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ struct arm_mbox_msg *msg)
+{
+ const u32 ch_idx = mhuv2_chan_idx(chan);
+
+ msg->data = kzalloc(MHUV2_STAT_BYTES, GFP_KERNEL);
+ if (!msg->data)
+ return -ENOMEM;
+
+ *(mhuv2_stat_reg_t *)msg->data =
+ readl_relaxed(&mhuv2->reg.recv->channel[ch_idx].STAT);
+ msg->len = MHUV2_STAT_BYTES;
+ return 0;
+}
+
+static inline int mhuv2_clear_data_single_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ struct arm_mbox_msg *msg)
+{
+ const u32 ch_idx = mhuv2_chan_idx(chan);
+
+ writel_relaxed(readl_relaxed(&mhuv2->reg.recv->channel[ch_idx].STAT),
+ &mhuv2->reg.recv->channel[ch_idx].STAT_CLEAR);
+ return 0;
+}
+
+static inline int mhuv2_send_data_single_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ const struct arm_mbox_msg *msg)
+{
+ const u32 ch_idx = mhuv2_chan_idx(chan);
+ int bytes_left = msg->len;
+ char *data = msg->data;
+
+ if (ch_idx >= readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH))
+ return -ENODEV;
+
+ while (bytes_left > 0) {
+ mhuv2_stat_reg_t word = *(mhuv2_stat_reg_t *)(data);
+
+ if (bytes_left < MHUV2_STAT_BYTES)
+ word &= LSB_MASK(bytes_left * __CHAR_BIT__);
+
+ if (!word) {
+ dev_err(mhuv2->dev,
+ "Data transmitted in single-word mode must be non-zero\n");
+ return -EINVAL;
+ }
+ writel_relaxed(word,
+ &mhuv2->reg.send->channel[ch_idx].STAT_SET);
+ while (readl_relaxed(&mhuv2->reg.send->channel[ch_idx].STAT))
+ continue;
+ bytes_left -= MHUV2_STAT_BYTES;
+ data += MHUV2_STAT_BYTES;
+ }
+
+ return 0;
+}
+
+static inline int mhuv2_last_tx_done_single_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan)
+{
+ const u32 ch_idx = mhuv2_chan_idx(chan);
+
+ return readl_relaxed(&mhuv2->reg.send->channel[ch_idx].STAT) == 0;
+}
+
+static inline int mhuv2_setup_single_word(struct arm_mhuv2 *mhuv2)
+{
+ int i;
+ const u32 channel_windows =
+ readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ?
+ &mhuv2->reg.recv->MHU_CFG :
+ &mhuv2->reg.send->MHU_CFG,
+ NUM_CH);
+
+ mhuv2->mbox.num_chans = channel_windows;
+ mhuv2->mbox.chans =
+ devm_kzalloc(mhuv2->dev,
+ mhuv2->mbox.num_chans * sizeof(struct mbox_chan),
+ GFP_KERNEL);
+
+ for (i = 0; i < mhuv2->mbox.num_chans; i++) {
+ mhuv2->mbox.chans[i].con_priv =
+ devm_kzalloc(mhuv2->dev,
+ sizeof(struct arm_mhuv2_mbox_chan_priv),
+ GFP_KERNEL);
+ mhuv2_chan_idx(&mhuv2->mbox.chans[i]) = i;
+ }
+
+ if (mhuv2->frame == RECEIVER_FRAME) {
+ /* Ensure all status registers are unmasked */
+ for (i = 0; i < channel_windows; i++) {
+ writel_relaxed(0x0,
+ &mhuv2->reg.recv->channel[i].MASK_SET);
+ }
+ }
+
+ return 0;
+}
+
+static inline struct mbox_chan *
+ mhuv2_get_active_mbox_chan_single_word(struct arm_mhuv2 *mhuv2)
+{
+ const u32 ch_idx = mhuv2_get_non_zero_ch_idx(mhuv2);
+
+ if (ch_idx >= mhuv2->mbox.num_chans) {
+ dev_err(mhuv2->dev,
+ "Invalid active channel in single word mode\n");
+ return ERR_PTR(-EINVAL);
+ }
+ return &mhuv2->mbox.chans[ch_idx];
+}
+
+static const struct mhuv2_ops mhuv2_single_word_ops = {
+ .read_data = mhuv2_read_data_single_word,
+ .clear_data = mhuv2_clear_data_single_word,
+ .send_data = mhuv2_send_data_single_word,
+ .setup = mhuv2_setup_single_word,
+ .last_tx_done = mhuv2_last_tx_done_single_word,
+ .get_active_mbox_chan = mhuv2_get_active_mbox_chan_single_word,
+};
+/* ========================================================================== */
+
+/*
+ * MHUv2 receiver interrupt service routine
+ *
+ * This routine will be called whenever a reception interrupt is raised on the
+ * MHU device. Given that an MHU device may manage multiple mailboxes, it is
+ * up to the protocol-specific operations to determine:
+ * - What is the active mailbox channel
+ * - Read the data within the MHU corresponding to the channel
+ * - Clear the data within the MHU corresponding to the channel
+ *
+ * These operations must also ensure to not overwrite any data which may belong
+ * to a different mailbox channel. For instance, if data is received in two
+ * channel windows in single-word mode, the ISR will read and clear the data
+ * from one of these channel windows within a pass. This will result in a status
+ * register being non-zero upon returning from this routine, which in turn
+ * will keep the interrupt asserted for a second round.
+ */
+static irqreturn_t mhuv2_rx_interrupt(int irq, void *data)
+{
+ struct arm_mbox_msg msg;
+ int status;
+ struct arm_mhuv2 *mhuv2 = data;
+ struct mbox_chan *chan = mhuv2->ops->get_active_mbox_chan(mhuv2);
+
+ msg.data = NULL;
+ msg.len = 0;
+
+ status = mhuv2->ops->read_data(mhuv2, chan, &msg);
+ if (status != 0)
+ goto rx_exit;
+
+ if (!chan->cl) {
+ dev_warn(
+ mhuv2->dev,
+ "Warning: Received data on channel not currently attached to "
+ "a mailbox client\n");
+ } else {
+ mbox_chan_received_data(chan, (void *)&msg);
+ }
+
+ status = mhuv2->ops->clear_data(mhuv2, chan, &msg);
+
+rx_exit:
+ kfree(msg.data);
+
+ return status == 0 ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static bool mhuv2_last_tx_done(struct mbox_chan *chan)
+{
+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_chan(chan);
+
+ return mhuv2->ops->last_tx_done(mhuv2, chan);
+}
+
+static int mhuv2_send_data(struct mbox_chan *chan, void *data)
+{
+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_chan(chan);
+ struct arm_mbox_msg *msg = data;
+ int ret;
+
+ if (!mhuv2->ops->last_tx_done(mhuv2, chan))
+ return -EBUSY;
+
+ ret = mhuv2->ops->send_data(mhuv2, chan, msg);
+ return ret;
+}
+
+static int mhuv2_startup(struct mbox_chan *chan)
+{
+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_ctrl(chan->mbox);
+
+ writel_relaxed(0x1, &mhuv2->reg.send->ACCESS_REQUEST);
+ while (!readl_relaxed(&mhuv2->reg.send->ACCESS_READY))
+ continue;
+
+ return 0;
+}
+
+static void mhuv2_shutdown(struct mbox_chan *chan)
+{
+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_ctrl(chan->mbox);
+
+ writel_relaxed(0x0, &mhuv2->reg.send->ACCESS_REQUEST);
+}
+
+static int mhuv2_recv_startup(struct mbox_chan *chan)
+{
+ return 0;
+}
+
+static void mhuv2_recv_shutdown(struct mbox_chan *chan)
+{
+}
+
+static int mhuv2_recv_send_data(struct mbox_chan *chan, void *data)
+{
+ dev_err(chan->mbox->dev,
+ "Trying to transmit on a receiver MHU frame\n");
+ return -EIO;
+}
+
+static bool mhuv2_recv_last_tx_done(struct mbox_chan *chan)
+{
+ dev_err(chan->mbox->dev, "Trying to Tx poll on a receiver MHU frame\n");
+ return true;
+}
+
+static const struct mbox_chan_ops mhuv2_receiver_ops = {
+ .send_data = mhuv2_recv_send_data,
+ .startup = mhuv2_recv_startup,
+ .shutdown = mhuv2_recv_shutdown,
+ .last_tx_done = mhuv2_recv_last_tx_done,
+};
+
+static const struct mbox_chan_ops mhuv2_sender_ops = {
+ .send_data = mhuv2_send_data,
+ .startup = mhuv2_startup,
+ .shutdown = mhuv2_shutdown,
+ .last_tx_done = mhuv2_last_tx_done,
+};
+
+static struct mbox_chan *mhuv2_mbox_of_xlate(struct mbox_controller *ctrl,
+ const struct of_phandle_args *pa)
+{
+ struct mbox_chan *chan;
+
+ if (pa->args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ if (pa->args[0] >= ctrl->num_chans)
+ return ERR_PTR(-ENOENT);
+
+ chan = &ctrl->chans[pa->args[0]];
+ return chan;
+}
+
+static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
+{
+ int err;
+ struct device *dev = &adev->dev;
+ const struct device_node *np = dev->of_node;
+ struct arm_mhuv2 *mhuv2;
+ const char *mhuv2_protocol_str;
+
+ /* Allocate memory for device */
+ mhuv2 = devm_kzalloc(dev, sizeof(*mhuv2), GFP_KERNEL);
+ if (!mhuv2)
+ return -ENOMEM;
+
+ mhuv2->dev = dev;
+
+ /* Assign transport protocol-specific operations */
+ err = of_property_read_string(np, "mhu-protocol", &mhuv2_protocol_str);
+
+ if (err) {
+ dev_err(dev,
+ "Probe failed: no transport protocol specified\n");
+ return -ENODEV;
+ } else if (strcmp(mhuv2_protocol_str,
+ mhuv2_protocol_dt_identifiers[SINGLE_WORD]) == 0) {
+ mhuv2->ops = &mhuv2_single_word_ops;
+ } else {
+ dev_err(dev,
+ "Probe failed: '%s' is not a valid transport protocol specifier\n",
+ mhuv2_protocol_str);
+ return -ENODEV;
+ }
+
+ /* Get MHU type specific properties from device tree */
+ if (adev->irq[0]) {
+ mhuv2->frame = RECEIVER_FRAME;
+ mhuv2->reg.recv = (struct mhu2_recv_frame_reg *)of_iomap(
+ (struct device_node *)np, 0);
+ if (!mhuv2->reg.recv)
+ goto io_fail;
+ mhuv2->irq = adev->irq[0];
+ } else {
+ mhuv2->frame = SENDER_FRAME;
+ mhuv2->reg.send = (struct mhu2_send_frame_reg *)of_iomap(
+ (struct device_node *)np, 0);
+ if (!mhuv2->reg.send)
+ goto io_fail;
+ }
+
+ /* Mailbox controller setup */
+ mhuv2->mbox.dev = dev;
+ mhuv2->mbox.txdone_irq = false;
+ mhuv2->mbox.txdone_poll = true;
+ mhuv2->mbox.txpoll_period = 1;
+ mhuv2->mbox.of_xlate = mhuv2_mbox_of_xlate;
+ mhuv2->mbox.ops = mhuv2->frame == SENDER_FRAME ? &mhuv2_sender_ops :
+ &mhuv2_receiver_ops;
+ /*
+ * Transport protocol specific setup
+ * Setup function _must_ allocate mailbox channels according to the
+ * number of channels provided in the given transport protocol mode.
+ */
+ err = mhuv2->ops->setup(mhuv2);
+ if (err)
+ return err;
+
+ /* Request an interrupt if this is a receiver frame */
+ if (mhuv2->frame == RECEIVER_FRAME) {
+ err = devm_request_threaded_irq(dev, adev->irq[0], NULL,
+ mhuv2_rx_interrupt, IRQF_ONESHOT, "mhuv2_link", mhuv2);
+ if (err) {
+ dev_err(dev, "unable to acquire IRQ %d\n", mhuv2->irq);
+ return err;
+ }
+ /*
+ * For minor version 1 and forward, the combined interrupt of
+ * the receiver frame must be explicitly enabled during startup.
+ */
+ if (readl_relaxed_bitfield(&mhuv2->reg.recv->AIDR,
+ ARCH_MINOR_REV) > 0) {
+ writel_relaxed_bitfield(1, &mhuv2->reg.recv->INT_EN,
+ CHCOMB);
+ }
+ }
+
+ amba_set_drvdata(adev, mhuv2);
+
+ err = devm_mbox_controller_register(dev, &mhuv2->mbox);
+ if (err) {
+ dev_err(dev, "failed to register ARM MHUv2 driver %d\n", err);
+ iounmap(mhuv2->frame == RECEIVER_FRAME ? mhuv2->reg.recv :
+ mhuv2->reg.send);
+ return err;
+ }
+
+ dev_info(dev, "ARM MHUv2 %s frame (%s) Mailbox driver registered\n",
+ mhuv2_frame_dt_identifiers[mhuv2->frame],
+ mhuv2_protocol_str);
+
+ return 0;
+
+io_fail:
+ dev_err(dev, "Probe failed: failed to map '%s' frame\n",
+ mhuv2_frame_dt_identifiers[mhuv2->frame]);
+ iounmap(mhuv2->frame == RECEIVER_FRAME ? mhuv2->reg.recv :
+ mhuv2->reg.send);
+ return -ENOMEM;
+}
+
+static int mhuv2_remove(struct amba_device *adev)
+{
+ return 0;
+}
+
+static struct amba_id mhuv2_ids[] = {
+ {
+ .id = 0x4b0d1,
+ .mask = 0xfffff,
+ },
+ {
+ .id = 0xbb0d1,
+ .mask = 0xfffff,
+ },
+ { 0, 0 },
+};
+MODULE_DEVICE_TABLE(amba, mhuv2_ids);
+
+static struct amba_driver arm_mhuv2_driver = {
+ .drv = {
+ .name = "mhuv2",
+ },
+ .id_table = mhuv2_ids,
+ .probe = mhuv2_probe,
+ .remove = mhuv2_remove,
+};
+module_amba_driver(arm_mhuv2_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ARM MHUv2 Driver");
+MODULE_AUTHOR("Morten Borup Petersen <morten.petersen@arm.com>");
diff --git a/include/linux/mailbox/arm-mbox-message.h b/include/linux/mailbox/arm-mbox-message.h
new file mode 100644
index 000000000000..112b4f927c1a
--- /dev/null
+++ b/include/linux/mailbox/arm-mbox-message.h
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Arm Mailbox Message
+ *
+ * The Arm mailbox message structure is used to pass data- and length
+ * information between a mailbox client and mailbox controller, through the
+ * provided void* of the common mailbox frameworks send- and receive APIs.
+ *
+ * This will be utilized when a mailbox controller is able to transmit
+ * more than a single word within a transmission, allowing the controller
+ * to fully utilize its available resources.
+ * No message protocol is enforced through this structure - a utilizing mailbox
+ * client driver shall implement its own message protocol, which may then be
+ * transmitted through an arm_mbox_msg.
+ *
+ * Given a message protocol of size A and an arm_mbox_msg containing data of
+ * length B, a mailbox channel may callback with B < A. In this case, the
+ * message protocol driver must implement a state machine which allows for
+ * multiple callbacks that provides parts of a full message of size A. This
+ * state machine must account for, that the length of the arm_mbox_msg received
+ * may vary between callbacks based on the underlying hardware as well as the
+ * transmitted data.
+ *
+ * Copyright (C) 2019 Arm Ltd.
+ */
+
+#ifndef _LINUX_ARM_MBOX_MESSAGE_H_
+#define _LINUX_ARM_MBOX_MESSAGE_H_
+
+#include <linux/types.h>
+
+struct arm_mbox_msg {
+ void *data;
+ size_t len;
+};
+
+#endif /* _LINUX_ARM_MBOX_MESSAGE_H_ */
--
2.17.1
@@ -0,0 +1,156 @@
From 515a936531a25a0c48a97efe3828962ed8d781dd Mon Sep 17 00:00:00 2001
From: Usama Arif <usama.arif@arm.com>
Date: Wed, 19 Jun 2019 16:55:20 +0100
Subject: [PATCH 5/9] mailbox: arm_mhuv2: add doorbell transport protocol
operations
In doorbell mode, the mailbox controller will provide a mailbox for each
flag bit available in the combined number of channel windows available
within the MHU device.
When in doorbell mode, the MHU should be used solely as an interrupt
generating mechanism. If data is to be transmitted, this must be done
out-band, ie. through shared memory, by a driving utilizing the mailbox
for interrupt generation.
Change-Id: I8410b21471743c0b624c873388f9629ea0863789
Signed-off-by: Usama Arif <usama.arif@arm.com>
Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Cc:Jassi Brar <jassisinghbrar@gmail.com
Cc: devicetree@vger.kernel.org
Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
---
drivers/mailbox/arm_mhu_v2.c | 108 +++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
index d809076eb47b..efde7a71a3f7 100644
--- a/drivers/mailbox/arm_mhu_v2.c
+++ b/drivers/mailbox/arm_mhu_v2.c
@@ -429,6 +429,111 @@ static const struct mhuv2_ops mhuv2_single_word_ops = {
};
/* ========================================================================== */
+/* =================== Doorbell transport protocol operations =============== */
+
+static inline int mhuv2_read_data_doorbell(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ struct arm_mbox_msg *msg)
+{
+ return 0;
+}
+
+static inline int mhuv2_clear_data_doorbell(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ struct arm_mbox_msg *msg)
+{
+ const u32 ch_mbox_idx = mhuv2_chan_idx(chan);
+ const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS;
+ const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS;
+
+ writel_relaxed(BIT(ch_window_reg_idx),
+ &mhuv2->reg.recv->channel[ch_window_idx].STAT_CLEAR);
+ return 0;
+}
+
+static inline int mhuv2_send_data_doorbell(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ const struct arm_mbox_msg *msg)
+{
+ const u32 ch_mbox_idx = mhuv2_chan_idx(chan);
+ const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS;
+ const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS;
+
+ writel_relaxed(
+ readl_relaxed(&mhuv2->reg.send->channel[ch_window_idx].STAT) |
+ BIT(ch_window_reg_idx),
+ &mhuv2->reg.send->channel[ch_window_idx].STAT_SET);
+ return 0;
+}
+
+static inline int mhuv2_last_tx_done_doorbell(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan)
+{
+ const u32 ch_mbox_idx = mhuv2_chan_idx(chan);
+ const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS;
+ const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS;
+
+ return (readl_relaxed(&mhuv2->reg.send->channel[ch_window_idx].STAT) &
+ BIT(ch_window_reg_idx)) == 0;
+}
+
+static inline int mhuv2_setup_doorbell(struct arm_mhuv2 *mhuv2)
+{
+ int i;
+ const u32 channel_windows =
+ readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ?
+ &mhuv2->reg.recv->MHU_CFG :
+ &mhuv2->reg.send->MHU_CFG,
+ NUM_CH);
+
+ mhuv2->mbox.num_chans = MHUV2_STAT_BITS * channel_windows;
+ mhuv2->mbox.chans =
+ devm_kzalloc(mhuv2->dev,
+ mhuv2->mbox.num_chans * sizeof(struct mbox_chan),
+ GFP_KERNEL);
+
+ for (i = 0; i < mhuv2->mbox.num_chans; i++) {
+ mhuv2->mbox.chans[i].con_priv =
+ devm_kzalloc(mhuv2->dev,
+ sizeof(struct arm_mhuv2_mbox_chan_priv),
+ GFP_KERNEL);
+ mhuv2_chan_idx(&mhuv2->mbox.chans[i]) = i;
+ }
+
+ if (mhuv2->frame == RECEIVER_FRAME) {
+ /* Ensure all status registers are unmasked */
+ for (i = 0; i < channel_windows; i++) {
+ writel_relaxed(0x0,
+ &mhuv2->reg.recv->channel[i].MASK_SET);
+ }
+ }
+
+ return 0;
+}
+
+static inline struct mbox_chan *
+ mhuv2_get_active_mbox_chan_doorbell(struct arm_mhuv2 *mhuv2)
+{
+ const u32 ch_window_idx = mhuv2_get_non_zero_ch_idx(mhuv2);
+ const u32 ch_window_reg_idx = __find_set_bit(
+ readl_relaxed(&mhuv2->reg.recv->channel[ch_window_idx].STAT));
+ if (ch_window_reg_idx == -1)
+ return ERR_PTR(-EIO);
+
+ return &mhuv2->mbox.chans[ch_window_reg_idx +
+ ch_window_idx * MHUV2_STAT_BITS];
+}
+
+static const struct mhuv2_ops mhuv2_doorbell_ops = {
+ .read_data = mhuv2_read_data_doorbell,
+ .clear_data = mhuv2_clear_data_doorbell,
+ .send_data = mhuv2_send_data_doorbell,
+ .setup = mhuv2_setup_doorbell,
+ .last_tx_done = mhuv2_last_tx_done_doorbell,
+ .get_active_mbox_chan = mhuv2_get_active_mbox_chan_doorbell,
+};
+/* ========================================================================== */
+
/*
* MHUv2 receiver interrupt service routine
*
@@ -591,6 +696,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
} else if (strcmp(mhuv2_protocol_str,
mhuv2_protocol_dt_identifiers[SINGLE_WORD]) == 0) {
mhuv2->ops = &mhuv2_single_word_ops;
+ } else if (strcmp(mhuv2_protocol_str,
+ mhuv2_protocol_dt_identifiers[DOORBELL]) == 0) {
+ mhuv2->ops = &mhuv2_doorbell_ops;
} else {
dev_err(dev,
"Probe failed: '%s' is not a valid transport protocol specifier\n",
--
2.17.1
@@ -0,0 +1,271 @@
From 31140984e2ead5d56b072d0fed0b5f18a1e7e825 Mon Sep 17 00:00:00 2001
From: Usama Arif <usama.arif@arm.com>
Date: Wed, 19 Jun 2019 17:00:31 +0100
Subject: [PATCH 6/9] mailbox: arm_mhuv2: add multi word transport protocol
operations
When in multi-word mode, the mailbox controller will provide a single
mailbox. It is required that the MHU device has at least 2 channel windows
available for the MHU to function in multi-word mode.
Transmitting and receiving data through the mailbox framework in
multi-word mode is done through a struct arm_mbox_msg.
Change-Id: Ibcf352d19ae3908093b20350853b16cf6a7933a2
Signed-off-by: Usama Arif <usama.arif@arm.com>
Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Cc: jassisinghbrar@gmail.com
Cc: devicetree@vger.kernel.org
Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
---
drivers/mailbox/arm_mhu_v2.c | 225 +++++++++++++++++++++++++++++++++++
1 file changed, 225 insertions(+)
diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
index efde7a71a3f7..e73e829d4f1e 100644
--- a/drivers/mailbox/arm_mhu_v2.c
+++ b/drivers/mailbox/arm_mhu_v2.c
@@ -429,6 +429,228 @@ static const struct mhuv2_ops mhuv2_single_word_ops = {
};
/* ========================================================================== */
+/* ================ Multi word transport protocol operations ================ */
+static inline int mhuv2_read_data_multi_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ struct arm_mbox_msg *msg)
+{
+ int ch;
+ const int channels =
+ readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
+
+ msg->data = kzalloc(MHUV2_STAT_BYTES * channels, GFP_KERNEL);
+
+ for (ch = 0; ch < channels; ch++) {
+ /*
+ * Messages are expected to be received in order of most
+ * significant word to least significant word.
+ * (see mhuv2_send_data_multi_word)
+ */
+ const mhuv2_stat_reg_t word =
+ readl_relaxed(&mhuv2->reg.recv->channel[ch].STAT);
+ ((mhuv2_stat_reg_t *)msg->data)[channels - 1 - ch] = word;
+ }
+
+ msg->len = channels * MHUV2_STAT_BYTES;
+ return 0;
+}
+
+static inline int mhuv2_clear_data_multi_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ struct arm_mbox_msg *msg)
+{
+ int ch;
+ const int channels =
+ readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
+
+ for (ch = 0; ch < channels; ch++) {
+ /*
+ * Last channel window must be cleared as the final operation.
+ * Upon clearing the last channel window register, which is
+ * unmasked in multi-word mode, the interrupt is deasserted.
+ */
+ writel_relaxed(
+ readl_relaxed(&mhuv2->reg.recv->channel[ch].STAT),
+ &mhuv2->reg.recv->channel[ch].STAT_CLEAR);
+ }
+ return 0;
+}
+
+static inline int __mhuv2_mw_bytes_to_send(const int bytes_in_round,
+ const int bytes_left)
+{
+ /*
+ * Bytes to send on the current channel will always be MHUV2_STAT_BYTES
+ * unless in the last round and
+ * msg->len % MHUV2_STAT_BYTES != 0
+ */
+ if (bytes_in_round % MHUV2_STAT_BYTES != 0) {
+ const int bts = bytes_left % MHUV2_STAT_BYTES;
+ return bts == 0 ? MHUV2_STAT_BYTES : bts;
+ } else {
+ return MHUV2_STAT_BYTES;
+ }
+}
+
+static inline int mhuv2_send_data_multi_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan,
+ const struct arm_mbox_msg *msg)
+{
+ /*
+ * Message will be transmitted from most significant to least
+ * significant word. This is to allow for messages shorter than
+ * $channels to still trigger the receiver interrupt which gets
+ * activated when the last STAT register is written. As an example, a
+ * 6-word message is to be written on a 4-channel MHU connection:
+ * Registers marked with '*' are masked, and will not generate an
+ * interrupt on the receiver side once written.
+ *
+ * uint32_t *data = [0x00000001],[0x00000002],[0x00000003],[0x00000004],
+ * [0x00000005], [0x00000006]
+ *
+ * ROUND 1:
+ * STAT reg To write Write sequence
+ * [ STAT 3 ] <- [0x00000001] 4 <- triggers interrupt on receiver
+ * *[ STAT 2 ] <- [0x00000002] 3
+ * *[ STAT 1 ] <- [0x00000003] 2
+ * *[ STAT 0 ] <- [0x00000004] 1
+ *
+ * data += 4 // Increment data pointer by number of STAT regs
+ *
+ * ROUND 2:
+ * STAT reg To write Write sequence
+ * [ STAT 3 ] <- [0x00000005] 2 <- triggers interrupt on receiver
+ * *[ STAT 2 ] <- [0x00000006] 1
+ * *[ STAT 1 ] <- [0x00000000]
+ * *[ STAT 0 ] <- [0x00000000]
+ */
+ int bytes_left, bytes_to_send, i, ch_idx;
+ const int ch_windows =
+ readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
+ const size_t round_capacity = ch_windows * MHUV2_STAT_BYTES;
+
+ bytes_left = msg->len;
+ mhuv2_stat_reg_t *data = msg->data;
+
+ while (bytes_left > 0) {
+ /* Note: Each entry of this loop indicates a new ROUND */
+ if (*(u32 *)data == 0) {
+ dev_err(mhuv2->dev,
+ "values in *data aligned on NUM_STAT boundaries must not be zero to ensure that receiver interrupt is triggered\n",
+ ch_windows);
+ return -EINVAL;
+ }
+
+ const int bytes_in_round = bytes_left > round_capacity ?
+ round_capacity :
+ bytes_left;
+
+ for (i = (ch_windows - 1); i >= 0; i--) {
+ ch_idx = ch_windows - 1 - i;
+ /*
+ * Check whether data should be transmitted in register
+ * of index 'ch'.
+ */
+ if (bytes_in_round > (i * MHUV2_STAT_BYTES)) {
+ mhuv2_stat_reg_t word = data[i];
+
+ bytes_to_send = __mhuv2_mw_bytes_to_send(
+ bytes_in_round, bytes_left);
+
+ if (bytes_to_send != MHUV2_STAT_BYTES) {
+ word &= LSB_MASK(bytes_to_send *
+ __CHAR_BIT__);
+ }
+ while (readl_relaxed(
+ &mhuv2->reg.send->channel[ch_idx]
+ .STAT) != 0)
+ continue;
+
+ writel_relaxed(
+ word,
+ &mhuv2->reg.send->channel[ch_idx].STAT_SET);
+ bytes_left -= bytes_to_send;
+ }
+ }
+
+ data += ch_windows;
+
+ for (ch_idx = 0; ch_idx < ch_windows; ch_idx++) {
+ while (readl_relaxed(
+ &mhuv2->reg.send->channel[ch_idx].STAT) != 0)
+ continue;
+ }
+ }
+ return 0;
+}
+
+
+static inline int mhuv2_last_tx_done_multi_word(struct arm_mhuv2 *mhuv2,
+ struct mbox_chan *chan)
+{
+ int ch_idx;
+ bool tx_done = true;
+
+ for (ch_idx = 0;
+ ch_idx < readl_relaxed_bitfield(&mhuv2->reg.send->MHU_CFG, NUM_CH);
+ ch_idx++) {
+ tx_done &= readl_relaxed(
+ &mhuv2->reg.send->channel[ch_idx].STAT) == 0;
+ }
+ return tx_done;
+}
+
+static inline int mhuv2_setup_multi_word(struct arm_mhuv2 *mhuv2)
+{
+ int ret, i;
+
+ const u32 channel_windows =
+ readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ?
+ &mhuv2->reg.recv->MHU_CFG :
+ &mhuv2->reg.send->MHU_CFG,
+ NUM_CH);
+ if (channel_windows < 2) {
+ dev_err(mhuv2->dev,
+ "Error: at least 2 MHU channel windows are required for using the multi-word transfer protocol");
+ return -ENODEV;
+ }
+
+ if (mhuv2->frame == RECEIVER_FRAME) {
+ /*
+ * The multi-word transport protocol mandates that all but
+ * the last status register must be masked.
+ */
+ for (i = 0; i < (channel_windows - 1); i++) {
+ writel_relaxed(-1,
+ &mhuv2->reg.recv->channel[i].MASK_SET);
+ }
+ }
+
+ mhuv2->mbox.num_chans = 1;
+ mhuv2->mbox.chans =
+ devm_kzalloc(mhuv2->dev,
+ mhuv2->mbox.num_chans * sizeof(struct mbox_chan),
+ GFP_KERNEL);
+
+ return 0;
+}
+
+static inline struct mbox_chan *
+ mhuv2_get_active_mbox_chan_multi_word(struct arm_mhuv2 *mhuv2)
+{
+ return &mhuv2->mbox.chans[0];
+}
+
+static const struct mhuv2_ops mhuv2_multi_word_ops = {
+ .read_data = mhuv2_read_data_multi_word,
+ .clear_data = mhuv2_clear_data_multi_word,
+ .send_data = mhuv2_send_data_multi_word,
+ .setup = mhuv2_setup_multi_word,
+ .last_tx_done = mhuv2_last_tx_done_multi_word,
+ .get_active_mbox_chan = mhuv2_get_active_mbox_chan_multi_word,
+};
+/* ========================================================================== */
+
/* =================== Doorbell transport protocol operations =============== */
static inline int mhuv2_read_data_doorbell(struct arm_mhuv2 *mhuv2,
@@ -696,6 +918,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
} else if (strcmp(mhuv2_protocol_str,
mhuv2_protocol_dt_identifiers[SINGLE_WORD]) == 0) {
mhuv2->ops = &mhuv2_single_word_ops;
+ } else if (strcmp(mhuv2_protocol_str,
+ mhuv2_protocol_dt_identifiers[MULTI_WORD]) == 0) {
+ mhuv2->ops = &mhuv2_multi_word_ops;
} else if (strcmp(mhuv2_protocol_str,
mhuv2_protocol_dt_identifiers[DOORBELL]) == 0) {
mhuv2->ops = &mhuv2_doorbell_ops;
--
2.17.1
@@ -0,0 +1,67 @@
From 68ce2dfe4c6f3806001fb8d682d6e99a9580dc2a Mon Sep 17 00:00:00 2001
From: Usama Arif <usama.arif@arm.com>
Date: Wed, 24 Jun 2020 11:16:01 +0100
Subject: [PATCH 7/9] firmware: arm_scmi: Add fast_switch_possible() api
Add a new fast_switch_possible interface to the existing
perf_ops api to export the information of whether or not
fast_switch is possible in this driver.
This can be used by the CPUFreq driver and framework to
choose proper mechanism for frequency change.
Suggested-by: Lukasz Luba <lukasz.luba@arm.com>
Signed-off-by: Nicola Mazzucato <nicola.mazzucato@arm.com>
Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/firmware/arm_scmi?id=1909872ff20fc378ec6a44ea1a2b2966d834e504]
---
drivers/firmware/arm_scmi/perf.c | 12 ++++++++++++
include/linux/scmi_protocol.h | 2 ++
2 files changed, 14 insertions(+)
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 601af4edad5e..c9350bb2ba1f 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -691,6 +691,17 @@ static int scmi_dvfs_est_power_get(const struct scmi_handle *handle, u32 domain,
return ret;
}
+static bool scmi_fast_switch_possible(const struct scmi_handle *handle,
+ struct device *dev)
+{
+ struct perf_dom_info *dom;
+ struct scmi_perf_info *pi = handle->perf_priv;
+
+ dom = pi->dom_info + scmi_dev_domain_id(dev);
+
+ return (dom->fc_info && dom->fc_info->level_set_addr);
+}
+
static struct scmi_perf_ops perf_ops = {
.limits_set = scmi_perf_limits_set,
.limits_get = scmi_perf_limits_get,
@@ -702,6 +713,7 @@ static struct scmi_perf_ops perf_ops = {
.freq_set = scmi_dvfs_freq_set,
.freq_get = scmi_dvfs_freq_get,
.est_power_get = scmi_dvfs_est_power_get,
+ .fast_switch_possible = scmi_fast_switch_possible,
};
static int scmi_perf_protocol_init(struct scmi_handle *handle)
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 881fea47c83d..b1f4a88219c5 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -114,6 +114,8 @@ struct scmi_perf_ops {
unsigned long *rate, bool poll);
int (*est_power_get)(const struct scmi_handle *handle, u32 domain,
unsigned long *rate, unsigned long *power);
+ bool (*fast_switch_possible)(const struct scmi_handle *handle,
+ struct device *dev);
};
/**
--
2.17.1
@@ -0,0 +1,42 @@
From 47300d8385801913709eda5fd237d54f51477546 Mon Sep 17 00:00:00 2001
From: Usama Arif <usama.arif@arm.com>
Date: Wed, 24 Jun 2020 11:25:02 +0100
Subject: [PATCH 8/9] cpufreq: arm_scmi: Set fast_switch_possible conditionally
Currently the fast_switch_possible flag is set unconditionally
to true. Based on this, schedutil does not create a
thread for frequency switching and would always use the
fast switch path.
However, if the platform does not support frequency
fast switch, this may cause the governor to attempt an
operation that is not supported by the platform.
Fix this by correctly retrieve the fast_switch capability
from the driver which knows if the platform can support
this feature.
Suggested-by: Lukasz Luba <lukasz.luba@arm.com>
Signed-off-by: Nicola Mazzucato <nicola.mazzucato@arm.com>
Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/cpufreq?id=fb3571276b970cbe7b45ecdc762e92f3f305ad6d]
---
drivers/cpufreq/scmi-cpufreq.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index e6182c89df79..931fcf0ef221 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -198,7 +198,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = latency;
- policy->fast_switch_possible = true;
+ policy->fast_switch_possible =
+ handle->perf_ops->fast_switch_possible(handle, cpu_dev);
em_register_perf_domain(policy->cpus, nr_opp, &em_cb);
--
2.17.1
@@ -6,18 +6,14 @@ CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_PSI=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_UCLAMP_TASK=y
CONFIG_NUMA_BALANCING=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_BLK_CGROUP=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_UCLAMP_TASK_GROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
@@ -26,15 +22,17 @@ CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_FHANDLE is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_ARCH_ACTIONS=y
CONFIG_ARCH_AGILEX=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_ALPINE=y
CONFIG_ARCH_BCM2835=y
@@ -49,6 +47,8 @@ CONFIG_ARCH_HISI=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_ARCH_MESON=y
CONFIG_ARCH_MVEBU=y
CONFIG_ARCH_MXC=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_RENESAS=y
CONFIG_ARCH_ROCKCHIP=y
CONFIG_ARCH_SEATTLE=y
@@ -72,31 +72,48 @@ CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
CONFIG_ARM64_SW_TTBR0_PAN=y
CONFIG_COMPAT=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_HIBERNATION=y
CONFIG_PM_DEBUG=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPUFREQ_DT=y
CONFIG_ACPI_CPPC_CPUFREQ=m
CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_IMX_CPUFREQ_DT=m
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_ARM_QCOM_CPUFREQ_HW=y
CONFIG_ARM_RASPBERRYPI_CPUFREQ=m
CONFIG_ARM_SCMI_CPUFREQ=y
CONFIG_ARM_TEGRA186_CPUFREQ=y
CONFIG_ARM_SCMI_PROTOCOL=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_RASPBERRYPI_FIRMWARE=y
CONFIG_INTEL_STRATIX10_SERVICE=y
CONFIG_INTEL_STRATIX10_RSU=m
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_IMX_SCU=y
CONFIG_IMX_SCU_PD=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
@@ -111,21 +128,18 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_CHACHA20_NEON=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CMA=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -134,22 +148,19 @@ CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IPVTI=y
CONFIG_INET_ESP=y
CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_VTI=y
CONFIG_IPV6_SIT=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -160,22 +171,14 @@ CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_CT=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -187,18 +190,17 @@ CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_LOG_IPV4=m
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
@@ -213,13 +215,15 @@ CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_LOG_IPV6=m
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_RPFILTER=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_L2TP=y
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=m
@@ -227,30 +231,33 @@ CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_NETEM=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_BPF_JIT=y
CONFIG_BT=m
CONFIG_BT_HIDP=m
# CONFIG_BT_HS is not set
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_CFG80211=m
CONFIG_BT_HCIUART_QCA=y
CONFIG_CFG80211=y
CONFIG_MAC80211=m
CONFIG_MAC80211_LEDS=y
CONFIG_RFKILL=m
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_IOV=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
@@ -259,21 +266,32 @@ CONFIG_PCI_TEGRA=y
CONFIG_PCIE_RCAR=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCIE_ALTERA=y
CONFIG_PCIE_ALTERA_MSI=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCIE_ROCKCHIP_HOST=m
CONFIG_PCI_LAYERSCAPE=y
CONFIG_PCI_HISI=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_ARMADA_8K=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_HISI_STB=y
CONFIG_PCIE_TEGRA194=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_HISILICON_LPC=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_NAND_MARVELL=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_SPI_NOR=y
CONFIG_SPI_CADENCE_QUADSPI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
@@ -281,16 +299,17 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=m
CONFIG_SRAM=y
CONFIG_UID_SYS_STATS=y
CONFIG_EEPROM_AT25=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_SCSI_HISI_SAS=y
CONFIG_SCSI_HISI_SAS_PCI=y
CONFIG_SCSI_UFSHCD=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_HISI=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
@@ -303,13 +322,14 @@ CONFIG_SATA_RCAR=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_SNAPSHOT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
CONFIG_DM_VERITY_AVB=y
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
@@ -319,17 +339,26 @@ CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y
CONFIG_ATL1C=m
CONFIG_BCMGENET=m
CONFIG_BNX2X=m
CONFIG_MACB=y
CONFIG_THUNDER_NIC_PF=y
CONFIG_FEC=y
CONFIG_HIX5HD2_GMAC=y
CONFIG_HNS_DSAF=y
CONFIG_HNS_ENET=y
CONFIG_HNS3=y
CONFIG_HNS3_HCLGE=y
CONFIG_HNS3_ENET=y
CONFIG_E1000E=y
CONFIG_IGB=y
CONFIG_IGBVF=y
CONFIG_MVNETA=y
CONFIG_MVPP2=y
CONFIG_SKY2=y
CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y
CONFIG_QCOM_EMAC=m
CONFIG_RAVB=y
CONFIG_SMC91X=y
@@ -338,7 +367,7 @@ CONFIG_SNI_AVE=y
CONFIG_SNI_NETSEC=y
CONFIG_STMMAC_ETH=m
CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_AT803X_PHY=m
CONFIG_AT803X_PHY=y
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=m
CONFIG_MESON_GXL_PHY=m
@@ -349,13 +378,11 @@ CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=y
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=y
CONFIG_USB_USBNET=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9800=m
CONFIG_USB_NET_SMSC75XX=m
@@ -364,41 +391,33 @@ CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
CONFIG_ATH10K_SNOC=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_PCIE=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
CONFIG_INPUT_JOYDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_SNVS_PWRKEY=m
CONFIG_KEYBOARD_CROS_EC=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_HISI_POWERKEY=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVMEM is not set
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_OMAP=y
CONFIG_SERIAL_8250_MT6577=y
CONFIG_SERIAL_8250_UNIPHIER=y
CONFIG_SERIAL_OF_PLATFORM=y
@@ -409,42 +428,86 @@ CONFIG_SERIAL_MESON_CONSOLE=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_SERIAL_TEGRA=y
CONFIG_SERIAL_TEGRA_TCU=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_QCOM_GENI=y
CONFIG_SERIAL_QCOM_GENI_CONSOLE=y
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_FSL_LINFLEXUART=y
CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
CONFIG_SERIAL_MVEBU_UART=y
CONFIG_SERIAL_OWL=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_BCM2835=m
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_GPIO=m
CONFIG_I2C_IMX=y
CONFIG_I2C_IMX_LPI2C=y
CONFIG_I2C_MESON=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_OWL=y
CONFIG_I2C_PXA=y
CONFIG_I2C_QCOM_GENI=m
CONFIG_I2C_QUP=y
CONFIG_I2C_RK3X=y
CONFIG_I2C_SH_MOBILE=y
CONFIG_I2C_TEGRA=y
CONFIG_I2C_UNIPHIER_F=y
CONFIG_I2C_VERSATILE=y
CONFIG_I2C_RCAR=y
CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_SPI=y
CONFIG_SPI_ARMADA_3700=y
CONFIG_SPI_BCM2835=m
CONFIG_SPI_BCM2835AUX=m
CONFIG_SPI_NXP_FLEXSPI=y
CONFIG_SPI_IMX=m
CONFIG_SPI_MESON_SPICC=m
CONFIG_SPI_MESON_SPIFC=m
CONFIG_SPI_ORION=y
CONFIG_SPI_PL022=y
CONFIG_SPI_ROCKCHIP=y
CONFIG_SPI_QCOM_QSPI=m
CONFIG_SPI_QUP=y
CONFIG_SPI_QCOM_GENI=m
CONFIG_SPI_S3C64XX=y
CONFIG_SPI_SUN6I=y
CONFIG_SPI_SPIDEV=m
CONFIG_SPMI=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_OWL=y
CONFIG_PINCTRL_S700=y
CONFIG_PINCTRL_S900=y
CONFIG_PINCTRL_IMX8MM=y
CONFIG_PINCTRL_IMX8MN=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_PINCTRL_IMX8QXP=y
CONFIG_PINCTRL_IPQ8074=y
CONFIG_PINCTRL_MSM8916=y
CONFIG_PINCTRL_MSM8994=y
CONFIG_PINCTRL_MSM8996=y
CONFIG_PINCTRL_MSM8998=y
CONFIG_PINCTRL_QCS404=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_SDM845=y
CONFIG_PINCTRL_SM8150=y
CONFIG_GPIO_ALTERA=m
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
CONFIG_GPIO_PL061=y
@@ -452,11 +515,13 @@ CONFIG_GPIO_RCAR=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_GPIO_XGENE=y
CONFIG_GPIO_XGENE_SB=y
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
CONFIG_POWER_AVS=y
CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
@@ -464,38 +529,73 @@ CONFIG_BATTERY_SBS=m
CONFIG_BATTERY_BQ27XXX=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_SENSORS_INA2XX=m
CONFIG_SENSORS_INA3221=m
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_QORIQ_THERMAL=m
CONFIG_ROCKCHIP_THERMAL=m
CONFIG_RCAR_THERMAL=y
CONFIG_RCAR_GEN3_THERMAL=y
CONFIG_ARMADA_THERMAL=y
CONFIG_BCM2835_THERMAL=m
CONFIG_BRCMSTB_THERMAL=m
CONFIG_EXYNOS_THERMAL=y
CONFIG_TEGRA_BPMP_THERMAL=m
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_UNIPHIER_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_S3C2410_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=m
CONFIG_IMX2_WDT=y
CONFIG_IMX_SC_WDT=m
CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_RENESAS_WDT=y
CONFIG_UNIPHIER_WATCHDOG=y
CONFIG_BCM2835_WDT=y
CONFIG_MFD_ALTERA_SYSMGR=y
CONFIG_MFD_BD9571MWV=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_AXP20X_RSB=y
CONFIG_MFD_EXYNOS_LPASS=m
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_HI655X_PMIC=y
CONFIG_MFD_MAX77620=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_RK808=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_ROHM_BD718XX=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD718XX=y
CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_HI655X=y
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_RPMH=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_VCTRL=m
CONFIG_RC_CORE=m
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_IR_MESON=m
CONFIG_IR_SUNXI=m
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
@@ -505,17 +605,23 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_DVB_NET is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_VIDEO_SUN6I_CSI=m
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
CONFIG_VIDEO_RENESAS_FCP=m
CONFIG_VIDEO_RENESAS_VSP1=m
CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
CONFIG_DRM=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_I2C_NXP_TDA998X=y
CONFIG_DRM_I2C_CH7006=m
CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
CONFIG_DRM_HDLCD=y
CONFIG_DRM_NOUVEAU=m
CONFIG_DRM_KOMEDA=y
CONFIG_DRM_VIRT_ENCODER=y
CONFIG_DRM_EXYNOS=m
CONFIG_DRM_EXYNOS5433_DECON=y
CONFIG_DRM_EXYNOS7_DECON=y
@@ -530,14 +636,26 @@ CONFIG_ROCKCHIP_DW_HDMI=y
CONFIG_ROCKCHIP_DW_MIPI_DSI=y
CONFIG_ROCKCHIP_INNO_HDMI=y
CONFIG_DRM_RCAR_DU=m
CONFIG_DRM_SUN4I=m
CONFIG_DRM_SUN8I_DW_HDMI=m
CONFIG_DRM_SUN8I_MIXER=m
CONFIG_DRM_MSM=m
CONFIG_DRM_TEGRA=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_TI_SN65DSI86=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_VC4=m
CONFIG_DRM_ETNAVIV=m
CONFIG_DRM_HISI_HIBMC=m
CONFIG_DRM_HISI_KIRIN=m
CONFIG_DRM_MESON=m
CONFIG_FB_ARMCLCD=y
CONFIG_DRM_PL111=m
CONFIG_DRM_LIMA=m
CONFIG_DRM_PANFROST=m
CONFIG_DRM_LEGACY=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_EFI=y
CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
@@ -547,78 +665,41 @@ CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_HDA_TEGRA=m
CONFIG_SND_HDA_CODEC_HDMI=m
CONFIG_SND_SOC=y
CONFIG_SND_BCM2835_SOC_I2S=m
CONFIG_SND_MESON_AXG_SOUND_CARD=m
CONFIG_SND_SOC_ROCKCHIP=m
CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
CONFIG_SND_SOC_ROCKCHIP_RT5645=m
CONFIG_SND_SOC_RK3399_GRU_SOUND=m
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SOC_RCAR=m
CONFIG_SND_SUN4I_SPDIF=m
CONFIG_SND_SOC_AK4613=m
CONFIG_SND_SOC_ES7134=m
CONFIG_SND_SOC_ES7241=m
CONFIG_SND_SOC_PCM3168A_I2C=m
CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_SND_AUDIO_GRAPH_CARD=m
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_HOLTEK=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_ITE=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_REDRAGON=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
CONFIG_USB_HIDDEV=y
CONFIG_I2C_HID=m
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_CONN_GPIO=m
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_TEGRA=y
@@ -640,16 +721,15 @@ CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_ISP1760=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
CONFIG_USB_RENESAS_USBHS_UDC=m
CONFIG_USB_RENESAS_USB3=m
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_FUSB302=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
@@ -659,11 +739,14 @@ CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_MMC_SDHCI_F_SDH30=y
CONFIG_MMC_MESON_GX=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_UNIPHIER=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_HI3798CV200=y
@@ -672,6 +755,8 @@ CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SUNXI=y
CONFIG_MMC_BCM2835=y
CONFIG_MMC_SDHCI_XENON=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_SYSCON=y
@@ -685,6 +770,7 @@ CONFIG_EDAC_GHES=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_EFI=y
@@ -694,13 +780,21 @@ CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_DRV_ARMADA38X=y
CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_SNVS=m
CONFIG_RTC_DRV_IMX_SC=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=m
CONFIG_DMA_SUN6I=m
CONFIG_FSL_EDMA=y
CONFIG_IMX_SDMA=y
CONFIG_K3_DMA=y
CONFIG_MV_XOR=y
CONFIG_MV_XOR_V2=y
CONFIG_OWL_DMA=y
CONFIG_PL330_DMA=y
CONFIG_TEGRA20_APB_DMA=y
CONFIG_QCOM_BAM_DMA=y
CONFIG_QCOM_HIDMA_MGMT=y
CONFIG_QCOM_HIDMA=y
CONFIG_RCAR_DMAC=y
@@ -715,26 +809,73 @@ CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ION=y
CONFIG_ION_SYSTEM_HEAP=y
CONFIG_MFD_CROS_EC=y
CONFIG_CROS_EC_I2C=y
CONFIG_CROS_EC_SPI=y
CONFIG_COMMON_CLK_RK808=y
CONFIG_COMMON_CLK_SCMI=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_CLK_RASPBERRYPI=m
CONFIG_CLK_IMX8MM=y
CONFIG_CLK_IMX8MN=y
CONFIG_CLK_IMX8MQ=y
CONFIG_CLK_IMX8QXP=y
CONFIG_TI_SCI_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_A53PLL=y
CONFIG_QCOM_CLK_APCS_MSM8916=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_QCOM_CLK_RPMH=y
CONFIG_IPQ_GCC_8074=y
CONFIG_MSM_GCC_8916=y
CONFIG_MSM_GCC_8994=y
CONFIG_MSM_MMCC_8996=y
CONFIG_MSM_GCC_8998=y
CONFIG_QCS_GCC_404=y
CONFIG_SDM_GCC_845=y
CONFIG_SM_GCC_8150=y
CONFIG_QCOM_HFPLL=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
CONFIG_IMX_MBOX=y
CONFIG_ARM_MHU_V2=y
CONFIG_PLATFORM_MHU=y
CONFIG_BCM2835_MBOX=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_ROCKCHIP_IOMMU=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARM_SMMU=m
CONFIG_ARM_SMMU_V3=y
CONFIG_REMOTEPROC=y
CONFIG_QCOM_Q6V5_MSS=m
CONFIG_QCOM_Q6V5_PAS=m
CONFIG_QCOM_SYSMON=m
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=m
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_OWL_PM_DOMAINS=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_IMX_SCU_SOC=y
CONFIG_QCOM_AOSS_QMP=y
CONFIG_QCOM_GENI_SE=y
CONFIG_QCOM_GLINK_SSR=m
CONFIG_QCOM_RMTFS_MEM=m
CONFIG_QCOM_RPMH=y
CONFIG_QCOM_RPMHPD=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=y
CONFIG_QCOM_SMSM=y
CONFIG_QCOM_SOCINFO=m
CONFIG_ARCH_R8A774A1=y
CONFIG_ARCH_R8A774C0=y
CONFIG_ARCH_R8A7795=y
CONFIG_ARCH_R8A7796=y
CONFIG_ARCH_R8A77965=y
CONFIG_ARCH_R8A77970=y
CONFIG_ARCH_R8A77980=y
@@ -746,17 +887,21 @@ CONFIG_ARCH_TEGRA_210_SOC=y
CONFIG_ARCH_TEGRA_186_SOC=y
CONFIG_ARCH_TEGRA_194_SOC=y
CONFIG_ARCH_K3_AM6_SOC=y
CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
CONFIG_ARCH_K3_J721E_SOC=y
CONFIG_TI_SCI_PM_DOMAINS=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
CONFIG_QCOM_SPMI_ADC5=m
CONFIG_ROCKCHIP_SARADC=m
CONFIG_IIO_CROS_EC_SENSORS_CORE=m
CONFIG_IIO_CROS_EC_SENSORS=m
CONFIG_IIO_CROS_EC_LIGHT_PROX=m
CONFIG_SENSORS_ISL29018=m
CONFIG_IIO_CROS_EC_BARO=m
CONFIG_MPL3115=m
CONFIG_PWM=y
CONFIG_PWM_BCM2835=m
CONFIG_PWM_CROS_EC=m
@@ -764,27 +909,51 @@ CONFIG_PWM_MESON=m
CONFIG_PWM_RCAR=m
CONFIG_PWM_ROCKCHIP=y
CONFIG_PWM_SAMSUNG=y
CONFIG_PWM_SUN4I=m
CONFIG_PWM_TEGRA=m
CONFIG_RESET_QCOM_AOSS=y
CONFIG_RESET_QCOM_PDC=m
CONFIG_RESET_TI_SCI=y
CONFIG_PHY_XGENE=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_HISTB_COMBPHY=y
CONFIG_PHY_HISI_INNO_USB2=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
CONFIG_PHY_QCOM_QMP=m
CONFIG_PHY_QCOM_QUSB2=m
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_RCAR_GEN3_USB3=m
CONFIG_PHY_ROCKCHIP_EMMC=y
CONFIG_PHY_ROCKCHIP_INNO_HDMI=m
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_PCIE=m
CONFIG_PHY_ROCKCHIP_TYPEC=y
CONFIG_PHY_UNIPHIER_USB2=y
CONFIG_PHY_UNIPHIER_USB3=y
CONFIG_PHY_TEGRA_XUSB=y
CONFIG_ARM_SMMU_V3_PMU=m
CONFIG_FSL_IMX8_DDR_PMU=m
CONFIG_HISI_PMU=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_IMX_OCOTP_SCU=y
CONFIG_QCOM_QFPROM=y
CONFIG_ROCKCHIP_EFUSE=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_UNIPHIER_EFUSE=y
CONFIG_MESON_EFUSE=m
CONFIG_FPGA=y
CONFIG_FPGA_MGR_STRATIX10_SOC=m
CONFIG_FPGA_BRIDGE=m
CONFIG_ALTERA_FREEZE_BRIDGE=m
CONFIG_FPGA_REGION=m
CONFIG_OF_FPGA_REGION=m
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_EXT2_FS=y
@@ -793,23 +962,23 @@ CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_QFMT_V2=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=m
CONFIG_OVERLAY_FS=y
CONFIG_MSDOS_FS=y
CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
CONFIG_HUGETLBFS=y
CONFIG_EFIVAR_FS=y
CONFIG_SQUASHFS=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_RAM=y
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_9P_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
@@ -817,16 +986,17 @@ CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_DEV_FSL_CAAM=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_CRYPTO_DEV_HISI_ZIP=m
CONFIG_CMA_SIZE_MBYTES=256
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_SCHEDSTATS=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_ENABLE_DEFAULT_TRACERS=y
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y
@@ -1,3 +1,5 @@
# Machine specific configurations
FILESEXTRAPATHS_prepend := "${THISDIR}/${BP}:"
require linux-arm-platforms.inc