From patchwork Tue Jan 17 12:22:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643708 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C10B4C3DA78 for ; Tue, 17 Jan 2023 12:22:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235947AbjAQMWT (ORCPT ); Tue, 17 Jan 2023 07:22:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236310AbjAQMWS (ORCPT ); Tue, 17 Jan 2023 07:22:18 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 996DF2B297; Tue, 17 Jan 2023 04:22:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958137; x=1705494137; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LcaRHKs0hEw6NKkOGZA+3UTE6Cn8/brkGDLsYNE6gOg=; b=T3OKszF/zDiFDWwQky9TE+DSIMLmUnOGOYY6pT2rJmUajPDDjCN4lH1k lEJ+E0J9R0tmDDnQrXrSzs6XHkdl14KodVUhe3LijXvzIvQiAUwxrTN9x QG+zNy28t9FNuPgeU10iTvzl50F8moxFckCxLajZ/ciZ1y/Hlbh+5+vHk p1nsW1vcyqcJtDK35Mz6/loPzhjwtr0H2QntP5yPJgQMLRlfPHJLG5gNL 8IuCHGOGkba5n2NCy25XkE6PKRh0FUwdltY2w/j6roYMd9SJDn1StridH Va0ik7f0qAfsHFdEBSGHQmWtd+FCR/D1fdwQn+QusxnUqvw0ze85JiFGe A==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920103" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920103" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:15 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772031" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772031" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:14 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id B23B420412; Tue, 17 Jan 2023 14:22:11 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgV6-FY; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 1/8] ACPI: property: Parse data node string references in properties Date: Tue, 17 Jan 2023 14:22:37 +0200 Message-Id: <20230117122244.2546597-2-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Add support for parsing property references using strings, besides reference objects that were previously supported. This allows also referencing data nodes which was not possible with reference objects. Signed-off-by: Sakari Ailus --- drivers/acpi/property.c | 101 ++++++++++++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index b8d9eb9a433ed..545f74673703d 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -795,7 +795,8 @@ acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode, static int acpi_get_ref_args(struct fwnode_reference_args *args, struct fwnode_handle *ref_fwnode, const union acpi_object **element, - const union acpi_object *end, size_t num_args) + const union acpi_object *end, size_t num_args, + bool subnode_string) { u32 nargs = 0, i; @@ -803,13 +804,16 @@ static int acpi_get_ref_args(struct fwnode_reference_args *args, * Find the referred data extension node under the * referred device node. */ - for (; *element < end && (*element)->type == ACPI_TYPE_STRING; - (*element)++) { - const char *child_name = (*element)->string.pointer; - - ref_fwnode = acpi_fwnode_get_named_child_node(ref_fwnode, child_name); - if (!ref_fwnode) - return -EINVAL; + if (subnode_string) { + for (; *element < end && (*element)->type == ACPI_TYPE_STRING; + (*element)++) { + const char *child_name = (*element)->string.pointer; + + ref_fwnode = acpi_fwnode_get_named_child_node(ref_fwnode, + child_name); + if (!ref_fwnode) + return -EINVAL; + } } /* @@ -820,7 +824,8 @@ static int acpi_get_ref_args(struct fwnode_reference_args *args, for (i = 0; (*element) + i < end && i < num_args; i++) { acpi_object_type type = (*element)[i].type; - if (type == ACPI_TYPE_LOCAL_REFERENCE) + if (type == ACPI_TYPE_LOCAL_REFERENCE || + (!subnode_string && type == ACPI_TYPE_STRING)) break; if (type == ACPI_TYPE_INTEGER) @@ -844,6 +849,43 @@ static int acpi_get_ref_args(struct fwnode_reference_args *args, return 0; } +static struct fwnode_handle * +acpi_parse_string_ref(const struct fwnode_handle *fwnode, const char *refstring) +{ + acpi_handle scope, handle; + struct acpi_data_node *dn; + struct acpi_device *device; + acpi_status status; + + if (is_acpi_device_node(fwnode)) { + scope = to_acpi_device_node(fwnode)->handle; + } else if (is_acpi_data_node(fwnode)) { + scope = to_acpi_data_node(fwnode)->handle; + } else { + pr_err("ACPI: bad node type\n"); + return ERR_PTR(-EINVAL); + } + + status = acpi_get_handle(scope, refstring, &handle); + if (ACPI_FAILURE(status)) { + acpi_handle_debug(scope, "can't get handle for %s", refstring); + return ERR_PTR(-EINVAL); + } + + device = acpi_fetch_acpi_dev(handle); + if (device) + return acpi_fwnode_handle(device); + + status = acpi_get_data_full(handle, acpi_nondev_subnode_tag, + (void **)&dn, NULL); + if (ACPI_FAILURE(status) || !dn) { + acpi_handle_debug(handle, "can't find subnode"); + return ERR_PTR(-EINVAL); + } + + return &dn->fwnode; +} + /** * __acpi_node_get_property_reference - returns handle to the referenced object * @fwnode: Firmware node to get the property from @@ -886,6 +928,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, const union acpi_object *element, *end; const union acpi_object *obj; const struct acpi_device_data *data; + struct fwnode_handle *ref_fwnode; struct acpi_device *device; int ret, idx = 0; @@ -909,16 +952,29 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, args->fwnode = acpi_fwnode_handle(device); args->nargs = 0; + return 0; + case ACPI_TYPE_STRING: + if (index) + return -ENOENT; + + ref_fwnode = acpi_parse_string_ref(fwnode, obj->string.pointer); + if (IS_ERR(ref_fwnode)) + return PTR_ERR(ref_fwnode); + + args->fwnode = ref_fwnode; + args->nargs = 0; + return 0; case ACPI_TYPE_PACKAGE: /* * If it is not a single reference, then it is a package of - * references followed by number of ints as follows: + * references, followed by number of ints as follows: * * Package () { REF, INT, REF, INT, INT } * - * The index argument is then used to determine which reference - * the caller wants (along with the arguments). + * Here, REF may be either a local reference or a string. The + * index argument is then used to determine which reference the + * caller wants (along with the arguments). */ break; default: @@ -942,7 +998,26 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ret = acpi_get_ref_args(idx == index ? args : NULL, acpi_fwnode_handle(device), - &element, end, num_args); + &element, end, num_args, true); + if (ret < 0) + return ret; + + if (idx == index) + return 0; + + break; + case ACPI_TYPE_STRING: + ref_fwnode = + acpi_parse_string_ref(fwnode, + element->string.pointer); + if (IS_ERR(ref_fwnode)) + return PTR_ERR(ref_fwnode); + + element++; + + ret = acpi_get_ref_args(idx == index ? args : NULL, + ref_fwnode, &element, end, + num_args, false); if (ret < 0) return ret; From patchwork Tue Jan 17 12:22:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643443 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B96EAC63797 for ; Tue, 17 Jan 2023 12:22:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236569AbjAQMWU (ORCPT ); Tue, 17 Jan 2023 07:22:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51218 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236029AbjAQMWS (ORCPT ); Tue, 17 Jan 2023 07:22:18 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 997FB2BF1D; Tue, 17 Jan 2023 04:22:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958137; x=1705494137; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v6HAXFpRr7SLIA2JbdJvjY1F5UgFHWYeLcwaXQXAcK8=; b=dvwJ+B8c4RKqoVZr72FcYNemerF/mZ84mjgfS7PCi9FALecr8ugN5GrJ FaQAj3CQp+irDuvCTZRdNGhbrzofy61strfmezV+I6XpLZRQ6W1pToNB7 iK5zoaG36+U8GnB0JE8OUsrZZIP6vyviHCHsstWivqk8RwmSTzzeLYevZ NcEDPQZtjABXR7uy6hiQe5lG3syn3A9f/r4+ALQ441DLvC4zrgujEakr0 6huwYybSl/m40d2CaGwxEyA294maqvCojOvU/kZYuZDiysbJ9+9IBeQVP VGMcc8unJji3dTszEEh8PXIhYsG0/xYwePNPl6WXW8mMlzsRA4CIw7fNs A==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920106" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920106" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:15 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772033" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772033" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:14 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id C7CF52057F; Tue, 17 Jan 2023 14:22:11 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgV9-I7; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 2/8] ACPI: property: Parse _CRS CSI-2 descriptor Date: Tue, 17 Jan 2023 14:22:38 +0200 Message-Id: <20230117122244.2546597-3-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Parse newly added ACPI _CRS CSI-2 descriptor for CSI-2 and camera configuration. For now, only figure out where the descriptor is present in order to allow adding information from it to related devices. Signed-off-by: Sakari Ailus --- drivers/acpi/Makefile | 2 +- drivers/acpi/internal.h | 7 + drivers/acpi/mipi.c | 318 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/scan.c | 16 +- include/acpi/acpi_bus.h | 11 ++ 5 files changed, 349 insertions(+), 5 deletions(-) create mode 100644 drivers/acpi/mipi.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index a5b649e71ab1b..a98fa1bc15548 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -37,7 +37,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o # ACPI Bus and Device Drivers # acpi-y += bus.o glue.o -acpi-y += scan.o +acpi-y += scan.o mipi.o acpi-y += resource.o acpi-y += acpi_processor.o acpi-y += processor_core.o diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ec584442fb298..1ec4aa92bf17a 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -282,4 +282,11 @@ void acpi_init_lpit(void); static inline void acpi_init_lpit(void) { } #endif +/*-------------------------------------------------------------------------- + ACPI and MIPI DisCo for Imaging conversion + -------------------------------------------------------------------------- */ + +void acpi_crs_csi2_swnodes_del_free(void); +void acpi_bus_scan_crs_csi2(acpi_handle handle); + #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/mipi.c b/drivers/acpi/mipi.c new file mode 100644 index 0000000000000..9701266bf5c67 --- /dev/null +++ b/drivers/acpi/mipi.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MIPI DisCo for Imaging support. + * + * Copyright (C) 2022 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +struct crs_csi2_swnodes { + struct list_head list; + acpi_handle handle; + struct acpi_device_software_nodes *ads; +}; + +static LIST_HEAD(crs_csi2_swnodes); + +static void crs_csi2_swnode_del_free(struct crs_csi2_swnodes *swnodes) +{ + list_del(&swnodes->list); + kfree(swnodes); +} + +void acpi_crs_csi2_swnodes_del_free(void) +{ + struct crs_csi2_swnodes *swnodes, *swnodes_tmp; + + list_for_each_entry_safe(swnodes, swnodes_tmp, &crs_csi2_swnodes, list) + crs_csi2_swnode_del_free(swnodes); +} + +struct crs_csi2_instance { + struct list_head list; + struct acpi_resource_csi2_serialbus csi2; + acpi_handle remote_handle; + char remote_name[]; +}; + +struct crs_csi2 { + struct list_head list; + acpi_handle handle; + struct list_head buses; +}; + +struct scan_check_crs_csi2_context { + struct list_head res_list; + acpi_handle handle; +}; + +static acpi_status scan_check_crs_csi2_instance(struct acpi_resource *res, + void *context) +{ + struct scan_check_crs_csi2_context *inst_context = context; + struct acpi_resource_csi2_serialbus *csi2; + struct crs_csi2_instance *inst; + acpi_handle remote_handle; + acpi_status status; + + if (res->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) + return AE_OK; + + csi2 = &res->data.csi2_serial_bus; + + if (csi2->type != ACPI_RESOURCE_SERIAL_TYPE_CSI2) + return AE_OK; + + if (!csi2->resource_source.string_length) { + acpi_handle_debug(inst_context->handle, + "invalid resource source string length\n"); + return AE_OK; + } + + status = acpi_get_handle(NULL, csi2->resource_source.string_ptr, + &remote_handle); + if (status != AE_OK) { + acpi_handle_warn(inst_context->handle, + "cannot get handle for %s\n", + csi2->resource_source.string_ptr); + return AE_OK; + } + + inst = kmalloc(struct_size(inst, remote_name, + csi2->resource_source.string_length), + GFP_KERNEL); + if (!inst) + return AE_OK; + + inst->csi2 = *csi2; + memcpy(inst->remote_name, csi2->resource_source.string_ptr, + csi2->resource_source.string_length); + inst->csi2.resource_source.string_ptr = inst->remote_name; + inst->remote_handle = remote_handle; + + list_add(&inst->list, &inst_context->res_list); + + return AE_OK; +} + +static acpi_status scan_check_crs_csi2(acpi_handle handle, u32 nesting_level, + void *context, void **ret) +{ + struct scan_check_crs_csi2_context inst_context = { + .handle = handle, + .res_list = LIST_HEAD_INIT(inst_context.res_list), + }; + struct list_head *list = context; + struct crs_csi2 *csi2; + + INIT_LIST_HEAD(&inst_context.res_list); + + acpi_walk_resources(handle, METHOD_NAME__CRS, + scan_check_crs_csi2_instance, &inst_context); + + if (list_empty(&inst_context.res_list)) + return AE_OK; + + csi2 = kmalloc(sizeof(*csi2), GFP_KERNEL); + if (!csi2) + return AE_OK; + + csi2->handle = handle; + list_replace(&inst_context.res_list, &csi2->buses); + list_add(&csi2->list, list); + + return AE_OK; +} + +struct acpi_handle_ref { + acpi_handle handle; + unsigned int count; +}; + +#define NO_CSI2_PORT (~1U) + +static int crs_handle_cmp(const void *__a, const void *__b) +{ + const struct acpi_handle_ref *a = __a, *b = __b; + + return a->handle < b->handle ? -1 : a->handle > b->handle; +} + +static void crs_csi2_release(struct list_head *crs_csi2_handles) +{ + struct crs_csi2 *csi2, *csi2_tmp; + + list_for_each_entry_safe(csi2, csi2_tmp, crs_csi2_handles, list) { + struct crs_csi2_instance *inst, *inst_tmp; + + list_for_each_entry_safe(inst, inst_tmp, &csi2->buses, list) { + list_del(&inst->list); + kfree(inst); + } + + list_del(&csi2->list); + kfree(csi2); + } +} + +/** + * acpi_bus_scan_crs_csi2 - Scan a device and its child devices for _CRS CSI-2 + * + * @handle: ACPI handle to scan + * + * This function does a number of things: + * + * 1. Scan an ACPI device and its children for _CRS CSI-2 instances. The + * instances are stored for later use. + * + * 2. Count how many references to other devices _CRS CSI-2 instances have in + * total. + * + * 3. Count the number of references to other devices for each _CRS CSI-2 + * instance. + * + * 4. Allocate memory for swnodes each ACPI device requires later on, and + * generate a list of such allocations. + * + * Note that struct acpi_device isn't available yet at this time. + * + * acpi_scan_lock in scan.c must be held when calling this function. + */ +void acpi_bus_scan_crs_csi2(acpi_handle handle) +{ + struct acpi_handle_ref *handle_refs; + struct acpi_handle_ref *this = NULL; + LIST_HEAD(crs_csi2_handles); + unsigned int handle_count = 0, this_count; + unsigned int curr = 0; + struct crs_csi2 *csi2; + + /* Collect the devices that have a _CRS CSI-2 resource */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, + scan_check_crs_csi2, NULL, &crs_csi2_handles, NULL); + + /* + * Figure out how much temporary storage we need for counting + * connections in each device. + */ + list_for_each_entry(csi2, &crs_csi2_handles, list) { + struct crs_csi2_instance *inst; + + handle_count++; + + list_for_each_entry(inst, &csi2->buses, list) + handle_count++; + } + + /* No handles? Bail out here. */ + if (!handle_count) + return; + + handle_refs = kcalloc(handle_count + 1, sizeof(*handle_refs), + GFP_KERNEL); + if (!handle_refs) { + acpi_handle_debug(handle, "no memory for %u handle refs\n", + handle_count + 1); + return; + } + + /* Associate handles to the number of references. */ + list_for_each_entry(csi2, &crs_csi2_handles, list) { + struct crs_csi2_instance *inst; + struct acpi_handle_ref *handle_ref; + + handle_ref = &handle_refs[curr++]; + handle_ref->handle = csi2->handle; + + list_for_each_entry(inst, &csi2->buses, list) { + handle_refs[curr].handle = inst->remote_handle; + handle_refs[curr].count = 1; + handle_ref->count++; + curr++; + } + } + + handle_refs[curr].handle = NULL; + + sort(handle_refs, handle_count, sizeof(*handle_refs), crs_handle_cmp, + NULL); + + /* + * Finally count references in each handle, allocate space for device + * specific ports, properties and fill the _CRS CSI2 descriptor + * originated data. + */ + this = handle_refs; + this_count = this->count; + for (curr = 1; curr < handle_count + 1; curr++) { + struct acpi_device_software_nodes *ads; + struct crs_csi2_swnodes *swnodes; + size_t alloc_size; + void *end; + + if (this->handle == handle_refs[curr].handle) { + this_count += handle_refs[curr].count; + continue; + } + + /* + * Allocate memory for ports, node pointers (number of nodes + + * 1 (guardian), nodes (root + number of ports * 2 (for for + * every port there is an endpoint)). + */ + if (check_mul_overflow(sizeof(*ads->ports) + + sizeof(*ads->nodes) * 2 + + sizeof(*ads->nodeptrs) * 2, + (size_t)this_count, &alloc_size) || + check_add_overflow(sizeof(*ads) + sizeof(*ads->nodes) + + sizeof(*ads->nodeptrs) * 2, + alloc_size, &alloc_size)) { + acpi_handle_warn(handle, "too many handles (%u)", + this_count); + continue; + } + + swnodes = kzalloc(sizeof(*swnodes), GFP_KERNEL); + ads = kzalloc(alloc_size, GFP_KERNEL); + ads->ports = (void *)(ads + 1); + ads->nodes = (void *)(ads->ports + this_count); + ads->nodeptrs = (void *)(ads->nodes + + this_count * 2 + 1); + end = ads->nodeptrs + this_count * 2 + 2; + if (!swnodes || !ads || + WARN_ON((void *)ads + alloc_size != end)) { + kfree(swnodes); + kfree(ads); + acpi_handle_debug(handle, + "cannot allocate for %u swnodes\n", + this_count); + } else { + unsigned int i; + + ads->num_ports = this_count; + for (i = 0; i < this_count * 2 + 1; i++) + ads->nodeptrs[i] = &ads->nodes[i]; + ads->nodeptrs[i] = NULL; + for (i = 0; i < this_count; i++) + ads->ports[i].port_nr = NO_CSI2_PORT; + swnodes->handle = this->handle; + swnodes->ads = ads; + list_add(&swnodes->list, &crs_csi2_swnodes); + } + + this = &handle_refs[curr]; + this_count = this->count; + } + + kfree(handle_refs); + + crs_csi2_release(&crs_csi2_handles); +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0c6f06abe3f47..50de874b8f208 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2423,9 +2423,12 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev); int acpi_bus_scan(acpi_handle handle) { struct acpi_device *device = NULL; + int ret = 0; acpi_bus_scan_second_pass = false; + acpi_bus_scan_crs_csi2(handle); + /* Pass 1: Avoid enumerating devices with missing dependencies. */ if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &device))) @@ -2433,13 +2436,15 @@ int acpi_bus_scan(acpi_handle handle) acpi_bus_check_add_1, NULL, NULL, (void **)&device); - if (!device) - return -ENODEV; + if (!device) { + ret = -ENODEV; + goto out_release; + } acpi_bus_attach(device, (void *)true); if (!acpi_bus_scan_second_pass) - return 0; + goto out_release; /* Pass 2: Enumerate all of the remaining devices. */ @@ -2452,7 +2457,10 @@ int acpi_bus_scan(acpi_handle handle) acpi_bus_attach(device, NULL); - return 0; +out_release: + acpi_crs_csi2_swnodes_del_free(); + + return ret; } EXPORT_SYMBOL(acpi_bus_scan); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e44be31115a67..a05fe22c1175c 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -360,6 +360,17 @@ struct acpi_device_data { struct acpi_gpio_mapping; +struct acpi_device_software_node_port { + unsigned int port_nr; +}; + +struct acpi_device_software_nodes { + struct acpi_device_software_node_port *ports; + struct software_node *nodes; + const struct software_node **nodeptrs; + unsigned int num_ports; +}; + /* Device */ struct acpi_device { u32 pld_crc; From patchwork Tue Jan 17 12:22:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643444 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 939B4C677F1 for ; Tue, 17 Jan 2023 12:22:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236288AbjAQMWS (ORCPT ); Tue, 17 Jan 2023 07:22:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51202 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235653AbjAQMWR (ORCPT ); Tue, 17 Jan 2023 07:22:17 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E7992B607; Tue, 17 Jan 2023 04:22:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958136; x=1705494136; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=TNAz2cqgFaXqjlPxK8X9IkOdWzQkM2gF5KFYWTN+1o4=; b=LxN+2YhuatoYA4+qmvMnJKZnIfAurhPZij7jv3nSCJ8P1Kzee6JbHdc7 PGhCgMBVX2l0Pkf5PxCaF0fXEorn1G75MLz8YGbzMgJPceiVMtUA25Gyu BQh4mk8SGDcRTKbvTd8hejEiXO8SGOORiz9ZW1rrJiE7DrnKufRvzg8Sx WTU13FIaDVT2s6PCBjz6qrJZHQenXK5JLlUkyFvpv4um0LR67HMtHOhQ6 J6gCQm0rNI+WtoN1DXzbfyrTZok3Tcreod1ikZnfKTVaIezxUayMEHQat D9EEav9Rd1HjZqhLsMbOyyc+HWy/uEE/+K+jfh0gux9vdml6oI8heXJmB g==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920100" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920100" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:15 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772032" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772032" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:14 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id D3973205E4; Tue, 17 Jan 2023 14:22:11 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgVC-Kr; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 3/8] device property: Add SOFTWARE_NODE() macro for defining software nodes Date: Tue, 17 Jan 2023 14:22:39 +0200 Message-Id: <20230117122244.2546597-4-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Add SOFTWARE_NODE() macro in order to make defining software nodes look nicer. This is analogous to different PROPERTY_ENTRY_*() macros for defining properties. Signed-off-by: Sakari Ailus Reviewed-by: Andy Shevchenko --- include/linux/property.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/property.h b/include/linux/property.h index 37179e3abad5c..6745a86bc9b97 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -477,6 +477,13 @@ struct software_node { const struct property_entry *properties; }; +#define SOFTWARE_NODE(_name_, _properties_, _parent_) \ + (struct software_node) { \ + .name = _name_, \ + .properties = _properties_, \ + .parent = _parent_, \ + } + bool is_software_node(const struct fwnode_handle *fwnode); const struct software_node * to_software_node(const struct fwnode_handle *fwnode); From patchwork Tue Jan 17 12:22:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643442 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A84CC678D7 for ; Tue, 17 Jan 2023 12:22:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236635AbjAQMWX (ORCPT ); Tue, 17 Jan 2023 07:22:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51218 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236494AbjAQMWU (ORCPT ); Tue, 17 Jan 2023 07:22:20 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 957DC2B607; Tue, 17 Jan 2023 04:22:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958138; x=1705494138; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qMfawY5MT+2/52QPf7wSbq7vT9ENHBjxfNyBCNSYgyk=; b=QqEr51tlow0++OYX4oqye/twD+aF5omL7ah/LyEjUAIkD5ZMaoSIX1tU Mi28EHgffAkfso/GVsAX4mi8YpjYrKIsbeUpaeS4UMl0T/KID1Iq0DXC6 YL7pR3qcSoEMZ4SbNoKlTq+Wnt4wurPzTjgFki4Av/h3LVC3dReccWc+O /bq0vPa58nqSIo4hFzTFjChkBQVAJc9d5JVW8Co7h+ffj/V2V2+I5K/60 DQAW1l7JAOE1wbcgo/7DnrbuWG4Nx60rd6XeOVIKm7zfcZPsH7n7cJCXF /eqe04AgX5l3e1vszijR9sTQYiOuUK3d0BfCT+wnfcN+5F5DT/o2AEaDz g==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920108" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920108" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:15 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772034" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772034" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:14 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id ED018205E8; Tue, 17 Jan 2023 14:22:11 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgVF-MY; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 4/8] ACPI: property: Generate camera swnodes for ACPI and DisCo for Imaging Date: Tue, 17 Jan 2023 14:22:40 +0200 Message-Id: <20230117122244.2546597-5-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Generate software nodes for information parsed from ACPI _CRS for CSI-2 as well as MIPI DisCo for Imaging spec. The software nodes are compliant with existing ACPI or DT definitions and are parsed by relevant drivers without changes. Signed-off-by: Sakari Ailus --- drivers/acpi/internal.h | 1 + drivers/acpi/mipi.c | 354 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/scan.c | 17 ++ include/acpi/acpi_bus.h | 49 ++++++ 4 files changed, 421 insertions(+) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 1ec4aa92bf17a..fac87404e294c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -288,5 +288,6 @@ static inline void acpi_init_lpit(void) { } void acpi_crs_csi2_swnodes_del_free(void); void acpi_bus_scan_crs_csi2(acpi_handle handle); +void acpi_init_swnodes(struct acpi_device *device); #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/mipi.c b/drivers/acpi/mipi.c index 9701266bf5c67..cc80d79f4a381 100644 --- a/drivers/acpi/mipi.c +++ b/drivers/acpi/mipi.c @@ -12,6 +12,8 @@ #include #include +#include + #include "internal.h" struct crs_csi2_swnodes { @@ -22,6 +24,18 @@ struct crs_csi2_swnodes { static LIST_HEAD(crs_csi2_swnodes); +static struct acpi_device_software_nodes * +crs_csi2_swnode_get(acpi_handle handle) +{ + struct crs_csi2_swnodes *swnodes; + + list_for_each_entry(swnodes, &crs_csi2_swnodes, list) + if (swnodes->handle == handle) + return swnodes->ads; + + return NULL; +} + static void crs_csi2_swnode_del_free(struct crs_csi2_swnodes *swnodes) { list_del(&swnodes->list); @@ -139,6 +153,31 @@ struct acpi_handle_ref { #define NO_CSI2_PORT (~1U) +static unsigned int next_csi2_port_index(struct acpi_device_software_nodes *ads, + unsigned int port_nr) +{ + unsigned int i; + + for (i = 0; i < ads->num_ports; i++) { + struct acpi_device_software_node_port *port = &ads->ports[i]; + + if (port->port_nr == port_nr) + return i; + + if (port->port_nr != NO_CSI2_PORT) + continue; + + port->port_nr = port_nr; + + return i; + } + + return NO_CSI2_PORT; +} + +#define GRAPH_PORT_NAME(var, num) \ + (snprintf((var), sizeof(var), "port@%u", (num)) > sizeof(var)) + static int crs_handle_cmp(const void *__a, const void *__b) { const struct acpi_handle_ref *a = __a, *b = __b; @@ -163,6 +202,9 @@ static void crs_csi2_release(struct list_head *crs_csi2_handles) } } +#define ACPI_CRS_CSI2_PHY_TYPE_C 0 +#define ACPI_CRS_CSI2_PHY_TYPE_D 1 + /** * acpi_bus_scan_crs_csi2 - Scan a device and its child devices for _CRS CSI-2 * @@ -182,6 +224,8 @@ static void crs_csi2_release(struct list_head *crs_csi2_handles) * 4. Allocate memory for swnodes each ACPI device requires later on, and * generate a list of such allocations. * + * 5. Set up properties for software nodes. + * * Note that struct acpi_device isn't available yet at this time. * * acpi_scan_lock in scan.c must be held when calling this function. @@ -312,7 +356,317 @@ void acpi_bus_scan_crs_csi2(acpi_handle handle) this_count = this->count; } + /* + * Allocate and set up necessary software nodes for each device and set + * up properties from _CRS CSI2 descriptor. + */ + list_for_each_entry(csi2, &crs_csi2_handles, list) { + struct acpi_device_software_nodes *local_swnodes; + struct crs_csi2_instance *inst; + + local_swnodes = crs_csi2_swnode_get(csi2->handle); + if (WARN_ON_ONCE(!local_swnodes)) + continue; + + list_for_each_entry(inst, &csi2->buses, list) { + struct acpi_device_software_nodes *remote_swnodes; + struct acpi_device_software_node_port *local_port; + struct acpi_device_software_node_port *remote_port; + struct software_node *local_node, *remote_node; + unsigned int local_index, remote_index; + unsigned int bus_type; + + remote_swnodes = crs_csi2_swnode_get(inst->remote_handle); + if (WARN_ON_ONCE(!remote_swnodes)) + continue; + + local_index = next_csi2_port_index(local_swnodes, inst->csi2.local_port_instance); + remote_index = next_csi2_port_index(remote_swnodes, inst->csi2.resource_source.index); + + if (WARN_ON_ONCE(local_index >= local_swnodes->num_ports) || + WARN_ON_ONCE(remote_index >= remote_swnodes->num_ports)) + goto out_free; + + switch (inst->csi2.phy_type) { + case ACPI_CRS_CSI2_PHY_TYPE_C: + bus_type = V4L2_FWNODE_BUS_TYPE_CSI2_CPHY; + break; + case ACPI_CRS_CSI2_PHY_TYPE_D: + bus_type = V4L2_FWNODE_BUS_TYPE_CSI2_DPHY; + break; + default: + acpi_handle_info(handle, + "ignoring CSI-2 PHY type %u\n", + inst->csi2.phy_type); + continue; + } + + local_port = &local_swnodes->ports[local_index]; + local_node = &local_swnodes->nodes[ACPI_DEVICE_SWNODE_EP(local_index)]; + local_port->remote_ep_ref[0] = SOFTWARE_NODE_REFERENCE(local_node); + local_port->crs_csi2_local = true; + + remote_port = &remote_swnodes->ports[remote_index]; + remote_node = &remote_swnodes->nodes[ACPI_DEVICE_SWNODE_EP(remote_index)]; + remote_port->remote_ep_ref[0] = SOFTWARE_NODE_REFERENCE(remote_node); + + local_port->ep_props[ACPI_DEVICE_SWNODE_EP_REMOTE_EP] = + PROPERTY_ENTRY_REF_ARRAY("remote-endpoint", + remote_port->remote_ep_ref); + local_port->ep_props[ACPI_DEVICE_SWNODE_EP_BUS_TYPE] = + PROPERTY_ENTRY_U32("bus-type", bus_type); + local_port->ep_props[ACPI_DEVICE_SWNODE_EP_REG] = + PROPERTY_ENTRY_U32("reg", 0); + local_port->port_props[ACPI_DEVICE_SWNODE_PRT_REG] = + PROPERTY_ENTRY_U32("reg", inst->csi2.local_port_instance); + if (GRAPH_PORT_NAME(local_port->port_name, + inst->csi2.local_port_instance)) + acpi_handle_warn(handle, + "name for local port %u too long", + inst->csi2.local_port_instance); + + remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_REMOTE_EP] = + PROPERTY_ENTRY_REF_ARRAY("remote-endpoint", local_port->remote_ep_ref); + remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_BUS_TYPE] = + PROPERTY_ENTRY_U32("bus-type", bus_type); + remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_REG] = + PROPERTY_ENTRY_U32("reg", 0); + remote_port->port_props[ACPI_DEVICE_SWNODE_PRT_REG] = + PROPERTY_ENTRY_U32("reg", + inst->csi2.resource_source.index); + if (GRAPH_PORT_NAME(remote_port->port_name, + inst->csi2.resource_source.index)) + acpi_handle_warn(handle, + "name for remote port %u too long", + inst->csi2.resource_source.index); + } + } + +out_free: kfree(handle_refs); crs_csi2_release(&crs_csi2_handles); } + +/* + * Get the index of the next property in the property array, with a given + * maximum values. + */ +#define NEXT_PROPERTY(index, max) \ + (WARN_ON(++(index) > ACPI_DEVICE_SWNODE_##max + 1) ? \ + ACPI_DEVICE_SWNODE_##max : (index) - 1) + +static struct fwnode_handle *get_mipi_port_handle(struct acpi_device *device, + unsigned int port) +{ + static const char mipi_port_prefix[] = "mipi-img-port-"; + char mipi_port_name[sizeof(mipi_port_prefix) + 2]; + + if (snprintf(mipi_port_name, sizeof(mipi_port_name), "%s%u", + mipi_port_prefix, port) > sizeof(mipi_port_name)) { + acpi_handle_info(acpi_device_handle(device), + "mipi port name too long for port %u\n", port); + return NULL; + } + + return fwnode_get_named_child_node(acpi_fwnode_handle(device), + mipi_port_name); +} + +static void init_port_csi2_common(struct acpi_device *device, + struct fwnode_handle *mipi_port_fwnode, + unsigned int *ep_prop_index, + unsigned int port_nr) +{ + unsigned int port_index = next_csi2_port_index(device->swnodes, port_nr); + struct acpi_device_software_nodes *ads = device->swnodes; + struct acpi_device_software_node_port *port = &ads->ports[port_index]; + unsigned int num_lanes = 0; + union { + u32 val; + /* Data lanes + the clock lane */ + u8 val8[BITS_TO_BYTES(ARRAY_SIZE(port->data_lanes) + 1)]; + } u; + int ret; + + *ep_prop_index = ACPI_DEVICE_SWNODE_EP_CLOCK_LANES; + + if (GRAPH_PORT_NAME(port->port_name, port_nr)) + return; + + ads->nodes[ACPI_DEVICE_SWNODE_PRT(port_index)] = + SOFTWARE_NODE(port->port_name, port->port_props, + &ads->nodes[ACPI_DEVICE_SWNODE_ROOT]); + + ret = fwnode_property_read_u8(mipi_port_fwnode, "mipi-img-clock-lane", + u.val8); + if (!ret) { + port->ep_props[NEXT_PROPERTY(*ep_prop_index, EP_CLOCK_LANES)] = + PROPERTY_ENTRY_U32("clock-lanes", *u.val8); + } + ret = fwnode_property_count_u8(mipi_port_fwnode, "mipi-img-data-lanes"); + if (ret > 0) { + num_lanes = ret; + + if (num_lanes > ARRAY_SIZE(port->data_lanes)) { + acpi_handle_warn(acpi_device_handle(device), + "too many data lanes (%u)\n", + num_lanes); + num_lanes = ARRAY_SIZE(port->data_lanes); + } + + ret = fwnode_property_read_u8_array(mipi_port_fwnode, + "mipi-img-data-lanes", + u.val8, num_lanes); + if (!ret) { + unsigned int i; + + for (i = 0; i < num_lanes; i++) + port->data_lanes[i] = u.val8[i]; + + port->ep_props[NEXT_PROPERTY(*ep_prop_index, + EP_DATA_LANES)] = + PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes", + port->data_lanes, + num_lanes); + } + } + ret = fwnode_property_read_u8_array(mipi_port_fwnode, + "mipi-img-lane-polarities", + u.val8, sizeof(u.val8)); + if (ret > 0) { + unsigned int bytes = ret; + + /* Total number of lanes here is clock lane + data lanes */ + if (bytes << 3 >= 1 + num_lanes) { + unsigned int i; + + /* Move polarity bits to the lane polarity u32 array */ + for (i = 0; i < 1 + num_lanes; i++) + port->lane_polarities[i] = + (u.val8[i >> 3] & (1 << (i & 7))) ? + 1U : 0U; + + port->ep_props[NEXT_PROPERTY(*ep_prop_index, + EP_LANE_POLARITIES)] = + PROPERTY_ENTRY_U32_ARRAY_LEN("lane-polarities", + port->lane_polarities, + 1 + num_lanes); + } else { + acpi_handle_warn(acpi_device_handle(device), + "too few lane polarity bytes (%u)\n", + bytes); + } + } + + ads->nodes[ACPI_DEVICE_SWNODE_EP(port_index)] = + SOFTWARE_NODE("endpoint@0", ads->ports[port_index].ep_props, + &ads->nodes[ACPI_DEVICE_SWNODE_PRT(port_index)]); +} + +static void init_port_csi2_local(struct acpi_device *device, + unsigned int port_nr) +{ + unsigned int port_index = next_csi2_port_index(device->swnodes, + port_nr); + struct fwnode_handle *mipi_port_fwnode = + get_mipi_port_handle(device, port_nr); + struct acpi_device_software_node_port *port = + &device->swnodes->ports[port_index]; + unsigned int ep_prop_index; + int ret; + + init_port_csi2_common(device, mipi_port_fwnode, &ep_prop_index, port_nr); + + ret = fwnode_property_count_u64(mipi_port_fwnode, "mipi-img-link-frequencies"); + if (ret > 0) { + unsigned int num_link_freqs = ret; + + if (num_link_freqs > ARRAY_SIZE(port->link_frequencies)) { + acpi_handle_info(acpi_device_handle(device), + "too many link frequencies %u\n", + num_link_freqs); + num_link_freqs = ARRAY_SIZE(port->link_frequencies); + } + + ret = fwnode_property_read_u64_array(mipi_port_fwnode, + "mipi-img-link-frequencies", + port->link_frequencies, + num_link_freqs); + if (!ret) + port->ep_props[NEXT_PROPERTY(ep_prop_index, + EP_LINK_FREQUENCIES)] = + PROPERTY_ENTRY_U64_ARRAY_LEN("link-frequencies", + port->link_frequencies, + num_link_freqs); + else + acpi_handle_info(acpi_device_handle(device), + "can't get link frequencies (%d)\n", + ret); + } + + fwnode_handle_put(mipi_port_fwnode); +} + +static void init_port_csi2_remote(struct acpi_device *device, + unsigned int port_nr) +{ + struct fwnode_handle *mipi_port_fwnode = get_mipi_port_handle(device, port_nr); + unsigned int ep_prop_index; + + init_port_csi2_common(device, mipi_port_fwnode, &ep_prop_index, port_nr); + + fwnode_handle_put(mipi_port_fwnode); +} + +/** + * acpi_init_swnodes - Set up software nodes for properties gathered elsewhere + * + * @device: ACPI device for which the software nodes are initialised + * + * Initialise and register software nodes for properties for which the data is + * gathered elsewhere, e.g. _CRS CSI-2 descriptors. The process itself takes + * place before this function is called. + * + * acpi_scan_lock in scan.c must be held when calling this function. + */ +void acpi_init_swnodes(struct acpi_device *device) +{ + struct acpi_device_software_nodes *ads; + struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER }; + unsigned int i; + int ret; + + device->swnodes = ads = crs_csi2_swnode_get(device->handle); + if (!ads) + return; + + if (acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK) { + acpi_handle_warn(acpi_device_handle(device), "cannot get path name\n"); + return; + } + + ads->nodes[ACPI_DEVICE_SWNODE_ROOT] = (struct software_node) { + .name = buffer.pointer, + .properties = ads->dev_props, + }; + + for (i = 0; i < ads->num_ports; i++) { + struct acpi_device_software_node_port *port = &ads->ports[i]; + + if (port->crs_csi2_local) + init_port_csi2_local(device, port->port_nr); + else + init_port_csi2_remote(device, port->port_nr); + } + + ret = software_node_register_node_group(ads->nodeptrs); + if (ret < 0) { + acpi_handle_warn(acpi_device_handle(device), + "cannot register software nodes (%d)!\n", ret); + device->swnodes = NULL; + return; + } + + device->fwnode.secondary = software_node_fwnode(ads->nodes); +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 50de874b8f208..29ef8200b50bb 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -449,10 +449,26 @@ static void acpi_free_power_resources_lists(struct acpi_device *device) } } +static void acpi_free_swnodes(struct acpi_device *device) +{ + struct acpi_device_software_nodes *ads = device->swnodes; + + if (!ads) + return; + + software_node_unregister_node_group(ads->nodeptrs); + set_secondary_fwnode(&device->dev, NULL); + kfree(ads->nodes[ACPI_DEVICE_SWNODE_ROOT].name); + kfree(ads); + + device->swnodes = NULL; +} + static void acpi_device_release(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); + acpi_free_swnodes(acpi_dev); acpi_free_properties(acpi_dev); acpi_free_pnp_ids(&acpi_dev->pnp); acpi_free_power_resources_lists(acpi_dev); @@ -1771,6 +1787,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, acpi_device_get_busid(device); acpi_set_pnp_ids(handle, &device->pnp, type); acpi_init_properties(device); + acpi_init_swnodes(device); acpi_bus_get_flags(device); device->flags.match_driver = false; device->flags.initialized = true; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a05fe22c1175c..9a7729e96d14c 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -360,8 +360,54 @@ struct acpi_device_data { struct acpi_gpio_mapping; +enum acpi_device_swnode_dev_props { + ACPI_DEVICE_SWNODE_DEV_NUM_OF, + ACPI_DEVICE_SWNODE_DEV_NUM_ENTRIES +}; + +enum acpi_device_swnode_port_props { + ACPI_DEVICE_SWNODE_PRT_REG, + ACPI_DEVICE_SWNODE_PRT_NUM_OF, + ACPI_DEVICE_SWNODE_PRT_NUM_ENTRIES +}; + +enum acpi_device_swnode_ep_props { + ACPI_DEVICE_SWNODE_EP_REMOTE_EP, + ACPI_DEVICE_SWNODE_EP_BUS_TYPE, + ACPI_DEVICE_SWNODE_EP_REG, + ACPI_DEVICE_SWNODE_EP_CLOCK_LANES, + ACPI_DEVICE_SWNODE_EP_DATA_LANES, + ACPI_DEVICE_SWNODE_EP_LANE_POLARITIES, + /* TX only */ + ACPI_DEVICE_SWNODE_EP_LINK_FREQUENCIES, + ACPI_DEVICE_SWNODE_EP_NUM_OF, + ACPI_DEVICE_SWNODE_EP_NUM_ENTRIES +}; + +#define ACPI_DEVICE_SWNODE_ROOT 0 +/* + * Each device has a root swnode plus two times as many nodes as the + * number of CSI-2 ports. + */ +#define ACPI_DEVICE_SWNODE_PRT(port) (1 + 2 * (port)) +#define ACPI_DEVICE_SWNODE_EP(endpoint) \ + (ACPI_DEVICE_SWNODE_PRT(endpoint) + 1) + +#define ACPI_DEVICE_SWNODE_CSI2_DATA_LANES 4 + struct acpi_device_software_node_port { + char port_name[8]; + u32 data_lanes[ACPI_DEVICE_SWNODE_CSI2_DATA_LANES]; + u32 lane_polarities[1 /* clock lane */ + + ACPI_DEVICE_SWNODE_CSI2_DATA_LANES]; + u64 link_frequencies[4]; unsigned int port_nr; + bool crs_csi2_local; + + struct property_entry port_props[ACPI_DEVICE_SWNODE_PRT_NUM_ENTRIES]; + struct property_entry ep_props[ACPI_DEVICE_SWNODE_EP_NUM_ENTRIES]; + + struct software_node_ref_args remote_ep_ref[1]; }; struct acpi_device_software_nodes { @@ -369,6 +415,8 @@ struct acpi_device_software_nodes { struct software_node *nodes; const struct software_node **nodeptrs; unsigned int num_ports; + + struct property_entry dev_props[ACPI_DEVICE_SWNODE_DEV_NUM_ENTRIES]; }; /* Device */ @@ -377,6 +425,7 @@ struct acpi_device { int device_type; acpi_handle handle; /* no handle for fixed hardware */ struct fwnode_handle fwnode; + struct acpi_device_software_nodes *swnodes; struct list_head wakeup_list; struct list_head del_list; struct acpi_device_status status; From patchwork Tue Jan 17 12:22:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643707 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B7C0C678D4 for ; Tue, 17 Jan 2023 12:22:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236310AbjAQMWX (ORCPT ); Tue, 17 Jan 2023 07:22:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236321AbjAQMWT (ORCPT ); Tue, 17 Jan 2023 07:22:19 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E5E332BF1E; Tue, 17 Jan 2023 04:22:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958138; x=1705494138; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iDSZujq+XtQrKm1vvqwkNrtKdKJtrb4ZIduGHFaghws=; b=aU3ExtznnZHv24hd1WkvY0QF6BAEW7zVjaRHb/7vQbgAjUCsc2Bo0FZL E/QhOn/U+Wgu9ojJQ7FWtusNnQQdDdLx0okD0ZzoxmFXKOImCyTWdsfrv r3qp1MwKT+iF6HZcCXqmOVvTWUjGmfbh/air7Nxe0k4gT7e1siHpejUHJ YA6vtpbOKgi7eXehLkl0DIyY+1ioJ+e9NPuZXK1TdHc52cxd2g1sJ9z4R dRf+FNWRk23NLcKEhvXtNBoBamHedMMNWHKj/8Y+6Onu5+hsEuyhYFCmF jMnAL7RYBuhGdkjJVDp0QThv8JjE80bLHY5lGsF7jnIQB6BV8QqbZvP3p w==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920113" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920113" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:18 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772043" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772043" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:17 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id 047612093B; Tue, 17 Jan 2023 14:22:12 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgVJ-Ph; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 5/8] ACPI: property: Dig "rotation" property for devices with CSI2 _CRS Date: Tue, 17 Jan 2023 14:22:41 +0200 Message-Id: <20230117122244.2546597-6-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Dig "rotation" property value for devices with _CRS CSI2 resource descriptor. The value comes from _PLD (physical location of device) object, if it exists for the device. This way camera sensor drivers that know the "rotation" property do not need to care about _PLD on ACPI. Signed-off-by: Sakari Ailus --- drivers/acpi/mipi.c | 17 +++++++++++++++++ include/acpi/acpi_bus.h | 1 + 2 files changed, 18 insertions(+) diff --git a/drivers/acpi/mipi.c b/drivers/acpi/mipi.c index cc80d79f4a381..bd09eac0a52e4 100644 --- a/drivers/acpi/mipi.c +++ b/drivers/acpi/mipi.c @@ -632,15 +632,32 @@ static void init_port_csi2_remote(struct acpi_device *device, */ void acpi_init_swnodes(struct acpi_device *device) { + struct fwnode_handle *fwnode = acpi_fwnode_handle(device); struct acpi_device_software_nodes *ads; struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER }; + struct acpi_pld_info *pld; + unsigned int prop_index = 0; unsigned int i; + u32 val; int ret; device->swnodes = ads = crs_csi2_swnode_get(device->handle); if (!ads) return; + /* + * Check if "rotation" property exists and if it doesn't but there's a + * _PLD object, then get the rotation value from there. + */ + if (fwnode_property_read_u32(fwnode, "rotation", &val) && + acpi_get_physical_device_location(acpi_device_handle(device), + &pld) == AE_OK) { + ads->dev_props[NEXT_PROPERTY(prop_index, DEV_ROTATION)] = + PROPERTY_ENTRY_U32("rotation", + (u32)pld->rotation * 45U); + kfree(pld); + } + if (acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK) { acpi_handle_warn(acpi_device_handle(device), "cannot get path name\n"); return; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 9a7729e96d14c..3c4a1daed33f1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -361,6 +361,7 @@ struct acpi_device_data { struct acpi_gpio_mapping; enum acpi_device_swnode_dev_props { + ACPI_DEVICE_SWNODE_DEV_ROTATION, ACPI_DEVICE_SWNODE_DEV_NUM_OF, ACPI_DEVICE_SWNODE_DEV_NUM_ENTRIES }; From patchwork Tue Jan 17 12:22:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643706 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71918C3DA78 for ; Tue, 17 Jan 2023 12:22:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236693AbjAQMWY (ORCPT ); Tue, 17 Jan 2023 07:22:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51250 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236589AbjAQMWV (ORCPT ); Tue, 17 Jan 2023 07:22:21 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 612002BF1D; Tue, 17 Jan 2023 04:22:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958140; x=1705494140; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hG18mLyYc1176oRVzTIz/UPqRlbH7NKsdxCEPctBXyk=; b=SVg7tyerQRlFwSsIqFfBeBm9ta0sDehrB/xihHInEd0YymvYHxrve4Ub Q+V+l0IO0sy8By+NLq8dqzDAUFv+BCuksyfGeu2I+BuMt6PxD124SSzWr YYRzQAOTbtqbYYs45/Hu0NndLLffcr0R7Hcg13M4quonK9ond4b2sle7L 3YPIDshXrfhnHhknaNdlNvY34ER7TXy815Fzyf1mhRYNjcNKKGFWJApZr 977lE8+ZfjbYJ+ZqWM1+KFsMuNurL5Ffozb4MydRc9iRAvSWXHQjX4g9g 60zzzusor4zLdNFgkYqpnKSAGaltF2/M5ha2zdiTN+H33bgACvngif8WY Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920120" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920120" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:18 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772042" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772042" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:17 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id 11267209C7; Tue, 17 Jan 2023 14:22:12 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgVM-RQ; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 6/8] ACPI: property: Rename parsed MIPI DisCo for Imaging properties Date: Tue, 17 Jan 2023 14:22:42 +0200 Message-Id: <20230117122244.2546597-7-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org MIPI DisCo for Imaging defines properties for sensor-adjacent devices such as EEPROM, LED flash or lens VCM as either device or sub-node references. This is compliant with existing DT definitions apart from property names. Rename parsed MIPI-defined properties so drivers will have a unified view of them as defined in DT and already parsed by drivers. This can be done in-place as the MIPI-defined property strings are always longer than the DT one. This also results in loss of constness in parser function arguments. Individual bindings to devices could define the references differently between MIPI DisCo for Imaging and DT, in terms of device or sub-node references. This will still need to be handled in the drivers themselves. Signed-off-by: Sakari Ailus --- drivers/acpi/internal.h | 1 + drivers/acpi/mipi.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/acpi/property.c | 20 +++++++++++--------- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index fac87404e294c..f107094bfe16f 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -289,5 +289,6 @@ static inline void acpi_init_lpit(void) { } void acpi_crs_csi2_swnodes_del_free(void); void acpi_bus_scan_crs_csi2(acpi_handle handle); void acpi_init_swnodes(struct acpi_device *device); +void acpi_properties_prepare_mipi(union acpi_object *elements); #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/mipi.c b/drivers/acpi/mipi.c index bd09eac0a52e4..2174e03a2eafd 100644 --- a/drivers/acpi/mipi.c +++ b/drivers/acpi/mipi.c @@ -687,3 +687,40 @@ void acpi_init_swnodes(struct acpi_device *device) device->fwnode.secondary = software_node_fwnode(ads->nodes); } + +static const struct mipi_disco_prop { + const char *mipi_prop; + const char *dt_prop; +} mipi_disco_props[] = { + { "mipi-img-lens-focus", "lens-focus" }, + { "mipi-img-flash-leds", "flash-leds" }, + { "mipi-img-clock-frequency", "clock-frequency" }, + { "mipi-img-led-max-current", "led-max-microamp" }, + { "mipi-img-flash-max-current", "flash-max-microamp" }, + { "mipi-img-flash-max-timeout", "flash-max-timeout-us" }, +}; + +/** + * acpi_properties_prepare_mipi - Rename MIPI properties as commin DT ones + * + * @elements: ACPI object containing _DSD properties for a device node + * + * Renames MIPI-defined properties as common DT ones. The pre-requisite is that + * the names of all such MIPI properties are no longer than the corresponding DT + * ones. + */ +void acpi_properties_prepare_mipi(union acpi_object *elements) +{ + unsigned int i; + + /* Replace MIPI DisCo for Imaging property names with DT equivalents. */ + for (i = 0; i < ARRAY_SIZE(mipi_disco_props); i++) { + if (!strcmp(mipi_disco_props[i].mipi_prop, + elements[0].string.pointer)) { + WARN_ON(strscpy(elements[0].string.pointer, + mipi_disco_props[i].dt_prop, + elements[0].string.length) < 0); + break; + } + } +} diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 545f74673703d..92fdc2adcac3d 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -121,7 +121,7 @@ static bool acpi_nondev_subnode_extract(union acpi_object *desc, } static bool acpi_nondev_subnode_data_ok(acpi_handle handle, - const union acpi_object *link, + union acpi_object *link, struct list_head *list, struct fwnode_handle *parent) { @@ -142,7 +142,7 @@ static bool acpi_nondev_subnode_data_ok(acpi_handle handle, } static bool acpi_nondev_subnode_ok(acpi_handle scope, - const union acpi_object *link, + union acpi_object *link, struct list_head *list, struct fwnode_handle *parent) { @@ -273,22 +273,24 @@ static bool acpi_property_value_ok(const union acpi_object *value) return false; } -static bool acpi_properties_format_valid(const union acpi_object *properties) +static bool acpi_properties_prepare(union acpi_object *properties) { - int i; + unsigned int i; for (i = 0; i < properties->package.count; i++) { - const union acpi_object *property; + union acpi_object *property = &properties->package.elements[i]; + union acpi_object *elements = property->package.elements; - property = &properties->package.elements[i]; /* * Only two elements allowed, the first one must be a string and * the second one has to satisfy certain conditions. */ if (property->package.count != 2 - || property->package.elements[0].type != ACPI_TYPE_STRING - || !acpi_property_value_ok(&property->package.elements[1])) + || elements[0].type != ACPI_TYPE_STRING + || !acpi_property_value_ok(&elements[1])) return false; + + acpi_properties_prepare_mipi(elements); } return true; } @@ -520,7 +522,7 @@ static bool acpi_extract_properties(acpi_handle scope, union acpi_object *desc, * We found the matching GUID. Now validate the format of the * package immediately following it. */ - if (!acpi_properties_format_valid(properties)) + if (!acpi_properties_prepare(properties)) continue; acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer, From patchwork Tue Jan 17 12:22:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4AA65C677F1 for ; Tue, 17 Jan 2023 12:22:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236702AbjAQMW0 (ORCPT ); Tue, 17 Jan 2023 07:22:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236509AbjAQMWU (ORCPT ); Tue, 17 Jan 2023 07:22:20 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 839FC3253F; Tue, 17 Jan 2023 04:22:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958139; x=1705494139; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0wsDAlznAxVzy0N03kzsPUdve6FSq9whygJ1bNbbiDM=; b=YVqzncnJfL6LhwTs9/ksMJmYzM+Zff/G0T1WKJzzteB1wRVaUs4lDxKh FJAQrmOOn/5BB4snxMux/DZPTB5ATljGaapZDmpfXO1Oda9Ei0lVzdGHs HRgEuB+gafDTOiBKZht+YKykVL/R5M68kmYyVCFtMflCFuP0+SuP7rZLQ 83mvvMpPbZnJUApP9Dcqsmdq0RttQwzjVS/El+0RhJG4GQghi3LtROegf XuPB63aIPyJ4giKB+psrFdsXRDu9LsKz08CBiJbmPF43+ql9mQ7VkPZYA Cc2BxF3EcN7RJCyPZNsTKMqNWOZqH9v51uef1MVleJrvsvNZuycnhnXqg g==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920116" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920116" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:18 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772044" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772044" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:17 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id 1D8B120B78; Tue, 17 Jan 2023 14:22:12 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgVQ-Sz; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 7/8] ACPI: property: Skip MIPI property table without "mipi-img" prefix Date: Tue, 17 Jan 2023 14:22:43 +0200 Message-Id: <20230117122244.2546597-8-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org For all _DSD properties, skip going through the MIPI DisCo for Imaging property name substitution table if the property doesn't have "mipi-img-" prefix. Signed-off-by: Sakari Ailus --- drivers/acpi/mipi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/mipi.c b/drivers/acpi/mipi.c index 2174e03a2eafd..840f565b1906f 100644 --- a/drivers/acpi/mipi.c +++ b/drivers/acpi/mipi.c @@ -688,16 +688,18 @@ void acpi_init_swnodes(struct acpi_device *device) device->fwnode.secondary = software_node_fwnode(ads->nodes); } +#define MIPI_IMG_PREFIX "mipi-img-" + static const struct mipi_disco_prop { const char *mipi_prop; const char *dt_prop; } mipi_disco_props[] = { - { "mipi-img-lens-focus", "lens-focus" }, - { "mipi-img-flash-leds", "flash-leds" }, - { "mipi-img-clock-frequency", "clock-frequency" }, - { "mipi-img-led-max-current", "led-max-microamp" }, - { "mipi-img-flash-max-current", "flash-max-microamp" }, - { "mipi-img-flash-max-timeout", "flash-max-timeout-us" }, + { MIPI_IMG_PREFIX "lens-focus", "lens-focus" }, + { MIPI_IMG_PREFIX "flash-leds", "flash-leds" }, + { MIPI_IMG_PREFIX "clock-frequency", "clock-frequency" }, + { MIPI_IMG_PREFIX "led-max-current", "led-max-microamp" }, + { MIPI_IMG_PREFIX "flash-max-current", "flash-max-microamp" }, + { MIPI_IMG_PREFIX "flash-max-timeout", "flash-max-timeout-us" }, }; /** @@ -713,6 +715,10 @@ void acpi_properties_prepare_mipi(union acpi_object *elements) { unsigned int i; + if (memcmp(elements[0].string.pointer, MIPI_IMG_PREFIX, + sizeof(MIPI_IMG_PREFIX) - 1)) + return; + /* Replace MIPI DisCo for Imaging property names with DT equivalents. */ for (i = 0; i < ARRAY_SIZE(mipi_disco_props); i++) { if (!strcmp(mipi_disco_props[i].mipi_prop, From patchwork Tue Jan 17 12:22:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 643441 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0AD8C678D4 for ; Tue, 17 Jan 2023 12:22:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232630AbjAQMWZ (ORCPT ); Tue, 17 Jan 2023 07:22:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51246 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236588AbjAQMWU (ORCPT ); Tue, 17 Jan 2023 07:22:20 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B30A2B297; Tue, 17 Jan 2023 04:22:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673958140; x=1705494140; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NKpBwl2Zc7SvCzkgs3bIn5JXfGjCH7WGccSr7o72C24=; b=EwAnTEiqwOjrxWaPYqvQRvNPyOgUsqu6kjuYPyBwkYwA3P0cY/r8vs12 mcCe7LdHATgFIEnc5lW6q+4d/GxMf2Z2lJTesdRxKauH24ZsytoQb0f5T MSbGLpFTHmYPLg0onfJp3mQhck5xyKfBwW7rVIv8gEVIrqLrmJQtPJ29/ DGVUftOXnFy9Zq0eVdJTza6Y2gpw466ffOFLeUDHxC3ZGxhJDN2BAvJqk agAqrrVkhy1dW5ZwPVSZkA2IY8BI1cemkITMvh3cw4e4ZboAEG4m0Skdx LHHkC5yVgaqRI7J1n+Z4AcCyW3Tpcjtk0s3L1yY9ZXiPzcCr2gWke2/U+ w==; X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="410920118" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="410920118" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:18 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10592"; a="727772045" X-IronPort-AV: E=Sophos;i="5.97,222,1669104000"; d="scan'208";a="727772045" Received: from punajuuri.fi.intel.com (HELO paasikivi.fi.intel.com) ([10.237.72.43]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2023 04:22:17 -0800 Received: from punajuuri.localdomain (punajuuri.localdomain [192.168.240.130]) by paasikivi.fi.intel.com (Postfix) with ESMTP id 27E3E20B97; Tue, 17 Jan 2023 14:22:12 +0200 (EET) Received: from sailus by punajuuri.localdomain with local (Exim 4.94.2) (envelope-from ) id 1pHkzE-00AgVU-UO; Tue, 17 Jan 2023 14:22:44 +0200 From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: rafael@kernel.org, linux-media@vger.kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH 8/8] ACPI: property: Document _CRS CSI-2 and DisCo for Imaging support Date: Tue, 17 Jan 2023 14:22:44 +0200 Message-Id: <20230117122244.2546597-9-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> References: <20230117122244.2546597-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Document how ACPI _CRS CSI-2 and DisCo for Imaging works. It's non-trivial so such documentation can be useful. Signed-off-by: Sakari Ailus --- drivers/acpi/mipi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/acpi/mipi.c b/drivers/acpi/mipi.c index 840f565b1906f..f20851400c041 100644 --- a/drivers/acpi/mipi.c +++ b/drivers/acpi/mipi.c @@ -3,6 +3,43 @@ * MIPI DisCo for Imaging support. * * Copyright (C) 2022 Intel Corporation + * + * _CRS CSI-2 descriptors, as defined starting from ACPI 6.4 [1], contain + * information on cross-device CSI-2 bus configuration. The descriptors are + * located under transmitter devices, and the receiver devices have no direct + * way to access them even if the information in these descriptors is equally + * important for receivers. This information is amended with MIPI DisCo for + * Imaging [2] specification that defines _DSD data nodes and properties. + * + * The support for these is based on two-fold approach, firstly renaming + * properties where semantics matches and secondly gathering information to + * generate properties using information gathered from various sources. The + * former is trivial (see acpi_properties_prepare_mipi() at the end of the + * file) whereas the latter requires a more elaborate explanation. + * + * acpi_bus_scan_crs_csi2() scans an ACPI bus for devices with _CRS CSI-2 + * descriptors and stores them to a linked list. This is done as traversing just + * this list is much smaller task than the entire DSDT. This list is then used + * to figure out how much memory is needed for swnodes related to a given ACPI + * device (handle). Further on, the same function sets the property values for + * the properties the values of which are obtained from the _CRS CSI-2 + * descriptor. The information is stored into another list where the information + * can be looked up based on device's acpi_handle as the struct acpi_device + * isn't available yet at this point (and could not, as cross-device references + * need to be set up before the devices are available for drivers to probe). + * + * For each struct acpi_device, acpi_init_swnodes() further obtains information + * required to find out the values for the rest of the properties needed by + * drivers. This includes all port and endpoint properties as the node + * structures used by DT graphs and DisCo for Imaging are different. Finally the + * function registers software nodes for the device and sets the secondary + * pointer for the ACPI device's fwnode. + * + * Access to data the structures is serialised using acpi_scan_lock in scan.c. + * + * [1] https://uefi.org/sites/default/files/resources/ACPI_Spec_6_4_Jan22.pdf + * + * [2] https://www.mipi.org/specifications/mipi-disco-imaging */ #include