From patchwork Thu Nov 25 16:53:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518446 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 D25EDC433EF for ; Thu, 25 Nov 2021 16:56:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242503AbhKYQ7q (ORCPT ); Thu, 25 Nov 2021 11:59:46 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:41630 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344276AbhKYQ5p (ORCPT ); Thu, 25 Nov 2021 11:57:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=k9bEnJSLw0b1m9mNcKIvp37nfxiJYGtI8n2PBiX7Wj4=; b=Tuok1w0cqQopoK7Bvs5yh4alxZRtGacp0YU6NxyGepDy8UfWX97F9nTxQJQcudUjkjzU7t zNKGnXe1MZndw24GyZS3xkETQ3sgkmtJx/jxA1aBRlVg87VkI8l2b88PyrgZEHRQMrsCUe 2fsJlYaJ3VbNom0PUDcRS8DBA7APKMM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-587-np-AMbiWMCmsN6HlSWpBmA-1; Thu, 25 Nov 2021 11:54:30 -0500 X-MC-Unique: np-AMbiWMCmsN6HlSWpBmA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4830083DD20; Thu, 25 Nov 2021 16:54:27 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2289560657; Thu, 25 Nov 2021 16:54:22 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org, Wolfram Sang , "Rafael J . Wysocki" , Andy Shevchenko Subject: [PATCH v6 02/15] i2c: acpi: Use acpi_dev_ready_for_enumeration() helper Date: Thu, 25 Nov 2021 17:53:59 +0100 Message-Id: <20211125165412.535063-3-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around cases where this info is not present in the firmware tables, which is often the case on x86/ACPI devices, both frameworks allow the provider-driver to attach info about consumers to the clks/regulators when registering these. This causes problems with the probe ordering wrt drivers for consumers of these clks/regulators. Since the lookups are only registered when the provider-driver binds, trying to get these clks/regulators before then results in a -ENOENT error for clks and a dummy regulator for regulators. To ensure the correct probe-ordering the ACPI core has code to defer the enumeration of consumers affected by this until the providers are ready. Call the new acpi_dev_ready_for_enumeration() helper to avoid enumerating / instantiating i2c-clients too early. Acked-by: Wolfram Sang Acked-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- drivers/i2c/i2c-core-acpi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 92c1cc07ed46..04338cbd08a9 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, struct list_head resource_list; int ret; - if (acpi_bus_get_status(adev) || !adev->status.present) + if (acpi_bus_get_status(adev)) return -EINVAL; + if (!acpi_dev_ready_for_enumeration(adev)) + return -ENODEV; + if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0) return -ENODEV; From patchwork Thu Nov 25 16:54:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518445 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 4C99AC433F5 for ; Thu, 25 Nov 2021 16:56:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344961AbhKYQ74 (ORCPT ); Thu, 25 Nov 2021 11:59:56 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:22220 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345299AbhKYQ54 (ORCPT ); Thu, 25 Nov 2021 11:57:56 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859284; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LHXty0teCNrwp0jbSsS/mq9/Q9Dk+WtZuVrqWuYBzrk=; b=GgrICANxSNl9SHhx24notkHB90wR+BSQLDHVoI9LmW9yXJTTc0iKdIo/KMSQ2eFGFj2ngh g4CSsaYMAx8sI+Y8o85e13njtL2d8VRlCP3uLFFryb/tu1tc4Pxpo7R6kxNN7Nn6291UsA 5N8pds6kA4wkzhJapDtNSiQoWhF7wnY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-495-AbfChbHLNmK96KLLDHOJvA-1; Thu, 25 Nov 2021 11:54:41 -0500 X-MC-Unique: AbfChbHLNmK96KLLDHOJvA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3EED5185302A; Thu, 25 Nov 2021 16:54:38 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 39CDD57CA5; Thu, 25 Nov 2021 16:54:34 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org, Andy Shevchenko Subject: [PATCH v6 04/15] platform_data: Add linux/platform_data/tps68470.h file Date: Thu, 25 Nov 2021 17:54:01 +0100 Message-Id: <20211125165412.535063-5-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around cases where this info is not present in the firmware tables, which is often the case on x86/ACPI devices, both frameworks allow the provider-driver to attach info about consumers to the provider-device during probe/registration of the provider device. The TI TPS68470 PMIC is used x86/ACPI devices with the consumer-info missing from the ACPI tables. Thus the tps68470-clk and tps68470-regulator drivers must provide the consumer-info at probe time. Define tps68470_clk_platform_data and tps68470_regulator_platform_data structs to allow the x86 platform code to pass the necessary consumer info to these drivers. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- include/linux/platform_data/tps68470.h | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 include/linux/platform_data/tps68470.h diff --git a/include/linux/platform_data/tps68470.h b/include/linux/platform_data/tps68470.h new file mode 100644 index 000000000000..126d082c3f2e --- /dev/null +++ b/include/linux/platform_data/tps68470.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TI TPS68470 PMIC platform data definition. + * + * Copyright (c) 2021 Red Hat Inc. + * + * Red Hat authors: + * Hans de Goede + */ +#ifndef __PDATA_TPS68470_H +#define __PDATA_TPS68470_H + +enum tps68470_regulators { + TPS68470_CORE, + TPS68470_ANA, + TPS68470_VCM, + TPS68470_VIO, + TPS68470_VSIO, + TPS68470_AUX1, + TPS68470_AUX2, + TPS68470_NUM_REGULATORS +}; + +struct regulator_init_data; + +struct tps68470_regulator_platform_data { + const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS]; +}; + +struct tps68470_clk_platform_data { + const char *consumer_dev_name; + const char *consumer_con_id; +}; + +#endif From patchwork Thu Nov 25 16:54:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518444 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 458D8C433F5 for ; Thu, 25 Nov 2021 16:57:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356816AbhKYRAM (ORCPT ); Thu, 25 Nov 2021 12:00:12 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:56625 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237317AbhKYQ6I (ORCPT ); Thu, 25 Nov 2021 11:58:08 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859297; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wsb7KlrO3809+mCLm2p9t4R1qixwrmO0ViYxTZXad98=; b=gXNT1k9x+hWMw08PfyyvAIcIpvEq7u+hRJrtuIxVJG6TQQ0rz7ye9AUTt+e2jYXksIAcTB NtaBmNM4fH2wFF+s2I0ITrvYcVkHeGaGAezWxVFJ7ZkVoZUnaVXViSQx4klnc110Cb9IDM qfQoi4n+yUGwSRwFzRPf2nTEPkakFhc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-579-dqiEDo81PR-XqYznd74UrA-1; Thu, 25 Nov 2021 11:54:51 -0500 X-MC-Unique: dqiEDo81PR-XqYznd74UrA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2F927107AD62; Thu, 25 Nov 2021 16:54:49 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id C981467840; Thu, 25 Nov 2021 16:54:42 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org, Andy Shevchenko Subject: [PATCH v6 06/15] clk: Introduce clk-tps68470 driver Date: Thu, 25 Nov 2021 17:54:03 +0100 Message-Id: <20211125165412.535063-7-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The TPS68470 PMIC provides Clocks, GPIOs and Regulators. At present in the kernel the Regulators and Clocks are controlled by an OpRegion driver designed to work with power control methods defined in ACPI, but some platforms lack those methods, meaning drivers need to be able to consume the resources of these chips through the usual frameworks. This commit adds a driver for the clocks provided by the tps68470, and is designed to bind to the platform_device registered by the intel_skl_int3472 module. This is based on this out of tree driver written by Intel: https://github.com/intel/linux-intel-lts/blob/4.14/base/drivers/clk/clk-tps68470.c with various cleanups added. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- Chnages in v6: - Use CLK_SET_RATE_GATE flag - Move programming of dividers to tps68470_clk_set_rate() - Put struct clk_init_data tps68470_clk_initdata on the stack Changes in v5: - Small comment cleanups based on review from Andy Changes in v4: - Kconfig: select REGMAP_I2C, add || COMPILE_TEST, fix help text - tps68470_clk_prepare(): Wait for the PLL to lock before returning - tps68470_clk_unprepare(): Remove unnecesary clearing of divider regs - tps68470_clk_probe(): Use devm_clk_hw_register() - Misc. small cleanups Changes in v2: - Update the comment on why a subsys_initcall is used to register the drv - Fix trailing whitespice on line 100 --- drivers/clk/Kconfig | 8 ++ drivers/clk/Makefile | 1 + drivers/clk/clk-tps68470.c | 261 +++++++++++++++++++++++++++++++++++ include/linux/mfd/tps68470.h | 11 ++ 4 files changed, 281 insertions(+) create mode 100644 drivers/clk/clk-tps68470.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c5b3dc97396a..4e9098d79249 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -169,6 +169,14 @@ config COMMON_CLK_CDCE706 help This driver supports TI CDCE706 programmable 3-PLL clock synthesizer. +config COMMON_CLK_TPS68470 + tristate "Clock Driver for TI TPS68470 PMIC" + depends on I2C + depends on INTEL_SKL_INT3472 || COMPILE_TEST + select REGMAP_I2C + help + This driver supports the clocks provided by the TPS68470 PMIC. + config COMMON_CLK_CDCE925 tristate "Clock driver for TI CDCE913/925/937/949 devices" depends on I2C diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index e42312121e51..6b6a88ae1425 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o +obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o diff --git a/drivers/clk/clk-tps68470.c b/drivers/clk/clk-tps68470.c new file mode 100644 index 000000000000..e5fbefd6ac2d --- /dev/null +++ b/drivers/clk/clk-tps68470.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Clock driver for TPS68470 PMIC + * + * Copyright (c) 2021 Red Hat Inc. + * Copyright (C) 2018 Intel Corporation + * + * Authors: + * Hans de Goede + * Zaikuo Wang + * Tianshu Qiu + * Jian Xu Zheng + * Yuning Pu + * Antti Laakso + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TPS68470_CLK_NAME "tps68470-clk" + +#define to_tps68470_clkdata(clkd) \ + container_of(clkd, struct tps68470_clkdata, clkout_hw) + +static struct tps68470_clkout_freqs { + unsigned long freq; + unsigned int xtaldiv; + unsigned int plldiv; + unsigned int postdiv; + unsigned int buckdiv; + unsigned int boostdiv; +} clk_freqs[] = { +/* + * The PLL is used to multiply the crystal oscillator + * frequency range of 3 MHz to 27 MHz by a programmable + * factor of F = (M/N)*(1/P) such that the output + * available at the HCLK_A or HCLK_B pins are in the range + * of 4 MHz to 64 MHz in increments of 0.1 MHz. + * + * hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv) + * + * PLL_REF_CLK should be as close as possible to 100kHz + * PLL_REF_CLK = input clk / XTALDIV[7:0] + 30) + * + * PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320)) + * + * BOOST should be as close as possible to 2Mhz + * BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) * + * + * BUCK should be as close as possible to 5.2Mhz + * BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5) + * + * osc_in xtaldiv plldiv postdiv hclk_# + * 20Mhz 170 32 1 19.2Mhz + * 20Mhz 170 40 1 20Mhz + * 20Mhz 170 80 1 24Mhz + */ + { 19200000, 170, 32, 1, 2, 3 }, + { 20000000, 170, 40, 1, 3, 4 }, + { 24000000, 170, 80, 1, 4, 8 }, +}; + +struct tps68470_clkdata { + struct clk_hw clkout_hw; + struct regmap *regmap; + unsigned long rate; +}; + +static int tps68470_clk_is_prepared(struct clk_hw *hw) +{ + struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); + int val; + + if (regmap_read(clkdata->regmap, TPS68470_REG_PLLCTL, &val)) + return 0; + + return val & TPS68470_PLL_EN_MASK; +} + +static int tps68470_clk_prepare(struct clk_hw *hw) +{ + struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); + + regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, + (TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_A_SHIFT) | + (TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_B_SHIFT)); + + regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, + TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK); + + /* + * The PLLCTL reg lock bit is set by the PMIC after approx. 4ms and + * does not indicate a true lock, so just wait 4 ms. + */ + usleep_range(4000, 5000); + + return 0; +} + +static void tps68470_clk_unprepare(struct clk_hw *hw) +{ + struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); + + /* Disable clock first ... */ + regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, 0); + + /* ... and then tri-state the clock outputs. */ + regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, 0); +} + +static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); + + return clkdata->rate; +} + +/* + * This returns the index of the clk_freqs[] cfg with the closest rate for + * use in tps68470_clk_round_rate(). tps68470_clk_set_rate() checks that + * the rate of the returned cfg is an exact match. + */ +static unsigned int tps68470_clk_cfg_lookup(unsigned long rate) +{ + long diff, best_diff = LONG_MAX; + unsigned int i, best_idx = 0; + + for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) { + diff = clk_freqs[i].freq - rate; + if (diff == 0) + return i; + + diff = abs(diff); + if (diff < best_diff) { + best_diff = diff; + best_idx = i; + } + } + + return best_idx; +} + +static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned int idx = tps68470_clk_cfg_lookup(rate); + + return clk_freqs[idx].freq; +} + +static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); + unsigned int idx = tps68470_clk_cfg_lookup(rate); + + if (rate != clk_freqs[idx].freq) + return -EINVAL; + + regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, clk_freqs[idx].boostdiv); + regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, clk_freqs[idx].buckdiv); + regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT); + regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, clk_freqs[idx].xtaldiv); + regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, clk_freqs[idx].plldiv); + regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, clk_freqs[idx].postdiv); + regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV2, clk_freqs[idx].postdiv); + regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA); + + regmap_write(clkdata->regmap, TPS68470_REG_PLLCTL, + TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT | + TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT); + + clkdata->rate = rate; + + return 0; +} + +static const struct clk_ops tps68470_clk_ops = { + .is_prepared = tps68470_clk_is_prepared, + .prepare = tps68470_clk_prepare, + .unprepare = tps68470_clk_unprepare, + .recalc_rate = tps68470_clk_recalc_rate, + .round_rate = tps68470_clk_round_rate, + .set_rate = tps68470_clk_set_rate, +}; + +static int tps68470_clk_probe(struct platform_device *pdev) +{ + struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data; + struct clk_init_data tps68470_clk_initdata = { + .name = TPS68470_CLK_NAME, + .ops = &tps68470_clk_ops, + /* Changing the dividers when the PLL is on is not allowed */ + .flags = CLK_SET_RATE_GATE, + }; + struct tps68470_clkdata *tps68470_clkdata; + int ret; + + tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata), + GFP_KERNEL); + if (!tps68470_clkdata) + return -ENOMEM; + + tps68470_clkdata->regmap = dev_get_drvdata(pdev->dev.parent); + tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata; + + /* Set initial rate */ + tps68470_clk_set_rate(&tps68470_clkdata->clkout_hw, clk_freqs[0].freq, 0); + + ret = devm_clk_hw_register(&pdev->dev, &tps68470_clkdata->clkout_hw); + if (ret) + return ret; + + ret = devm_clk_hw_register_clkdev(&pdev->dev, &tps68470_clkdata->clkout_hw, + TPS68470_CLK_NAME, NULL); + if (ret) + return ret; + + if (pdata) { + ret = devm_clk_hw_register_clkdev(&pdev->dev, + &tps68470_clkdata->clkout_hw, + pdata->consumer_con_id, + pdata->consumer_dev_name); + } + + return ret; +} + +static struct platform_driver tps68470_clk_driver = { + .driver = { + .name = TPS68470_CLK_NAME, + }, + .probe = tps68470_clk_probe, +}; + +/* + * The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers + * registering before the drivers for the camera-sensors which use them bind. + * subsys_initcall() ensures this when the drivers are builtin. + */ +static int __init tps68470_clk_init(void) +{ + return platform_driver_register(&tps68470_clk_driver); +} +subsys_initcall(tps68470_clk_init); + +static void __exit tps68470_clk_exit(void) +{ + platform_driver_unregister(&tps68470_clk_driver); +} +module_exit(tps68470_clk_exit); + +MODULE_ALIAS("platform:tps68470-clk"); +MODULE_DESCRIPTION("clock driver for TPS68470 pmic"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/tps68470.h b/include/linux/mfd/tps68470.h index ffe81127d91c..7807fa329db0 100644 --- a/include/linux/mfd/tps68470.h +++ b/include/linux/mfd/tps68470.h @@ -75,6 +75,17 @@ #define TPS68470_CLKCFG1_MODE_A_MASK GENMASK(1, 0) #define TPS68470_CLKCFG1_MODE_B_MASK GENMASK(3, 2) +#define TPS68470_CLKCFG2_DRV_STR_2MA 0x05 +#define TPS68470_PLL_OUTPUT_ENABLE 0x02 +#define TPS68470_CLK_SRC_XTAL BIT(0) +#define TPS68470_PLLSWR_DEFAULT GENMASK(1, 0) +#define TPS68470_OSC_EXT_CAP_DEFAULT 0x05 + +#define TPS68470_OUTPUT_A_SHIFT 0x00 +#define TPS68470_OUTPUT_B_SHIFT 0x02 +#define TPS68470_CLK_SRC_SHIFT GENMASK(2, 0) +#define TPS68470_OSC_EXT_CAP_SHIFT BIT(2) + #define TPS68470_GPIO_CTL_REG_A(x) (TPS68470_REG_GPCTL0A + (x) * 2) #define TPS68470_GPIO_CTL_REG_B(x) (TPS68470_REG_GPCTL0B + (x) * 2) #define TPS68470_GPIO_MODE_MASK GENMASK(1, 0) From patchwork Thu Nov 25 16:54:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518443 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 19337C4321E for ; Thu, 25 Nov 2021 16:57:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356577AbhKYRAT (ORCPT ); Thu, 25 Nov 2021 12:00:19 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:48598 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356603AbhKYQ6R (ORCPT ); Thu, 25 Nov 2021 11:58:17 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859306; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RtiW06aHTebE8dAV+W6N5fHoiNQl/oXsrb5+wcdvs0o=; b=dNLsmaA2AkbRTPrBSDdKw8bz/EZCXGXCXpQRvsrsN628J7rYKxGJwjBnMRs0JKCoZxqNuu oe3k29sQX45os7oQPhYPkfqmFmNZ/LD+23Nb7RjO2a9brrFvLQHTcdgNb8rr4BhRw34j9w mofoMUIBZBhYIDJ3NXr2Jh5KRUTRXhg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-60-HaiCikxzMlOdhczQXvSvpw-1; Thu, 25 Nov 2021 11:55:04 -0500 X-MC-Unique: HaiCikxzMlOdhczQXvSvpw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 422E7801B00; Thu, 25 Nov 2021 16:55:02 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 16B2767840; Thu, 25 Nov 2021 16:54:57 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org, Andy Shevchenko Subject: [PATCH v6 09/15] platform/x86: int3472: Add get_sensor_adev_and_name() helper Date: Thu, 25 Nov 2021 17:54:06 +0100 Message-Id: <20211125165412.535063-10-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The discrete.c code is not the only code which needs to lookup the acpi_device and device-name for the sensor for which the INT3472 ACPI-device is a GPIO/clk/regulator provider. The tps68470.c code also needs this functionality, so factor this out into a new get_sensor_adev_and_name() helper. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/int3472/common.c | 28 +++++++++++++++++++ drivers/platform/x86/intel/int3472/common.h | 3 ++ drivers/platform/x86/intel/int3472/discrete.c | 22 +++------------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c index 350655a9515b..77cf058e4168 100644 --- a/drivers/platform/x86/intel/int3472/common.c +++ b/drivers/platform/x86/intel/int3472/common.c @@ -52,3 +52,31 @@ int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb) kfree(obj); return ret; } + +/* sensor_adev_ret may be NULL, name_ret must not be NULL */ +int skl_int3472_get_sensor_adev_and_name(struct device *dev, + struct acpi_device **sensor_adev_ret, + const char **name_ret) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct acpi_device *sensor; + int ret = 0; + + sensor = acpi_dev_get_first_consumer_dev(adev); + if (!sensor) { + dev_err(dev, "INT3472 seems to have no dependents.\n"); + return -ENODEV; + } + + *name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT, + acpi_dev_name(sensor)); + if (!*name_ret) + ret = -ENOMEM; + + if (ret == 0 && sensor_adev_ret) + *sensor_adev_ret = sensor; + else + acpi_dev_put(sensor); + + return ret; +} diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h index d14944ee8586..53270d19c73a 100644 --- a/drivers/platform/x86/intel/int3472/common.h +++ b/drivers/platform/x86/intel/int3472/common.h @@ -108,6 +108,9 @@ struct int3472_discrete_device { union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id); int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb); +int skl_int3472_get_sensor_adev_and_name(struct device *dev, + struct acpi_device **sensor_adev_ret, + const char **name_ret); int skl_int3472_register_clock(struct int3472_discrete_device *int3472); void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index d2e8a87a077e..ff2bdbb8722c 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -363,19 +363,10 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) int3472->dev = &pdev->dev; platform_set_drvdata(pdev, int3472); - int3472->sensor = acpi_dev_get_first_consumer_dev(adev); - if (!int3472->sensor) { - dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n"); - return -ENODEV; - } - - int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL, - I2C_DEV_NAME_FORMAT, - acpi_dev_name(int3472->sensor)); - if (!int3472->sensor_name) { - ret = -ENOMEM; - goto err_put_sensor; - } + ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor, + &int3472->sensor_name); + if (ret) + return ret; /* * Initialising this list means we can call gpiod_remove_lookup_table() @@ -390,11 +381,6 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) } return 0; - -err_put_sensor: - acpi_dev_put(int3472->sensor); - - return ret; } static int skl_int3472_discrete_remove(struct platform_device *pdev) From patchwork Thu Nov 25 16:54:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518442 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 4F3DAC433F5 for ; Thu, 25 Nov 2021 16:57:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356596AbhKYRAj (ORCPT ); Thu, 25 Nov 2021 12:00:39 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:32805 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356590AbhKYQ6h (ORCPT ); Thu, 25 Nov 2021 11:58:37 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859325; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fN3YhXXvwh9WcxCsDxfwvCGBjFKE1y0xpcHqnwETn9U=; b=dqjLOIF1HxRaH/IZgJ3ftrBrBJWzTU0RhNcj+eEHvXZfW410zvaokS7hvnnYLFzcetCEjX AK2Lj8+8pDCV8vzVNh+g8X9/NSNLqgt0ik7MtO3kZZMN3m/8wcSlwNBnyCsWXz8GOZAOxW VTerE4mPbMsisURZMahSi6WHiUwb/pI= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-388-LzbuyazBO-S2iMAQoLNqlw-1; Thu, 25 Nov 2021 11:55:20 -0500 X-MC-Unique: LzbuyazBO-S2iMAQoLNqlw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CB0651853024; Thu, 25 Nov 2021 16:55:17 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id C49A667842; Thu, 25 Nov 2021 16:55:06 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org, Andy Shevchenko Subject: [PATCH v6 11/15] platform/x86: int3472: Pass tps68470_regulator_platform_data to the tps68470-regulator MFD-cell Date: Thu, 25 Nov 2021 17:54:08 +0100 Message-Id: <20211125165412.535063-12-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Pass tps68470_regulator_platform_data to the tps68470-regulator MFD-cell, specifying the voltages of the various regulators and tying the regulators to the sensor supplies so that sensors which use the TPS68470 can find their regulators. Since the voltages and supply connections are board-specific, this introduces a DMI matches int3472_tps68470_board_data struct which contains the necessary per-board info. This per-board info also includes GPIO lookup information for the sensor IO lines which may be connected to the tps68470 GPIOs. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- Changes in v6: - Also list the VCM module as VSIO regulator consumer - Add constraints for VIO, it MUST have the same voltage configured as VSIO and mark it as always-on (it is always on there is no on/off control for it in the PMIC, as the PMIC uses it internally) - Fix logic error in int3472_tps68470_get_board_data() (thank you Andy) Changes in v5: - Also pass regulator_init_data for the regulator used for the VCM (Voice Coil Motor) used for the focus of the back-camera lens --- drivers/platform/x86/intel/int3472/Makefile | 2 +- drivers/platform/x86/intel/int3472/tps68470.c | 28 ++++ drivers/platform/x86/intel/int3472/tps68470.h | 25 +++ .../x86/intel/int3472/tps68470_board_data.c | 145 ++++++++++++++++++ 4 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 drivers/platform/x86/intel/int3472/tps68470.h create mode 100644 drivers/platform/x86/intel/int3472/tps68470_board_data.c diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile index 771e720528a0..cfec7784c5c9 100644 --- a/drivers/platform/x86/intel/int3472/Makefile +++ b/drivers/platform/x86/intel/int3472/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \ intel_skl_int3472_tps68470.o intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o -intel_skl_int3472_tps68470-y := tps68470.o common.o +intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index 05fcf35c1662..9c213b8e99a0 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -2,13 +2,16 @@ /* Author: Dan Scally */ #include +#include #include #include #include #include #include +#include #include "common.h" +#include "tps68470.h" #define DESIGNED_FOR_CHROMEOS 1 #define DESIGNED_FOR_WINDOWS 2 @@ -102,6 +105,7 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) static int skl_int3472_tps68470_probe(struct i2c_client *client) { struct acpi_device *adev = ACPI_COMPANION(&client->dev); + const struct int3472_tps68470_board_data *board_data; struct tps68470_clk_platform_data clk_pdata = {}; struct mfd_cell *cells; struct regmap *regmap; @@ -130,6 +134,10 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) device_type = skl_int3472_tps68470_calc_type(adev); switch (device_type) { case DESIGNED_FOR_WINDOWS: + board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); + if (!board_data) + return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n"); + cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL); if (!cells) return -ENOMEM; @@ -144,12 +152,20 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) cells[0].platform_data = &clk_pdata; cells[0].pdata_size = sizeof(clk_pdata); cells[1].name = "tps68470-regulator"; + cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata; + cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data); cells[2].name = "tps68470-gpio"; + gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table); + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, cells, TPS68470_WIN_MFD_CELL_COUNT, NULL, 0, NULL); kfree(cells); + + if (ret) + gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); + break; case DESIGNED_FOR_CHROMEOS: ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, @@ -164,6 +180,17 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) return ret; } +static int skl_int3472_tps68470_remove(struct i2c_client *client) +{ + const struct int3472_tps68470_board_data *board_data; + + board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); + if (board_data) + gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); + + return 0; +} + static const struct acpi_device_id int3472_device_id[] = { { "INT3472", 0 }, { } @@ -176,6 +203,7 @@ static struct i2c_driver int3472_tps68470 = { .acpi_match_table = int3472_device_id, }, .probe_new = skl_int3472_tps68470_probe, + .remove = skl_int3472_tps68470_remove, }; module_i2c_driver(int3472_tps68470); diff --git a/drivers/platform/x86/intel/int3472/tps68470.h b/drivers/platform/x86/intel/int3472/tps68470.h new file mode 100644 index 000000000000..cfd33eb62740 --- /dev/null +++ b/drivers/platform/x86/intel/int3472/tps68470.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * TI TPS68470 PMIC platform data definition. + * + * Copyright (c) 2021 Red Hat Inc. + * + * Red Hat authors: + * Hans de Goede + */ + +#ifndef _INTEL_SKL_INT3472_TPS68470_H +#define _INTEL_SKL_INT3472_TPS68470_H + +struct gpiod_lookup_table; +struct tps68470_regulator_platform_data; + +struct int3472_tps68470_board_data { + const char *dev_name; + struct gpiod_lookup_table *tps68470_gpio_lookup_table; + const struct tps68470_regulator_platform_data *tps68470_regulator_pdata; +}; + +const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name); + +#endif diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c new file mode 100644 index 000000000000..faa5570f6e6b --- /dev/null +++ b/drivers/platform/x86/intel/int3472/tps68470_board_data.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI TPS68470 PMIC platform data definition. + * + * Copyright (c) 2021 Dan Scally + * Copyright (c) 2021 Red Hat Inc. + * + * Red Hat authors: + * Hans de Goede + */ + +#include +#include +#include +#include +#include "tps68470.h" + +static struct regulator_consumer_supply int347a_core_consumer_supplies[] = { + REGULATOR_SUPPLY("dvdd", "i2c-INT347A:00"), +}; + +static struct regulator_consumer_supply int347a_ana_consumer_supplies[] = { + REGULATOR_SUPPLY("avdd", "i2c-INT347A:00"), +}; + +static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = { + REGULATOR_SUPPLY("vdd", "i2c-INT347A:00-VCM"), +}; + +static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = { + REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"), + REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"), +}; + +static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = { + .constraints = { + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_core_consumer_supplies), + .consumer_supplies = int347a_core_consumer_supplies, +}; + +static const struct regulator_init_data surface_go_tps68470_ana_reg_init_data = { + .constraints = { + .min_uV = 2815200, + .max_uV = 2815200, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_ana_consumer_supplies), + .consumer_supplies = int347a_ana_consumer_supplies, +}; + +static const struct regulator_init_data surface_go_tps68470_vcm_reg_init_data = { + .constraints = { + .min_uV = 2815200, + .max_uV = 2815200, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_vcm_consumer_supplies), + .consumer_supplies = int347a_vcm_consumer_supplies, +}; + +/* Ensure the always-on VIO regulator has the same voltage as VSIO */ +static const struct regulator_init_data surface_go_tps68470_vio_reg_init_data = { + .constraints = { + .min_uV = 1800600, + .max_uV = 1800600, + .apply_uV = true, + .always_on = true, + }, +}; + +static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = { + .constraints = { + .min_uV = 1800600, + .max_uV = 1800600, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_vsio_consumer_supplies), + .consumer_supplies = int347a_vsio_consumer_supplies, +}; + +static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = { + .reg_init_data = { + [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data, + [TPS68470_ANA] = &surface_go_tps68470_ana_reg_init_data, + [TPS68470_VCM] = &surface_go_tps68470_vcm_reg_init_data, + [TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data, + [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data, + }, +}; + +static struct gpiod_lookup_table surface_go_tps68470_gpios = { + .dev_id = "i2c-INT347A:00", + .table = { + GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW), + GPIO_LOOKUP("tps68470-gpio", 7, "powerdown", GPIO_ACTIVE_LOW) + } +}; + +static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = { + .dev_name = "i2c-INT3472:05", + .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios, + .tps68470_regulator_pdata = &surface_go_tps68470_pdata, +}; + +static const struct dmi_system_id int3472_tps68470_board_data_table[] = { + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go"), + }, + .driver_data = (void *)&surface_go_tps68470_board_data, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go 2"), + }, + .driver_data = (void *)&surface_go_tps68470_board_data, + }, + { } +}; + +const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name) +{ + const struct int3472_tps68470_board_data *board_data; + const struct dmi_system_id *match; + + for (match = dmi_first_match(int3472_tps68470_board_data_table); + match; + match = dmi_first_match(match + 1)) { + board_data = match->driver_data; + if (strcmp(board_data->dev_name, dev_name) == 0) + return board_data; + } + + return NULL; +} From patchwork Thu Nov 25 16:54:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518441 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 E9789C433EF for ; Thu, 25 Nov 2021 16:57:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237330AbhKYRAs (ORCPT ); Thu, 25 Nov 2021 12:00:48 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:52783 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356623AbhKYQ6p (ORCPT ); Thu, 25 Nov 2021 11:58:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859333; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LUrG4jqNJu6mVXKc6QsIJBUF4M5Dz78pxASMnLdBkbM=; b=YTCYEQEYkmCBopsi72XXHMn+1T/o70KZMgfUKhKV6neh/JpHZrmDojK5akxNFFC/gjtkKs r82vK6IBV0C2eOfKRgcpwisMQ1S7wuOKz24mtvehdY2JFF/oOf/LmxioWVWvdCGz6tISHN 3RWjIegF+N/rzYgWRbIQmQqNXAbB5Ms= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-485-fKjlI72qOAGApb-egKqtrQ-1; Thu, 25 Nov 2021 11:55:28 -0500 X-MC-Unique: fKjlI72qOAGApb-egKqtrQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 10F532F20; Thu, 25 Nov 2021 16:55:26 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 54B04604CC; Thu, 25 Nov 2021 16:55:22 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org Subject: [PATCH v6 13/15] media: ipu3-cio2: Defer probing until the PMIC is fully setup Date: Thu, 25 Nov 2021 17:54:10 +0100 Message-Id: <20211125165412.535063-14-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org On devices where things are not fully describe in devicetree (1) and where the code thus falls back to calling cio2_bridge_init(), the i2c-clients for any VCMs also need to be instantiated manually. The VCM can be probed by its driver as soon as the code instantiates the i2c-client and this probing must not happen before the PMIC is fully setup. Make cio2_bridge_init() return -EPROBE_DEFER when the PMIC is not fully-setup, deferring the probe of the ipu3-cio2 driver. This is a preparation patch for adding VCM enumeration support to the ipu3-cio2-bridge code. 1) Through embedding of devicetree info in the ACPI tables Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 1cbbcbf4e157..460ef7f78234 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -308,6 +308,40 @@ static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge, return ret; } +/* + * The VCM cannot be probed until the PMIC is completely setup. We cannot rely + * on -EPROBE_DEFER for this, since the consumer<->supplier relations between + * the VCM and regulators/clks are not described in ACPI, instead they are + * passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work + * for the clks/regulators the VCM i2c-clients must not be instantiated until + * the PMIC is fully setup. + * + * The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the + * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does + * for the sensors. + */ +int cio2_bridge_sensors_are_ready(void) +{ + struct acpi_device *adev; + bool ready = true; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) { + const struct cio2_sensor_config *cfg = + &cio2_supported_sensors[i]; + + for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { + if (!adev->status.enabled) + continue; + + if (!acpi_dev_ready_for_enumeration(adev)) + ready = false; + } + } + + return ready; +} + int cio2_bridge_init(struct pci_dev *cio2) { struct device *dev = &cio2->dev; @@ -316,6 +350,9 @@ int cio2_bridge_init(struct pci_dev *cio2) unsigned int i; int ret; + if (!cio2_bridge_sensors_are_ready()) + return -EPROBE_DEFER; + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) return -ENOMEM; From patchwork Thu Nov 25 16:54:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 518440 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 A4A4DC433EF for ; Thu, 25 Nov 2021 16:57:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356643AbhKYRAz (ORCPT ); Thu, 25 Nov 2021 12:00:55 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:35005 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356639AbhKYQ6x (ORCPT ); Thu, 25 Nov 2021 11:58:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1637859340; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CnaCRXQQDkNaLaN82LcLlN5i1GlnXuJtYhrqJc4aPrU=; b=XJ+hVHNO7R2ejPbQOHNPDGbVBBMd2+jWWYWTuGlJ3JZB6g+iNQOd43GVCMVzvRguF0U0WV CYztywzZmiX7p4uhbUU8rR5c8Yis15wtVwAGwFUS7jEPYT3AuCzK/r9NH0GQM9Oz/KqztV CMHOBdy9JURxCZshYqLFp6xFUPVR0fo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-98-heASMzY_PHmzitdPyzmRMw-1; Thu, 25 Nov 2021 11:55:36 -0500 X-MC-Unique: heASMzY_PHmzitdPyzmRMw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 311E1801B00; Thu, 25 Nov 2021 16:55:34 +0000 (UTC) Received: from x1.localdomain (unknown [10.39.195.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 62E7D67842; Thu, 25 Nov 2021 16:55:30 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Mark Gross , Andy Shevchenko , Wolfram Sang , Mika Westerberg , Daniel Scally , Laurent Pinchart , Mauro Carvalho Chehab , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd Cc: Hans de Goede , Len Brown , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Sakari Ailus , Kate Hsuan , linux-media@vger.kernel.org, linux-clk@vger.kernel.org Subject: [PATCH v6 15/15] media: ipu3-cio2: Add support for instantiating i2c-clients for VCMs Date: Thu, 25 Nov 2021 17:54:12 +0100 Message-Id: <20211125165412.535063-16-hdegoede@redhat.com> In-Reply-To: <20211125165412.535063-1-hdegoede@redhat.com> References: <20211125165412.535063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Some sensors come with a variable-focus lens where the lens focus is controller by a VCM (Voice Coil Motor). If there is a VCM for the lens-focus, and if so which one, is described on the vcm_type field of the ACPI SSDB table. These VCMs are a second I2C device listed as an extra I2cSerialBusV2 resource in the same ACPI device as the sensor. The i2c-core-acpi.c code only instantiates an i2c-client for the first I2cSerialBusV2 resource. Add support for instantiating an i2c-client for the VCM with the type of the i2c-client set based on the SSDB vcm_type field. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 55 ++++++++++++++++++++++ drivers/media/pci/intel/ipu3/cio2-bridge.h | 16 ++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 460ef7f78234..9b02f5599082 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,18 @@ static const struct cio2_property_names prop_names = { .link_frequencies = "link-frequencies", }; +static const char * const cio2_vcm_types[] = { + "ad5823", + "dw9714", + "ad5816", + "dw9719", + "dw9718", + "dw9806b", + "wv517s", + "lc898122xa", + "lc898212axb", +}; + static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id, void *data, u32 size) { @@ -134,6 +147,12 @@ static void cio2_bridge_create_fwnode_properties( sensor->dev_properties[2] = PROPERTY_ENTRY_U32( sensor->prop_names.orientation, orientation); + if (sensor->ssdb.vcmtype) { + sensor->vcm_ref[0] = + SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); + sensor->dev_properties[3] = + PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); + } sensor->ep_properties[0] = PROPERTY_ENTRY_U32( sensor->prop_names.bus_type, @@ -195,6 +214,33 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, sensor->node_names.endpoint, &nodes[SWNODE_CIO2_PORT], sensor->cio2_properties); + if (sensor->ssdb.vcmtype) + nodes[SWNODE_VCM] = + NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]); +} + +static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) +{ + struct i2c_board_info board_info = { }; + char name[16]; + + if (!sensor->ssdb.vcmtype) + return; + + snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev)); + board_info.dev_name = name; + strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1], + ARRAY_SIZE(board_info.type)); + board_info.swnode = &sensor->swnodes[SWNODE_VCM]; + + sensor->vcm_i2c_client = + i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev), + 1, &board_info); + if (IS_ERR(sensor->vcm_i2c_client)) { + dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n", + PTR_ERR(sensor->vcm_i2c_client)); + sensor->vcm_i2c_client = NULL; + } } static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) @@ -207,6 +253,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) software_node_unregister_nodes(sensor->swnodes); ACPI_FREE(sensor->pld); acpi_dev_put(sensor->adev); + i2c_unregister_device(sensor->vcm_i2c_client); } } @@ -239,6 +286,12 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, if (ret) goto err_put_adev; + if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) { + dev_warn(&adev->dev, "Unknown VCM type %d\n", + sensor->ssdb.vcmtype); + sensor->ssdb.vcmtype = 0; + } + status = acpi_get_physical_device_location(adev->handle, &sensor->pld); if (ACPI_FAILURE(status)) { ret = -ENODEV; @@ -269,6 +322,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, sensor->adev = acpi_dev_get(adev); adev->fwnode.secondary = fwnode; + cio2_bridge_instantiate_vcm_i2c_client(sensor); + dev_info(&cio2->dev, "Found supported sensor %s\n", acpi_dev_name(adev)); diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index 202c7d494f7a..4418cbd08208 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -8,6 +8,8 @@ #include "ipu3-cio2.h" +struct i2c_client; + #define CIO2_HID "INT343E" #define CIO2_MAX_LANES 4 #define MAX_NUM_LINK_FREQS 3 @@ -42,12 +44,19 @@ .properties = _PROPS, \ } +#define NODE_VCM(_TYPE) \ + (const struct software_node) { \ + .name = _TYPE, \ + } + enum cio2_sensor_swnodes { SWNODE_SENSOR_HID, SWNODE_SENSOR_PORT, SWNODE_SENSOR_ENDPOINT, SWNODE_CIO2_PORT, SWNODE_CIO2_ENDPOINT, + /* Must be last because it is optional / maybe empty */ + SWNODE_VCM, SWNODE_COUNT }; @@ -106,8 +115,10 @@ struct cio2_sensor_config { struct cio2_sensor { char name[ACPI_ID_LEN]; struct acpi_device *adev; + struct i2c_client *vcm_i2c_client; - struct software_node swnodes[6]; + /* SWNODE_COUNT + 1 for terminating empty node */ + struct software_node swnodes[SWNODE_COUNT + 1]; struct cio2_node_names node_names; struct cio2_sensor_ssdb ssdb; @@ -115,10 +126,11 @@ struct cio2_sensor { struct cio2_property_names prop_names; struct property_entry ep_properties[5]; - struct property_entry dev_properties[4]; + struct property_entry dev_properties[5]; struct property_entry cio2_properties[3]; struct software_node_ref_args local_ref[1]; struct software_node_ref_args remote_ref[1]; + struct software_node_ref_args vcm_ref[1]; }; struct cio2_bridge {