1
0
linux/debian/patches/patchset-xanmod/valve/0005-mfd-Add-MFD-core-driver-for-Steam-Deck.patch

177 lines
4.7 KiB
Diff
Raw Normal View History

From c3cf089a9da1216d3e1e047eba2ec46e0febe457 Mon Sep 17 00:00:00 2001
From: Andrey Smirnov <andrew.smirnov@gmail.com>
Date: Sat, 19 Feb 2022 16:08:36 -0800
Subject: [PATCH 5/6] mfd: Add MFD core driver for Steam Deck
Add MFD core driver for Steam Deck. Doesn't really do much so far
besides instantiating a number of MFD cells that implement all the
interesting functionality.
(cherry picked from commit 5f534c2d6ebdefccb9c024eb0f013bc1c0c622d9)
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Signed-off-by: Alexandre Frade <kernel@xanmod.org>
---
drivers/mfd/Kconfig | 11 ++++
drivers/mfd/Makefile | 2 +
drivers/mfd/steamdeck.c | 127 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+)
create mode 100644 drivers/mfd/steamdeck.c
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2390,5 +2390,16 @@ config MFD_RSMU_SPI
Additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_STEAMDECK
+ tristate "Valve Steam Deck"
+ select MFD_CORE
+ depends on ACPI
+ depends on X86_64 || COMPILE_TEST
+ help
+ This driver registers various MFD cells that expose aspects
+ of Steam Deck specific ACPI functionality.
+
+ Say N here, unless you are running on Steam Deck hardware.
+
endmenu
endif
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -288,3 +288,5 @@ obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x
obj-$(CONFIG_MFD_RSMU_I2C) += rsmu_i2c.o rsmu_core.o
obj-$(CONFIG_MFD_RSMU_SPI) += rsmu_spi.o rsmu_core.o
+
+obj-$(CONFIG_MFD_STEAMDECK) += steamdeck.o
--- /dev/null
+++ b/drivers/mfd/steamdeck.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Steam Deck EC MFD core driver
+ *
+ * Copyright (C) 2021-2022 Valve Corporation
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+
+#define STEAMDECK_STA_OK \
+ (ACPI_STA_DEVICE_ENABLED | \
+ ACPI_STA_DEVICE_PRESENT | \
+ ACPI_STA_DEVICE_FUNCTIONING)
+
+struct steamdeck {
+ struct acpi_device *adev;
+ struct device *dev;
+};
+
+#define STEAMDECK_ATTR_RO(_name, _method) \
+ static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ struct steamdeck *sd = dev_get_drvdata(dev); \
+ unsigned long long val; \
+ \
+ if (ACPI_FAILURE(acpi_evaluate_integer( \
+ sd->adev->handle, \
+ _method, NULL, &val))) \
+ return -EIO; \
+ \
+ return sysfs_emit(buf, "%llu\n", val); \
+ } \
+ static DEVICE_ATTR_RO(_name)
+
+STEAMDECK_ATTR_RO(firmware_version, "PDFW");
+STEAMDECK_ATTR_RO(board_id, "BOID");
+
+static struct attribute *steamdeck_attrs[] = {
+ &dev_attr_firmware_version.attr,
+ &dev_attr_board_id.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(steamdeck);
+
+static const struct mfd_cell steamdeck_cells[] = {
+ { .name = "steamdeck-hwmon" },
+ { .name = "steamdeck-leds" },
+ { .name = "steamdeck-extcon" },
+};
+
+static void steamdeck_remove_sysfs_groups(void *data)
+{
+ struct steamdeck *sd = data;
+
+ sysfs_remove_groups(&sd->dev->kobj, steamdeck_groups);
+}
+
+static int steamdeck_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ unsigned long long sta;
+ struct steamdeck *sd;
+ acpi_status status;
+ int ret;
+
+ sd = devm_kzalloc(dev, sizeof(*sd), GFP_KERNEL);
+ if (!sd)
+ return -ENOMEM;
+ sd->adev = ACPI_COMPANION(dev);
+ sd->dev = dev;
+ platform_set_drvdata(pdev, sd);
+
+ status = acpi_evaluate_integer(sd->adev->handle, "_STA",
+ NULL, &sta);
+ if (ACPI_FAILURE(status)) {
+ dev_err(dev, "Status check failed (0x%x)\n", status);
+ return -EINVAL;
+ }
+
+ if ((sta & STEAMDECK_STA_OK) != STEAMDECK_STA_OK) {
+ dev_err(dev, "Device is not ready\n");
+ return -EINVAL;
+ }
+
+ ret = sysfs_create_groups(&dev->kobj, steamdeck_groups);
+ if (ret) {
+ dev_err(dev, "Failed to create sysfs group\n");
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev, steamdeck_remove_sysfs_groups,
+ sd);
+ if (ret) {
+ dev_err(dev, "Failed to register devres action\n");
+ return ret;
+ }
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ steamdeck_cells, ARRAY_SIZE(steamdeck_cells),
+ NULL, 0, NULL);
+}
+
+static const struct acpi_device_id steamdeck_device_ids[] = {
+ { "VLV0100", 0 },
+ { "", 0 },
+};
+MODULE_DEVICE_TABLE(acpi, steamdeck_device_ids);
+
+static struct platform_driver steamdeck_driver = {
+ .probe = steamdeck_probe,
+ .driver = {
+ .name = "steamdeck",
+ .acpi_match_table = steamdeck_device_ids,
+ },
+};
+module_platform_driver(steamdeck_driver);
+
+MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
+MODULE_DESCRIPTION("Steam Deck EC MFD core driver");
+MODULE_LICENSE("GPL");