[PATCH 3/3] usb: type-c: UCSI ACPI driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Driver for ACPI enumerated UCSI devices.

Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>
---
 drivers/usb/type-c/Kconfig     |  10 ++++
 drivers/usb/type-c/Makefile    |   1 +
 drivers/usb/type-c/ucsi_acpi.c | 133 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 drivers/usb/type-c/ucsi_acpi.c

diff --git a/drivers/usb/type-c/Kconfig b/drivers/usb/type-c/Kconfig
index 02abd74..72b002e 100644
--- a/drivers/usb/type-c/Kconfig
+++ b/drivers/usb/type-c/Kconfig
@@ -12,4 +12,14 @@ config TYPEC_UCSI
 	  registers and data structures used to interface with the USB Type-C
 	  connectors on a system.
 
+if TYPEC_UCSI
+
+config TYPEC_UCSI_ACPI
+	tristate "UCSI ACPI Driver"
+	depends on ACPI
+	help
+	  Driver for ACPI enumerated UCSI devices.
+
+endif
+
 endmenu
diff --git a/drivers/usb/type-c/Makefile b/drivers/usb/type-c/Makefile
index ab974ba..17933dc 100644
--- a/drivers/usb/type-c/Makefile
+++ b/drivers/usb/type-c/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_TYPEC)		+= typec.o
 obj-$(CONFIG_TYPEC_UCSI)	+= ucsi.o
+obj-$(CONFIG_TYPEC_UCSI_ACPI)	+= ucsi_acpi.o
diff --git a/drivers/usb/type-c/ucsi_acpi.c b/drivers/usb/type-c/ucsi_acpi.c
new file mode 100644
index 0000000..8445a7d
--- /dev/null
+++ b/drivers/usb/type-c/ucsi_acpi.c
@@ -0,0 +1,133 @@
+/*
+ * UCSI ACPI driver
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+#include "ucsi.h"
+
+struct ucsi_acpi {
+	struct device *dev;
+	struct ucsi *ucsi;
+	struct ucsi_ppm ppm;
+};
+
+static const u8 ucsi_uuid[] = {
+	0xc2, 0x98, 0x83, 0x6f,	0xa4, 0x7c, 0xe4, 0x11,
+	0xad, 0x36, 0x63, 0x10, 0x42, 0xb5, 0x00, 0x8f,
+};
+
+static int ucsi_acpi_cmd(struct ucsi_ppm *ppm)
+{
+	struct ucsi_acpi *ua = container_of(ppm, struct ucsi_acpi, ppm);
+	union acpi_object *obj;
+
+	obj = acpi_evaluate_dsm(ACPI_HANDLE(ua->dev), ucsi_uuid, 1, 1, NULL);
+	if (!obj) {
+		dev_err(ua->dev, "%s: failed to evaluate _DSM\n", __func__);
+		return -EIO;
+	}
+
+	ACPI_FREE(obj);
+	return 0;
+}
+
+static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct ucsi_acpi *ua = data;
+
+	if (!ucsi_interrupt(ua->ucsi))
+		dev_err(ua->dev, "spurious ACPI notification\n");
+}
+
+static int ucsi_acpi_probe(struct platform_device *pdev)
+{
+	struct ucsi_acpi *ua;
+	struct resource *res;
+	acpi_status status;
+	int ret;
+
+	ua = devm_kzalloc(&pdev->dev, sizeof(*ua), GFP_KERNEL);
+	if (!ua)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "missing memory resource\n");
+		return -ENODEV;
+	}
+
+	ua->ppm.data = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!ua->ppm.data)
+		return -ENOMEM;
+
+	ua->ppm.cmd = ucsi_acpi_cmd;
+	ua->dev = &pdev->dev;
+
+	ua->ucsi = ucsi_register_ppm(&pdev->dev, &ua->ppm);
+	if (IS_ERR(ua->ucsi))
+		return PTR_ERR(ua->ucsi);
+
+	status = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
+					     ACPI_DEVICE_NOTIFY,
+					     ucsi_acpi_notify, ua);
+	if (ACPI_FAILURE(status)) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = ucsi_init(ua->ucsi);
+	if (ret) {
+		acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
+					   ACPI_DEVICE_NOTIFY,
+					   ucsi_acpi_notify);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, ua);
+	return 0;
+err:
+	ucsi_unregister_ppm(ua->ucsi);
+	return ret;
+}
+
+static int ucsi_acpi_remove(struct platform_device *pdev)
+{
+	struct ucsi_acpi *ua = platform_get_drvdata(pdev);
+
+	acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
+				   ACPI_DEVICE_NOTIFY, ucsi_acpi_notify);
+	ucsi_unregister_ppm(ua->ucsi);
+	return 0;
+}
+
+static const struct acpi_device_id ucsi_acpi_match[] = {
+	{ "PNP0CA0", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match);
+
+static struct platform_driver ucsi_acpi_platform_driver = {
+	.driver = {
+		.name = "ucsi_acpi",
+		.acpi_match_table = ACPI_PTR(ucsi_acpi_match),
+	},
+	.probe = ucsi_acpi_probe,
+	.remove = ucsi_acpi_remove,
+};
+
+module_platform_driver(ucsi_acpi_platform_driver);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("UCSI ACPI driver");
-- 
2.7.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux