* [dtor-input:next] BUILD SUCCESS d3e09f57345f86cf5c47a89fc216f6c98f9a4a7a
From: kernel test robot @ 2023-12-10 0:19 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: d3e09f57345f86cf5c47a89fc216f6c98f9a4a7a dt-bindings: input: gpio-mouse: Convert to json-schema
elapsed time: 1463m
configs tested: 110
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc
alpha defconfig gcc
arc allnoconfig gcc
arc defconfig gcc
arc randconfig-001-20231210 gcc
arc randconfig-002-20231210 gcc
arm allnoconfig gcc
arm at91_dt_defconfig gcc
arm defconfig clang
arm randconfig-001-20231210 gcc
arm randconfig-002-20231210 gcc
arm randconfig-003-20231210 gcc
arm randconfig-004-20231210 gcc
arm64 allnoconfig gcc
arm64 defconfig gcc
arm64 randconfig-001-20231210 gcc
arm64 randconfig-002-20231210 gcc
arm64 randconfig-003-20231210 gcc
arm64 randconfig-004-20231210 gcc
csky allnoconfig gcc
csky defconfig gcc
csky randconfig-001-20231210 gcc
csky randconfig-002-20231210 gcc
hexagon allnoconfig clang
hexagon defconfig clang
hexagon randconfig-001-20231210 clang
hexagon randconfig-002-20231210 clang
i386 allmodconfig clang
i386 allnoconfig clang
i386 allyesconfig clang
i386 buildonly-randconfig-001-20231209 gcc
i386 buildonly-randconfig-002-20231209 gcc
i386 buildonly-randconfig-003-20231209 gcc
i386 buildonly-randconfig-004-20231209 gcc
i386 buildonly-randconfig-005-20231209 gcc
i386 buildonly-randconfig-006-20231209 gcc
i386 defconfig gcc
i386 randconfig-001-20231209 gcc
i386 randconfig-002-20231209 gcc
i386 randconfig-003-20231209 gcc
i386 randconfig-004-20231209 gcc
i386 randconfig-005-20231209 gcc
i386 randconfig-006-20231209 gcc
i386 randconfig-011-20231209 clang
i386 randconfig-012-20231209 clang
i386 randconfig-013-20231209 clang
i386 randconfig-014-20231209 clang
i386 randconfig-015-20231209 clang
i386 randconfig-016-20231209 clang
loongarch allmodconfig gcc
loongarch allnoconfig gcc
loongarch defconfig gcc
loongarch randconfig-001-20231210 gcc
loongarch randconfig-002-20231210 gcc
m68k allmodconfig gcc
m68k allnoconfig gcc
m68k allyesconfig gcc
m68k defconfig gcc
microblaze allmodconfig gcc
microblaze allnoconfig gcc
microblaze defconfig gcc
mips allnoconfig clang
nios2 allnoconfig gcc
nios2 defconfig gcc
nios2 randconfig-001-20231210 gcc
nios2 randconfig-002-20231210 gcc
openrisc allnoconfig gcc
openrisc defconfig gcc
parisc allnoconfig gcc
parisc defconfig gcc
parisc randconfig-001-20231210 gcc
parisc randconfig-002-20231210 gcc
parisc64 defconfig gcc
powerpc allnoconfig gcc
powerpc randconfig-001-20231210 gcc
powerpc randconfig-002-20231210 gcc
powerpc randconfig-003-20231210 gcc
powerpc64 randconfig-001-20231210 gcc
powerpc64 randconfig-002-20231210 gcc
powerpc64 randconfig-003-20231210 gcc
riscv allnoconfig clang
riscv defconfig gcc
riscv randconfig-001-20231210 gcc
riscv randconfig-002-20231210 gcc
s390 allmodconfig gcc
s390 allnoconfig gcc
s390 allyesconfig gcc
s390 defconfig gcc
s390 randconfig-001-20231210 clang
s390 randconfig-002-20231210 clang
sh allmodconfig gcc
sh allnoconfig gcc
sh allyesconfig gcc
sh defconfig gcc
sh randconfig-001-20231210 gcc
sh randconfig-002-20231210 gcc
sparc allmodconfig gcc
sparc64 allmodconfig gcc
sparc64 allyesconfig gcc
sparc64 randconfig-001-20231210 gcc
sparc64 randconfig-002-20231210 gcc
um allmodconfig clang
um allyesconfig clang
um randconfig-001-20231210 gcc
um randconfig-002-20231210 gcc
x86_64 allnoconfig gcc
x86_64 allyesconfig clang
x86_64 defconfig gcc
x86_64 rhel-8.3-rust clang
xtensa randconfig-001-20231210 gcc
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [dtor-input:for-linus] BUILD SUCCESS 59b6a747e2d39227ac2325c5e29d6ab3bb070c2a
From: kernel test robot @ 2023-12-10 1:16 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
branch HEAD: 59b6a747e2d39227ac2325c5e29d6ab3bb070c2a Input: ipaq-micro-keys - add error handling for devm_kmemdup
elapsed time: 1520m
configs tested: 89
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc
alpha defconfig gcc
arc allmodconfig gcc
arc allnoconfig gcc
arc allyesconfig gcc
arc axs103_defconfig gcc
arc defconfig gcc
arc nsimosci_hs_smp_defconfig gcc
arc randconfig-001-20231210 gcc
arc randconfig-002-20231210 gcc
arm allnoconfig gcc
arm am200epdkit_defconfig clang
arm assabet_defconfig gcc
arm defconfig clang
arm milbeaut_m10v_defconfig clang
arm randconfig-001-20231210 gcc
arm randconfig-002-20231210 gcc
arm64 allnoconfig gcc
arm64 defconfig gcc
csky allnoconfig gcc
csky defconfig gcc
hexagon allnoconfig clang
hexagon defconfig clang
i386 allmodconfig clang
i386 allnoconfig clang
i386 allyesconfig clang
i386 buildonly-randconfig-001-20231209 gcc
i386 buildonly-randconfig-002-20231209 gcc
i386 buildonly-randconfig-003-20231209 gcc
i386 buildonly-randconfig-004-20231209 gcc
i386 buildonly-randconfig-005-20231209 gcc
i386 buildonly-randconfig-006-20231209 gcc
i386 defconfig gcc
i386 randconfig-001-20231209 gcc
i386 randconfig-002-20231209 gcc
i386 randconfig-003-20231209 gcc
i386 randconfig-004-20231209 gcc
i386 randconfig-005-20231209 gcc
i386 randconfig-006-20231209 gcc
i386 randconfig-011-20231209 clang
i386 randconfig-012-20231209 clang
i386 randconfig-013-20231209 clang
i386 randconfig-014-20231209 clang
i386 randconfig-015-20231209 clang
i386 randconfig-016-20231209 clang
loongarch allnoconfig gcc
loongarch defconfig gcc
m68k allnoconfig gcc
m68k defconfig gcc
m68k m5407c3_defconfig gcc
m68k m5475evb_defconfig gcc
microblaze allnoconfig gcc
microblaze defconfig gcc
mips allnoconfig clang
mips pic32mzda_defconfig clang
nios2 allnoconfig gcc
nios2 defconfig gcc
openrisc allnoconfig gcc
openrisc defconfig gcc
parisc allnoconfig gcc
parisc defconfig gcc
parisc64 defconfig gcc
powerpc allnoconfig gcc
powerpc ppc64_defconfig gcc
riscv allnoconfig clang
riscv defconfig gcc
s390 allmodconfig gcc
s390 allnoconfig gcc
s390 allyesconfig gcc
s390 defconfig gcc
sh allmodconfig gcc
sh allnoconfig gcc
sh allyesconfig gcc
sh defconfig gcc
sparc allmodconfig gcc
sparc64 allmodconfig gcc
sparc64 allyesconfig gcc
sparc64 defconfig gcc
um allmodconfig clang
um allnoconfig clang
um allyesconfig clang
um defconfig gcc
um i386_defconfig gcc
um x86_64_defconfig gcc
x86_64 allnoconfig gcc
x86_64 allyesconfig clang
x86_64 defconfig gcc
x86_64 rhel-8.3-rust clang
xtensa allnoconfig gcc
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v6 1/4] pwm: rename pwm_apply_state() to pwm_apply_might_sleep()
From: Dmitry Torokhov @ 2023-12-10 3:59 UTC (permalink / raw)
To: Sean Young
Cc: linux-media, linux-pwm, Ivaylo Dimitrov, Thierry Reding,
Uwe Kleine-König, Jonathan Corbet, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, David Airlie,
Daniel Vetter, Javier Martinez Canillas, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Jean Delvare, Guenter Roeck,
Support Opensource, Pavel Machek, Lee Jones,
Mauro Carvalho Chehab, Hans de Goede, Ilpo Järvinen,
Mark Gross, Liam Girdwood, Mark Brown, Daniel Thompson,
Jingoo Han, Helge Deller, Jani Nikula, linux-doc, linux-kernel,
intel-gfx, dri-devel, linux-hwmon, linux-input, linux-leds,
platform-driver-x86, linux-arm-kernel, linux-fbdev
In-Reply-To: <37090c1d8d8f42f1e12fa84942027d995189a99e.1701248996.git.sean@mess.org>
On Wed, Nov 29, 2023 at 09:13:34AM +0000, Sean Young wrote:
> drivers/input/misc/da7280.c | 4 +--
> drivers/input/misc/pwm-beeper.c | 4 +--
> drivers/input/misc/pwm-vibra.c | 8 +++---
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> # for input
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3] Input: pxrc - simplify mutex handling with guard macro
From: Dmitry Torokhov @ 2023-12-10 6:40 UTC (permalink / raw)
To: Marcus Folkesson; +Cc: linux-input, linux-kernel
In-Reply-To: <20231202-pxrc-guard-v3-1-2ca8bc8cf689@gmail.com>
On Sat, Dec 02, 2023 at 05:59:48PM +0100, Marcus Folkesson wrote:
> Use the guard(mutex) macro for handle mutex lock/unlocks.
>
> Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
Applied, thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH RESEND] Input: omap4-keypad: react on keypresses if device is runtime-suspended
From: Dmitry Torokhov @ 2023-12-10 6:42 UTC (permalink / raw)
To: Andreas Kemnade
Cc: tony, frank.li, u.kleine-koenig, Jonathan.Cameron, robh,
linux-input, linux-kernel
In-Reply-To: <20231209112058.453030-1-andreas@kemnade.info>
Hi Andreas,
On Sat, Dec 09, 2023 at 12:20:58PM +0100, Andreas Kemnade wrote:
> According to SWPU235AB, table 26-6, fclk is required to generate events
> at least on OMAP4460, so keep fclk enabled all the time the device
> is opened.
>
> Suggested-by: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
> Reviewed-by: Tony Lindgren <tony@atomide.com>
> ---
> Changes since RFC:
> - add R-by:
>
> drivers/input/keyboard/omap4-keypad.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
> index d3f8688fdd9c3..7d83aff95617f 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -11,6 +11,7 @@
> #include <linux/module.h>
> #include <linux/interrupt.h>
> #include <linux/platform_device.h>
> +#include <linux/clk.h>
> #include <linux/errno.h>
> #include <linux/io.h>
> #include <linux/of.h>
> @@ -83,6 +84,7 @@ struct omap4_keypad {
> bool no_autorepeat;
> u64 keys;
> unsigned short *keymap;
> + struct clk *fck;
> };
>
> static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> @@ -211,6 +213,8 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> + clk_prepare_enable(keypad_data->fck);
I believe this needs error handling.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v12 2/4] Input: add core support for Goodix Berlin Touchscreen IC
From: Dmitry Torokhov @ 2023-12-10 6:53 UTC (permalink / raw)
To: Neil Armstrong
Cc: linux-input, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg, Jeff LaBundy,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20231209-topic-goodix-berlin-upstream-initial-v12-2-eaffaeb53fb5@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 1920 bytes --]
Hi Neil,
On Sat, Dec 09, 2023 at 08:33:40AM +0100, Neil Armstrong wrote:
> Add initial support for the new Goodix "Berlin" touchscreen ICs.
>
> These touchscreen ICs support SPI, I2C and I3C interface, up to
> 10 finger touch, stylus and gestures events.
>
> This initial driver is derived from the Goodix goodix_ts_berlin
> available at [1] and [2] and only supports the GT9916 IC
> present on the Qualcomm SM8550 MTP & QRD touch panel.
>
> The current implementation only supports BerlinD, aka GT9916.
>
> Support for advanced features like:
> - Firmware & config update
> - Stylus events
> - Gestures events
> - Previous revisions support (BerlinA or BerlinB)
> is not included in current version.
>
> The current support will work with currently flashed firmware
> and config, and bail out if firmware or config aren't flashed yet.
>
> [1] https://github.com/goodix/goodix_ts_berlin
> [2] https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
>
> Reviewed-by: Jeff LaBundy <jeff@labundy.com>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Thank you for resending the patch. I think there is an issue in how you
read and parse the data in case of more than 2 fingers. It looks like in
that case you are overwriting the checksum form the first 2 and then not
reading the new checksum but use some garbage past the touch data. I
might be mistaken though...
I also believe you are leaking afe_data in case of success. We have the
newfangled __free(kfree) from cleanup.h that should help there.
Another request - we should not have anything in goodix_berlin.h that is
not used by the I2C and SPI sub-drivers, so the only thing it should
contain is goodix_berlin_probe() declaration and dev_pm_ops. All other
defines and definitions should go to goodix_berlin_core.h.
I made a few more cosmetic changes in the attached patch, please
consider applying it.
Thanks.
--
Dmitry
[-- Attachment #2: tmp.patch --]
[-- Type: text/x-diff, Size: 21179 bytes --]
diff --git a/drivers/input/touchscreen/goodix_berlin.h b/drivers/input/touchscreen/goodix_berlin.h
index 235f44947a28..1fd77eb69c9a 100644
--- a/drivers/input/touchscreen/goodix_berlin.h
+++ b/drivers/input/touchscreen/goodix_berlin.h
@@ -10,146 +10,11 @@
#ifndef __GOODIX_BERLIN_H_
#define __GOODIX_BERLIN_H_
-#include <linux/gpio/consumer.h>
-#include <linux/input.h>
-#include <linux/input/touchscreen.h>
-#include <linux/regulator/consumer.h>
-#include <linux/sizes.h>
+#include <linux/pm.h>
-#define GOODIX_BERLIN_MAX_TOUCH 10
-
-#define GOODIX_BERLIN_NORMAL_RESET_DELAY_MS 100
-
-#define GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN 8
-#define GOODIX_BERLIN_STATUS_OFFSET 0
-#define GOODIX_BERLIN_REQUEST_TYPE_OFFSET 2
-
-#define GOODIX_BERLIN_BYTES_PER_POINT 8
-#define GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE 2
-#define GOODIX_BERLIN_COOR_DATA_CHECKSUM_MASK GENMASK(15, 0)
-
-/* Read n finger events */
-#define GOODIX_BERLIN_IRQ_READ_LEN(n) (GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN + \
- (GOODIX_BERLIN_BYTES_PER_POINT * (n)) + \
- GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE)
-
-#define GOODIX_BERLIN_TOUCH_EVENT BIT(7)
-#define GOODIX_BERLIN_REQUEST_EVENT BIT(6)
-#define GOODIX_BERLIN_TOUCH_COUNT_MASK GENMASK(3, 0)
-
-#define GOODIX_BERLIN_REQUEST_CODE_RESET 3
-
-#define GOODIX_BERLIN_POINT_TYPE_MASK GENMASK(3, 0)
-#define GOODIX_BERLIN_POINT_TYPE_STYLUS_HOVER 1
-#define GOODIX_BERLIN_POINT_TYPE_STYLUS 3
-
-#define GOODIX_BERLIN_TOUCH_ID_MASK GENMASK(7, 4)
-
-#define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA
-#define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000
-#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014
-
-#define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K
-#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070
-
-struct goodix_berlin_fw_version {
- u8 rom_pid[6];
- u8 rom_vid[3];
- u8 rom_vid_reserved;
- u8 patch_pid[8];
- u8 patch_vid[4];
- u8 patch_vid_reserved;
- u8 sensor_id;
- u8 reserved[2];
- __le16 checksum;
-} __packed;
-
-struct goodix_berlin_ic_info_version {
- u8 info_customer_id;
- u8 info_version_id;
- u8 ic_die_id;
- u8 ic_version_id;
- __le32 config_id;
- u8 config_version;
- u8 frame_data_customer_id;
- u8 frame_data_version_id;
- u8 touch_data_customer_id;
- u8 touch_data_version_id;
- u8 reserved[3];
-} __packed;
-
-struct goodix_berlin_ic_info_feature {
- __le16 freqhop_feature;
- __le16 calibration_feature;
- __le16 gesture_feature;
- __le16 side_touch_feature;
- __le16 stylus_feature;
-} __packed;
-
-struct goodix_berlin_ic_info_misc {
- __le32 cmd_addr;
- __le16 cmd_max_len;
- __le32 cmd_reply_addr;
- __le16 cmd_reply_len;
- __le32 fw_state_addr;
- __le16 fw_state_len;
- __le32 fw_buffer_addr;
- __le16 fw_buffer_max_len;
- __le32 frame_data_addr;
- __le16 frame_data_head_len;
- __le16 fw_attr_len;
- __le16 fw_log_len;
- u8 pack_max_num;
- u8 pack_compress_version;
- __le16 stylus_struct_len;
- __le16 mutual_struct_len;
- __le16 self_struct_len;
- __le16 noise_struct_len;
- __le32 touch_data_addr;
- __le16 touch_data_head_len;
- __le16 point_struct_len;
- __le16 reserved1;
- __le16 reserved2;
- __le32 mutual_rawdata_addr;
- __le32 mutual_diffdata_addr;
- __le32 mutual_refdata_addr;
- __le32 self_rawdata_addr;
- __le32 self_diffdata_addr;
- __le32 self_refdata_addr;
- __le32 iq_rawdata_addr;
- __le32 iq_refdata_addr;
- __le32 im_rawdata_addr;
- __le16 im_readata_len;
- __le32 noise_rawdata_addr;
- __le16 noise_rawdata_len;
- __le32 stylus_rawdata_addr;
- __le16 stylus_rawdata_len;
- __le32 noise_data_addr;
- __le32 esd_addr;
-} __packed;
-
-struct goodix_berlin_touch_data {
- u8 id;
- u8 unused;
- __le16 x;
- __le16 y;
- __le16 w;
-} __packed;
-
-struct goodix_berlin_core {
- struct device *dev;
- struct regmap *regmap;
- struct regulator *avdd;
- struct regulator *iovdd;
- struct gpio_desc *reset_gpio;
- struct touchscreen_properties props;
- struct goodix_berlin_fw_version fw_version;
- struct input_dev *input_dev;
- int irq;
-
- /* Runtime parameters extracted from IC_INFO buffer */
- u32 touch_data_addr;
-};
+struct device;
+struct input_id;
+struct regmap;
int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
struct regmap *regmap);
diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c
index c66e2f0c6529..88a88e77d940 100644
--- a/drivers/input/touchscreen/goodix_berlin_core.c
+++ b/drivers/input/touchscreen/goodix_berlin_core.c
@@ -1,28 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Goodix Touchscreen Driver
+ * Goodix "Berlin" Touchscreen IC driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
* Copyright (C) 2023 Linaro Ltd.
*
* Based on goodix_ts_berlin driver.
- */
-#include <asm/unaligned.h>
-#include <linux/bitfield.h>
-#include <linux/input/mt.h>
-#include <linux/input/touchscreen.h>
-#include <linux/regmap.h>
-
-#include "goodix_berlin.h"
-
-/*
- * Goodix "Berlin" Touchscreen IC driver
*
* This driver is distinct from goodix.c since hardware interface
* is different enough to require a new driver.
* None of the register address or data structure are close enough
* to the previous generations.
*
- * Currently only handles Multitouch events with already
+ * Currently the driver only handles Multitouch events with already
* programmed firmware and "config" for "Revision D" Berlin IC.
*
* Support is missing for:
@@ -34,6 +23,153 @@
* - Support for older revisions (A & B)
*/
+#include <linux/bitfield.h>
+#include <linux/gpio/consumer.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sizes.h>
+#include <asm/unaligned.h>
+
+#include "goodix_berlin.h"
+
+#define GOODIX_BERLIN_MAX_TOUCH 10
+
+#define GOODIX_BERLIN_NORMAL_RESET_DELAY_MS 100
+
+#define GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN 8
+#define GOODIX_BERLIN_STATUS_OFFSET 0
+#define GOODIX_BERLIN_REQUEST_TYPE_OFFSET 2
+
+#define GOODIX_BERLIN_BYTES_PER_POINT 8
+#define GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE 2
+#define GOODIX_BERLIN_COOR_DATA_CHECKSUM_MASK GENMASK(15, 0)
+
+/* Read n finger events */
+#define GOODIX_BERLIN_IRQ_READ_LEN(n) (GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN + \
+ (GOODIX_BERLIN_BYTES_PER_POINT * (n)) + \
+ GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE)
+
+#define GOODIX_BERLIN_TOUCH_EVENT BIT(7)
+#define GOODIX_BERLIN_REQUEST_EVENT BIT(6)
+#define GOODIX_BERLIN_TOUCH_COUNT_MASK GENMASK(3, 0)
+
+#define GOODIX_BERLIN_REQUEST_CODE_RESET 3
+
+#define GOODIX_BERLIN_POINT_TYPE_MASK GENMASK(3, 0)
+#define GOODIX_BERLIN_POINT_TYPE_STYLUS_HOVER 1
+#define GOODIX_BERLIN_POINT_TYPE_STYLUS 3
+
+#define GOODIX_BERLIN_TOUCH_ID_MASK GENMASK(7, 4)
+
+#define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA
+#define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000
+#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014
+
+#define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K
+#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070
+
+struct goodix_berlin_fw_version {
+ u8 rom_pid[6];
+ u8 rom_vid[3];
+ u8 rom_vid_reserved;
+ u8 patch_pid[8];
+ u8 patch_vid[4];
+ u8 patch_vid_reserved;
+ u8 sensor_id;
+ u8 reserved[2];
+ __le16 checksum;
+} __packed;
+
+struct goodix_berlin_ic_info_version {
+ u8 info_customer_id;
+ u8 info_version_id;
+ u8 ic_die_id;
+ u8 ic_version_id;
+ __le32 config_id;
+ u8 config_version;
+ u8 frame_data_customer_id;
+ u8 frame_data_version_id;
+ u8 touch_data_customer_id;
+ u8 touch_data_version_id;
+ u8 reserved[3];
+} __packed;
+
+struct goodix_berlin_ic_info_feature {
+ __le16 freqhop_feature;
+ __le16 calibration_feature;
+ __le16 gesture_feature;
+ __le16 side_touch_feature;
+ __le16 stylus_feature;
+} __packed;
+
+struct goodix_berlin_ic_info_misc {
+ __le32 cmd_addr;
+ __le16 cmd_max_len;
+ __le32 cmd_reply_addr;
+ __le16 cmd_reply_len;
+ __le32 fw_state_addr;
+ __le16 fw_state_len;
+ __le32 fw_buffer_addr;
+ __le16 fw_buffer_max_len;
+ __le32 frame_data_addr;
+ __le16 frame_data_head_len;
+ __le16 fw_attr_len;
+ __le16 fw_log_len;
+ u8 pack_max_num;
+ u8 pack_compress_version;
+ __le16 stylus_struct_len;
+ __le16 mutual_struct_len;
+ __le16 self_struct_len;
+ __le16 noise_struct_len;
+ __le32 touch_data_addr;
+ __le16 touch_data_head_len;
+ __le16 point_struct_len;
+ __le16 reserved1;
+ __le16 reserved2;
+ __le32 mutual_rawdata_addr;
+ __le32 mutual_diffdata_addr;
+ __le32 mutual_refdata_addr;
+ __le32 self_rawdata_addr;
+ __le32 self_diffdata_addr;
+ __le32 self_refdata_addr;
+ __le32 iq_rawdata_addr;
+ __le32 iq_refdata_addr;
+ __le32 im_rawdata_addr;
+ __le16 im_readata_len;
+ __le32 noise_rawdata_addr;
+ __le16 noise_rawdata_len;
+ __le32 stylus_rawdata_addr;
+ __le16 stylus_rawdata_len;
+ __le32 noise_data_addr;
+ __le32 esd_addr;
+} __packed;
+
+struct goodix_berlin_touch_data {
+ u8 id;
+ u8 unused;
+ __le16 x;
+ __le16 y;
+ __le16 w;
+} __packed;
+
+struct goodix_berlin_core {
+ struct device *dev;
+ struct regmap *regmap;
+ struct regulator *avdd;
+ struct regulator *iovdd;
+ struct gpio_desc *reset_gpio;
+ struct touchscreen_properties props;
+ struct goodix_berlin_fw_version fw_version;
+ struct input_dev *input_dev;
+ int irq;
+
+ /* Runtime parameters extracted from IC_INFO buffer */
+ u32 touch_data_addr;
+};
+
static bool goodix_berlin_checksum_valid(const u8 *data, int size)
{
u32 cal_checksum = 0;
@@ -46,9 +182,11 @@ static bool goodix_berlin_checksum_valid(const u8 *data, int size)
for (i = 0; i < size - GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE; i++)
cal_checksum += data[i];
+ cal_checksum = FIELD_GET(GOODIX_BERLIN_COOR_DATA_CHECKSUM_MASK,
+ cal_checksum);
r_checksum = get_unaligned_le16(&data[i]);
- return FIELD_GET(GOODIX_BERLIN_COOR_DATA_CHECKSUM_MASK, cal_checksum) == r_checksum;
+ return cal_checksum == r_checksum;
}
static bool goodix_berlin_is_dummy_data(struct goodix_berlin_core *cd,
@@ -76,13 +214,15 @@ static int goodix_berlin_dev_confirm(struct goodix_berlin_core *cd)
memset(tx_buf, GOODIX_BERLIN_DEV_CONFIRM_VAL, sizeof(tx_buf));
while (retry--) {
- error = regmap_raw_write(cd->regmap, GOODIX_BERLIN_BOOTOPTION_ADDR, tx_buf,
- sizeof(tx_buf));
+ error = regmap_raw_write(cd->regmap,
+ GOODIX_BERLIN_BOOTOPTION_ADDR,
+ tx_buf, sizeof(tx_buf));
if (error)
return error;
- error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_BOOTOPTION_ADDR, rx_buf,
- sizeof(rx_buf));
+ error = regmap_raw_read(cd->regmap,
+ GOODIX_BERLIN_BOOTOPTION_ADDR,
+ rx_buf, sizeof(rx_buf));
if (error)
return error;
@@ -92,66 +232,70 @@ static int goodix_berlin_dev_confirm(struct goodix_berlin_core *cd)
usleep_range(5000, 5100);
}
- dev_err(cd->dev, "device confirm failed, rx_buf: %*ph\n", 8, rx_buf);
+ dev_err(cd->dev, "device confirm failed, rx_buf: %*ph\n",
+ (int)sizeof(rx_buf), rx_buf);
return -EINVAL;
}
-static int goodix_berlin_power_on(struct goodix_berlin_core *cd, bool on)
+static int goodix_berlin_power_on(struct goodix_berlin_core *cd)
{
- int error = 0;
+ int error;
- if (on) {
- error = regulator_enable(cd->iovdd);
- if (error) {
- dev_err(cd->dev, "Failed to enable iovdd: %d\n", error);
- return error;
- }
+ error = regulator_enable(cd->iovdd);
+ if (error) {
+ dev_err(cd->dev, "Failed to enable iovdd: %d\n", error);
+ return error;
+ }
- /* Vendor waits 3ms for IOVDD to settle */
- usleep_range(3000, 3100);
+ /* Vendor waits 3ms for IOVDD to settle */
+ usleep_range(3000, 3100);
- error = regulator_enable(cd->avdd);
- if (error) {
- dev_err(cd->dev, "Failed to enable avdd: %d\n", error);
- goto err_iovdd_disable;
- }
+ error = regulator_enable(cd->avdd);
+ if (error) {
+ dev_err(cd->dev, "Failed to enable avdd: %d\n", error);
+ goto err_iovdd_disable;
+ }
- /* Vendor waits 15ms for IOVDD to settle */
- usleep_range(15000, 15100);
+ /* Vendor waits 15ms for IOVDD to settle */
+ usleep_range(15000, 15100);
- gpiod_set_value(cd->reset_gpio, 0);
+ gpiod_set_value_cansleep(cd->reset_gpio, 0);
- /* Vendor waits 4ms for Firmware to initialize */
- usleep_range(4000, 4100);
+ /* Vendor waits 4ms for Firmware to initialize */
+ usleep_range(4000, 4100);
- error = goodix_berlin_dev_confirm(cd);
- if (error)
- goto err_dev_reset;
+ error = goodix_berlin_dev_confirm(cd);
+ if (error)
+ goto err_dev_reset;
- /* Vendor waits 100ms for Firmware to fully boot */
- msleep(GOODIX_BERLIN_NORMAL_RESET_DELAY_MS);
+ /* Vendor waits 100ms for Firmware to fully boot */
+ msleep(GOODIX_BERLIN_NORMAL_RESET_DELAY_MS);
- return 0;
- }
+ return 0;
err_dev_reset:
- gpiod_set_value(cd->reset_gpio, 1);
-
+ gpiod_set_value_cansleep(cd->reset_gpio, 1);
regulator_disable(cd->avdd);
-
err_iovdd_disable:
regulator_disable(cd->iovdd);
-
return error;
}
+static void goodix_berlin_power_off(struct goodix_berlin_core *cd)
+{
+ gpiod_set_value_cansleep(cd->reset_gpio, 1);
+ regulator_disable(cd->avdd);
+ regulator_disable(cd->iovdd);
+}
+
static int goodix_berlin_read_version(struct goodix_berlin_core *cd)
{
u8 buf[sizeof(struct goodix_berlin_fw_version)];
int error;
- error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR, buf, sizeof(buf));
+ error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR,
+ buf, sizeof(buf));
if (error) {
dev_err(cd->dev, "error reading fw version, %d\n", error);
return error;
@@ -235,8 +379,8 @@ static int goodix_berlin_convert_ic_info(struct goodix_berlin_core *cd,
static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
{
+ u8 *afe_data __free(kfree) = NULL;
__le16 length_raw;
- u8 *afe_data;
u16 length;
int error;
@@ -248,53 +392,44 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
&length_raw, sizeof(length_raw));
if (error) {
dev_err(cd->dev, "failed get ic info length, %d\n", error);
- goto free_afe_data;
+ return error;
}
length = le16_to_cpu(length_raw);
if (length >= GOODIX_BERLIN_IC_INFO_MAX_LEN) {
dev_err(cd->dev, "invalid ic info length %d\n", length);
- error = -EINVAL;
- goto free_afe_data;
+ return -EINVAL;
}
error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
afe_data, length);
if (error) {
dev_err(cd->dev, "failed get ic info data, %d\n", error);
- goto free_afe_data;
+ return error;
}
/* check whether the data is valid (ex. bus default values) */
if (goodix_berlin_is_dummy_data(cd, afe_data, length)) {
dev_err(cd->dev, "fw info data invalid\n");
- error = -EINVAL;
- goto free_afe_data;
+ return -EINVAL;
}
if (!goodix_berlin_checksum_valid(afe_data, length)) {
dev_err(cd->dev, "fw info checksum error\n");
- error = -EINVAL;
- goto free_afe_data;
+ return -EINVAL;
}
error = goodix_berlin_convert_ic_info(cd, afe_data, length);
if (error)
- goto free_afe_data;
+ return error;
/* check some key info */
if (!cd->touch_data_addr) {
dev_err(cd->dev, "touch_data_addr is null\n");
- error = -EINVAL;
- goto free_afe_data;
+ return -EINVAL;
}
return 0;
-
-free_afe_data:
- kfree(afe_data);
-
- return error;
}
static void goodix_berlin_parse_finger(struct goodix_berlin_core *cd,
@@ -305,12 +440,12 @@ static void goodix_berlin_parse_finger(struct goodix_berlin_core *cd,
/* Report finger touches */
for (i = 0; i < touch_num; i++) {
- unsigned int id;
-
- id = FIELD_GET(GOODIX_BERLIN_TOUCH_ID_MASK, touch_data[i].id);
+ unsigned int id = FIELD_GET(GOODIX_BERLIN_TOUCH_ID_MASK,
+ touch_data[i].id);
if (id >= GOODIX_BERLIN_MAX_TOUCH) {
- dev_warn_ratelimited(cd->dev, "invalid finger id %d\n", id);
+ dev_warn_ratelimited(cd->dev,
+ "invalid finger id %d\n", id);
continue;
}
@@ -372,7 +507,7 @@ static void goodix_berlin_touch_handler(struct goodix_berlin_core *cd,
if (!goodix_berlin_checksum_valid(&buffer[GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN],
touch_num * GOODIX_BERLIN_BYTES_PER_POINT + 2)) {
- dev_err(cd->dev, "touch data checksum error, data: %*ph\n",
+ dev_err(cd->dev, "touch data checksum error: %*ph\n",
touch_num * GOODIX_BERLIN_BYTES_PER_POINT + 2,
&buffer[GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN]);
return;
@@ -385,16 +520,16 @@ static void goodix_berlin_touch_handler(struct goodix_berlin_core *cd,
static int goodix_berlin_request_handle_reset(struct goodix_berlin_core *cd)
{
- gpiod_set_value(cd->reset_gpio, 1);
+ gpiod_set_value_cansleep(cd->reset_gpio, 1);
usleep_range(2000, 2100);
- gpiod_set_value(cd->reset_gpio, 0);
+ gpiod_set_value_cansleep(cd->reset_gpio, 0);
msleep(GOODIX_BERLIN_NORMAL_RESET_DELAY_MS);
return 0;
}
-static irqreturn_t goodix_berlin_threadirq_func(int irq, void *data)
+static irqreturn_t goodix_berlin_irq(int irq, void *data)
{
struct goodix_berlin_core *cd = data;
u8 buf[GOODIX_BERLIN_IRQ_READ_LEN(2)];
@@ -405,7 +540,8 @@ static irqreturn_t goodix_berlin_threadirq_func(int irq, void *data)
error = regmap_raw_read(cd->regmap, cd->touch_data_addr, buf,
GOODIX_BERLIN_IRQ_READ_LEN(2));
if (error) {
- dev_err_ratelimited(cd->dev, "failed get event head data, %d\n", error);
+ dev_warn_ratelimited(cd->dev,
+ "failed get event head data: %d\n", error);
return IRQ_HANDLED;
}
@@ -413,7 +549,8 @@ static irqreturn_t goodix_berlin_threadirq_func(int irq, void *data)
return IRQ_HANDLED;
if (!goodix_berlin_checksum_valid(buf, GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN)) {
- dev_warn_ratelimited(cd->dev, "touch head checksum err : %*ph\n",
+ dev_warn_ratelimited(cd->dev,
+ "touch head checksum error: %*ph\n",
GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN, buf);
return IRQ_HANDLED;
}
@@ -421,7 +558,8 @@ static irqreturn_t goodix_berlin_threadirq_func(int irq, void *data)
event_status = buf[GOODIX_BERLIN_STATUS_OFFSET];
if (event_status & GOODIX_BERLIN_TOUCH_EVENT)
- goodix_berlin_touch_handler(cd, buf, GOODIX_BERLIN_IRQ_READ_LEN(2));
+ goodix_berlin_touch_handler(cd, buf,
+ GOODIX_BERLIN_IRQ_READ_LEN(2));
if (event_status & GOODIX_BERLIN_REQUEST_EVENT) {
switch (buf[GOODIX_BERLIN_REQUEST_TYPE_OFFSET]) {
@@ -460,8 +598,10 @@ static int goodix_berlin_input_dev_config(struct goodix_berlin_core *cd,
input_dev->id = *id;
- input_set_abs_params(cd->input_dev, ABS_MT_POSITION_X, 0, SZ_64K - 1, 0, 0);
- input_set_abs_params(cd->input_dev, ABS_MT_POSITION_Y, 0, SZ_64K - 1, 0, 0);
+ input_set_abs_params(cd->input_dev, ABS_MT_POSITION_X,
+ 0, SZ_64K - 1, 0, 0);
+ input_set_abs_params(cd->input_dev, ABS_MT_POSITION_Y,
+ 0, SZ_64K - 1, 0, 0);
input_set_abs_params(cd->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
touchscreen_parse_properties(cd->input_dev, true, &cd->props);
@@ -478,21 +618,22 @@ static int goodix_berlin_input_dev_config(struct goodix_berlin_core *cd,
return 0;
}
-static int goodix_berlin_pm_suspend(struct device *dev)
+static int goodix_berlin_suspend(struct device *dev)
{
struct goodix_berlin_core *cd = dev_get_drvdata(dev);
disable_irq(cd->irq);
+ goodix_berlin_power_off(cd);
- return goodix_berlin_power_on(cd, false);
+ return 0;
}
-static int goodix_berlin_pm_resume(struct device *dev)
+static int goodix_berlin_resume(struct device *dev)
{
struct goodix_berlin_core *cd = dev_get_drvdata(dev);
int error;
- error = goodix_berlin_power_on(cd, true);
+ error = goodix_berlin_power_on(cd);
if (error)
return error;
@@ -502,14 +643,13 @@ static int goodix_berlin_pm_resume(struct device *dev)
}
EXPORT_GPL_SIMPLE_DEV_PM_OPS(goodix_berlin_pm_ops,
- goodix_berlin_pm_suspend,
- goodix_berlin_pm_resume);
+ goodix_berlin_suspend, goodix_berlin_resume);
-static void goodix_berlin_power_off(void *data)
+static void goodix_berlin_power_off_act(void *data)
{
struct goodix_berlin_core *cd = data;
- goodix_berlin_power_on(cd, false);
+ goodix_berlin_power_off(cd);
}
int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
@@ -546,13 +686,13 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
return dev_err_probe(dev, PTR_ERR(cd->iovdd),
"Failed to request iovdd regulator\n");
- error = goodix_berlin_power_on(cd, true);
+ error = goodix_berlin_power_on(cd);
if (error) {
dev_err(dev, "failed power on");
return error;
}
- error = devm_add_action_or_reset(dev, goodix_berlin_power_off, cd);
+ error = devm_add_action_or_reset(dev, goodix_berlin_power_off_act, cd);
if (error)
return error;
@@ -574,8 +714,7 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
return error;
}
- error = devm_request_threaded_irq(dev, irq, NULL,
- goodix_berlin_threadirq_func,
+ error = devm_request_threaded_irq(dev, cd->irq, NULL, goodix_berlin_irq,
IRQF_ONESHOT, "goodix-berlin", cd);
if (error) {
dev_err(dev, "request threaded irq failed: %d\n", error);
@@ -584,7 +723,8 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
dev_set_drvdata(dev, cd);
- dev_dbg(dev, "Goodix Berlin %s Touchscreen Controller", cd->fw_version.patch_pid);
+ dev_dbg(dev, "Goodix Berlin %s Touchscreen Controller",
+ cd->fw_version.patch_pid);
return 0;
}
^ permalink raw reply related
* Re: [PATCH v2 0/9] Support light color temperature and chromaticity
From: Jonathan Cameron @ 2023-12-10 11:07 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Basavaraj Natikar, jikos, benjamin.tissoires, lars,
srinivas.pandruvada, linux-input, linux-iio, regressions
In-Reply-To: <4441bd6b-01cd-4f26-bf85-bde2e1bf404e@t-8ch.de>
On Thu, 7 Dec 2023 00:39:28 +0100
Thomas Weißschuh <thomas@t-8ch.de> wrote:
> Hi everybody,
>
> On 2023-09-19 13:40:45+0530, Basavaraj Natikar wrote:
> > This series adds support for light color temperature and chromaticity.
> >
> > v1->v2:
> > *Rename the series.
> > *Rename als_illum to als channel as it supports other channels.
> > *Update patch description to include same reading for the two existing
> > channels to use channel index to support more hub attributes.
> > *Keep line length under 80chars in hid-sensor-als.
> > *Add new channel type IIO_COLORTEMP.
> > *Update patch description and its subject to add channel type for
> > chromaticity.
> >
> > Basavaraj Natikar (9):
> > iio: hid-sensor-als: Use channel index to support more hub attributes
> > iio: Add channel type light color temperature
> > iio: hid-sensor-als: Add light color temperature support
> > HID: amd_sfh: Add support for light color temperature
> > HID: amd_sfh: Add support for SFH1.1 light color temperature
> > iio: Add channel type for chromaticity
> > iio: hid-sensor-als: Add light chromaticity support
> > HID: amd_sfh: Add light chromaticity support
> > HID: amd_sfh: Add light chromaticity for SFH1.1
>
> This series is breaking probing of hid-sensor-als on Framework 13 AMD
> laptops [0].
> The problem is that the patches require hid-sensors-als sensors to also
> report chromaticity and color temparature which they don't.
Gah. Missed that in review. Sorry about that and thanks for digging into
this.
>
> When I remove the 'if (ret < 0) return ret;' checks in
> als_parse_report() probing works and the illuminance/intensity channels
> that show up behave as expected.
> Unfortunately this still leaves behind a bunch of unusable channels.
> A nice fix would be to have something like sysfs/hwmon .is_visible()
> callback but that's not supported by IIO.
It's tricky to do because there is no simple association between
what is registered as channels and the resulting attribute. We could probably
make it work, but not a simple thing to do.
>
> One aproach would be to detect the usable channels in als_parse_report()
> and then adapt the indio_dev->channels based on that information.
>
> [0] https://bugzilla.kernel.org/show_bug.cgi?id=218223
Agreed that adapting the channels is the way to go.
Easiest option probably to set the relevant masks to 0 if the chromacity and
temp channels aren't there + set their scan index values to -1.
That 'should' suppress any attributes being created.
Having a gap in scan indexes is common anyway so any userspace should cope
with the timestamp being after a gap.
Alternatives would be to rebuild the chan_spec array to not have the entries,
or pass in and fill in two copies of the array, picking the relevant one only
on discovering if the temp and chromacity channels are present.
Jonathan
>
> #regzbot introduced: 5f05285df691b1e82108eead7165feae238c95ef
> #regzbot monitor: https://bugzilla.kernel.org/show_bug.cgi?id=218223
>
^ permalink raw reply
* [PATCH v5 0/8] Convert DA906{1,2} bindings to json-schema
From: Biju Das @ 2023-12-10 13:47 UTC (permalink / raw)
To: Lee Jones, Wim Van Sebroeck, Guenter Roeck, Dmitry Torokhov,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Biju Das, Support Opensource, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Steve Twiss, linux-input, devicetree,
linux-pm, linux-watchdog, Geert Uytterhoeven,
Prabhakar Mahadev Lad, Biju Das, linux-renesas-soc
Convert the below bindings to json-schema
1) DA906{1,2} mfd bindings
2) DA906{1,2,3} onkey bindings
3) DA906{1,2,3} thermal bindings
Also add fallback for DA9061 watchdog device and document
DA9063 watchdog device.
Document missing gpio child node for da9062 and update MAINTAINERS entries.
Merge strategy:
Since there is binding dependency between input, thermal, watchdog and MFD
subsystem. it is decided that this series will go through the MFD tree.
So once the respective subsystem maintainers, DT and Renesas are happy
with the patch they can give an ack/rb tag, so that it can be applied to
MFD tree.
Note:
This patch series is same as v3.1 as it allows the tools (PW, b4)
to compare against previous versions.
The review comments/tags received for v4 + (a.k.a v3.1) will be
addressed in the next version(v5).
Link to v3.1: https://lore.kernel.org/all/20231204172510.35041-1-biju.das.jz@bp.renesas.com/
v4->v5:
* Updated cover letter with merging strategy.
* Added fixes tag for patch#1
* Added Rb tags from Geert and Krzysztof for patch#1
* Added Ack from Conor for patch#1
* Added Rb tag from Geert and Ack from Conor for patch#2
* Drop items and just use enum as it is easier to read for compatibles.
* Retained the tags for patch#2 as it is trivial change.
* Added Rb tag from Geert for patch#3
* Updated commit header and description by replacing
'watchdog property'->'watchdog child node'
* Added Rb tag from Geert for patch#4.
* Added Rb tag from Krzysztof and Conor for patch#5
* Dropped Items, Just enum as it is easier to read compatibles.
* Retained tags for patch#5 as the changes are trivial.
* Updated commit description for patch#8
* Dropped unnecessary ref from gpio child node.
* Added gpio-hog pattern property
* Moved gpio-controller,gpio-cells above child nodes
* Sorted compatible in rtc child node.
* Dropped status from example.
* Updated the example.
v3->v4:
* Patch#1 is merge of patch#1 from v2 + patch#8 from v2.
* Dropped comment for d9061 watchdog fallback
* Replaced enum->const for dlg,da9061-watchdog and its fallback.
* Restored patch#4 in series 1 and dropped the thermal example
* Added Ack from Conor Dooley for da9063 watchdog binding support.
* Updated title DA9062/61->DA906{1,2,3} as it supports DA9063.
* Retained Rb tag since the changes are trivial.
* Added Ack from Conor for updating watchdog property
* Dropped link to product information.
* Patch#5(onkey) is squashed with patch#6 and patch#9 from v2.
* Replaced enum->const for dlg,da9061-onkey and its fallback.
* Dropped example
* Restored the thermal binding patch from v2.
* Dropped example
* Replaced enum->const for compatible property.
* Added Rb tag from Rob and retained Rb tag as changes are trivial.
* Added Ack from Conor Dooley for patch#7.
* Split the thermal binding patch separate
* Updated the description
v2->v3:
* Updated Maintainer entries for watchdog,onkey and thermal bindings
* Fixed bot errors related to MAINTAINERS entry, invalid doc
references and thermal examples by merging patch#4.
v1->v2:
Link: https://lore.kernel.org/all/20231201110840.37408-5-biju.das.jz@bp.renesas.com/
* DA9062 and DA9061 merged with DA9063
* Sorted the child devices
* mfd,onkey and thermal are pointing to child bindings
Biju Das (8):
dt-bindings: mfd: da9062: Update watchdog description
dt-bindings: watchdog: dlg,da9062-watchdog: Add fallback for DA9061
watchdog
dt-bindings: watchdog: dlg,da9062-watchdog: Document DA9063 watchdog
dt-bindings: mfd: dlg,da9063: Update watchdog child node
dt-bindings: input: Convert da906{1,2,3} onkey to json-schema
dt-bindings: thermal: Convert da906{1,2} thermal to json-schema
dt-bindings: mfd: dlg,da9063: Sort child devices
dt-bindings: mfd: dlg,da9063: Convert da9062 to json-schema
.../bindings/input/da9062-onkey.txt | 47 ----
.../bindings/input/dlg,da9062-onkey.yaml | 38 +++
.../devicetree/bindings/mfd/da9062.txt | 124 ---------
.../devicetree/bindings/mfd/dlg,da9063.yaml | 248 +++++++++++++++---
.../bindings/thermal/da9062-thermal.txt | 36 ---
.../bindings/thermal/dlg,da9062-thermal.yaml | 35 +++
.../watchdog/dlg,da9062-watchdog.yaml | 12 +-
MAINTAINERS | 6 +-
8 files changed, 298 insertions(+), 248 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/input/da9062-onkey.txt
create mode 100644 Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
delete mode 100644 Documentation/devicetree/bindings/mfd/da9062.txt
delete mode 100644 Documentation/devicetree/bindings/thermal/da9062-thermal.txt
create mode 100644 Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml
--
2.39.2
^ permalink raw reply
* [PATCH v5 5/8] dt-bindings: input: Convert da906{1,2,3} onkey to json-schema
From: Biju Das @ 2023-12-10 13:47 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Biju Das, Support Opensource, linux-input, devicetree,
Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das,
linux-renesas-soc, Conor Dooley, Krzysztof Kozlowski
In-Reply-To: <20231210134717.94020-1-biju.das.jz@bp.renesas.com>
Convert the da906{1,2,3} onkey device tree binding documentation to
json-schema.
Update MAINTAINERS entries, description and onkey property by
referring to dlg,da9062-onkey binding file.
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
v4->v5:
* Added Rb tag from Krzysztof and Conor
* Dropped Items, Just enum as it is easier to read compatibles.
* Retained tags as the changes are trivial.
v3->v4:
* Squashed with patch#6 and patch#9 from v2.
* Replaced enum->const for dlg,da9061-onkey and its fallback.
* Dropped example
v2->v3:
* Updated MAINTAINERS entries.
v2:
* New patch
---
.../bindings/input/da9062-onkey.txt | 47 -------------------
.../bindings/input/dlg,da9062-onkey.yaml | 39 +++++++++++++++
.../devicetree/bindings/mfd/da9062.txt | 2 +-
.../devicetree/bindings/mfd/dlg,da9063.yaml | 15 +-----
MAINTAINERS | 2 +-
5 files changed, 42 insertions(+), 63 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/input/da9062-onkey.txt
create mode 100644 Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
diff --git a/Documentation/devicetree/bindings/input/da9062-onkey.txt b/Documentation/devicetree/bindings/input/da9062-onkey.txt
deleted file mode 100644
index e5eef59a93dc..000000000000
--- a/Documentation/devicetree/bindings/input/da9062-onkey.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-* Dialog DA9061/62/63 OnKey Module
-
-This module is part of the DA9061/DA9062/DA9063. For more details about entire
-DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
-For DA9063 see Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
-
-This module provides the KEY_POWER event.
-
-Required properties:
-
-- compatible: should be one of the following valid compatible string lines:
- "dlg,da9061-onkey", "dlg,da9062-onkey"
- "dlg,da9062-onkey"
- "dlg,da9063-onkey"
-
-Optional properties:
-
-- dlg,disable-key-power : Disable power-down using a long key-press. If this
- entry exists the OnKey driver will remove support for the KEY_POWER key
- press when triggered using a long press of the OnKey.
-
-Example: DA9063
-
- pmic0: da9063@58 {
- onkey {
- compatible = "dlg,da9063-onkey";
- dlg,disable-key-power;
- };
- };
-
-Example: DA9062
-
- pmic0: da9062@58 {
- onkey {
- compatible = "dlg,da9062-onkey";
- dlg,disable-key-power;
- };
- };
-
-Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
-
- pmic0: da9061@58 {
- onkey {
- compatible = "dlg,da9061-onkey", "dlg,da9062-onkey";
- dlg,disable-key-power;
- };
- };
diff --git a/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml b/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
new file mode 100644
index 000000000000..757a522c102c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/dlg,da9062-onkey.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Dialog DA9061/62/63 OnKey Module
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+
+description: |
+ This module is part of the DA9061/DA9062/DA9063. For more details about entire
+ DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
+ For DA9063 see Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
+
+ This module provides the KEY_POWER event.
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - dlg,da9062-onkey
+ - dlg,da9063-onkey
+ - items:
+ - const: dlg,da9061-onkey
+ - const: dlg,da9062-onkey
+
+ dlg,disable-key-power:
+ type: boolean
+ description:
+ Disable power-down using a long key-press. If this entry exists
+ the OnKey driver will remove support for the KEY_POWER key press
+ when triggered using a long press of the OnKey.
+
+required:
+ - compatible
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/da9062.txt b/Documentation/devicetree/bindings/mfd/da9062.txt
index 18463b7fbb42..154c31fa4443 100644
--- a/Documentation/devicetree/bindings/mfd/da9062.txt
+++ b/Documentation/devicetree/bindings/mfd/da9062.txt
@@ -84,7 +84,7 @@ Sub-nodes:
with the DA9062. There are currently no entries in this binding, however
compatible = "dlg,da9062-rtc" should be added if a node is created.
-- onkey : See ../input/da9062-onkey.txt
+- onkey : See ../input/dlg,da9062-onkey.yaml
- watchdog: See ../watchdog/dlg,da9062-watchdog.yaml
diff --git a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
index ce81e0b029cc..1e5a847a6be2 100644
--- a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
+++ b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
@@ -44,20 +44,7 @@ properties:
const: dlg,da9063-rtc
onkey:
- type: object
- $ref: /schemas/input/input.yaml#
- unevaluatedProperties: false
- properties:
- compatible:
- const: dlg,da9063-onkey
-
- dlg,disable-key-power:
- type: boolean
- description: |
- Disable power-down using a long key-press.
- If this entry does not exist then by default the key-press triggered
- power down is enabled and the OnKey will support both KEY_POWER and
- KEY_SLEEP.
+ $ref: /schemas/input/dlg,da9062-onkey.yaml
regulators:
type: object
diff --git a/MAINTAINERS b/MAINTAINERS
index 4e0c4a4581bf..e8782768368f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6109,8 +6109,8 @@ DIALOG SEMICONDUCTOR DRIVERS
M: Support Opensource <support.opensource@diasemi.com>
S: Supported
W: http://www.dialog-semiconductor.com/products
-F: Documentation/devicetree/bindings/input/da90??-onkey.txt
F: Documentation/devicetree/bindings/input/dlg,da72??.txt
+F: Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
F: Documentation/devicetree/bindings/mfd/da90*.txt
F: Documentation/devicetree/bindings/mfd/dlg,da90*.yaml
F: Documentation/devicetree/bindings/regulator/da92*.txt
--
2.39.2
^ permalink raw reply related
* [PATCH v5 8/8] dt-bindings: mfd: dlg,da9063: Convert da9062 to json-schema
From: Biju Das @ 2023-12-10 13:47 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lee Jones
Cc: Biju Das, Support Opensource, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Steve Twiss, linux-input, devicetree,
linux-pm, Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das,
linux-renesas-soc
In-Reply-To: <20231210134717.94020-1-biju.das.jz@bp.renesas.com>
Convert the da9062 PMIC device tree binding documentation to json-schema.
Document the missing gpio child node for da9062.
While at it, update description with link to product information and
example.
The missing child node with of_compatible defined in MFD_CELL_OF is
causing the below warning message:
da9062-gpio: Failed to locate of_node [id: -1]
So, make all child nodes with of_compatible defined in struct mfd_cell
as required property for da906{1,2} devices.
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v4->v5:
* Updated commit description
* Dropped unnecessary ref from gpio child node.
* Added gpio-hog pattern property
* Moved gpio-controller,gpio-cells above child nodes
* Sorted compatible in rtc child node.
* Dropped status from example.
* Updated the example.
v3->v4:
* Split the thermal binding patch separate.
* Updated the description.
v2->v3:
* Fixed bot errors related to MAINTAINERS entry, invalid doc
references and thermal examples by merging patch#4.
v2:
* New patch
---
.../bindings/input/dlg,da9062-onkey.yaml | 3 +-
.../devicetree/bindings/mfd/da9062.txt | 124 ----------
.../devicetree/bindings/mfd/dlg,da9063.yaml | 215 +++++++++++++++++-
.../bindings/thermal/dlg,da9062-thermal.yaml | 2 +-
4 files changed, 212 insertions(+), 132 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/mfd/da9062.txt
diff --git a/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml b/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
index 757a522c102c..1480d95421e1 100644
--- a/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
+++ b/Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
@@ -11,8 +11,7 @@ maintainers:
description: |
This module is part of the DA9061/DA9062/DA9063. For more details about entire
- DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
- For DA9063 see Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
+ DA906{1,2,3} chips see Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
This module provides the KEY_POWER event.
diff --git a/Documentation/devicetree/bindings/mfd/da9062.txt b/Documentation/devicetree/bindings/mfd/da9062.txt
deleted file mode 100644
index c8a7f119ac84..000000000000
--- a/Documentation/devicetree/bindings/mfd/da9062.txt
+++ /dev/null
@@ -1,124 +0,0 @@
-* Dialog DA9062 Power Management Integrated Circuit (PMIC)
-
-Product information for the DA9062 and DA9061 devices can be found here:
-- https://www.dialog-semiconductor.com/products/da9062
-- https://www.dialog-semiconductor.com/products/da9061
-
-The DA9062 PMIC consists of:
-
-Device Supply Names Description
------- ------------ -----------
-da9062-regulator : : LDOs & BUCKs
-da9062-rtc : : Real-Time Clock
-da9062-onkey : : On Key
-da9062-watchdog : : Watchdog Timer
-da9062-thermal : : Thermal
-da9062-gpio : : GPIOs
-
-The DA9061 PMIC consists of:
-
-Device Supply Names Description
------- ------------ -----------
-da9062-regulator : : LDOs & BUCKs
-da9062-onkey : : On Key
-da9062-watchdog : : Watchdog Timer
-da9062-thermal : : Thermal
-
-======
-
-Required properties:
-
-- compatible : Should be
- "dlg,da9062" for DA9062
- "dlg,da9061" for DA9061
-- reg : Specifies the I2C slave address (this defaults to 0x58 but it can be
- modified to match the chip's OTP settings).
-
-Optional properties:
-
-- gpio-controller : Marks the device as a gpio controller.
-- #gpio-cells : Should be two. The first cell is the pin number and the
- second cell is used to specify the gpio polarity.
-
-See Documentation/devicetree/bindings/gpio/gpio.txt for further information on
-GPIO bindings.
-
-- interrupts : IRQ line information.
-- interrupt-controller
-
-See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
-further information on IRQ bindings.
-
-Sub-nodes:
-
-- regulators : This node defines the settings for the LDOs and BUCKs.
- The DA9062 regulators are bound using their names listed below:
-
- buck1 : BUCK_1
- buck2 : BUCK_2
- buck3 : BUCK_3
- buck4 : BUCK_4
- ldo1 : LDO_1
- ldo2 : LDO_2
- ldo3 : LDO_3
- ldo4 : LDO_4
-
- The DA9061 regulators are bound using their names listed below:
-
- buck1 : BUCK_1
- buck2 : BUCK_2
- buck3 : BUCK_3
- ldo1 : LDO_1
- ldo2 : LDO_2
- ldo3 : LDO_3
- ldo4 : LDO_4
-
- The component follows the standard regulator framework and the bindings
- details of individual regulator device can be found in:
- Documentation/devicetree/bindings/regulator/regulator.txt
-
- regulator-initial-mode may be specified for buck regulators using mode values
- from include/dt-bindings/regulator/dlg,da9063-regulator.h.
-
-- rtc : This node defines settings required for the Real-Time Clock associated
- with the DA9062. There are currently no entries in this binding, however
- compatible = "dlg,da9062-rtc" should be added if a node is created.
-
-- onkey : See ../input/dlg,da9062-onkey.yaml
-
-- watchdog: See ../watchdog/dlg,da9062-watchdog.yaml
-
-- thermal : See ../thermal/dlg,da9062-thermal.yaml
-
-Example:
-
- pmic0: da9062@58 {
- compatible = "dlg,da9062";
- reg = <0x58>;
- interrupt-parent = <&gpio6>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
- interrupt-controller;
-
- rtc {
- compatible = "dlg,da9062-rtc";
- };
-
- regulators {
- DA9062_BUCK1: buck1 {
- regulator-name = "BUCK1";
- regulator-min-microvolt = <300000>;
- regulator-max-microvolt = <1570000>;
- regulator-min-microamp = <500000>;
- regulator-max-microamp = <2000000>;
- regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
- regulator-boot-on;
- };
- DA9062_LDO1: ldo1 {
- regulator-name = "LDO_1";
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <3600000>;
- regulator-boot-on;
- };
- };
- };
-
diff --git a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
index 676b4f2566ae..da741c999445 100644
--- a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
+++ b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/mfd/dlg,da9063.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Dialog DA9063/DA9063L Power Management Integrated Circuit (PMIC)
+title: Dialog DA906{3L,3,2,1} Power Management Integrated Circuit (PMIC)
maintainers:
- Steve Twiss <stwiss.opensource@diasemi.com>
@@ -17,10 +17,17 @@ description: |
moment where all voltage monitors are disabled. Next, as da9063 only supports
UV *and* OV monitoring, both must be set to the same severity and value
(0: disable, 1: enable).
+ Product information for the DA906{3L,3,2,1} devices can be found here:
+ - https://www.dialog-semiconductor.com/products/da9063l
+ - https://www.dialog-semiconductor.com/products/da9063
+ - https://www.dialog-semiconductor.com/products/da9062
+ - https://www.dialog-semiconductor.com/products/da9061
properties:
compatible:
enum:
+ - dlg,da9061
+ - dlg,da9062
- dlg,da9063
- dlg,da9063l
@@ -35,6 +42,18 @@ properties:
"#interrupt-cells":
const: 2
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+ gpio:
+ type: object
+ additionalProperties: false
+ properties:
+ compatible:
+ const: dlg,da9062-gpio
+
onkey:
$ref: /schemas/input/dlg,da9062-onkey.yaml
@@ -42,7 +61,7 @@ properties:
type: object
additionalProperties: false
patternProperties:
- "^(ldo([1-9]|1[01])|bcore([1-2]|s-merged)|b(pro|mem|io|peri)|bmem-bio-merged)$":
+ "^(ldo([1-9]|1[01])|bcore([1-2]|s-merged)|b(pro|mem|io|peri)|bmem-bio-merged|buck[1-4])$":
$ref: /schemas/regulator/regulator.yaml
unevaluatedProperties: false
@@ -52,16 +71,85 @@ properties:
unevaluatedProperties: false
properties:
compatible:
- const: dlg,da9063-rtc
+ enum:
+ - dlg,da9062-rtc
+ - dlg,da9063-rtc
+
+ thermal:
+ $ref: /schemas/thermal/dlg,da9062-thermal.yaml
watchdog:
$ref: /schemas/watchdog/dlg,da9062-watchdog.yaml
+patternProperties:
+ "^(.+-hog(-[0-9]+)?)$":
+ type: object
+
+ required:
+ - gpio-hog
+
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - dlg,da9063
+ - dlg,da9063l
+ then:
+ properties:
+ gpio-controller: false
+ "#gpio-cells": false
+ gpio: false
+ regulators:
+ patternProperties:
+ "^buck[1-4]$": false
+ thermal: false
+ required:
+ - interrupts
+ - interrupt-controller
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - dlg,da9062
+ then:
+ properties:
+ regulators:
+ patternProperties:
+ "^(ldo([5-9]|10|11)|bcore([1-2]|s-merged)|b(pro|mem|io|peri)|bmem-bio-merged)$": false
+ required:
+ - gpio
+ - onkey
+ - rtc
+ - thermal
+ - watchdog
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - dlg,da9061
+ then:
+ properties:
+ gpio-controller: false
+ "#gpio-cells": false
+ gpio: false
+ regulators:
+ patternProperties:
+ "^(ldo([5-9]|10|11)|bcore([1-2]|s-merged)|b(pro|mem|io|peri)|bmem-bio-merged|buck4)$": false
+ rtc: false
+ required:
+ - onkey
+ - thermal
+ - watchdog
additionalProperties: false
@@ -118,4 +206,121 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/regulator/dlg,da9063-regulator.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pmic@58 {
+ compatible = "dlg,da9062";
+ reg = <0x58>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ sd0-pwr-sel-hog {
+ gpio-hog;
+ gpios = <1 0>;
+ input;
+ line-name = "SD0_PWR_SEL";
+ };
+
+ sd1-pwr-sel-hog {
+ gpio-hog;
+ gpios = <2 0>;
+ input;
+ line-name = "SD1_PWR_SEL";
+ };
+
+ sw-et0-en-hog {
+ gpio-hog;
+ gpios = <3 0>;
+ input;
+ line-name = "SW_ET0_EN#";
+ };
+
+ pmic-good-hog {
+ gpio-hog;
+ gpios = <4 0>;
+ output-high;
+ line-name = "PMIC_PGOOD";
+ };
+
+ gpio {
+ compatible = "dlg,da9062-gpio";
+ };
+
+ onkey {
+ compatible = "dlg,da9062-onkey";
+ };
+
+ regulators {
+ buck1 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1380000>;
+ regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
+ regulator-always-on;
+ };
+ buck2 {
+ regulator-name = "vdd_soc";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1380000>;
+ regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
+ regulator-always-on;
+ };
+ buck3 {
+ regulator-name = "vdd_ddr3";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
+ regulator-always-on;
+ };
+ buck4 {
+ regulator-name = "vdd_eth";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
+ regulator-always-on;
+ };
+ ldo1 {
+ regulator-name = "vdd_snvs";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+ ldo2 {
+ regulator-name = "vdd_high";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+ ldo3 {
+ regulator-name = "vdd_eth_io";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ };
+ ldo4 {
+ regulator-name = "vdd_emmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ };
+
+ rtc {
+ compatible = "dlg,da9062-rtc";
+ };
+
+ thermal {
+ compatible = "dlg,da9062-thermal";
+ };
+
+ watchdog {
+ compatible = "dlg,da9062-watchdog";
+ dlg,use-sw-pm;
+ };
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml b/Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml
index 206635f74850..e8b2cac41084 100644
--- a/Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml
@@ -11,7 +11,7 @@ maintainers:
description: |
This module is part of the DA9061/DA9062. For more details about entire
- DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
+ DA906{1,2} chips see Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
Junction temperature thermal module uses an interrupt signal to identify
high THERMAL_TRIP_HOT temperatures for the PMIC device.
--
2.39.2
^ permalink raw reply related
* [PATCH] Input: xpad - Remove usage of the deprecated ida_simple_xx() API
From: Christophe JAILLET @ 2023-12-10 17:20 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, kernel-janitors, Christophe JAILLET, linux-input
ida_alloc() and ida_free() should be preferred to the deprecated
ida_simple_get() and ida_simple_remove().
This is less verbose.
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
---
drivers/input/joystick/xpad.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f5c21565bb3c..00c77e906744 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1669,7 +1669,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
if (!led)
return -ENOMEM;
- xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL);
+ xpad->pad_nr = ida_alloc(&xpad_pad_seq, GFP_KERNEL);
if (xpad->pad_nr < 0) {
error = xpad->pad_nr;
goto err_free_mem;
@@ -1692,7 +1692,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
return 0;
err_free_id:
- ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
+ ida_free(&xpad_pad_seq, xpad->pad_nr);
err_free_mem:
kfree(led);
xpad->led = NULL;
@@ -1705,7 +1705,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)
if (xpad_led) {
led_classdev_unregister(&xpad_led->led_cdev);
- ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
+ ida_free(&xpad_pad_seq, xpad->pad_nr);
kfree(xpad_led);
}
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] irq: Resolve that mask_irq/unmask_irq may not be called in pairs
From: xiongxin @ 2023-12-11 3:10 UTC (permalink / raw)
To: Thomas Gleixner, jikos, benjamin.tissoires; +Cc: linux-input, stable, Riwen Lu
In-Reply-To: <87ttosssxd.ffs@tglx>
在 2023/12/8 21:52, Thomas Gleixner 写道:
> On Thu, Dec 07 2023 at 09:40, xiongxin@kylinos.cn wrote:
>> When an interrupt controller uses a function such as handle_level_irq()
>> as an interrupt handler and the controller implements the irq_disable()
>> callback, the following scenario will appear in the i2c-hid driver in
>> the sleep scenario:
>>
>> in the sleep flow, while the user is still triggering the i2c-hid
>> interrupt, we get the following function call:
>>
>> handle_level_irq()
>> -> mask_ack_irq()
>> -> mask_irq()
>> i2c_hid_core_suspend()
>> -> disable_irq()
>> -> __irq_disable()
>> -> irq_state_set_disabled()
>> -> irq_state_set_masked()
>>
>> irq_thread_fn()
>> -> irq_finalize_oneshot()
>> -> if (!desc->threads_oneshot && !irqd_irq_disabled() &&
>> irqd_irq_masked())
>> unmask_threaded_irq()
>> -> unmask_irq()
>>
>> That is, when __irq_disable() is called between mask_irq() and
>> irq_finalize_oneshot(), the code in irq_finalize_oneshot() will cause
>> the !irqd_irq_disabled() fails to enter the unmask_irq() branch, which
>> causes mask_irq/unmask_irq to be called unpaired and the i2c-hid
>> interrupt to be masked.
>>
>> Since mask_irq/unmask_irq and irq_disabled() belong to two different
>> hardware registers or policies, the !irqd_irq_disabled() assertion may
>> not be used to determine whether unmask_irq() needs to be called.
>
> No. That's fundamentally wrong.
>
> Disabled interrupts are disabled and can only be reenabled by the
> corresponding enable call. The existing code is entirely correct.
>
> What you are trying to do is unmasking a disabled interrupt, which
> results in inconsistent state.
>
> Which interrupt chip is involved here?
i2c hid driver use gpio interrupt controller like
drivers/gpio/gpio-dwapb.c, The gpio interrupt controller code implements
handle_level_irq() and irq_disabled().
>
> Thanks,
>
> tglx
>
According to my code tracking and analysis:
Normally, when using the i2c hid device, the gpio interrupt controller's
mask_irq() and unmask_irq() are called in pairs.For example, the process
is as follows:
mask_irq();
if (!irqd_irq_disabled() && irqd_irq_masked())
unmask_irq();
irq_state_set_disabled();
irq_state_set_masked();
In this process, unmask_irq() will be called, and the following
mask_irq()/unmask_irq() will return directly.
But when doing a sleep process, such as suspend to RAM,
i2c_hid_core_suspend() of the i2c hid driver is called, which implements
the disable_irq() function, which finally calls __irq_disable(). Because
the desc parameter is set to the __irq_disabled() function without a
lock (desk->lock), the __irq_disabled() function can be called during
the execution of the handle_level_irq() function, which causes the
following:
mask_irq();
irq_state_set_disabled();
irq_state_set_masked();
if (!irqd_irq_disabled() && irqd_irq_masked())
unmask_irq();
In this scenario, unmask_irq() will not be called, and then gpio
corresponding interrupt pin will be masked. Finally, in the suspend()
process driven by gpio interrupt controller, the interrupt mask register
will be saved, and then masked will continue to be read when resuming ()
process. After the kernel resumed, the i2c hid gpio interrupt was masked
and the i2c hid device was unavailable.
^ permalink raw reply
* [dtor-input:next] BUILD SUCCESS 909484169a7bd935b4e56e1d77d63e8fccf6c6f1
From: kernel test robot @ 2023-12-11 7:30 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: 909484169a7bd935b4e56e1d77d63e8fccf6c6f1 Input: pxrc - simplify mutex handling with guard macro
Warning ids grouped by kconfigs:
gcc_recent_errors
|-- alpha-randconfig-r053-20231211
| `-- drivers-input-touchscreen-edt-ft5x06.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
|-- arc-randconfig-r132-20231211
| |-- kernel-fork.c:sparse:sparse:incorrect-type-in-assignment-(different-address-spaces)-expected-struct-file-assigned-old_exe_file-got-struct-file-noderef-__rcu-assigned-_val_
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-assigned-usertype-expec-got-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-assigned-usertype-sum-got-unsigned-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-expec-got-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-expec-got-restricted-__sum16-const
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-result-got-restricted-__sum16
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-sum-got-unsigned-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-initializer-(different-base-types)-expected-long-long-left_value-got-restricted-__wsum-const-__left
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-initializer-(different-base-types)-expected-long-long-right_value-got-restricted-__wsum-const-__right
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-initializer-(different-base-types)-expected-restricted-__wsum-got-unsigned-int
| `-- lib-checksum_kunit.c:sparse:sparse:restricted-__wsum-degrades-to-integer
|-- csky-allmodconfig
| |-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-pata_ftide010.o
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-sata_gemini.o
|-- nios2-allmodconfig
| |-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-pata_ftide010.o
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-sata_gemini.o
|-- nios2-randconfig-r063-20231211
| `-- drivers-input-misc-iqs7222.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
|-- openrisc-randconfig-r051-20231211
| `-- drivers-input-touchscreen-edt-ft5x06.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
|-- riscv-allmodconfig
| |-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-pata_ftide010.o
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-sata_gemini.o
|-- sh-randconfig-r121-20231211
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-assigned-usertype-expec-got-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-assigned-usertype-sum-got-unsigned-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-expec-got-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-expec-got-restricted-__sum16-const
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-result-got-restricted-__sum16
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-restricted-__wsum-usertype-sum-got-unsigned-int
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-initializer-(different-base-types)-expected-long-long-left_value-got-restricted-__wsum-const-__left
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-initializer-(different-base-types)-expected-long-long-right_value-got-restricted-__wsum-const-__right
| |-- lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-initializer-(different-base-types)-expected-restricted-__wsum-got-unsigned-int
| `-- lib-checksum_kunit.c:sparse:sparse:restricted-__wsum-degrades-to-integer
`-- um-randconfig-r052-20231211
`-- drivers-input-touchscreen-edt-ft5x06.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
clang_recent_errors
|-- arm64-allmodconfig
| |-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-pata_ftide010.o
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-sata_gemini.o
|-- arm64-randconfig-r123-20231211
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-soc-amlogic-meson-secure-pwrc.o
|-- hexagon-allmodconfig
| |-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-pata_ftide010.o
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-sata_gemini.o
|-- i386-randconfig-051-20231211
| `-- drivers-input-misc-iqs7222.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
|-- i386-randconfig-054-20231211
| |-- drivers-input-touchscreen-edt-ft5x06.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
| `-- drivers-input-touchscreen-iqs7211.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
|-- powerpc-randconfig-001-20231211
| `-- PLEASE-submit-a-bug-report-to-https:github.com-llvm-llvm-project-issues-and-include-the-crash-backtrace-preprocessed-source-and-associated-run-script.
|-- x86_64-allmodconfig
| |-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-pata_ftide010.o
| `-- WARNING:modpost:missing-MODULE_DESCRIPTION()-in-drivers-ata-sata_gemini.o
|-- x86_64-randconfig-103-20231211
| |-- drivers-input-touchscreen-edt-ft5x06.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
| `-- drivers-input-touchscreen-iqs7211.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
`-- x86_64-randconfig-104-20231211
`-- drivers-input-touchscreen-edt-ft5x06.c:WARNING:Threaded-IRQ-with-no-primary-handler-requested-without-IRQF_ONESHOT-(unless-it-is-nested-IRQ)
elapsed time: 1451m
configs tested: 194
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc
alpha allyesconfig gcc
alpha defconfig gcc
arc allmodconfig gcc
arc allnoconfig gcc
arc allyesconfig gcc
arc defconfig gcc
arc haps_hs_smp_defconfig gcc
arc nsimosci_hs_smp_defconfig gcc
arc randconfig-001-20231211 gcc
arc randconfig-002-20231211 gcc
arm allmodconfig gcc
arm allnoconfig gcc
arm allyesconfig gcc
arm assabet_defconfig gcc
arm axm55xx_defconfig gcc
arm defconfig clang
arm jornada720_defconfig gcc
arm multi_v4t_defconfig gcc
arm pxa910_defconfig gcc
arm randconfig-001-20231211 clang
arm randconfig-002-20231211 clang
arm randconfig-003-20231211 clang
arm randconfig-004-20231211 clang
arm spitz_defconfig clang
arm64 allmodconfig clang
arm64 allnoconfig gcc
arm64 defconfig gcc
arm64 randconfig-001-20231211 clang
arm64 randconfig-002-20231211 clang
arm64 randconfig-003-20231211 clang
arm64 randconfig-004-20231211 clang
csky allmodconfig gcc
csky allnoconfig gcc
csky allyesconfig gcc
csky defconfig gcc
csky randconfig-001-20231211 gcc
csky randconfig-002-20231211 gcc
hexagon allmodconfig clang
hexagon allnoconfig clang
hexagon allyesconfig clang
hexagon defconfig clang
hexagon randconfig-001-20231211 clang
hexagon randconfig-002-20231211 clang
i386 allmodconfig clang
i386 allnoconfig clang
i386 allyesconfig clang
i386 buildonly-randconfig-001-20231210 gcc
i386 buildonly-randconfig-002-20231210 gcc
i386 buildonly-randconfig-003-20231210 gcc
i386 buildonly-randconfig-004-20231210 gcc
i386 buildonly-randconfig-005-20231210 gcc
i386 buildonly-randconfig-006-20231210 gcc
i386 defconfig gcc
i386 randconfig-001-20231210 gcc
i386 randconfig-002-20231210 gcc
i386 randconfig-003-20231210 gcc
i386 randconfig-004-20231210 gcc
i386 randconfig-005-20231210 gcc
i386 randconfig-006-20231210 gcc
i386 randconfig-011-20231210 clang
i386 randconfig-012-20231210 clang
i386 randconfig-013-20231210 clang
i386 randconfig-014-20231210 clang
i386 randconfig-015-20231210 clang
i386 randconfig-016-20231210 clang
loongarch allmodconfig gcc
loongarch allnoconfig gcc
loongarch defconfig gcc
loongarch randconfig-001-20231211 gcc
loongarch randconfig-002-20231211 gcc
m68k allmodconfig gcc
m68k allnoconfig gcc
m68k allyesconfig gcc
m68k defconfig gcc
m68k mvme147_defconfig gcc
m68k virt_defconfig gcc
microblaze allmodconfig gcc
microblaze allnoconfig gcc
microblaze allyesconfig gcc
microblaze defconfig gcc
mips allnoconfig clang
mips allyesconfig gcc
mips ath25_defconfig clang
mips bmips_be_defconfig gcc
mips cobalt_defconfig gcc
mips gcw0_defconfig gcc
mips ip28_defconfig gcc
mips loongson1c_defconfig clang
nios2 allmodconfig gcc
nios2 allnoconfig gcc
nios2 allyesconfig gcc
nios2 defconfig gcc
nios2 randconfig-001-20231211 gcc
nios2 randconfig-002-20231211 gcc
openrisc allnoconfig gcc
openrisc allyesconfig gcc
openrisc defconfig gcc
openrisc virt_defconfig gcc
parisc allmodconfig gcc
parisc allnoconfig gcc
parisc allyesconfig gcc
parisc defconfig gcc
parisc randconfig-001-20231211 gcc
parisc randconfig-002-20231211 gcc
parisc64 defconfig gcc
powerpc allmodconfig clang
powerpc allnoconfig gcc
powerpc allyesconfig clang
powerpc amigaone_defconfig gcc
powerpc arches_defconfig gcc
powerpc canyonlands_defconfig gcc
powerpc fsp2_defconfig clang
powerpc linkstation_defconfig gcc
powerpc powernv_defconfig clang
powerpc ppc40x_defconfig gcc
powerpc randconfig-001-20231211 clang
powerpc randconfig-002-20231211 clang
powerpc randconfig-003-20231211 clang
powerpc tqm8548_defconfig gcc
powerpc64 randconfig-001-20231211 clang
powerpc64 randconfig-002-20231211 clang
powerpc64 randconfig-003-20231211 clang
riscv allmodconfig gcc
riscv allnoconfig clang
riscv allyesconfig gcc
riscv defconfig gcc
riscv randconfig-001-20231211 clang
riscv randconfig-002-20231211 clang
riscv rv32_defconfig clang
s390 alldefconfig clang
s390 allmodconfig gcc
s390 allnoconfig gcc
s390 allyesconfig gcc
s390 defconfig gcc
s390 randconfig-001-20231211 gcc
s390 randconfig-002-20231211 gcc
s390 zfcpdump_defconfig gcc
sh allmodconfig gcc
sh allnoconfig gcc
sh allyesconfig gcc
sh defconfig gcc
sh randconfig-001-20231211 gcc
sh randconfig-002-20231211 gcc
sh se7705_defconfig gcc
sh se7722_defconfig gcc
sh sh2007_defconfig gcc
sparc allmodconfig gcc
sparc sparc32_defconfig gcc
sparc64 allmodconfig gcc
sparc64 allyesconfig gcc
sparc64 defconfig gcc
sparc64 randconfig-001-20231211 gcc
sparc64 randconfig-002-20231211 gcc
um allmodconfig clang
um allnoconfig clang
um allyesconfig clang
um defconfig gcc
um i386_defconfig gcc
um randconfig-001-20231211 clang
um randconfig-002-20231211 clang
um x86_64_defconfig gcc
x86_64 allnoconfig gcc
x86_64 allyesconfig clang
x86_64 buildonly-randconfig-001-20231211 clang
x86_64 buildonly-randconfig-002-20231211 clang
x86_64 buildonly-randconfig-003-20231211 clang
x86_64 buildonly-randconfig-004-20231211 clang
x86_64 buildonly-randconfig-005-20231211 clang
x86_64 buildonly-randconfig-006-20231211 clang
x86_64 defconfig gcc
x86_64 randconfig-001-20231211 gcc
x86_64 randconfig-002-20231211 gcc
x86_64 randconfig-003-20231211 gcc
x86_64 randconfig-004-20231211 gcc
x86_64 randconfig-005-20231211 gcc
x86_64 randconfig-006-20231211 gcc
x86_64 randconfig-011-20231211 clang
x86_64 randconfig-012-20231211 clang
x86_64 randconfig-013-20231211 clang
x86_64 randconfig-014-20231211 clang
x86_64 randconfig-015-20231211 clang
x86_64 randconfig-016-20231211 clang
x86_64 randconfig-071-20231211 clang
x86_64 randconfig-072-20231211 clang
x86_64 randconfig-073-20231211 clang
x86_64 randconfig-074-20231211 clang
x86_64 randconfig-075-20231211 clang
x86_64 randconfig-076-20231211 clang
x86_64 rhel-8.3-rust clang
xtensa allnoconfig gcc
xtensa nommu_kc705_defconfig gcc
xtensa randconfig-001-20231211 gcc
xtensa randconfig-002-20231211 gcc
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH v7 1/4] pwm: Rename pwm_apply_state() to pwm_apply_might_sleep()
From: Sean Young @ 2023-12-11 8:24 UTC (permalink / raw)
To: linux-media, linux-pwm, Ivaylo Dimitrov, Thierry Reding,
Uwe Kleine-König, Jonathan Corbet, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, David Airlie,
Daniel Vetter, Javier Martinez Canillas, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Jean Delvare, Guenter Roeck,
Support Opensource, Dmitry Torokhov, Pavel Machek, Lee Jones,
Sean Young, Mauro Carvalho Chehab, Hans de Goede,
Ilpo Järvinen, Liam Girdwood, Mark Brown, Daniel Thompson,
Jingoo Han, Helge Deller
Cc: Jani Nikula, linux-doc, linux-kernel, intel-gfx, dri-devel,
linux-hwmon, linux-input, linux-leds, platform-driver-x86,
linux-arm-kernel, linux-fbdev
In-Reply-To: <cover.1702282806.git.sean@mess.org>
In order to introduce a pwm api which can be used from atomic context,
we will need two functions for applying pwm changes:
int pwm_apply_might_sleep(struct pwm *, struct pwm_state *);
int pwm_apply_atomic(struct pwm *, struct pwm_state *);
This commit just deals with renaming pwm_apply_state(), a following
commit will introduce the pwm_apply_atomic() function.
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> # for input
Acked-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Acked-by: Lee Jones <lee@kernel.org>
Signed-off-by: Sean Young <sean@mess.org>
---
Documentation/driver-api/pwm.rst | 8 +++---
MAINTAINERS | 2 +-
.../gpu/drm/i915/display/intel_backlight.c | 6 ++--
drivers/gpu/drm/solomon/ssd130x.c | 2 +-
drivers/hwmon/pwm-fan.c | 8 +++---
drivers/input/misc/da7280.c | 4 +--
drivers/input/misc/pwm-beeper.c | 4 +--
drivers/input/misc/pwm-vibra.c | 8 +++---
drivers/leds/leds-pwm.c | 2 +-
drivers/leds/rgb/leds-pwm-multicolor.c | 4 +--
drivers/media/rc/pwm-ir-tx.c | 4 +--
drivers/platform/x86/lenovo-yogabook.c | 2 +-
drivers/pwm/core.c | 18 ++++++------
drivers/pwm/pwm-twl-led.c | 2 +-
drivers/pwm/pwm-vt8500.c | 2 +-
drivers/pwm/sysfs.c | 10 +++----
drivers/regulator/pwm-regulator.c | 4 +--
drivers/video/backlight/lm3630a_bl.c | 2 +-
drivers/video/backlight/lp855x_bl.c | 2 +-
drivers/video/backlight/pwm_bl.c | 12 ++++----
drivers/video/fbdev/ssd1307fb.c | 2 +-
include/linux/pwm.h | 28 +++++++++----------
22 files changed, 68 insertions(+), 68 deletions(-)
diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst
index bb264490a87a1..f1d8197c8c430 100644
--- a/Documentation/driver-api/pwm.rst
+++ b/Documentation/driver-api/pwm.rst
@@ -41,7 +41,7 @@ the getter, devm_pwm_get() and devm_fwnode_pwm_get(), also exist.
After being requested, a PWM has to be configured using::
- int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state);
+ int pwm_apply_might_sleep(struct pwm_device *pwm, struct pwm_state *state);
This API controls both the PWM period/duty_cycle config and the
enable/disable state.
@@ -57,13 +57,13 @@ If supported by the driver, the signal can be optimized, for example to improve
EMI by phase shifting the individual channels of a chip.
The pwm_config(), pwm_enable() and pwm_disable() functions are just wrappers
-around pwm_apply_state() and should not be used if the user wants to change
+around pwm_apply_might_sleep() and should not be used if the user wants to change
several parameter at once. For example, if you see pwm_config() and
pwm_{enable,disable}() calls in the same function, this probably means you
-should switch to pwm_apply_state().
+should switch to pwm_apply_might_sleep().
The PWM user API also allows one to query the PWM state that was passed to the
-last invocation of pwm_apply_state() using pwm_get_state(). Note this is
+last invocation of pwm_apply_might_sleep() using pwm_get_state(). Note this is
different to what the driver has actually implemented if the request cannot be
satisfied exactly with the hardware in use. There is currently no way for
consumers to get the actually implemented settings.
diff --git a/MAINTAINERS b/MAINTAINERS
index 0d96db7e1a9e4..c2a9e0b5594e7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17585,7 +17585,7 @@ F: drivers/video/backlight/pwm_bl.c
F: include/dt-bindings/pwm/
F: include/linux/pwm.h
F: include/linux/pwm_backlight.h
-K: pwm_(config|apply_state|ops)
+K: pwm_(config|apply_might_sleep|ops)
PXA GPIO DRIVER
M: Robert Jarzmik <robert.jarzmik@free.fr>
diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c
index 2e8f17c045222..ff9b9918b0a13 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_backlight.c
@@ -274,7 +274,7 @@ static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state,
struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100);
- pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state);
+ pwm_apply_might_sleep(panel->backlight.pwm, &panel->backlight.pwm_state);
}
static void
@@ -427,7 +427,7 @@ static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn
intel_backlight_set_pwm_level(old_conn_state, level);
panel->backlight.pwm_state.enabled = false;
- pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state);
+ pwm_apply_might_sleep(panel->backlight.pwm, &panel->backlight.pwm_state);
}
void intel_backlight_disable(const struct drm_connector_state *old_conn_state)
@@ -749,7 +749,7 @@ static void ext_pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100);
panel->backlight.pwm_state.enabled = true;
- pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state);
+ pwm_apply_might_sleep(panel->backlight.pwm, &panel->backlight.pwm_state);
}
static void __intel_backlight_enable(const struct intel_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index e0174f82e3537..cce043a4a1dcd 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -319,7 +319,7 @@ static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
pwm_init_state(ssd130x->pwm, &pwmstate);
pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
- pwm_apply_state(ssd130x->pwm, &pwmstate);
+ pwm_apply_might_sleep(ssd130x->pwm, &pwmstate);
/* Enable the PWM */
pwm_enable(ssd130x->pwm);
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index 6e4516c2ab894..b67bc9e833c01 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -151,7 +151,7 @@ static int pwm_fan_power_on(struct pwm_fan_ctx *ctx)
}
state->enabled = true;
- ret = pwm_apply_state(ctx->pwm, state);
+ ret = pwm_apply_might_sleep(ctx->pwm, state);
if (ret) {
dev_err(ctx->dev, "failed to enable PWM\n");
goto disable_regulator;
@@ -181,7 +181,7 @@ static int pwm_fan_power_off(struct pwm_fan_ctx *ctx)
state->enabled = false;
state->duty_cycle = 0;
- ret = pwm_apply_state(ctx->pwm, state);
+ ret = pwm_apply_might_sleep(ctx->pwm, state);
if (ret) {
dev_err(ctx->dev, "failed to disable PWM\n");
return ret;
@@ -207,7 +207,7 @@ static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
period = state->period;
state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
- ret = pwm_apply_state(ctx->pwm, state);
+ ret = pwm_apply_might_sleep(ctx->pwm, state);
if (ret)
return ret;
ret = pwm_fan_power_on(ctx);
@@ -278,7 +278,7 @@ static int pwm_fan_update_enable(struct pwm_fan_ctx *ctx, long val)
state,
&enable_regulator);
- pwm_apply_state(ctx->pwm, state);
+ pwm_apply_might_sleep(ctx->pwm, state);
pwm_fan_switch_power(ctx, enable_regulator);
pwm_fan_update_state(ctx, 0);
}
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c
index ce82548916bbc..c1fa75c0f970a 100644
--- a/drivers/input/misc/da7280.c
+++ b/drivers/input/misc/da7280.c
@@ -352,7 +352,7 @@ static int da7280_haptic_set_pwm(struct da7280_haptic *haptics, bool enabled)
state.duty_cycle = period_mag_multi;
}
- error = pwm_apply_state(haptics->pwm_dev, &state);
+ error = pwm_apply_might_sleep(haptics->pwm_dev, &state);
if (error)
dev_err(haptics->dev, "Failed to apply pwm state: %d\n", error);
@@ -1175,7 +1175,7 @@ static int da7280_probe(struct i2c_client *client)
/* Sync up PWM state and ensure it is off. */
pwm_init_state(haptics->pwm_dev, &state);
state.enabled = false;
- error = pwm_apply_state(haptics->pwm_dev, &state);
+ error = pwm_apply_might_sleep(haptics->pwm_dev, &state);
if (error) {
dev_err(dev, "Failed to apply PWM state: %d\n", error);
return error;
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index 1e731d8397c6f..5b9aedf4362f4 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -39,7 +39,7 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
state.period = period;
pwm_set_relative_duty_cycle(&state, 50, 100);
- error = pwm_apply_state(beeper->pwm, &state);
+ error = pwm_apply_might_sleep(beeper->pwm, &state);
if (error)
return error;
@@ -138,7 +138,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
/* Sync up PWM state and ensure it is off. */
pwm_init_state(beeper->pwm, &state);
state.enabled = false;
- error = pwm_apply_state(beeper->pwm, &state);
+ error = pwm_apply_might_sleep(beeper->pwm, &state);
if (error) {
dev_err(dev, "failed to apply initial PWM state: %d\n",
error);
diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c
index acac79c488aa1..3e5ed685ed8f5 100644
--- a/drivers/input/misc/pwm-vibra.c
+++ b/drivers/input/misc/pwm-vibra.c
@@ -56,7 +56,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff);
state.enabled = true;
- err = pwm_apply_state(vibrator->pwm, &state);
+ err = pwm_apply_might_sleep(vibrator->pwm, &state);
if (err) {
dev_err(pdev, "failed to apply pwm state: %d\n", err);
return err;
@@ -67,7 +67,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
state.duty_cycle = vibrator->direction_duty_cycle;
state.enabled = true;
- err = pwm_apply_state(vibrator->pwm_dir, &state);
+ err = pwm_apply_might_sleep(vibrator->pwm_dir, &state);
if (err) {
dev_err(pdev, "failed to apply dir-pwm state: %d\n", err);
pwm_disable(vibrator->pwm);
@@ -160,7 +160,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
/* Sync up PWM state and ensure it is off. */
pwm_init_state(vibrator->pwm, &state);
state.enabled = false;
- err = pwm_apply_state(vibrator->pwm, &state);
+ err = pwm_apply_might_sleep(vibrator->pwm, &state);
if (err) {
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
err);
@@ -174,7 +174,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
/* Sync up PWM state and ensure it is off. */
pwm_init_state(vibrator->pwm_dir, &state);
state.enabled = false;
- err = pwm_apply_state(vibrator->pwm_dir, &state);
+ err = pwm_apply_might_sleep(vibrator->pwm_dir, &state);
if (err) {
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
err);
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 2b3bf1353b707..4e3936a39d0ed 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -54,7 +54,7 @@ static int led_pwm_set(struct led_classdev *led_cdev,
led_dat->pwmstate.duty_cycle = duty;
led_dat->pwmstate.enabled = true;
- return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate);
+ return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate);
}
__attribute__((nonnull))
diff --git a/drivers/leds/rgb/leds-pwm-multicolor.c b/drivers/leds/rgb/leds-pwm-multicolor.c
index 46cd062b8b24c..e1a81e0109e8a 100644
--- a/drivers/leds/rgb/leds-pwm-multicolor.c
+++ b/drivers/leds/rgb/leds-pwm-multicolor.c
@@ -51,8 +51,8 @@ static int led_pwm_mc_set(struct led_classdev *cdev,
priv->leds[i].state.duty_cycle = duty;
priv->leds[i].state.enabled = duty > 0;
- ret = pwm_apply_state(priv->leds[i].pwm,
- &priv->leds[i].state);
+ ret = pwm_apply_might_sleep(priv->leds[i].pwm,
+ &priv->leds[i].state);
if (ret)
break;
}
diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c
index c5f37c03af9c9..cf51e27609759 100644
--- a/drivers/media/rc/pwm-ir-tx.c
+++ b/drivers/media/rc/pwm-ir-tx.c
@@ -68,7 +68,7 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
for (i = 0; i < count; i++) {
state.enabled = !(i % 2);
- pwm_apply_state(pwm, &state);
+ pwm_apply_might_sleep(pwm, &state);
edge = ktime_add_us(edge, txbuf[i]);
delta = ktime_us_delta(edge, ktime_get());
@@ -77,7 +77,7 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
}
state.enabled = false;
- pwm_apply_state(pwm, &state);
+ pwm_apply_might_sleep(pwm, &state);
return count;
}
diff --git a/drivers/platform/x86/lenovo-yogabook.c b/drivers/platform/x86/lenovo-yogabook.c
index b8d0239192cbf..fd62bf746ebde 100644
--- a/drivers/platform/x86/lenovo-yogabook.c
+++ b/drivers/platform/x86/lenovo-yogabook.c
@@ -435,7 +435,7 @@ static int yogabook_pdev_set_kbd_backlight(struct yogabook_data *data, u8 level)
.enabled = level,
};
- pwm_apply_state(data->kbd_bl_pwm, &state);
+ pwm_apply_might_sleep(data->kbd_bl_pwm, &state);
gpiod_set_value(data->kbd_bl_led_enable, level ? 1 : 0);
return 0;
}
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index f60b715abe62b..c2d78136625d5 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -326,8 +326,8 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
}
EXPORT_SYMBOL_GPL(pwm_request_from_chip);
-static void pwm_apply_state_debug(struct pwm_device *pwm,
- const struct pwm_state *state)
+static void pwm_apply_debug(struct pwm_device *pwm,
+ const struct pwm_state *state)
{
struct pwm_state *last = &pwm->last;
struct pwm_chip *chip = pwm->chip;
@@ -433,11 +433,11 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
}
/**
- * pwm_apply_state() - atomically apply a new state to a PWM device
+ * pwm_apply_might_sleep() - atomically apply a new state to a PWM device
* @pwm: PWM device
* @state: new state to apply
*/
-int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
+int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
{
struct pwm_chip *chip;
int err;
@@ -445,7 +445,7 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
/*
* Some lowlevel driver's implementations of .apply() make use of
* mutexes, also with some drivers only returning when the new
- * configuration is active calling pwm_apply_state() from atomic context
+ * configuration is active calling pwm_apply_might_sleep() from atomic context
* is a bad idea. So make it explicit that calling this function might
* sleep.
*/
@@ -475,11 +475,11 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
* only do this after pwm->state was applied as some
* implementations of .get_state depend on this
*/
- pwm_apply_state_debug(pwm, state);
+ pwm_apply_debug(pwm, state);
return 0;
}
-EXPORT_SYMBOL_GPL(pwm_apply_state);
+EXPORT_SYMBOL_GPL(pwm_apply_might_sleep);
/**
* pwm_capture() - capture and report a PWM signal
@@ -537,7 +537,7 @@ int pwm_adjust_config(struct pwm_device *pwm)
state.period = pargs.period;
state.polarity = pargs.polarity;
- return pwm_apply_state(pwm, &state);
+ return pwm_apply_might_sleep(pwm, &state);
}
/*
@@ -560,7 +560,7 @@ int pwm_adjust_config(struct pwm_device *pwm)
state.duty_cycle = state.period - state.duty_cycle;
}
- return pwm_apply_state(pwm, &state);
+ return pwm_apply_might_sleep(pwm, &state);
}
EXPORT_SYMBOL_GPL(pwm_adjust_config);
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c
index 8a870d0db3c69..c670ccb816536 100644
--- a/drivers/pwm/pwm-twl-led.c
+++ b/drivers/pwm/pwm-twl-led.c
@@ -172,7 +172,7 @@ static int twl4030_pwmled_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* We cannot skip calling ->config even if state->period ==
* pwm->state.period && state->duty_cycle == pwm->state.duty_cycle
* because we might have exited early in the last call to
- * pwm_apply_state because of !state->enabled and so the two values in
+ * pwm_apply_might_sleep because of !state->enabled and so the two values in
* pwm->state might not be configured in hardware.
*/
ret = twl4030_pwmled_config(chip, pwm,
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c
index bdea60389487e..7bfeacee05d0f 100644
--- a/drivers/pwm/pwm-vt8500.c
+++ b/drivers/pwm/pwm-vt8500.c
@@ -206,7 +206,7 @@ static int vt8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* We cannot skip calling ->config even if state->period ==
* pwm->state.period && state->duty_cycle == pwm->state.duty_cycle
* because we might have exited early in the last call to
- * pwm_apply_state because of !state->enabled and so the two values in
+ * pwm_apply_might_sleep because of !state->enabled and so the two values in
* pwm->state might not be configured in hardware.
*/
err = vt8500_pwm_config(chip, pwm, state->duty_cycle, state->period);
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 4edb994fa2e12..1698609d91c8a 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -62,7 +62,7 @@ static ssize_t period_store(struct device *child,
mutex_lock(&export->lock);
pwm_get_state(pwm, &state);
state.period = val;
- ret = pwm_apply_state(pwm, &state);
+ ret = pwm_apply_might_sleep(pwm, &state);
mutex_unlock(&export->lock);
return ret ? : size;
@@ -97,7 +97,7 @@ static ssize_t duty_cycle_store(struct device *child,
mutex_lock(&export->lock);
pwm_get_state(pwm, &state);
state.duty_cycle = val;
- ret = pwm_apply_state(pwm, &state);
+ ret = pwm_apply_might_sleep(pwm, &state);
mutex_unlock(&export->lock);
return ret ? : size;
@@ -144,7 +144,7 @@ static ssize_t enable_store(struct device *child,
goto unlock;
}
- ret = pwm_apply_state(pwm, &state);
+ ret = pwm_apply_might_sleep(pwm, &state);
unlock:
mutex_unlock(&export->lock);
@@ -194,7 +194,7 @@ static ssize_t polarity_store(struct device *child,
mutex_lock(&export->lock);
pwm_get_state(pwm, &state);
state.polarity = polarity;
- ret = pwm_apply_state(pwm, &state);
+ ret = pwm_apply_might_sleep(pwm, &state);
mutex_unlock(&export->lock);
return ret ? : size;
@@ -401,7 +401,7 @@ static int pwm_class_apply_state(struct pwm_export *export,
struct pwm_device *pwm,
struct pwm_state *state)
{
- int ret = pwm_apply_state(pwm, state);
+ int ret = pwm_apply_might_sleep(pwm, state);
/* release lock taken in pwm_class_get_state */
mutex_unlock(&export->lock);
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index 2aff6db748e2c..698c420e0869b 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -90,7 +90,7 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
pwm_set_relative_duty_cycle(&pstate,
drvdata->duty_cycle_table[selector].dutycycle, 100);
- ret = pwm_apply_state(drvdata->pwm, &pstate);
+ ret = pwm_apply_might_sleep(drvdata->pwm, &pstate);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
@@ -216,7 +216,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit);
- ret = pwm_apply_state(drvdata->pwm, &pstate);
+ ret = pwm_apply_might_sleep(drvdata->pwm, &pstate);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c
index 8fcb62be597b8..a3412c936ca28 100644
--- a/drivers/video/backlight/lm3630a_bl.c
+++ b/drivers/video/backlight/lm3630a_bl.c
@@ -180,7 +180,7 @@ static int lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
pchip->pwmd_state.enabled = pchip->pwmd_state.duty_cycle ? true : false;
- return pwm_apply_state(pchip->pwmd, &pchip->pwmd_state);
+ return pwm_apply_might_sleep(pchip->pwmd, &pchip->pwmd_state);
}
/* update and get brightness */
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index da1f124db69c0..7075bfab59c4d 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -234,7 +234,7 @@ static int lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
state.duty_cycle = div_u64(br * state.period, max_br);
state.enabled = state.duty_cycle;
- return pwm_apply_state(lp->pwm, &state);
+ return pwm_apply_might_sleep(lp->pwm, &state);
}
static int lp855x_bl_update_status(struct backlight_device *bl)
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 289bd9ce4d36d..35c716e9043c3 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -103,7 +103,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
pwm_get_state(pb->pwm, &state);
state.duty_cycle = compute_duty_cycle(pb, brightness, &state);
state.enabled = true;
- pwm_apply_state(pb->pwm, &state);
+ pwm_apply_might_sleep(pb->pwm, &state);
pwm_backlight_power_on(pb);
} else {
@@ -120,7 +120,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
* inactive output.
*/
state.enabled = !pb->power_supply && !pb->enable_gpio;
- pwm_apply_state(pb->pwm, &state);
+ pwm_apply_might_sleep(pb->pwm, &state);
}
if (pb->notify_after)
@@ -528,7 +528,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
if (!state.period && (data->pwm_period_ns > 0))
state.period = data->pwm_period_ns;
- ret = pwm_apply_state(pb->pwm, &state);
+ ret = pwm_apply_might_sleep(pb->pwm, &state);
if (ret) {
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
ret);
@@ -633,7 +633,7 @@ static void pwm_backlight_remove(struct platform_device *pdev)
pwm_get_state(pb->pwm, &state);
state.duty_cycle = 0;
state.enabled = false;
- pwm_apply_state(pb->pwm, &state);
+ pwm_apply_might_sleep(pb->pwm, &state);
if (pb->exit)
pb->exit(&pdev->dev);
@@ -649,7 +649,7 @@ static void pwm_backlight_shutdown(struct platform_device *pdev)
pwm_get_state(pb->pwm, &state);
state.duty_cycle = 0;
state.enabled = false;
- pwm_apply_state(pb->pwm, &state);
+ pwm_apply_might_sleep(pb->pwm, &state);
}
#ifdef CONFIG_PM_SLEEP
@@ -673,7 +673,7 @@ static int pwm_backlight_suspend(struct device *dev)
pwm_get_state(pb->pwm, &state);
state.duty_cycle = 0;
state.enabled = false;
- pwm_apply_state(pb->pwm, &state);
+ pwm_apply_might_sleep(pb->pwm, &state);
if (pb->notify_after)
pb->notify_after(pb->dev, 0);
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 5ae48e36fccb4..1a4f90ea7d5a8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -347,7 +347,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
pwm_init_state(par->pwm, &pwmstate);
pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
- pwm_apply_state(par->pwm, &pwmstate);
+ pwm_apply_might_sleep(par->pwm, &pwmstate);
/* Enable the PWM */
pwm_enable(par->pwm);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index f87655c06c825..b64b8a82415c4 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -92,8 +92,8 @@ struct pwm_device {
* @state: state to fill with the current PWM state
*
* The returned PWM state represents the state that was applied by a previous call to
- * pwm_apply_state(). Drivers may have to slightly tweak that state before programming it to
- * hardware. If pwm_apply_state() was never called, this returns either the current hardware
+ * pwm_apply_might_sleep(). Drivers may have to slightly tweak that state before programming it to
+ * hardware. If pwm_apply_might_sleep() was never called, this returns either the current hardware
* state (if supported) or the default settings.
*/
static inline void pwm_get_state(const struct pwm_device *pwm,
@@ -157,20 +157,20 @@ static inline void pwm_get_args(const struct pwm_device *pwm,
}
/**
- * pwm_init_state() - prepare a new state to be applied with pwm_apply_state()
+ * pwm_init_state() - prepare a new state to be applied with pwm_apply_might_sleep()
* @pwm: PWM device
* @state: state to fill with the prepared PWM state
*
* This functions prepares a state that can later be tweaked and applied
- * to the PWM device with pwm_apply_state(). This is a convenient function
+ * to the PWM device with pwm_apply_might_sleep(). This is a convenient function
* that first retrieves the current PWM state and the replaces the period
* and polarity fields with the reference values defined in pwm->args.
* Once the function returns, you can adjust the ->enabled and ->duty_cycle
- * fields according to your needs before calling pwm_apply_state().
+ * fields according to your needs before calling pwm_apply_might_sleep().
*
* ->duty_cycle is initially set to zero to avoid cases where the current
* ->duty_cycle value exceed the pwm_args->period one, which would trigger
- * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle
+ * an error if the user calls pwm_apply_might_sleep() without adjusting ->duty_cycle
* first.
*/
static inline void pwm_init_state(const struct pwm_device *pwm,
@@ -226,7 +226,7 @@ pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale)
*
* pwm_init_state(pwm, &state);
* pwm_set_relative_duty_cycle(&state, 50, 100);
- * pwm_apply_state(pwm, &state);
+ * pwm_apply_might_sleep(pwm, &state);
*
* This functions returns -EINVAL if @duty_cycle and/or @scale are
* inconsistent (@scale == 0 or @duty_cycle > @scale).
@@ -304,7 +304,7 @@ struct pwm_chip {
#if IS_ENABLED(CONFIG_PWM)
/* PWM user APIs */
-int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);
+int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state);
int pwm_adjust_config(struct pwm_device *pwm);
/**
@@ -332,7 +332,7 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
state.duty_cycle = duty_ns;
state.period = period_ns;
- return pwm_apply_state(pwm, &state);
+ return pwm_apply_might_sleep(pwm, &state);
}
/**
@@ -353,7 +353,7 @@ static inline int pwm_enable(struct pwm_device *pwm)
return 0;
state.enabled = true;
- return pwm_apply_state(pwm, &state);
+ return pwm_apply_might_sleep(pwm, &state);
}
/**
@@ -372,7 +372,7 @@ static inline void pwm_disable(struct pwm_device *pwm)
return;
state.enabled = false;
- pwm_apply_state(pwm, &state);
+ pwm_apply_might_sleep(pwm, &state);
}
/* PWM provider APIs */
@@ -403,8 +403,8 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev,
struct fwnode_handle *fwnode,
const char *con_id);
#else
-static inline int pwm_apply_state(struct pwm_device *pwm,
- const struct pwm_state *state)
+static inline int pwm_apply_might_sleep(struct pwm_device *pwm,
+ const struct pwm_state *state)
{
might_sleep();
return -ENOTSUPP;
@@ -521,7 +521,7 @@ static inline void pwm_apply_args(struct pwm_device *pwm)
state.period = pwm->args.period;
state.usage_power = false;
- pwm_apply_state(pwm, &state);
+ pwm_apply_might_sleep(pwm, &state);
}
struct pwm_lookup {
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v6 1/4] pwm: rename pwm_apply_state() to pwm_apply_might_sleep()
From: Sean Young @ 2023-12-11 8:30 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: linux-media, linux-pwm, Ivaylo Dimitrov, Thierry Reding,
Jonathan Corbet, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Daniel Vetter,
Javier Martinez Canillas, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Jean Delvare, Guenter Roeck,
Support Opensource, Dmitry Torokhov, Pavel Machek, Lee Jones,
Mauro Carvalho Chehab, Hans de Goede, Ilpo Järvinen,
Mark Gross, Liam Girdwood, Mark Brown, Daniel Thompson,
Jingoo Han, Helge Deller, Jani Nikula, linux-doc, linux-kernel,
intel-gfx, dri-devel, linux-hwmon, linux-input, linux-leds,
platform-driver-x86, linux-arm-kernel, linux-fbdev
In-Reply-To: <20231209135742.3ieusuq3h3xlvjfn@pengutronix.de>
On Sat, Dec 09, 2023 at 02:57:42PM +0100, Uwe Kleine-König wrote:
> On Wed, Nov 29, 2023 at 09:13:34AM +0000, Sean Young wrote:
> > In order to introduce a pwm api which can be used from atomic context,
> > we will need two functions for applying pwm changes:
> >
> > int pwm_apply_might_sleep(struct pwm *, struct pwm_state *);
> > int pwm_apply_atomic(struct pwm *, struct pwm_state *);
> >
> > This commit just deals with renaming pwm_apply_state(), a following
> > commit will introduce the pwm_apply_atomic() function.
> >
> > Acked-by: Hans de Goede <hdegoede@redhat.com>
> > Acked-by: Jani Nikula <jani.nikula@intel.com>
> > Acked-by: Lee Jones <lee@kernel.org>
> > Signed-off-by: Sean Young <sean@mess.org>
>
> Not a in-detail-review, but I just noticed again, that we have
>
> K: pwm_(config|apply_state|ops)
>
> in MAINTAINERS. That one needs adaption, too.
Fixed in v7.
Thanks,
Sean
^ permalink raw reply
* Re: [PATCH v6 03/15] platform/x86/amd/pmf: Change return type of amd_pmf_set_dram_addr()
From: Hans de Goede @ 2023-12-11 8:40 UTC (permalink / raw)
To: Shyam Sundar S K, markgross, ilpo.jarvinen, basavaraj.natikar,
jikos, benjamin.tissoires
Cc: Patil.Reddy, mario.limonciello, platform-driver-x86, linux-input
In-Reply-To: <20231204101548.1458499-4-Shyam-sundar.S-k@amd.com>
Hi,
On 12/4/23 11:15, Shyam Sundar S K wrote:
> In the current code, the metrics table information was required only
> for auto-mode or CnQF at a given time. Hence keeping the return type
> of amd_pmf_set_dram_addr() as static made sense.
>
> But with the addition of Smart PC builder feature, the metrics table
> information has to be shared by the Smart PC also and this feature
> resides outside of core.c.
>
> To make amd_pmf_set_dram_addr() visible outside of core.c make it
> as a non-static function and move the allocation of memory for
> metrics table from amd_pmf_init_metrics_table() to amd_pmf_set_dram_addr()
> as amd_pmf_set_dram_addr() is the common function to set the DRAM
> address.
>
> Add a suspend handler that can free up the allocated memory for getting
> the metrics table information.
>
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
> drivers/platform/x86/amd/pmf/core.c | 42 ++++++++++++++++++++++-------
> drivers/platform/x86/amd/pmf/pmf.h | 1 +
> 2 files changed, 34 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index ec92d1cc0dac..f50b7ec9a625 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -251,29 +251,35 @@ static const struct pci_device_id pmf_pci_ids[] = {
> { }
> };
>
> -static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
> +int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
> {
> u64 phys_addr;
> u32 hi, low;
>
> + /* Get Metrics Table Address */
> + dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
> + if (!dev->buf)
> + return -ENOMEM;
> +
> phys_addr = virt_to_phys(dev->buf);
> hi = phys_addr >> 32;
> low = phys_addr & GENMASK(31, 0);
>
> amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
> amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
> +
> + return 0;
> }
>
> int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
> {
> - /* Get Metrics Table Address */
> - dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
> - if (!dev->buf)
> - return -ENOMEM;
> + int ret;
>
> INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
>
> - amd_pmf_set_dram_addr(dev);
> + ret = amd_pmf_set_dram_addr(dev);
> + if (ret)
> + return ret;
>
> /*
> * Start collecting the metrics data after a small delay
> @@ -284,17 +290,35 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
> return 0;
> }
>
> +static int amd_pmf_suspend_handler(struct device *dev)
> +{
> + struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
> +
> + /*
> + * Free the buffer allocated for storing the metrics table
> + * information, as will have to allocate it freshly after
> + * resume.
> + */
> + kfree(pdev->buf);
This seems quite risky. You are freeing the memory here,
but the SET_DRAM_ADDR_HIGH and SET_DRAM_ADDR_LO registers
still point to it, so the hw may still access it.
IMHO it would be better to add a "bool alloc_buffer"
parameter to amd_pmf_set_dram_addr() and set that
to true on init and false on resume.
Also I guess that this DRAM buffer is used by the new
smartpc mode and specifically by the command send by
amd_pmf_invoke_cmd() work. In that case you really
need to make sure to cancel the work before
freeing the buffer and then re-submit the work
on resume.
Regards,
Hans
> +
> + return 0;
> +}
> +
> static int amd_pmf_resume_handler(struct device *dev)
> {
> struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
> + int ret;
>
> - if (pdev->buf)
> - amd_pmf_set_dram_addr(pdev);
> + if (pdev->buf) {
> + ret = amd_pmf_set_dram_addr(pdev);
> + if (ret)
> + return ret;
> + }
>
> return 0;
> }
>
> -static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler);
> +static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, amd_pmf_suspend_handler, amd_pmf_resume_handler);
>
> static void amd_pmf_init_features(struct amd_pmf_dev *dev)
> {
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index a24e34e42032..6a0e4c446dd3 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -421,6 +421,7 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
> int amd_pmf_get_power_source(void);
> int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
> int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
> +int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev);
>
> /* SPS Layer */
> int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
^ permalink raw reply
* Re: [PATCH v6 04/15] platform/x86/amd/pmf: Add support for PMF Policy Binary
From: Hans de Goede @ 2023-12-11 8:53 UTC (permalink / raw)
To: Shyam Sundar S K, markgross, ilpo.jarvinen, basavaraj.natikar,
jikos, benjamin.tissoires
Cc: Patil.Reddy, mario.limonciello, platform-driver-x86, linux-input
In-Reply-To: <20231204101548.1458499-5-Shyam-sundar.S-k@amd.com>
Hi,
On 12/4/23 11:15, Shyam Sundar S K wrote:
> PMF Policy binary is a encrypted and signed binary that will be part
> of the BIOS. PMF driver via the ACPI interface checks the existence
> of Smart PC bit. If the advertised bit is found, PMF driver walks
> the acpi namespace to find out the policy binary size and the address
> which has to be passed to the TA during the TA init sequence.
>
> The policy binary is comprised of inputs (or the events) and outputs
> (or the actions). With the PMF ecosystem, OEMs generate the policy
> binary (or could be multiple binaries) that contains a supported set
> of inputs and outputs which could be specifically carved out for each
> usage segment (or for each user also) that could influence the system
> behavior either by enriching the user experience or/and boost/throttle
> power limits.
>
> Once the TA init command succeeds, the PMF driver sends the changing
> events in the current environment to the TA for a constant sampling
> frequency time (the event here could be a lid close or open) and
> if the policy binary has corresponding action built within it, the
> TA sends the action for it in the subsequent enact command.
>
> If the inputs sent to the TA has no output defined in the policy
> binary generated by OEMs, there will be no action to be performed
> by the PMF driver.
>
> Example policies:
>
> 1) if slider is performance ; set the SPL to 40W
> Here PMF driver registers with the platform profile interface and
> when the slider position is changed, PMF driver lets the TA know
> about this. TA sends back an action to update the Sustained
> Power Limit (SPL). PMF driver updates this limit via the PMFW mailbox.
>
> 2) if user_away ; then lock the system
> Here PMF driver hooks to the AMD SFH driver to know the user presence
> and send the inputs to TA and if the condition is met, the TA sends
> the action of locking the system. PMF driver generates a uevent and
> based on the udev rule in the userland the system gets locked with
> systemctl.
>
> The intent here is to provide the OEM's to make a policy to lock the
> system when the user is away ; but the userland can make a choice to
> ignore it.
>
> and so on.
>
> The OEMs will have an utility to create numerous such policies and
> the policies shall be reviewed by AMD before signing and encrypting
> them. Policies are shared between operating systems to have seemless user
> experience.
>
> Since all this action has to happen via the "amdtee" driver, currently
> there is no caller for it in the kernel which can load the amdtee driver.
> Without amdtee driver loading onto the system the "tee" calls shall fail
> from the PMF driver. Hence an explicit MODULE_SOFTDEP has been added
> to address this.
>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
> drivers/platform/x86/amd/pmf/Kconfig | 2 +-
> drivers/platform/x86/amd/pmf/acpi.c | 37 +++++++
> drivers/platform/x86/amd/pmf/core.c | 9 ++
> drivers/platform/x86/amd/pmf/pmf.h | 141 ++++++++++++++++++++++++
> drivers/platform/x86/amd/pmf/tee-if.c | 147 +++++++++++++++++++++++++-
> 5 files changed, 333 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 32a029e8db80..f246252bddd8 100644
> --- a/drivers/platform/x86/amd/pmf/Kconfig
> +++ b/drivers/platform/x86/amd/pmf/Kconfig
> @@ -9,7 +9,7 @@ config AMD_PMF
> depends on POWER_SUPPLY
> depends on AMD_NB
> select ACPI_PLATFORM_PROFILE
> - depends on TEE
> + depends on TEE && AMDTEE
> help
> This driver provides support for the AMD Platform Management Framework.
> The goal is to enhance end user experience by making AMD PCs smarter,
> diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
> index 3fc5e4547d9f..4ec7957eb707 100644
> --- a/drivers/platform/x86/amd/pmf/acpi.c
> +++ b/drivers/platform/x86/amd/pmf/acpi.c
> @@ -286,6 +286,43 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
> return 0;
> }
>
> +static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)
> +{
> + struct amd_pmf_dev *dev = data;
> +
> + switch (res->type) {
> + case ACPI_RESOURCE_TYPE_ADDRESS64:
> + dev->policy_addr = res->data.address64.address.minimum;
> + dev->policy_sz = res->data.address64.address.address_length;
> + break;
> + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> + dev->policy_addr = res->data.fixed_memory32.address;
> + dev->policy_sz = res->data.fixed_memory32.address_length;
> + break;
> + }
> +
> + if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || dev->policy_sz == 0) {
> + pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
> + return AE_ERROR;
> + }
> +
> + return AE_OK;
> +}
> +
> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
> +{
> + acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
> + acpi_status status;
> +
> + status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
> + if (ACPI_FAILURE(status)) {
> + dev_err(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
> {
> acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index f50b7ec9a625..c8f6ec4c2e2c 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -395,6 +395,14 @@ static int amd_pmf_probe(struct platform_device *pdev)
> return -ENOMEM;
>
> dev->dev = &pdev->dev;
> + err = apmf_check_smart_pc(dev);
> + if (err)
> + /*
> + * Lets not return from here if Smart PC bit is not advertised in
> + * the BIOS. This way, there will be some amount of power savings
> + * to the user with static slider (if enabled).
> + */
> + pr_err("PMF Smart PC not advertised in BIOS!:%d\n", err);
3 remarks:
1. It seems to me that this should be called from amd_pmf_init_smart_pc()
rather then calling it here.
2. It seems to me that if this fails that amd_pmf_init_smart_pc() should
then exit early, rather then continuing with calling
amd_pmf_get_bios_buffer(dev); Which cannot work without the information
retreived by apmf_check_smart_pc().
3. Logging this as an error seems wrong. AFAIK this is a new feature
so old hw will not have this. So on old hw this should fail graciously
and thus not log an error. Maybe make this an info level log msg ?
Regards,
Hans
>
> rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
> if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
> @@ -474,3 +482,4 @@ module_platform_driver(amd_pmf_driver);
>
> MODULE_LICENSE("GPL");
> MODULE_DESCRIPTION("AMD Platform Management Framework Driver");
> +MODULE_SOFTDEP("pre: amdtee");
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 6a0e4c446dd3..092be501d4d3 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -14,6 +14,11 @@
> #include <linux/acpi.h>
> #include <linux/platform_profile.h>
>
> +#define POLICY_BUF_MAX_SZ 0x4b000
> +#define POLICY_SIGN_COOKIE 0x31535024
> +#define POLICY_COOKIE_OFFSET 0x10
> +#define POLICY_COOKIE_LEN 0x14
> +
> /* APMF Functions */
> #define APMF_FUNC_VERIFY_INTERFACE 0
> #define APMF_FUNC_GET_SYS_PARAMS 1
> @@ -59,8 +64,21 @@
> #define ARG_NONE 0
> #define AVG_SAMPLE_SIZE 3
>
> +/* Policy Actions */
> +#define PMF_POLICY_SPL 2
> +#define PMF_POLICY_SPPT 3
> +#define PMF_POLICY_FPPT 4
> +#define PMF_POLICY_SPPT_APU_ONLY 5
> +#define PMF_POLICY_STT_MIN 6
> +#define PMF_POLICY_STT_SKINTEMP_APU 7
> +#define PMF_POLICY_STT_SKINTEMP_HS2 8
> +
> /* TA macros */
> #define PMF_TA_IF_VERSION_MAJOR 1
> +#define TA_PMF_ACTION_MAX 32
> +#define TA_PMF_UNDO_MAX 8
> +#define TA_OUTPUT_RESERVED_MEM 906
> +#define MAX_OPERATION_PARAMS 4
>
> /* AMD PMF BIOS interfaces */
> struct apmf_verify_interface {
> @@ -183,11 +201,16 @@ struct amd_pmf_dev {
> bool cnqf_supported;
> struct notifier_block pwr_src_notifier;
> /* Smart PC solution builder */
> + unsigned char *policy_buf;
> + u32 policy_sz;
> struct tee_context *tee_ctx;
> struct tee_shm *fw_shm_pool;
> u32 session_id;
> void *shbuf;
> struct delayed_work pb_work;
> + struct pmf_action_table *prev_data;
> + u64 policy_addr;
> + void *policy_base;
> bool smart_pc_enabled;
> };
>
> @@ -399,17 +422,134 @@ struct apmf_dyn_slider_output {
> struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
> } __packed;
>
> +enum smart_pc_status {
> + PMF_SMART_PC_ENABLED,
> + PMF_SMART_PC_DISABLED,
> +};
> +
> +/* Smart PC - TA internals */
> +enum ta_slider {
> + TA_BEST_BATTERY,
> + TA_BETTER_BATTERY,
> + TA_BETTER_PERFORMANCE,
> + TA_BEST_PERFORMANCE,
> + TA_MAX,
> +};
> +
> /* Command ids for TA communication */
> enum ta_pmf_command {
> TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE,
> TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES,
> };
>
> +enum ta_pmf_error_type {
> + TA_PMF_TYPE_SUCCESS,
> + TA_PMF_ERROR_TYPE_GENERIC,
> + TA_PMF_ERROR_TYPE_CRYPTO,
> + TA_PMF_ERROR_TYPE_CRYPTO_VALIDATE,
> + TA_PMF_ERROR_TYPE_CRYPTO_VERIFY_OEM,
> + TA_PMF_ERROR_TYPE_POLICY_BUILDER,
> + TA_PMF_ERROR_TYPE_PB_CONVERT,
> + TA_PMF_ERROR_TYPE_PB_SETUP,
> + TA_PMF_ERROR_TYPE_PB_ENACT,
> + TA_PMF_ERROR_TYPE_ASD_GET_DEVICE_INFO,
> + TA_PMF_ERROR_TYPE_ASD_GET_DEVICE_PCIE_INFO,
> + TA_PMF_ERROR_TYPE_SYS_DRV_FW_VALIDATION,
> + TA_PMF_ERROR_TYPE_MAX,
> +};
> +
> +struct pmf_action_table {
> + u32 spl; /* in mW */
> + u32 sppt; /* in mW */
> + u32 sppt_apuonly; /* in mW */
> + u32 fppt; /* in mW */
> + u32 stt_minlimit; /* in mW */
> + u32 stt_skintemp_apu; /* in C */
> + u32 stt_skintemp_hs2; /* in C */
> +};
> +
> +/* Input conditions */
> +struct ta_pmf_condition_info {
> + u32 power_source;
> + u32 bat_percentage;
> + u32 power_slider;
> + u32 lid_state;
> + bool user_present;
> + u32 rsvd1[2];
> + u32 monitor_count;
> + u32 rsvd2[2];
> + u32 bat_design;
> + u32 full_charge_capacity;
> + int drain_rate;
> + bool user_engaged;
> + u32 device_state;
> + u32 socket_power;
> + u32 skin_temperature;
> + u32 rsvd3[5];
> + u32 ambient_light;
> + u32 length;
> + u32 avg_c0residency;
> + u32 max_c0residency;
> + u32 s0i3_entry;
> + u32 gfx_busy;
> + u32 rsvd4[7];
> + bool camera_state;
> + u32 workload_type;
> + u32 display_type;
> + u32 display_state;
> + u32 rsvd5[150];
> +};
> +
> +struct ta_pmf_load_policy_table {
> + u32 table_size;
> + u8 table[POLICY_BUF_MAX_SZ];
> +};
> +
> +/* TA initialization params */
> +struct ta_pmf_init_table {
> + u32 frequency; /* SMU sampling frequency */
> + bool validate;
> + bool sku_check;
> + bool metadata_macrocheck;
> + struct ta_pmf_load_policy_table policies_table;
> +};
> +
> +/* Everything the TA needs to Enact Policies */
> +struct ta_pmf_enact_table {
> + struct ta_pmf_condition_info ev_info;
> + u32 name;
> +};
> +
> +struct ta_pmf_action {
> + u32 action_index;
> + u32 value;
> +};
> +
> +/* Output actions from TA */
> +struct ta_pmf_enact_result {
> + u32 actions_count;
> + struct ta_pmf_action actions_list[TA_PMF_ACTION_MAX];
> + u32 undo_count;
> + struct ta_pmf_action undo_list[TA_PMF_UNDO_MAX];
> +};
> +
> +union ta_pmf_input {
> + struct ta_pmf_enact_table enact_table;
> + struct ta_pmf_init_table init_table;
> +};
> +
> +union ta_pmf_output {
> + struct ta_pmf_enact_result policy_apply_table;
> + u32 rsvd[TA_OUTPUT_RESERVED_MEM];
> +};
> +
> struct ta_pmf_shared_memory {
> int command_id;
> int resp_id;
> u32 pmf_result;
> u32 if_version;
> + union ta_pmf_output pmf_output;
> + union ta_pmf_input pmf_input;
> };
>
> /* Core Layer */
> @@ -460,4 +600,5 @@ extern const struct attribute_group cnqf_feature_attribute_group;
> /* Smart PC builder Layer */
> int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
> void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
> +int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
> #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 4036f435f1e2..468f3797a848 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -42,9 +42,77 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
> param[0].u.memref.shm_offs = 0;
> }
>
> +static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> +{
> + u32 val;
> + int idx;
> +
> + for (idx = 0; idx < out->actions_count; idx++) {
> + val = out->actions_list[idx].value;
> + switch (out->actions_list[idx].action_index) {
> + case PMF_POLICY_SPL:
> + if (dev->prev_data->spl != val) {
> + amd_pmf_send_cmd(dev, SET_SPL, false, val, NULL);
> + dev_dbg(dev->dev, "update SPL: %u\n", val);
> + dev->prev_data->spl = val;
> + }
> + break;
> +
> + case PMF_POLICY_SPPT:
> + if (dev->prev_data->sppt != val) {
> + amd_pmf_send_cmd(dev, SET_SPPT, false, val, NULL);
> + dev_dbg(dev->dev, "update SPPT: %u\n", val);
> + dev->prev_data->sppt = val;
> + }
> + break;
> +
> + case PMF_POLICY_FPPT:
> + if (dev->prev_data->fppt != val) {
> + amd_pmf_send_cmd(dev, SET_FPPT, false, val, NULL);
> + dev_dbg(dev->dev, "update FPPT: %u\n", val);
> + dev->prev_data->fppt = val;
> + }
> + break;
> +
> + case PMF_POLICY_SPPT_APU_ONLY:
> + if (dev->prev_data->sppt_apuonly != val) {
> + amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, val, NULL);
> + dev_dbg(dev->dev, "update SPPT_APU_ONLY: %u\n", val);
> + dev->prev_data->sppt_apuonly = val;
> + }
> + break;
> +
> + case PMF_POLICY_STT_MIN:
> + if (dev->prev_data->stt_minlimit != val) {
> + amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, val, NULL);
> + dev_dbg(dev->dev, "update STT_MIN: %u\n", val);
> + dev->prev_data->stt_minlimit = val;
> + }
> + break;
> +
> + case PMF_POLICY_STT_SKINTEMP_APU:
> + if (dev->prev_data->stt_skintemp_apu != val) {
> + amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, val, NULL);
> + dev_dbg(dev->dev, "update STT_SKINTEMP_APU: %u\n", val);
> + dev->prev_data->stt_skintemp_apu = val;
> + }
> + break;
> +
> + case PMF_POLICY_STT_SKINTEMP_HS2:
> + if (dev->prev_data->stt_skintemp_hs2 != val) {
> + amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, val, NULL);
> + dev_dbg(dev->dev, "update STT_SKINTEMP_HS2: %u\n", val);
> + dev->prev_data->stt_skintemp_hs2 = val;
> + }
> + break;
> + }
> + }
> +}
> +
> static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> {
> struct ta_pmf_shared_memory *ta_sm = NULL;
> + struct ta_pmf_enact_result *out = NULL;
> struct tee_param param[MAX_TEE_PARAM];
> struct tee_ioctl_invoke_arg arg;
> int ret = 0;
> @@ -52,7 +120,10 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> if (!dev->tee_ctx)
> return -ENODEV;
>
> + memset(dev->shbuf, 0, dev->policy_sz);
> ta_sm = dev->shbuf;
> + out = &ta_sm->pmf_output.policy_apply_table;
> +
> memset(ta_sm, 0, sizeof(*ta_sm));
> ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES;
> ta_sm->if_version = PMF_TA_IF_VERSION_MAJOR;
> @@ -65,6 +136,12 @@ static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
> return ret;
> }
>
> + if (ta_sm->pmf_result == TA_PMF_TYPE_SUCCESS && out->actions_count) {
> + dev_dbg(dev->dev, "action count:%u result:%x\n", out->actions_count,
> + ta_sm->pmf_result);
> + amd_pmf_apply_policies(dev, out);
> + }
> +
> return 0;
> }
>
> @@ -72,6 +149,7 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
> {
> struct ta_pmf_shared_memory *ta_sm = NULL;
> struct tee_param param[MAX_TEE_PARAM];
> + struct ta_pmf_init_table *in = NULL;
> struct tee_ioctl_invoke_arg arg;
> int ret = 0;
>
> @@ -80,10 +158,21 @@ static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
> return -ENODEV;
> }
>
> + dev_dbg(dev->dev, "Policy Binary size: %u bytes\n", dev->policy_sz);
> + memset(dev->shbuf, 0, dev->policy_sz);
> ta_sm = dev->shbuf;
> + in = &ta_sm->pmf_input.init_table;
> +
> ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE;
> ta_sm->if_version = PMF_TA_IF_VERSION_MAJOR;
>
> + in->metadata_macrocheck = false;
> + in->sku_check = false;
> + in->validate = true;
> + in->frequency = pb_actions_ms;
> + in->policies_table.table_size = dev->policy_sz;
> +
> + memcpy(in->policies_table.table, dev->policy_buf, dev->policy_sz);
> amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE, &arg, param);
>
> ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
> @@ -103,6 +192,52 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
> schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
> }
>
> +static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
> +{
> + u32 cookie, length;
> + int res;
> +
> + cookie = readl(dev->policy_buf + POLICY_COOKIE_OFFSET);
> + length = readl(dev->policy_buf + POLICY_COOKIE_LEN);
> +
> + if (cookie != POLICY_SIGN_COOKIE || !length)
> + return -EINVAL;
> +
> + /* Update the actual length */
> + dev->policy_sz = length + 512;
> + res = amd_pmf_invoke_cmd_init(dev);
> + if (res == TA_PMF_TYPE_SUCCESS) {
> + /* Now its safe to announce that smart pc is enabled */
> + dev->smart_pc_enabled = PMF_SMART_PC_ENABLED;
> + /*
> + * Start collecting the data from TA FW after a small delay
> + * or else, we might end up getting stale values.
> + */
> + schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
> + } else {
> + dev_err(dev->dev, "ta invoke cmd init failed err: %x\n", res);
> + dev->smart_pc_enabled = PMF_SMART_PC_DISABLED;
> + return res;
> + }
> +
> + return 0;
> +}
> +
> +static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
> +{
> + dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
> + if (!dev->policy_buf)
> + return -ENOMEM;
> +
> + dev->policy_base = devm_ioremap(dev->dev, dev->policy_addr, dev->policy_sz);
> + if (!dev->policy_base)
> + return -ENOMEM;
> +
> + memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
> +
> + return amd_pmf_start_policy_engine(dev);
> +}
> +
> static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
> {
> return ver->impl_id == TEE_IMPL_ID_AMDTEE;
> @@ -146,7 +281,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
> goto out_ctx;
> }
>
> - size = sizeof(struct ta_pmf_shared_memory);
> + size = sizeof(struct ta_pmf_shared_memory) + dev->policy_sz;
> dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
> if (IS_ERR(dev->fw_shm_pool)) {
> dev_err(dev->dev, "Failed to alloc TEE shared memory\n");
> @@ -190,11 +325,19 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
> return ret;
>
> INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
> - return 0;
> + amd_pmf_set_dram_addr(dev);
> + amd_pmf_get_bios_buffer(dev);
> + dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
> + if (!dev->prev_data)
> + return -ENOMEM;
> +
> + return dev->smart_pc_enabled;
> }
>
> void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
> {
> + kfree(dev->prev_data);
> + kfree(dev->policy_buf);
> cancel_delayed_work_sync(&dev->pb_work);
> amd_pmf_tee_deinit(dev);
> }
^ permalink raw reply
* Re: [PATCH v6 11/15] platform/x86/amd/pmf: Add capability to sideload of policy binary
From: Hans de Goede @ 2023-12-11 8:59 UTC (permalink / raw)
To: Shyam Sundar S K, markgross, ilpo.jarvinen, basavaraj.natikar,
jikos, benjamin.tissoires
Cc: Patil.Reddy, mario.limonciello, platform-driver-x86, linux-input
In-Reply-To: <20231204101548.1458499-12-Shyam-sundar.S-k@amd.com>
Hi,
On 12/4/23 11:15, Shyam Sundar S K wrote:
> A policy binary is OS agnostic, and the same policies are expected to work
> across the OSes. At times it becomes difficult to debug when the policies
> inside the policy binaries starts to misbehave. Add a way to sideload such
> policies independently to debug them via a debugfs entry.
>
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
> drivers/platform/x86/amd/pmf/pmf.h | 1 +
> drivers/platform/x86/amd/pmf/tee-if.c | 54 +++++++++++++++++++++++++++
> 2 files changed, 55 insertions(+)
>
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 593930519039..8712299ad52b 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -219,6 +219,7 @@ struct amd_pmf_dev {
> bool cnqf_supported;
> struct notifier_block pwr_src_notifier;
> /* Smart PC solution builder */
> + struct dentry *esbin;
> unsigned char *policy_buf;
> u32 policy_sz;
> struct tee_context *tee_ctx;
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 5f10e5c6335e..f73663c629fe 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -8,6 +8,7 @@
> * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> */
>
> +#include <linux/debugfs.h>
> #include <linux/tee_drv.h>
> #include <linux/uuid.h>
> #include "pmf.h"
> @@ -16,9 +17,14 @@
>
> /* Policy binary actions sampling frequency (in ms) */
> static int pb_actions_ms = MSEC_PER_SEC;
> +/* Sideload policy binaries to debug policy failures */
> +static bool pb_side_load;
> +
> #ifdef CONFIG_AMD_PMF_DEBUG
> module_param(pb_actions_ms, int, 0644);
> MODULE_PARM_DESC(pb_actions_ms, "Policy binary actions sampling frequency (default = 1000ms)");
> +module_param(pb_side_load, bool, 0444);
> +MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures");
> #endif
>
> static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
> @@ -269,6 +275,48 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
> return 0;
> }
>
> +#ifdef CONFIG_AMD_PMF_DEBUG
> +static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
> + size_t length, loff_t *pos)
> +{
> + struct amd_pmf_dev *dev = filp->private_data;
> + int ret;
> +
> + /* Policy binary size cannot exceed POLICY_BUF_MAX_SZ */
> + if (length > POLICY_BUF_MAX_SZ || length == 0)
> + return -EINVAL;
> +
> + dev->policy_sz = length;
> + if (copy_from_user(dev->policy_buf, buf, dev->policy_sz))
> + return -EFAULT;
dev->policy_buf = allocated in amd_pmf_get_bios_buffer() to
be of the original dev->policy_sz. So this needs to re-alloc
dev->policy_buf to make sure it is large enough.
Regards,
Hans
> +
> + ret = amd_pmf_start_policy_engine(dev);
> + if (ret)
> + return -EINVAL;
> +
> + return length;
> +}
> +
> +static const struct file_operations pb_fops = {
> + .write = amd_pmf_get_pb_data,
> + .open = simple_open,
> +};
> +
> +static void amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root)
> +{
> + dev->esbin = debugfs_create_dir("pb", debugfs_root);
> + debugfs_create_file("update_policy", 0644, dev->esbin, dev, &pb_fops);
> +}
> +
> +static void amd_pmf_remove_pb(struct amd_pmf_dev *dev)
> +{
> + debugfs_remove_recursive(dev->esbin);
> +}
> +#else
> +static void amd_pmf_open_pb(struct amd_pmf_dev *dev, struct dentry *debugfs_root) {}
> +static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
> +#endif
> +
> static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
> {
> dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
> @@ -281,6 +329,9 @@ static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
>
> memcpy(dev->policy_buf, dev->policy_base, dev->policy_sz);
>
> + if (pb_side_load)
> + amd_pmf_open_pb(dev, dev->dbgfs_dir);
> +
> return amd_pmf_start_policy_engine(dev);
> }
>
> @@ -382,6 +433,9 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
>
> void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
> {
> + if (pb_side_load)
> + amd_pmf_remove_pb(dev);
> +
> kfree(dev->prev_data);
> kfree(dev->policy_buf);
> cancel_delayed_work_sync(&dev->pb_work);
^ permalink raw reply
* Re: [PATCH v6 14/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for HPD
From: Hans de Goede @ 2023-12-11 9:07 UTC (permalink / raw)
To: Shyam Sundar S K, markgross, ilpo.jarvinen, basavaraj.natikar,
jikos, benjamin.tissoires
Cc: Patil.Reddy, mario.limonciello, platform-driver-x86, linux-input
In-Reply-To: <20231204101548.1458499-15-Shyam-sundar.S-k@amd.com>
Hi,
On 12/4/23 11:15, Shyam Sundar S K wrote:
> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>
> AMDSFH has information about the User presence information via the Human
> Presence Detection (HPD) sensor which is part of the AMD sensor fusion hub.
> Add PMF and AMDSFH interface to get this information.
>
> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> ---
> drivers/hid/amd-sfh-hid/amd_sfh_common.h | 5 ++
> drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 14 ++++++
> .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 33 +++++++++++++
> .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h | 1 +
> drivers/platform/x86/amd/pmf/Kconfig | 1 +
> drivers/platform/x86/amd/pmf/spc.c | 22 +++++++++
> include/linux/amd-pmf-io.h | 46 +++++++++++++++++++
> 7 files changed, 122 insertions(+)
> create mode 100644 include/linux/amd-pmf-io.h
<snip>
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 4f81ef2d4f56..f8758fb70b1a 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -7,11 +7,14 @@
> *
> * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> */
> +#include <linux/amd-pmf-io.h>
> #include <linux/io-64-nonatomic-lo-hi.h>
> #include <linux/iopoll.h>
>
> #include "amd_sfh_interface.h"
>
> +static struct amd_mp2_dev *emp2;
> +
> static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
> {
> struct sfh_cmd_response cmd_resp;
> @@ -73,7 +76,37 @@ static struct amd_mp2_ops amd_sfh_ops = {
> .response = amd_sfh_wait_response,
> };
>
> +void sfh_deinit_emp2(void)
> +{
> + emp2 = NULL;
> +}
> +
> void sfh_interface_init(struct amd_mp2_dev *mp2)
> {
> mp2->mp2_ops = &amd_sfh_ops;
> + emp2 = mp2;
> +}
> +
> +static int amd_sfh_hpd_info(u8 *user_present)
> +{
> + struct hpd_status hpdstatus;
> +
> + if (!emp2 || !emp2->dev_en.is_hpd_present)
> + return -ENODEV;
> +
> + hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
> + *user_present = hpdstatus.shpd.presence;
> + return 0;
> +}
> +
> +int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
> +{
> + if (sfh_info) {
> + switch (op) {
> + case MT_HPD:
> + return amd_sfh_hpd_info(&sfh_info->user_present);
> + }
> + }
> + return -EINVAL;
> }
> +EXPORT_SYMBOL_GPL(amd_get_sfh_info);
This whole amd_get_sfh_info() interface seems over engineered
why not just export amd_sfh_hpd_info() itself and directly
use that in the pmf code ? That seems a whole lot simpler to me.
Also this patch MUST be split into 2 separate patches
for the HID and the PMF changes.
<snip>
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index a0423942f771..5e769dcb075a 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -10,6 +10,7 @@
> */
>
> #include <acpi/button.h>
> +#include <linux/amd-pmf-io.h>
> #include <linux/power_supply.h>
> #include <linux/units.h>
> #include "pmf.h"
> @@ -44,6 +45,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
> dev_dbg(dev->dev, "Max C0 Residency: %u\n", in->ev_info.max_c0residency);
> dev_dbg(dev->dev, "GFX Busy: %u\n", in->ev_info.gfx_busy);
> dev_dbg(dev->dev, "LID State: %s\n", in->ev_info.lid_state ? "close" : "open");
> + dev_dbg(dev->dev, "User Presence: %s\n", in->ev_info.user_present ? "Present" : "Away");
> dev_dbg(dev->dev, "==== TA inputs END ====\n");
> }
> #else
> @@ -147,6 +149,25 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_
> return 0;
> }
>
> +static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
> +{
> + struct amd_sfh_info sfh_info;
> +
> + /* get HPD data */
> + amd_get_sfh_info(&sfh_info, MT_HPD);
As Mario also pointed out, this needs to be error checked.
Regards,
Hans
^ permalink raw reply
* Re: [PATCH v6 15/15] platform/x86/amd/pmf: Add PMF-AMDSFH interface for ALS
From: Hans de Goede @ 2023-12-11 9:15 UTC (permalink / raw)
To: Shyam Sundar S K, markgross, ilpo.jarvinen, basavaraj.natikar,
jikos, benjamin.tissoires
Cc: Patil.Reddy, mario.limonciello, platform-driver-x86, linux-input
In-Reply-To: <20231204101548.1458499-16-Shyam-sundar.S-k@amd.com>
Hi,
On 12/4/23 11:15, Shyam Sundar S K wrote:
> From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>
> AMDSFH has information about the Ambient light via the Ambient
> Light Sensor (ALS) which is part of the AMD sensor fusion hub.
> Add PMF and AMDSFH interface to get this information.
>
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> ---
> drivers/hid/amd-sfh-hid/amd_sfh_common.h | 1 +
> drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 6 ++++++
> .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 19 +++++++++++++++++++
> drivers/platform/x86/amd/pmf/spc.c | 9 ++++++++-
> include/linux/amd-pmf-io.h | 4 ++++
> 5 files changed, 38 insertions(+), 1 deletion(-)
Ok so with this patch also added in the mix I guess the
multi-plexing nature of amd_get_sfh_info() makes sense,
so it is ok to keep that.
But this patch also needs to have its HID parts split out
from the rest and the HID patches need to be merged
separately.
Since the merge-window is getting close I would like
to propose the following:
1. Send a v7 addressing review remarks consisting of
only patches 1-12, assuming all review remarks are
fixed in v7 I can merge that then.
2. Send a 3 patch HID patch series separately:
[PATCH 1/3] HID: amd_sfh: rename float_to_int() to amd_sfh_float_to_int()
[PATCH 2/3] HID: amd_sfh: adding the HID hpd bits + amd_get_sfh_info() function
[PATCH 3/3] HID: amd_sfh: adding the HID als bits
3. Once v7 of patches 1-12 + hopefully the 3 patch HID series have
landed in 6.8-rc1 then I would be willing to take a patch using
amd_get_sfh_info() to implement hpd + als support in the spc code
as a fix for 6.8-rc# .
Regards,
Hans
^ permalink raw reply
* Re: [PATCH v12 2/4] Input: add core support for Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2023-12-11 9:31 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg, Jeff LaBundy,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <ZXVgYuzE6jPPSfnZ@google.com>
Hi Dmitry,
On 10/12/2023 07:53, Dmitry Torokhov wrote:
> Hi Neil,
>
> On Sat, Dec 09, 2023 at 08:33:40AM +0100, Neil Armstrong wrote:
>> Add initial support for the new Goodix "Berlin" touchscreen ICs.
>>
>> These touchscreen ICs support SPI, I2C and I3C interface, up to
>> 10 finger touch, stylus and gestures events.
>>
>> This initial driver is derived from the Goodix goodix_ts_berlin
>> available at [1] and [2] and only supports the GT9916 IC
>> present on the Qualcomm SM8550 MTP & QRD touch panel.
>>
>> The current implementation only supports BerlinD, aka GT9916.
>>
>> Support for advanced features like:
>> - Firmware & config update
>> - Stylus events
>> - Gestures events
>> - Previous revisions support (BerlinA or BerlinB)
>> is not included in current version.
>>
>> The current support will work with currently flashed firmware
>> and config, and bail out if firmware or config aren't flashed yet.
>>
>> [1] https://github.com/goodix/goodix_ts_berlin
>> [2] https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
>>
>> Reviewed-by: Jeff LaBundy <jeff@labundy.com>
>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>
> Thank you for resending the patch. I think there is an issue in how you
> read and parse the data in case of more than 2 fingers. It looks like in
> that case you are overwriting the checksum form the first 2 and then not
> reading the new checksum but use some garbage past the touch data. I
> might be mistaken though...
Sure, let me check again to be sure it's not the case
>
> I also believe you are leaking afe_data in case of success. We have the
> newfangled __free(kfree) from cleanup.h that should help there.
Indeed, it was added in the meantime, so let's switch to it
>
> Another request - we should not have anything in goodix_berlin.h that is
> not used by the I2C and SPI sub-drivers, so the only thing it should
> contain is goodix_berlin_probe() declaration and dev_pm_ops. All other
> defines and definitions should go to goodix_berlin_core.h.
>
> I made a few more cosmetic changes in the attached patch, please
> consider applying it.
Sure, I'll apply it, thanks for the suggestions,
Neil
>
> Thanks.
>
^ permalink raw reply
* [PATCH v5 0/3] Input: Add TouchNetix axiom touchscreen driver
From: Kamel Bouhara @ 2023-12-11 12:14 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg, linux-input, linux-kernel, devicetree,
Marco Felsch, Jeff LaBundy
Cc: catalin.popescu, mark.satterthwaite, bartp, hannah.rossiter,
Thomas Petazzoni, Gregory Clement, bsp-development.geo,
Kamel Bouhara
Add a new driver for the TouchNetix's axiom family of
touchscreen controller. This driver only support i2c
and can be later adapted for SPI and USB support.
---
Changes in v2:
- Add device tree binding documentation
- Move core functions in axiom_i2c as we only care about i2c support now
- Use static function when required
- Use syntax dev_err_probe()
- Add an hardware based reset
Changes in v3:
- Remove irq-gpios property in dt-binding
- Use a generic node name
- Fix issues reported in https://lore.kernel.org/oe-kbuild-all/202310100300.oAC2M62R-lkp@intel.com/
Changes in v4:
- Cleanup unused headers and macros
- Use standard kernel type
- Namespace structures and functions
- Use packed struct when possible to avoid bitfield operators
- Fix missing break when address is found in axiom_populate_target_address()
- Split reads in two steps for the reports, first length then report
itself so we only read required bytes
- Get poll-interval from devicetree
- Add VDDI/VDDA regulators
- Add a startup delay of 110 ms required after VDDA/VDDI is applied
- Remove axiom_i2c_write() as it is no more used
Changes in v5:
- Fix wrong message constructed in axiom_i2c_read
- Delay required between i2c reads is >= 250us
- Do not split report reading in two phases as we'll
have to wait 500us
- Use lower-case in properties names
- Make regulators properties are required in dt-binding
- Fix bug report: https://lore.kernel.org/lkml/202312051457.y3N1q3sZ-lkp@intel.com/
- Fix bug report: https://lore.kernel.org/lkml/6f8e3b64-5b21-4a50-8680-063ef7a93bdb@suswa.mountain/
Kamel Bouhara (3):
dt-bindings: vendor-prefixes: Add TouchNetix AS
dt-bindings: input: Add TouchNetix axiom touchscreen
Input: Add TouchNetix axiom i2c touchscreen driver
.../input/touchscreen/touchnetix,ax54a.yaml | 64 ++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
MAINTAINERS | 7 +
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/touchnetix_axiom.c | 667 ++++++++++++++++++
6 files changed, 753 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml
create mode 100644 drivers/input/touchscreen/touchnetix_axiom.c
--
2.25.1
^ permalink raw reply
* [PATCH v5 1/3] dt-bindings: vendor-prefixes: Add TouchNetix AS
From: Kamel Bouhara @ 2023-12-11 12:14 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg, linux-input, linux-kernel, devicetree,
Marco Felsch, Jeff LaBundy
Cc: catalin.popescu, mark.satterthwaite, bartp, hannah.rossiter,
Thomas Petazzoni, Gregory Clement, bsp-development.geo,
Kamel Bouhara, Krzysztof Kozlowski
In-Reply-To: <20231211121430.1689139-1-kamel.bouhara@bootlin.com>
Add vendor prefix for TouchNetix AS (https://www.touchnetix.com/products/).
Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 573578db9509..78581001a79c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1400,6 +1400,8 @@ patternProperties:
description: Toradex AG
"^toshiba,.*":
description: Toshiba Corporation
+ "^touchnetix,.*":
+ description: TouchNetix AS
"^toumaz,.*":
description: Toumaz
"^tpk,.*":
--
2.25.1
^ permalink raw reply related
* [PATCH v5 2/3] dt-bindings: input: Add TouchNetix axiom touchscreen
From: Kamel Bouhara @ 2023-12-11 12:14 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg, linux-input, linux-kernel, devicetree,
Marco Felsch, Jeff LaBundy
Cc: catalin.popescu, mark.satterthwaite, bartp, hannah.rossiter,
Thomas Petazzoni, Gregory Clement, bsp-development.geo,
Kamel Bouhara
In-Reply-To: <20231211121430.1689139-1-kamel.bouhara@bootlin.com>
Add the TouchNetix axiom I2C touchscreen device tree bindings
documentation.
Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
---
.../input/touchscreen/touchnetix,ax54a.yaml | 64 +++++++++++++++++++
MAINTAINERS | 6 ++
2 files changed, 70 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml
new file mode 100644
index 000000000000..cbdf48fc538b
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/touchnetix,ax54a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TouchNetix Axiom series touchscreen controller
+
+maintainers:
+ - Kamel Bouhara <kamel.bouhara@bootlin.com>
+
+allOf:
+ - $ref: /schemas/input/touchscreen/touchscreen.yaml#
+ - $ref: /schemas/input/input.yaml#
+
+properties:
+ compatible:
+ const: touchnetix,ax54a
+
+ reg:
+ const: 0x66
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ vdda-supply:
+ description: Analog power supply regulator on VDDA pin
+
+ vddi-supply:
+ description: I/O power supply regulator on VDDI pin
+
+ poll-interval: true
+
+required:
+ - compatible
+ - reg
+ - vdda-supply
+ - vddi-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@66 {
+ compatible = "touchnetix,ax54a";
+ reg = <0x66>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+ vdda-supply = <&vdda_reg>;
+ vddi-supply = <&vddi_reg>;
+ poll-interval = <20>;
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 7608b714653f..4752d8436dbb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21431,6 +21431,12 @@ S: Maintained
F: Documentation/ABI/testing/sysfs-class-firmware-attributes
F: drivers/platform/x86/think-lmi.?
+TOUCHNETIX AXIOM I2C TOUCHSCREEN DRIVER
+M: Kamel Bouhara <kamel.bouhara@bootlin.com>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml
+
THUNDERBOLT DMA TRAFFIC TEST DRIVER
M: Isaac Hazan <isaac.hazan@intel.com>
L: linux-usb@vger.kernel.org
--
2.25.1
^ permalink raw reply related
* [PATCH v5 3/3] Input: Add TouchNetix axiom i2c touchscreen driver
From: Kamel Bouhara @ 2023-12-11 12:14 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg, linux-input, linux-kernel, devicetree,
Marco Felsch, Jeff LaBundy
Cc: catalin.popescu, mark.satterthwaite, bartp, hannah.rossiter,
Thomas Petazzoni, Gregory Clement, bsp-development.geo,
Kamel Bouhara
In-Reply-To: <20231211121430.1689139-1-kamel.bouhara@bootlin.com>
Add a new driver for the TouchNetix's axiom family of
touchscreen controllers. This driver only supports i2c
and can be later adapted for SPI and USB support.
Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
---
MAINTAINERS | 1 +
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/touchnetix_axiom.c | 667 +++++++++++++++++++
4 files changed, 681 insertions(+)
create mode 100644 drivers/input/touchscreen/touchnetix_axiom.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 4752d8436dbb..337ddac6c74b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21436,6 +21436,7 @@ M: Kamel Bouhara <kamel.bouhara@bootlin.com>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/touchscreen/touchnetix,ax54a.yaml
+F: drivers/input/touchscreen/touchnetix_axiom.c
THUNDERBOLT DMA TRAFFIC TEST DRIVER
M: Isaac Hazan <isaac.hazan@intel.com>
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e3e2324547b9..f36bee8d8696 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -803,6 +803,18 @@ config TOUCHSCREEN_MIGOR
To compile this driver as a module, choose M here: the
module will be called migor_ts.
+config TOUCHSCREEN_TOUCHNETIX_AXIOM
+ tristate "TouchNetix AXIOM based touchscreen controllers"
+ depends on I2C
+ help
+ Say Y here if you have a axiom touchscreen connected to
+ your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called axiom.
+
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 62bd24f3ac8e..8e32a2df5e18 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_SURFACE3_SPI) += surface3_spi.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHNETIX_AXIOM) += touchnetix_axiom.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
obj-$(CONFIG_TOUCHSCREEN_TS4800) += ts4800-ts.o
diff --git a/drivers/input/touchscreen/touchnetix_axiom.c b/drivers/input/touchscreen/touchnetix_axiom.c
new file mode 100644
index 000000000000..4ade2d1adba0
--- /dev/null
+++ b/drivers/input/touchscreen/touchnetix_axiom.c
@@ -0,0 +1,667 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TouchNetix axiom Touchscreen Driver
+ *
+ * Copyright (C) 2020-2023 TouchNetix Ltd.
+ *
+ * Author(s): Bart Prescott <bartp@baasheep.co.uk>
+ * Pedro Torruella <pedro.torruella@touchnetix.com>
+ * Mark Satterthwaite <mark.satterthwaite@touchnetix.com>
+ * Hannah Rossiter <hannah.rossiter@touchnetix.com>
+ * Kamel Bouhara <kamel.bouhara@bootlin.com>
+ *
+ */
+#include <linux/bitfield.h>
+#include <linux/crc16.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#define AXIOM_PROX_LEVEL -128
+/*
+ * Register group u31 has 2 pages for usage table entries.
+ */
+#define AXIOM_U31_MAX_USAGES ((2 * AXIOM_COMMS_PAGE_SIZE) / AXIOM_U31_BYTES_PER_USAGE)
+#define AXIOM_U31_BYTES_PER_USAGE 6
+#define AXIOM_U31_PAGE0_LENGTH 0x0C
+#define AXIOM_U31_BOOTMODE_MASK BIT(7)
+#define AXIOM_U31_DEVID_MASK GENMASK(14, 0)
+
+#define AXIOM_CMD_HEADER_READ_MASK BIT(15)
+#define AXIOM_U41_MAX_TARGETS 10
+
+#define AXIOM_U46_AUX_CHANNELS 4
+#define AXIOM_U46_AUX_MASK GENMASK(11, 0)
+
+#define AXIOM_COMMS_MAX_USAGE_PAGES 3
+#define AXIOM_COMMS_PAGE_SIZE 256
+#define AXIOM_COMMS_REPORT_LEN_MASK GENMASK(6, 0)
+
+#define AXIOM_REPORT_USAGE_ID 0x34
+#define AXIOM_DEVINFO_USAGE_ID 0x31
+#define AXIOM_USAGE_2HB_REPORT_ID 0x01
+#define AXIOM_USAGE_2AUX_REPORT_ID 0x46
+#define AXIOM_USAGE_2DCTS_REPORT_ID 0x41
+
+#define AXIOM_PAGE_OFFSET_MASK GENMASK(6, 0)
+
+struct axiom_devinfo {
+ u16 device_id;
+ u8 fw_minor;
+ u8 fw_major;
+ u8 fw_info_extra;
+ u8 tcp_revision;
+ u8 bootloader_fw_minor;
+ u8 bootloader_fw_major;
+ u16 jedec_id;
+ u8 num_usages;
+} __packed;
+
+/*
+ * Describes parameters of a specific usage, essentially a single element of
+ * the "Usage Table"
+ */
+struct axiom_usage_entry {
+ u8 id;
+ u8 is_report;
+ u8 start_page;
+ u8 num_pages;
+};
+
+/*
+ * Represents state of a touch or target when detected prior a touch (eg.
+ * hover or proximity events).
+ */
+enum axiom_target_state {
+ AXIOM_TARGET_STATE_NOT_PRESENT = 0,
+ AXIOM_TARGET_STATE_PROX = 1,
+ AXIOM_TARGET_STATE_HOVER = 2,
+ AXIOM_TARGET_STATE_TOUCHING = 3,
+};
+
+struct axiom_u41_target {
+ enum axiom_target_state state;
+ u16 x;
+ u16 y;
+ s8 z;
+ bool insert;
+ bool touch;
+};
+
+struct axiom_target_report {
+ u8 index;
+ u8 present;
+ u16 x;
+ u16 y;
+ s8 z;
+};
+
+struct axiom_cmd_header {
+ __le16 target_address;
+ __le16 length;
+} __packed;
+
+struct axiom_data {
+ struct axiom_devinfo devinfo;
+ struct device *dev;
+ struct gpio_desc *reset_gpio;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ u32 max_report_len;
+ char rx_buf[AXIOM_COMMS_MAX_USAGE_PAGES * AXIOM_COMMS_PAGE_SIZE];
+ struct axiom_u41_target targets[AXIOM_U41_MAX_TARGETS];
+ struct axiom_usage_entry usage_table[AXIOM_U31_MAX_USAGES];
+ bool usage_table_populated;
+ struct regulator *vdda;
+ struct regulator *vddi;
+};
+
+/*
+ * axiom devices are typically configured to report
+ * touches at a rate of 100Hz (10ms). For systems
+ * that require polling for reports.
+ * When reports are polled, it will be expected to
+ * occasionally observe the overflow bit being set
+ * in the reports. This indicates that reports are not
+ * being read fast enough.
+ */
+#define POLL_INTERVAL_DEFAULT_MS 10
+
+/* Translate usage/page/offset triplet into physical address. */
+static u16 axiom_usage_to_target_address(struct axiom_data *ts, char usage, char page,
+ char offset)
+{
+ u32 i;
+
+ /* At the moment the convention is that u31 is always at physical address 0x0 */
+ if (!ts->usage_table_populated) {
+ if (usage == AXIOM_DEVINFO_USAGE_ID)
+ return ((page << 8) + offset);
+ else
+ return 0xffff;
+ }
+
+ for (i = 0; i < ts->devinfo.num_usages; i++) {
+ if (ts->usage_table[i].id != usage)
+ continue;
+
+ if (page >= ts->usage_table[i].num_pages) {
+ dev_err(ts->dev, "Invalid usage table! usage: %u, page: %u, offset: %u\n",
+ usage, page, offset);
+ return 0xffff;
+ }
+ break;
+ }
+
+ return ((ts->usage_table[i].start_page + page) << 8) + offset;
+}
+
+static int axiom_i2c_read(struct i2c_client *client, u8 usage, u8 page, u8 *buf, u16 len)
+{
+ struct axiom_data *ts = i2c_get_clientdata(client);
+ struct axiom_cmd_header cmd_header;
+ struct i2c_msg msg[2];
+ int error;
+
+ cmd_header.target_address = cpu_to_le16(axiom_usage_to_target_address(ts, usage, page, 0));
+ cmd_header.length = cpu_to_le16(len | AXIOM_CMD_HEADER_READ_MASK);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = sizeof(cmd_header);
+ msg[0].buf = (u8 *)&cmd_header;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = (char *)buf;
+
+ error = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (error != ARRAY_SIZE(msg)) {
+ dev_err(&client->dev,
+ "Failed reading usage %#x page %#x, error=%d\n",
+ usage, page, error);
+ return -EIO;
+ }
+
+ usleep_range(250, 300);
+
+ return 0;
+}
+
+/*
+ * One of the main purposes for reading the usage table is to identify
+ * which usages reside at which target address.
+ * When performing subsequent reads or writes to AXIOM, the target address
+ * is used to specify which usage is being accessed.
+ * Consider the following discovery code which will build up the usage table.
+ */
+static u32 axiom_populate_usage_table(struct axiom_data *ts)
+{
+ struct axiom_usage_entry *usage_table;
+ u32 max_report_len = 0;
+ char *rx_data = ts->rx_buf;
+ u32 usage_id;
+ int error;
+
+ usage_table = ts->usage_table;
+
+ /* Read the second page of usage u31 to get the usage table */
+ error = axiom_i2c_read(ts->client, AXIOM_DEVINFO_USAGE_ID, 1, rx_data,
+ (AXIOM_U31_BYTES_PER_USAGE * ts->devinfo.num_usages));
+ if (error)
+ return error;
+
+ for (usage_id = 0; usage_id < ts->devinfo.num_usages; usage_id++) {
+ u16 offset = (usage_id * AXIOM_U31_BYTES_PER_USAGE);
+ u8 id = rx_data[offset + 0];
+ u8 start_page = rx_data[offset + 1];
+ u8 num_pages = rx_data[offset + 2];
+ u32 max_offset = ((rx_data[offset + 3] & AXIOM_PAGE_OFFSET_MASK) + 1) * 2;
+
+ if (!num_pages)
+ usage_table[usage_id].is_report = true;
+
+ /* Store the entry into the usage table */
+ usage_table[usage_id].id = id;
+ usage_table[usage_id].start_page = start_page;
+ usage_table[usage_id].num_pages = num_pages;
+
+ dev_dbg(ts->dev, "Usage u%02x Info: %*ph\n", id,
+ AXIOM_U31_BYTES_PER_USAGE, &rx_data[offset]);
+
+ /* Identify the max report length the module will receive */
+ if (usage_table[usage_id].is_report && max_offset > max_report_len)
+ max_report_len = max_offset;
+ }
+
+ ts->usage_table_populated = true;
+
+ return max_report_len;
+}
+
+static int axiom_discover(struct axiom_data *ts)
+{
+ int error;
+
+ /*
+ * Fetch the first page of usage u31 to get the
+ * device information and the number of usages
+ */
+ error = axiom_i2c_read(ts->client, AXIOM_DEVINFO_USAGE_ID, 0, (char *)&ts->devinfo,
+ AXIOM_U31_PAGE0_LENGTH);
+ if (error)
+ return error;
+
+ dev_dbg(ts->dev, " Boot Mode : %s\n",
+ FIELD_GET(AXIOM_U31_BOOTMODE_MASK, ts->devinfo.device_id) ? "BLP" : "TCP");
+ dev_dbg(ts->dev, " Device ID : %04lx\n",
+ FIELD_GET(AXIOM_U31_DEVID_MASK, ts->devinfo.device_id));
+ dev_dbg(ts->dev, " Firmware Rev : %02x.%02x\n", ts->devinfo.fw_major,
+ ts->devinfo.fw_minor);
+ dev_dbg(ts->dev, " Bootloader Rev : %02x.%02x\n", ts->devinfo.bootloader_fw_major,
+ ts->devinfo.bootloader_fw_minor);
+ dev_dbg(ts->dev, " FW Extra Info : %04x\n", ts->devinfo.fw_info_extra);
+ dev_dbg(ts->dev, " Silicon : %04x\n", ts->devinfo.jedec_id);
+ dev_dbg(ts->dev, " Number usages : %04x\n", ts->devinfo.num_usages);
+
+ ts->max_report_len = axiom_populate_usage_table(ts);
+ if (!ts->max_report_len || !ts->devinfo.num_usages)
+ return -EINVAL;
+
+ dev_dbg(ts->dev, "Max Report Length: %u\n", ts->max_report_len);
+
+ return 0;
+}
+
+/*
+ * Support function to axiom_process_u41_report.
+ * Generates input-subsystem events for every target.
+ * After calling this function the caller shall issue
+ * a Sync to the input sub-system.
+ */
+static bool axiom_process_u41_report_target(struct axiom_data *ts,
+ struct axiom_target_report *target)
+{
+ struct input_dev *input_dev = ts->input_dev;
+ struct axiom_u41_target *target_prev_state;
+ enum axiom_target_state current_state;
+ bool update = false;
+ int slot;
+
+ /* Verify the target index */
+ if (target->index >= AXIOM_U41_MAX_TARGETS) {
+ dev_dbg(ts->dev, "Invalid target index! %u\n", target->index);
+ return false;
+ }
+
+ target_prev_state = &ts->targets[target->index];
+
+ current_state = AXIOM_TARGET_STATE_NOT_PRESENT;
+
+ if (target->present) {
+ if (target->z >= 0)
+ current_state = AXIOM_TARGET_STATE_TOUCHING;
+ else if (target->z > AXIOM_PROX_LEVEL && target->z < 0)
+ current_state = AXIOM_TARGET_STATE_HOVER;
+ else if (target->z == AXIOM_PROX_LEVEL)
+ current_state = AXIOM_TARGET_STATE_PROX;
+ }
+
+ if (target_prev_state->state == current_state &&
+ target_prev_state->x == target->x &&
+ target_prev_state->y == target->y &&
+ target_prev_state->z == target->z) {
+ return false;
+ }
+
+ slot = target->index;
+
+ dev_dbg(ts->dev, "U41 Target T%u, slot:%u present:%u, x:%u, y:%u, z:%d\n",
+ target->index, slot, target->present,
+ target->x, target->y, target->z);
+
+ switch (current_state) {
+ case AXIOM_TARGET_STATE_NOT_PRESENT:
+ case AXIOM_TARGET_STATE_PROX:
+ if (!target_prev_state->insert)
+ break;
+ update = true;
+ target_prev_state->insert = false;
+ input_mt_slot(input_dev, slot);
+
+ if (!slot)
+ input_report_key(input_dev, BTN_TOUCH, 0);
+
+ input_mt_report_slot_inactive(input_dev);
+ /*
+ * make sure the previous coordinates are
+ * all off screen when the finger comes back
+ */
+ target->x = 65535;
+ target->y = 65535;
+ target->z = AXIOM_PROX_LEVEL;
+ break;
+ case AXIOM_TARGET_STATE_HOVER:
+ case AXIOM_TARGET_STATE_TOUCHING:
+ target_prev_state->insert = true;
+ update = true;
+ input_mt_slot(input_dev, slot);
+ input_report_abs(input_dev, ABS_MT_TRACKING_ID, slot);
+ input_report_abs(input_dev, ABS_MT_POSITION_X, target->x);
+ input_report_abs(input_dev, ABS_X, target->x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, target->y);
+ input_report_abs(input_dev, ABS_Y, target->y);
+
+ if (current_state == AXIOM_TARGET_STATE_TOUCHING) {
+ input_report_abs(input_dev, ABS_MT_DISTANCE, 0);
+ input_report_abs(input_dev, ABS_DISTANCE, 0);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, target->z);
+ input_report_abs(input_dev, ABS_PRESSURE, target->z);
+ } else {
+ input_report_abs(input_dev, ABS_MT_DISTANCE, -target->z);
+ input_report_abs(input_dev, ABS_DISTANCE, -target->z);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, 0);
+ input_report_abs(input_dev, ABS_PRESSURE, 0);
+ }
+
+ if (!slot)
+ input_report_key(input_dev, BTN_TOUCH, (current_state ==
+ AXIOM_TARGET_STATE_TOUCHING));
+ break;
+ default:
+ break;
+ }
+
+ target_prev_state->state = current_state;
+ target_prev_state->x = target->x;
+ target_prev_state->y = target->y;
+ target_prev_state->z = target->z;
+
+ return update;
+}
+
+/*
+ * U41 is the output report of the 2D CTS and contains the status of targets
+ * (including contacts and pre-contacts) along with their X,Y,Z values.
+ * When a target has been removed (no longer detected),
+ * the corresponding X,Y,Z values will be zeroed.
+ */
+static bool axiom_process_u41_report(struct axiom_data *ts, char *rx_buf)
+{
+ struct axiom_target_report target;
+ bool update_done = false;
+ u16 target_status;
+ u32 i;
+
+ target_status = ((rx_buf[1]) | (rx_buf[2] << 8));
+
+ for (i = 0; i < AXIOM_U41_MAX_TARGETS; i++) {
+ char target_step = i * 4;
+
+ target.index = i;
+ target.present = ((target_status & (1 << i)) != 0) ? 1 : 0;
+ target.x = (rx_buf[(target_step + 3)] | (rx_buf[target_step + 4] << 8));
+ target.y = (rx_buf[(target_step + 5)] | (rx_buf[target_step + 6] << 8));
+ target.z = (s8)(rx_buf[i + 43]);
+ update_done |= axiom_process_u41_report_target(ts, &target);
+ }
+
+ return update_done;
+}
+
+/*
+ * U46 report contains a low level measurement data generated by the CDS
+ * algorithms from the AUX channels. This information is useful when tuning
+ * multi-press to assess mechanical consistency in the unit's construction.
+ */
+static void axiom_process_u46_report(struct axiom_data *ts, char *rx_buf)
+{
+ struct input_dev *input_dev = ts->input_dev;
+ u32 event_value;
+ u16 aux_value;
+ u32 i = 0;
+
+ for (i = 0; i < AXIOM_U46_AUX_CHANNELS; i++) {
+ char target_step = i * 2;
+
+ aux_value = ((rx_buf[target_step + 2] << 8) | (rx_buf[target_step + 1]))
+ & AXIOM_U46_AUX_MASK;
+ event_value = (i << 16) | (aux_value);
+ input_event(input_dev, EV_MSC, MSC_RAW, event_value);
+ }
+}
+
+/*
+ * Validates the crc and demultiplexes the axiom reports to the appropriate
+ * report handler
+ */
+static int axiom_handle_events(struct axiom_data *ts)
+{
+ struct input_dev *input_dev = ts->input_dev;
+ char *report_data = ts->rx_buf;
+ struct device *dev = ts->dev;
+ u16 crc_report;
+ u16 crc_calc;
+ int error;
+ char len;
+
+ error = axiom_i2c_read(ts->client, AXIOM_REPORT_USAGE_ID, 0, report_data,
+ ts->max_report_len);
+ if (error)
+ return error;
+
+ len = (report_data[0] & AXIOM_COMMS_REPORT_LEN_MASK) << 1;
+ if (!len) {
+ dev_err(dev, "Zero length report discarded.\n");
+ return -ENODATA;
+ }
+
+ /* Validate the report CRC */
+ crc_report = (report_data[len - 1] << 8) | (report_data[len - 2]);
+ /* Length is in 16 bit words and remove the size of the CRC16 itself */
+ crc_calc = crc16(0, report_data, (len - 2));
+
+ if (crc_calc != crc_report) {
+ dev_err(dev,
+ "CRC mismatch! Expected: %#x, Calculated CRC: %#x.\n",
+ crc_report, crc_calc);
+ return -EINVAL;
+ }
+
+ switch (report_data[1]) {
+ case AXIOM_USAGE_2DCTS_REPORT_ID:
+ if (axiom_process_u41_report(ts, &report_data[1])) {
+ input_mt_sync_frame(input_dev);
+ input_sync(input_dev);
+ }
+ break;
+
+ case AXIOM_USAGE_2AUX_REPORT_ID:
+ /* This is an aux report (force) */
+ axiom_process_u46_report(ts, &report_data[1]);
+ input_mt_sync(input_dev);
+ input_sync(input_dev);
+ break;
+
+ case AXIOM_USAGE_2HB_REPORT_ID:
+ /* This is a heartbeat report */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void axiom_i2c_poll(struct input_dev *input_dev)
+{
+ struct axiom_data *ts = input_get_drvdata(input_dev);
+
+ axiom_handle_events(ts);
+}
+
+static irqreturn_t axiom_irq(int irq, void *dev_id)
+{
+ struct axiom_data *ts = dev_id;
+
+ axiom_handle_events(ts);
+
+ return IRQ_HANDLED;
+}
+
+static void axiom_reset(struct gpio_desc *reset_gpio)
+{
+ gpiod_set_value_cansleep(reset_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(reset_gpio, 0);
+ msleep(110);
+}
+
+static int axiom_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct input_dev *input_dev;
+ struct axiom_data *ts;
+ u32 startup_delay_ms;
+ u32 poll_interval;
+ int target;
+ int error;
+
+ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+ ts->dev = dev;
+
+ ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ts->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ts->reset_gpio), "failed to get reset GPIO\n");
+
+ if (ts->reset_gpio)
+ axiom_reset(ts->reset_gpio);
+
+ ts->vddi = devm_regulator_get_optional(dev, "VDDI");
+ if (!IS_ERR(ts->vddi)) {
+ error = regulator_enable(ts->vddi);
+ if (error)
+ return dev_err_probe(&client->dev, error,
+ "Failed to enable VDDI regulator\n");
+ }
+
+ ts->vdda = devm_regulator_get_optional(dev, "VDDA");
+ if (!IS_ERR(ts->vdda)) {
+ error = regulator_enable(ts->vdda);
+ if (error) {
+ dev_err(dev, "Failed to get VDDA regulator\n");
+ regulator_disable(ts->vddi);
+ return error;
+ }
+ if (!device_property_read_u32(dev, "startup-time-ms", &startup_delay_ms))
+ msleep(startup_delay_ms);
+ }
+
+ error = axiom_discover(ts);
+ if (error)
+ return dev_err_probe(dev, error, "Failed touchscreen discover\n");
+
+ input_dev = devm_input_allocate_device(ts->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "TouchNetix axiom Touchscreen";
+ input_dev->phys = "input/axiom_ts";
+
+ /* Single Touch */
+ input_set_abs_params(input_dev, ABS_X, 0, 65535, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 65535, 0, 0);
+
+ /* Multi Touch */
+ /* Min, Max, Fuzz (expected noise in px, try 4?) and Flat */
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 65535, 0, 0);
+ /* Min, Max, Fuzz (expected noise in px, try 4?) and Flat */
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 65535, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_DISTANCE, 0, 127, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 127, 0, 0);
+
+ input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
+
+ /* Registers the axiom device as a touchscreen instead of a mouse pointer */
+ error = input_mt_init_slots(input_dev, AXIOM_U41_MAX_TARGETS, INPUT_MT_DIRECT);
+ if (error)
+ return error;
+
+ /* Enables the raw data for up to 4 force channels to be sent to the input subsystem */
+ set_bit(EV_REL, input_dev->evbit);
+ set_bit(EV_MSC, input_dev->evbit);
+ /* Declare that we support "RAW" Miscellaneous events */
+ set_bit(MSC_RAW, input_dev->mscbit);
+
+ ts->input_dev = input_dev;
+ input_set_drvdata(ts->input_dev, ts);
+
+ /* Ensure that all reports are initialised to not be present. */
+ for (target = 0; target < AXIOM_U41_MAX_TARGETS; target++)
+ ts->targets[target].state = AXIOM_TARGET_STATE_NOT_PRESENT;
+
+ error = input_register_device(input_dev);
+ if (error)
+ return dev_err_probe(ts->dev, error,
+ "Could not register with Input Sub-system.\n");
+
+ error = devm_request_threaded_irq(dev, client->irq, NULL,
+ axiom_irq, IRQF_ONESHOT, dev_name(dev), ts);
+ if (error < 0) {
+ dev_warn(dev, "Request irq failed, falling back to polling mode");
+
+ error = input_setup_polling(input_dev, axiom_i2c_poll);
+ if (error)
+ return dev_err_probe(ts->dev, error, "Unable to set up polling mode\n");
+
+ if (!device_property_read_u32(ts->dev, "poll-interval", &poll_interval))
+ input_set_poll_interval(input_dev, poll_interval);
+ else
+ input_set_poll_interval(input_dev, POLL_INTERVAL_DEFAULT_MS);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id axiom_i2c_id_table[] = {
+ { "ax54a" },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, axiom_i2c_id_table);
+
+static const struct of_device_id axiom_i2c_of_match[] = {
+ { .compatible = "touchnetix,ax54a", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, axiom_i2c_of_match);
+
+static struct i2c_driver axiom_i2c_driver = {
+ .driver = {
+ .name = "axiom",
+ .of_match_table = axiom_i2c_of_match,
+ },
+ .id_table = axiom_i2c_id_table,
+ .probe = axiom_i2c_probe,
+};
+module_i2c_driver(axiom_i2c_driver);
+MODULE_AUTHOR("Bart Prescott <bartp@baasheep.co.uk>");
+MODULE_AUTHOR("Pedro Torruella <pedro.torruella@touchnetix.com>");
+MODULE_AUTHOR("Mark Satterthwaite <mark.satterthwaite@touchnetix.com>");
+MODULE_AUTHOR("Hannah Rossiter <hannah.rossiter@touchnetix.com>");
+MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>");
+MODULE_DESCRIPTION("TouchNetix axiom touchscreen I2C bus driver");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox