From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757562AbcBIRDx (ORCPT ); Tue, 9 Feb 2016 12:03:53 -0500 Received: from mga04.intel.com ([192.55.52.120]:50831 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756830AbcBIRDd (ORCPT ); Tue, 9 Feb 2016 12:03:33 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,421,1449561600"; d="scan'208";a="908659954" From: Heikki Krogerus To: Greg KH Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Mathias Nyman , Felipe Balbi Subject: [PATCH 3/3] usb: type-c: UCSI ACPI driver Date: Tue, 9 Feb 2016 19:01:23 +0200 Message-Id: <1455037283-106479-4-git-send-email-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1455037283-106479-1-git-send-email-heikki.krogerus@linux.intel.com> References: <1455037283-106479-1-git-send-email-heikki.krogerus@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Driver for ACPI enumerated UCSI devices. Signed-off-by: Heikki Krogerus --- 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 + * + * 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 +#include +#include +#include + +#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 "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("UCSI ACPI driver"); -- 2.7.0