From patchwork Wed Dec 3 12:33:37 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken Xue X-Patchwork-Id: 5430471 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 10D62BEEA8 for ; Wed, 3 Dec 2014 13:00:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B65C12035C for ; Wed, 3 Dec 2014 13:00:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4C39B20120 for ; Wed, 3 Dec 2014 12:59:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751404AbaLCM76 (ORCPT ); Wed, 3 Dec 2014 07:59:58 -0500 Received: from mail-bn1bon0142.outbound.protection.outlook.com ([157.56.111.142]:32208 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751061AbaLCM75 (ORCPT ); Wed, 3 Dec 2014 07:59:57 -0500 Received: from BN1PR02CA0052.namprd02.prod.outlook.com (10.141.56.52) by BY2PR02MB201.namprd02.prod.outlook.com (10.242.232.12) with Microsoft SMTP Server (TLS) id 15.1.26.15; Wed, 3 Dec 2014 12:44:30 +0000 Received: from BN1AFFO11FD008.protection.gbl (2a01:111:f400:7c10::133) by BN1PR02CA0052.outlook.office365.com (2a01:111:e400:2a::52) with Microsoft SMTP Server (TLS) id 15.1.26.15 via Frontend Transport; Wed, 3 Dec 2014 12:44:29 +0000 Received: from atltwp02.amd.com (165.204.84.222) by BN1AFFO11FD008.mail.protection.outlook.com (10.58.52.68) with Microsoft SMTP Server id 15.1.6.13 via Frontend Transport; Wed, 3 Dec 2014 12:44:29 +0000 X-WSS-ID: 0NG0BE4-08-RJT-02 X-M-MSG: Received: from satlvexedge01.amd.com (satlvexedge01.amd.com [10.177.96.28]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by atltwp02.amd.com (Axway MailGate 5.3.1) with ESMTPS id 251F5D16001; Wed, 3 Dec 2014 06:44:27 -0600 (CST) Received: from SATLEXDAG02.amd.com (10.181.40.5) by satlvexedge01.amd.com (10.177.96.28) with Microsoft SMTP Server (TLS) id 14.3.195.1; Wed, 3 Dec 2014 06:44:59 -0600 Received: from SCYBEXDAG03.amd.com (10.34.11.13) by SATLEXDAG02.amd.com (10.181.40.5) with Microsoft SMTP Server (TLS) id 14.3.195.1; Wed, 3 Dec 2014 07:44:28 -0500 Received: from kxue-X58A-UD3R.amd.com (10.237.74.21) by SCYBEXDAG03.amd.com (10.34.11.13) with Microsoft SMTP Server id 14.3.195.1; Wed, 3 Dec 2014 20:44:24 +0800 From: Ken Xue To: , CC: , , Ken Xue Subject: [PATCH 1/2] acpi:soc: merge common codes for creating platform device Date: Wed, 3 Dec 2014 20:33:37 +0800 Message-ID: <1417610017-2140-1-git-send-email-Ken.Xue@amd.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:165.204.84.222; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(428002)(199003)(189002)(50986999)(77096005)(4396001)(229853001)(31966008)(107046002)(101416001)(62966003)(99396003)(102836001)(77156002)(84676001)(48376002)(64706001)(20776003)(47776003)(36756003)(89996001)(106466001)(120916001)(104166001)(87936001)(105586002)(46102003)(19580395003)(19580405001)(44976005)(50466002)(53416004)(87286001)(92726001)(97736003)(95666004)(92566001)(68736005)(21056001)(50226001)(86362001)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:BY2PR02MB201; H:atltwp02.amd.com; FPR:; SPF:None; MLV:sfv; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:BY2PR02MB201; X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601001); SRVR:BY2PR02MB201; X-Forefront-PRVS: 0414DF926F Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Authentication-Results: spf=none (sender IP is 165.204.84.222) smtp.mailfrom=Ken.Xue@amd.com; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:;SRVR:BY2PR02MB201; X-OriginatorOrg: amd4.onmicrosoft.com Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch is supposed to deliver some common codes for AMD APD and INTEL LPSS. It can help to convert some specific acpi devices to be platform devices. Signed-off-by: Ken Xue --- drivers/acpi/Makefile | 2 +- drivers/acpi/acpi_soc.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpi_soc.h | 90 +++++++++++++++++++++ 3 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 drivers/acpi/acpi_soc.c create mode 100644 drivers/acpi/acpi_soc.h diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c3b2fcb..ae3397d 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -40,7 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o -acpi-y += acpi_lpss.o +acpi-y += acpi_soc.o acpi_lpss.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o acpi-y += int340x_thermal.o diff --git a/drivers/acpi/acpi_soc.c b/drivers/acpi/acpi_soc.c new file mode 100644 index 0000000..25089a0 --- /dev/null +++ b/drivers/acpi/acpi_soc.c @@ -0,0 +1,211 @@ +/* + * ACPI SOC support for Intel Lynxpoint LPSS and AMD APD. + * + * Copyright (C) 2015, Intel Corporation & AMD Corporation + * Authors: Ken Xue + * Mika Westerberg + * Rafael J. Wysocki + * + * 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 +#include +#include + +#include "internal.h" +#include "acpi_soc.h" + +ACPI_MODULE_NAME("acpi_soc"); + +/* A list for all acpi soc device */ +static LIST_HEAD(a_soc_list); + +static int is_memory(struct acpi_resource *res, void *not_used) +{ + struct resource r; + + return !acpi_dev_resource_memory(res, &r); +} + +static int acpi_soc_create_device(struct acpi_device *adev, + const struct acpi_device_id *id) +{ + struct acpi_soc_dev_desc *dev_desc; + struct acpi_soc_dev_private_data *pdata; + struct resource_list_entry *rentry; + struct list_head resource_list; + struct platform_device *pdev; + int ret; + + dev_desc = (struct acpi_soc_dev_desc *)id->driver_data; + if (!dev_desc) { + pdev = acpi_create_platform_device(adev); + return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1; + } + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL); + if (ret < 0) + goto err_out; + + list_for_each_entry(rentry, &resource_list, node) + if (resource_type(&rentry->res) == IORESOURCE_MEM) { + if (dev_desc->mem_size_override) + pdata->mmio_size = dev_desc->mem_size_override; + else + pdata->mmio_size = resource_size(&rentry->res); + pdata->mmio_base = ioremap(rentry->res.start, + pdata->mmio_size); + break; + } + + acpi_dev_free_resource_list(&resource_list); + + pdata->adev = adev; + pdata->dev_desc = dev_desc; + + if (dev_desc->setup) + dev_desc->setup(pdata); + + /* + * This works around a known issue in ACPI tables where acpi soc devices + * have _PS0 and _PS3 without _PSC (and no power resources), so + * acpi_bus_init_power() will assume that the BIOS has put them into D0. + */ + ret = acpi_device_fix_up_power(adev); + if (ret) { + /* Skip the device, but continue the namespace scan. */ + ret = 0; + goto err_out; + } + + adev->driver_data = pdata; + pdev = acpi_create_platform_device(adev); + if (!IS_ERR_OR_NULL(pdev)) + return 1; + + ret = PTR_ERR(pdev); + adev->driver_data = NULL; + + err_out: + kfree(pdata); + return ret; +} + +static int acpi_soc_platform_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct platform_device *pdev = to_platform_device(data); + struct acpi_soc_dev_private_data *pdata; + struct acpi_device *adev; + struct acpi_soc *a_soc_entry; + const struct acpi_device_id *id = NULL; + + list_for_each_entry(a_soc_entry, &a_soc_list, list) { + id = acpi_match_device(a_soc_entry->ids, &pdev->dev); + if (!id) + break; + } + + if (!id || !id->driver_data) + return 0; + + if (acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) + return 0; + + pdata = acpi_driver_data(adev); + if (!pdata || !pdata->mmio_base) + return 0; + + switch (action) { + case BUS_NOTIFY_BOUND_DRIVER: + if ((pdata->dev_desc->flags & ACPI_SOC_PM)) { + if (a_soc_entry->pm_domain) + pdev->dev.pm_domain = a_soc_entry->pm_domain; + else if (pdata->dev_desc->flags & ACPI_SOC_PM_ON) + dev_pm_domain_attach(&pdev->dev, true); + else + dev_pm_domain_attach(&pdev->dev, false); + } + break; + case BUS_NOTIFY_UNBOUND_DRIVER: + if ((pdata->dev_desc->flags & ACPI_SOC_PM)) { + if (a_soc_entry->pm_domain) + pdev->dev.pm_domain = a_soc_entry->pm_domain; + else if (pdata->dev_desc->flags & ACPI_SOC_PM_ON) + dev_pm_domain_detach(&pdev->dev, true); + else + dev_pm_domain_detach(&pdev->dev, false); + } + break; + case BUS_NOTIFY_ADD_DEVICE: + if ((pdata->dev_desc->flags & ACPI_SOC_SYSFS) + && a_soc_entry->pm_domain) + return sysfs_create_group(&pdev->dev.kobj, + a_soc_entry->attr_group); + case BUS_NOTIFY_DEL_DEVICE: + if ((pdata->dev_desc->flags & ACPI_SOC_SYSFS) + && a_soc_entry->pm_domain) + sysfs_remove_group(&pdev->dev.kobj, + a_soc_entry->attr_group); + break; + } + + return 0; +} + +static struct notifier_block acpi_soc_nb = { + .notifier_call = acpi_soc_platform_notify, +}; + +static void acpi_soc_bind(struct device *dev) +{ + struct acpi_soc_dev_private_data *pdata; + + pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (!pdata || !pdata->dev_desc || !pdata->dev_desc->bind) + return; + + pdata->dev_desc->bind(pdata); +} + +static void acpi_soc_unbind(struct device *dev) +{ + struct acpi_soc_dev_private_data *pdata; + + pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (!pdata || !pdata->dev_desc || !pdata->dev_desc->unbind) + return; + + pdata->dev_desc->unbind(pdata); +} + +void register_acpi_soc(struct acpi_soc *a_soc, bool disable_scan_handler) +{ + struct acpi_scan_handler *acpi_soc_handler; + + INIT_LIST_HEAD(&a_soc->list); + list_add(&a_soc->list, &a_soc_list); + + acpi_soc_handler = kzalloc(sizeof(*acpi_soc_handler), GFP_KERNEL); + acpi_soc_handler->ids = a_soc->ids; + if (!disable_scan_handler) { + acpi_soc_handler->attach = acpi_soc_create_device; + acpi_soc_handler->bind = acpi_soc_bind; + acpi_soc_handler->unbind = acpi_soc_unbind; + } + acpi_scan_add_handler(acpi_soc_handler); + bus_register_notifier(&platform_bus_type, &acpi_soc_nb); +} diff --git a/drivers/acpi/acpi_soc.h b/drivers/acpi/acpi_soc.h new file mode 100644 index 0000000..cc270a5 --- /dev/null +++ b/drivers/acpi/acpi_soc.h @@ -0,0 +1,90 @@ +/* + * ACPI SOC support for Intel Lynxpoint LPSS and AMD APD. + * + * Copyright (C) 2015, Intel Corporation & AMD Corporation + * Authors: Ken Xue + * Mika Westerberg + * Rafael J. Wysocki + * + * 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. + */ +#ifndef _ACPI_SOC_H +#define _ACPI_SOC_H + +#include +#include +#include + +/* Flags */ +#define ACPI_SOC_SYSFS BIT(0) +#define ACPI_SOC_PM BIT(1) +#define ACPI_SOC_PM_ON BIT(2) + +struct acpi_soc_dev_private_data; + +/** + * struct acpi_soc - acpi soc + * @list: list head + * @ids: all acpi device ids for acpi soc + * @pm_domain: power domain for all acpi device;can be NULL + * @attr_group: attribute group for sysfs support of acpi soc;can be NULL + */ +struct acpi_soc { + struct list_head list; + struct acpi_device_id *ids; + struct dev_pm_domain *pm_domain; + struct attribute_group *attr_group; +}; + +/** + * struct acpi_soc_dev_desc - a descriptor for acpi device + * @flags: some device feature flags + * @clk: clock device + * @fixed_clk_rate: fixed rate input clock source for acpi device; + * 0 means no fixed rate input clock source + * @mem_size_override: a workaround for override device memsize; + * 0 means no needs for this WA + * @setup: a hook routine to set device resource during create platform device + * @bind: a hook of acpi_scan_handler.bind + * @unbind: a hook of acpi_scan_handler.unbind + * + *device description defined as acpi_device_id.driver_data + */ +struct acpi_soc_dev_desc { + unsigned int flags; + struct clk *clk; + unsigned int fixed_clk_rate; + size_t mem_size_override; + int (*setup)(struct acpi_soc_dev_private_data *pdata); + void (*bind)(struct acpi_soc_dev_private_data *pdata); + void (*unbind)(struct acpi_soc_dev_private_data *pdata); +}; + +/** + * struct acpi_soc_dev_private_data - acpi device private data + * @mmio_base: virtual memory base addr of the device + * @mmio_size: device memory size + * @dev_desc: device description + * @adev: apci device + */ +struct acpi_soc_dev_private_data { + void __iomem *mmio_base; + resource_size_t mmio_size; + + struct acpi_soc_dev_desc *dev_desc; + struct acpi_device *adev; +}; + +/** + * register_acpi_soc - register a new acpi soc + * @a_soc: acpi soc + * @disable_scan_handler: true means remove default scan handle + * false means use default scan handle + * + * register a new acpi soc into asoc_list and install default scan handle. + */ +void register_acpi_soc(struct acpi_soc *a_soc, bool disable_scan_handler); + +#endif