diff mbox series

[2/3] pinctrl: amd: Get and update IOMUX details

Message ID 20220523130944.473416-3-Basavaraj.Natikar@amd.com
State New
Headers show
Series Enhancements to AMD pinctrl and implementation of AMD pinmux | expand

Commit Message

Basavaraj Natikar May 23, 2022, 1:09 p.m. UTC
Presently there is no way to change pinmux configuration runtime.
Hence add IOMUX details which can be used to configure IOMUX
gpio pins runtime to different functionalities.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/pinctrl/pinctrl-amd.c | 65 +++++++++++++++++++++++++++++++++++
 drivers/pinctrl/pinctrl-amd.h |  1 +
 2 files changed, 66 insertions(+)
diff mbox series

Patch

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 1a7d686494ff..3058b6d35e47 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -32,6 +32,8 @@ 
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinconf-generic.h>
 
+#include "../acpi/acpica/accommon.h"
+
 #include "core.h"
 #include "pinctrl-utils.h"
 #include "pinctrl-amd.h"
@@ -958,6 +960,68 @@  static struct pinctrl_desc amd_pinctrl_desc = {
 	.owner = THIS_MODULE,
 };
 
+static acpi_status acpi_get_iomux_region(acpi_handle handle, u32 level,
+					 void *ctx, void **return_value)
+{
+	struct acpi_namespace_node *node = handle;
+	union acpi_operand_object *region_obj;
+	struct amd_gpio *gpio_dev = ctx;
+
+	/* Already mapped the IOMUX base */
+	if (gpio_dev->iomux_base)
+		return AE_OK;
+
+	/* Valid object */
+	if (!node || !node->object)
+		return AE_OK;
+
+	/* Valid operand or namespace node*/
+	if ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) &&
+	    (ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_NAMED))
+		return AE_OK;
+
+	/* Valid object type*/
+	if (node->object->common.type == ACPI_TYPE_LOCAL_DATA)
+		return AE_OK;
+
+	region_obj = node->object;
+	if (!region_obj->region.handler)
+		return AE_OK;
+
+	if (region_obj->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+		return AE_OK;
+
+	if (strncmp("IOMX", region_obj->region.node->name.ascii, strlen("IOMX")))
+		return AE_OK;
+
+	gpio_dev->iomux_base = devm_ioremap(&gpio_dev->pdev->dev,
+					    region_obj->region.address,
+					    region_obj->region.length);
+	if (!gpio_dev->iomux_base)
+		dev_err(&gpio_dev->pdev->dev, "failed to devm_ioremap() iomux_base\n");
+
+	return AE_OK;
+}
+
+static void amd_update_iomux_info(struct amd_gpio *gpio_dev)
+{
+	acpi_handle sys_bus_handle;
+	int status = acpi_get_handle(NULL, "\\_SB", &sys_bus_handle);
+
+	if (ACPI_FAILURE(status)) {
+		dev_err(&gpio_dev->pdev->dev, "Failed to get SB handle\n");
+		return;
+	}
+
+	status = acpi_walk_namespace(ACPI_TYPE_REGION, sys_bus_handle, ACPI_UINT32_MAX,
+				     acpi_get_iomux_region, NULL, gpio_dev, NULL);
+
+	if (ACPI_FAILURE(status)) {
+		dev_err(&gpio_dev->pdev->dev, "Failed to get acpi_get_iomux_region\n");
+		return;
+	}
+}
+
 static int amd_gpio_probe(struct platform_device *pdev)
 {
 	int ret = 0;
@@ -1052,6 +1116,7 @@  static int amd_gpio_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, gpio_dev);
 	acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev);
+	amd_update_iomux_info(gpio_dev);
 
 	dev_dbg(&pdev->dev, "amd gpio driver loaded\n");
 	return ret;
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index de2bc9dddc9c..8296426f4c81 100644
--- a/drivers/pinctrl/pinctrl-amd.h
+++ b/drivers/pinctrl/pinctrl-amd.h
@@ -89,6 +89,7 @@  struct amd_function {
 struct amd_gpio {
 	raw_spinlock_t          lock;
 	void __iomem            *base;
+	void __iomem            *iomux_base;
 
 	const struct amd_pingroup *groups;
 	u32 ngroups;