Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] soc: qcom: socinfo: add SoC ID for IPQ9650 family
From: Dmitry Baryshkov @ 2026-04-09  1:53 UTC (permalink / raw)
  To: Kathiravan Thirumoorthy
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260408-ipq9650_soc_ids-v1-2-e76faac33f77@oss.qualcomm.com>

On Wed, Apr 08, 2026 at 03:28:35PM +0530, Kathiravan Thirumoorthy wrote:
> Add SoC IDs for Qualcomm's IPQ9650 family.
> 
> Signed-off-by: Kathiravan Thirumoorthy <kathiravan.thirumoorthy@oss.qualcomm.com>
> ---
>  drivers/soc/qcom/socinfo.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v2 2/2] pinctrl: qcom: Add Hawi pinctrl driver
From: Bjorn Andersson @ 2026-04-09  1:50 UTC (permalink / raw)
  To: Mukesh Ojha
  Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-arm-msm, linux-gpio, devicetree, linux-kernel,
	Konrad Dybcio
In-Reply-To: <20260408-hawi-pinctrl-v2-2-fd7f681f5e05@oss.qualcomm.com>

On Wed, Apr 08, 2026 at 07:45:48PM +0530, Mukesh Ojha wrote:
> Add pinctrl driver for TLMM block found in the Hawi SoC.
> 
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>

Thanks for updating those functions.

Reviewed-by: Bjorn Andersson <andersson@kernel.org>

Regards,
Bjorn

> ---
>  drivers/pinctrl/qcom/Kconfig.msm    |   10 +
>  drivers/pinctrl/qcom/Makefile       |    1 +
>  drivers/pinctrl/qcom/pinctrl-hawi.c | 1610 +++++++++++++++++++++++++++++++++++
>  3 files changed, 1621 insertions(+)
> 
> diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm
> index 17416dce8e70..836cdeca1006 100644
> --- a/drivers/pinctrl/qcom/Kconfig.msm
> +++ b/drivers/pinctrl/qcom/Kconfig.msm
> @@ -35,6 +35,16 @@ config PINCTRL_GLYMUR
>  	  Say Y here to compile statically, or M here to compile it as a module.
>  	  If unsure, say N.
>  
> +config PINCTRL_HAWI
> +	tristate "Qualcomm Technologies Inc Hawi pin controller driver"
> +	depends on ARM64 || COMPILE_TEST
> +	help
> +	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
> +	  Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
> +	  block found on the Qualcomm Technologies Inc Hawi platform.
> +	  Say Y here to compile statically, or M here to compile it as a module.
> +	  If unsure, say N.
> +
>  config PINCTRL_IPQ4019
>  	tristate "Qualcomm IPQ4019 pin controller driver"
>  	depends on ARM || COMPILE_TEST
> diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
> index 4c585bad813c..84bda3ada874 100644
> --- a/drivers/pinctrl/qcom/Makefile
> +++ b/drivers/pinctrl/qcom/Makefile
> @@ -5,6 +5,7 @@ obj-$(CONFIG_PINCTRL_APQ8064)	+= pinctrl-apq8064.o
>  obj-$(CONFIG_PINCTRL_APQ8084)	+= pinctrl-apq8084.o
>  obj-$(CONFIG_PINCTRL_ELIZA)	+= pinctrl-eliza.o
>  obj-$(CONFIG_PINCTRL_GLYMUR)	+= pinctrl-glymur.o
> +obj-$(CONFIG_PINCTRL_HAWI)	+= pinctrl-hawi.o
>  obj-$(CONFIG_PINCTRL_IPQ4019)	+= pinctrl-ipq4019.o
>  obj-$(CONFIG_PINCTRL_IPQ5018)	+= pinctrl-ipq5018.o
>  obj-$(CONFIG_PINCTRL_IPQ8064)	+= pinctrl-ipq8064.o
> diff --git a/drivers/pinctrl/qcom/pinctrl-hawi.c b/drivers/pinctrl/qcom/pinctrl-hawi.c
> new file mode 100644
> index 000000000000..5c7894f3b9cb
> --- /dev/null
> +++ b/drivers/pinctrl/qcom/pinctrl-hawi.c
> @@ -0,0 +1,1610 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#include "pinctrl-msm.h"
> +
> +#define REG_SIZE 0x1000
> +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
> +	{						\
> +		.grp = PINCTRL_PINGROUP("gpio" #id,	\
> +			gpio##id##_pins,		\
> +			ARRAY_SIZE(gpio##id##_pins)),	\
> +		.funcs = (int[]){			\
> +			msm_mux_gpio, /* gpio mode */	\
> +			msm_mux_##f1,			\
> +			msm_mux_##f2,			\
> +			msm_mux_##f3,			\
> +			msm_mux_##f4,			\
> +			msm_mux_##f5,			\
> +			msm_mux_##f6,			\
> +			msm_mux_##f7,			\
> +			msm_mux_##f8,			\
> +			msm_mux_##f9,			\
> +			msm_mux_##f10,			\
> +			msm_mux_##f11 /* egpio mode */	\
> +		},					\
> +		.nfuncs = 12,				\
> +		.ctl_reg = REG_SIZE * id,		\
> +		.io_reg = 0x4 + REG_SIZE * id,		\
> +		.intr_cfg_reg = 0x8 + REG_SIZE * id,	\
> +		.intr_status_reg = 0xc + REG_SIZE * id,	\
> +		.mux_bit = 2,				\
> +		.pull_bit = 0,				\
> +		.drv_bit = 6,				\
> +		.egpio_enable = 12,			\
> +		.egpio_present = 11,			\
> +		.oe_bit = 9,				\
> +		.in_bit = 0,				\
> +		.out_bit = 1,				\
> +		.intr_enable_bit = 0,			\
> +		.intr_status_bit = 0,			\
> +		.intr_wakeup_present_bit = 6,	\
> +		.intr_wakeup_enable_bit = 7,	\
> +		.intr_target_bit = 8,			\
> +		.intr_target_kpss_val = 3,		\
> +		.intr_raw_status_bit = 4,		\
> +		.intr_polarity_bit = 1,			\
> +		.intr_detection_bit = 2,		\
> +		.intr_detection_width = 2,		\
> +	}
> +
> +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)	\
> +	{					        \
> +		.grp = PINCTRL_PINGROUP(#pg_name,	\
> +			pg_name##_pins,			\
> +			ARRAY_SIZE(pg_name##_pins)),	\
> +		.ctl_reg = ctl,				\
> +		.io_reg = 0,				\
> +		.intr_cfg_reg = 0,			\
> +		.intr_status_reg = 0,			\
> +		.intr_target_reg = 0,			\
> +		.mux_bit = -1,				\
> +		.pull_bit = pull,			\
> +		.drv_bit = drv,				\
> +		.oe_bit = -1,				\
> +		.in_bit = -1,				\
> +		.out_bit = -1,				\
> +		.intr_enable_bit = -1,			\
> +		.intr_status_bit = -1,			\
> +		.intr_target_bit = -1,			\
> +		.intr_raw_status_bit = -1,		\
> +		.intr_polarity_bit = -1,		\
> +		.intr_detection_bit = -1,		\
> +		.intr_detection_width = -1,		\
> +	}
> +
> +#define UFS_RESET(pg_name, ctl, io)			\
> +	{						\
> +		.grp = PINCTRL_PINGROUP(#pg_name,	\
> +			pg_name##_pins,			\
> +			ARRAY_SIZE(pg_name##_pins)),	\
> +		.ctl_reg = ctl,				\
> +		.io_reg = io,				\
> +		.intr_cfg_reg = 0,			\
> +		.intr_status_reg = 0,			\
> +		.intr_target_reg = 0,			\
> +		.mux_bit = -1,				\
> +		.pull_bit = 3,				\
> +		.drv_bit = 0,				\
> +		.oe_bit = -1,				\
> +		.in_bit = -1,				\
> +		.out_bit = 0,				\
> +		.intr_enable_bit = -1,			\
> +		.intr_status_bit = -1,			\
> +		.intr_target_bit = -1,			\
> +		.intr_raw_status_bit = -1,		\
> +		.intr_polarity_bit = -1,		\
> +		.intr_detection_bit = -1,		\
> +		.intr_detection_width = -1,		\
> +	}
> +
> +static const struct pinctrl_pin_desc hawi_pins[] = {
> +	PINCTRL_PIN(0, "GPIO_0"),
> +	PINCTRL_PIN(1, "GPIO_1"),
> +	PINCTRL_PIN(2, "GPIO_2"),
> +	PINCTRL_PIN(3, "GPIO_3"),
> +	PINCTRL_PIN(4, "GPIO_4"),
> +	PINCTRL_PIN(5, "GPIO_5"),
> +	PINCTRL_PIN(6, "GPIO_6"),
> +	PINCTRL_PIN(7, "GPIO_7"),
> +	PINCTRL_PIN(8, "GPIO_8"),
> +	PINCTRL_PIN(9, "GPIO_9"),
> +	PINCTRL_PIN(10, "GPIO_10"),
> +	PINCTRL_PIN(11, "GPIO_11"),
> +	PINCTRL_PIN(12, "GPIO_12"),
> +	PINCTRL_PIN(13, "GPIO_13"),
> +	PINCTRL_PIN(14, "GPIO_14"),
> +	PINCTRL_PIN(15, "GPIO_15"),
> +	PINCTRL_PIN(16, "GPIO_16"),
> +	PINCTRL_PIN(17, "GPIO_17"),
> +	PINCTRL_PIN(18, "GPIO_18"),
> +	PINCTRL_PIN(19, "GPIO_19"),
> +	PINCTRL_PIN(20, "GPIO_20"),
> +	PINCTRL_PIN(21, "GPIO_21"),
> +	PINCTRL_PIN(22, "GPIO_22"),
> +	PINCTRL_PIN(23, "GPIO_23"),
> +	PINCTRL_PIN(24, "GPIO_24"),
> +	PINCTRL_PIN(25, "GPIO_25"),
> +	PINCTRL_PIN(26, "GPIO_26"),
> +	PINCTRL_PIN(27, "GPIO_27"),
> +	PINCTRL_PIN(28, "GPIO_28"),
> +	PINCTRL_PIN(29, "GPIO_29"),
> +	PINCTRL_PIN(30, "GPIO_30"),
> +	PINCTRL_PIN(31, "GPIO_31"),
> +	PINCTRL_PIN(32, "GPIO_32"),
> +	PINCTRL_PIN(33, "GPIO_33"),
> +	PINCTRL_PIN(34, "GPIO_34"),
> +	PINCTRL_PIN(35, "GPIO_35"),
> +	PINCTRL_PIN(36, "GPIO_36"),
> +	PINCTRL_PIN(37, "GPIO_37"),
> +	PINCTRL_PIN(38, "GPIO_38"),
> +	PINCTRL_PIN(39, "GPIO_39"),
> +	PINCTRL_PIN(40, "GPIO_40"),
> +	PINCTRL_PIN(41, "GPIO_41"),
> +	PINCTRL_PIN(42, "GPIO_42"),
> +	PINCTRL_PIN(43, "GPIO_43"),
> +	PINCTRL_PIN(44, "GPIO_44"),
> +	PINCTRL_PIN(45, "GPIO_45"),
> +	PINCTRL_PIN(46, "GPIO_46"),
> +	PINCTRL_PIN(47, "GPIO_47"),
> +	PINCTRL_PIN(48, "GPIO_48"),
> +	PINCTRL_PIN(49, "GPIO_49"),
> +	PINCTRL_PIN(50, "GPIO_50"),
> +	PINCTRL_PIN(51, "GPIO_51"),
> +	PINCTRL_PIN(52, "GPIO_52"),
> +	PINCTRL_PIN(53, "GPIO_53"),
> +	PINCTRL_PIN(54, "GPIO_54"),
> +	PINCTRL_PIN(55, "GPIO_55"),
> +	PINCTRL_PIN(56, "GPIO_56"),
> +	PINCTRL_PIN(57, "GPIO_57"),
> +	PINCTRL_PIN(58, "GPIO_58"),
> +	PINCTRL_PIN(59, "GPIO_59"),
> +	PINCTRL_PIN(60, "GPIO_60"),
> +	PINCTRL_PIN(61, "GPIO_61"),
> +	PINCTRL_PIN(62, "GPIO_62"),
> +	PINCTRL_PIN(63, "GPIO_63"),
> +	PINCTRL_PIN(64, "GPIO_64"),
> +	PINCTRL_PIN(65, "GPIO_65"),
> +	PINCTRL_PIN(66, "GPIO_66"),
> +	PINCTRL_PIN(67, "GPIO_67"),
> +	PINCTRL_PIN(68, "GPIO_68"),
> +	PINCTRL_PIN(69, "GPIO_69"),
> +	PINCTRL_PIN(70, "GPIO_70"),
> +	PINCTRL_PIN(71, "GPIO_71"),
> +	PINCTRL_PIN(72, "GPIO_72"),
> +	PINCTRL_PIN(73, "GPIO_73"),
> +	PINCTRL_PIN(74, "GPIO_74"),
> +	PINCTRL_PIN(75, "GPIO_75"),
> +	PINCTRL_PIN(76, "GPIO_76"),
> +	PINCTRL_PIN(77, "GPIO_77"),
> +	PINCTRL_PIN(78, "GPIO_78"),
> +	PINCTRL_PIN(79, "GPIO_79"),
> +	PINCTRL_PIN(80, "GPIO_80"),
> +	PINCTRL_PIN(81, "GPIO_81"),
> +	PINCTRL_PIN(82, "GPIO_82"),
> +	PINCTRL_PIN(83, "GPIO_83"),
> +	PINCTRL_PIN(84, "GPIO_84"),
> +	PINCTRL_PIN(85, "GPIO_85"),
> +	PINCTRL_PIN(86, "GPIO_86"),
> +	PINCTRL_PIN(87, "GPIO_87"),
> +	PINCTRL_PIN(88, "GPIO_88"),
> +	PINCTRL_PIN(89, "GPIO_89"),
> +	PINCTRL_PIN(90, "GPIO_90"),
> +	PINCTRL_PIN(91, "GPIO_91"),
> +	PINCTRL_PIN(92, "GPIO_92"),
> +	PINCTRL_PIN(93, "GPIO_93"),
> +	PINCTRL_PIN(94, "GPIO_94"),
> +	PINCTRL_PIN(95, "GPIO_95"),
> +	PINCTRL_PIN(96, "GPIO_96"),
> +	PINCTRL_PIN(97, "GPIO_97"),
> +	PINCTRL_PIN(98, "GPIO_98"),
> +	PINCTRL_PIN(99, "GPIO_99"),
> +	PINCTRL_PIN(100, "GPIO_100"),
> +	PINCTRL_PIN(101, "GPIO_101"),
> +	PINCTRL_PIN(102, "GPIO_102"),
> +	PINCTRL_PIN(103, "GPIO_103"),
> +	PINCTRL_PIN(104, "GPIO_104"),
> +	PINCTRL_PIN(105, "GPIO_105"),
> +	PINCTRL_PIN(106, "GPIO_106"),
> +	PINCTRL_PIN(107, "GPIO_107"),
> +	PINCTRL_PIN(108, "GPIO_108"),
> +	PINCTRL_PIN(109, "GPIO_109"),
> +	PINCTRL_PIN(110, "GPIO_110"),
> +	PINCTRL_PIN(111, "GPIO_111"),
> +	PINCTRL_PIN(112, "GPIO_112"),
> +	PINCTRL_PIN(113, "GPIO_113"),
> +	PINCTRL_PIN(114, "GPIO_114"),
> +	PINCTRL_PIN(115, "GPIO_115"),
> +	PINCTRL_PIN(116, "GPIO_116"),
> +	PINCTRL_PIN(117, "GPIO_117"),
> +	PINCTRL_PIN(118, "GPIO_118"),
> +	PINCTRL_PIN(119, "GPIO_119"),
> +	PINCTRL_PIN(120, "GPIO_120"),
> +	PINCTRL_PIN(121, "GPIO_121"),
> +	PINCTRL_PIN(122, "GPIO_122"),
> +	PINCTRL_PIN(123, "GPIO_123"),
> +	PINCTRL_PIN(124, "GPIO_124"),
> +	PINCTRL_PIN(125, "GPIO_125"),
> +	PINCTRL_PIN(126, "GPIO_126"),
> +	PINCTRL_PIN(127, "GPIO_127"),
> +	PINCTRL_PIN(128, "GPIO_128"),
> +	PINCTRL_PIN(129, "GPIO_129"),
> +	PINCTRL_PIN(130, "GPIO_130"),
> +	PINCTRL_PIN(131, "GPIO_131"),
> +	PINCTRL_PIN(132, "GPIO_132"),
> +	PINCTRL_PIN(133, "GPIO_133"),
> +	PINCTRL_PIN(134, "GPIO_134"),
> +	PINCTRL_PIN(135, "GPIO_135"),
> +	PINCTRL_PIN(136, "GPIO_136"),
> +	PINCTRL_PIN(137, "GPIO_137"),
> +	PINCTRL_PIN(138, "GPIO_138"),
> +	PINCTRL_PIN(139, "GPIO_139"),
> +	PINCTRL_PIN(140, "GPIO_140"),
> +	PINCTRL_PIN(141, "GPIO_141"),
> +	PINCTRL_PIN(142, "GPIO_142"),
> +	PINCTRL_PIN(143, "GPIO_143"),
> +	PINCTRL_PIN(144, "GPIO_144"),
> +	PINCTRL_PIN(145, "GPIO_145"),
> +	PINCTRL_PIN(146, "GPIO_146"),
> +	PINCTRL_PIN(147, "GPIO_147"),
> +	PINCTRL_PIN(148, "GPIO_148"),
> +	PINCTRL_PIN(149, "GPIO_149"),
> +	PINCTRL_PIN(150, "GPIO_150"),
> +	PINCTRL_PIN(151, "GPIO_151"),
> +	PINCTRL_PIN(152, "GPIO_152"),
> +	PINCTRL_PIN(153, "GPIO_153"),
> +	PINCTRL_PIN(154, "GPIO_154"),
> +	PINCTRL_PIN(155, "GPIO_155"),
> +	PINCTRL_PIN(156, "GPIO_156"),
> +	PINCTRL_PIN(157, "GPIO_157"),
> +	PINCTRL_PIN(158, "GPIO_158"),
> +	PINCTRL_PIN(159, "GPIO_159"),
> +	PINCTRL_PIN(160, "GPIO_160"),
> +	PINCTRL_PIN(161, "GPIO_161"),
> +	PINCTRL_PIN(162, "GPIO_162"),
> +	PINCTRL_PIN(163, "GPIO_163"),
> +	PINCTRL_PIN(164, "GPIO_164"),
> +	PINCTRL_PIN(165, "GPIO_165"),
> +	PINCTRL_PIN(166, "GPIO_166"),
> +	PINCTRL_PIN(167, "GPIO_167"),
> +	PINCTRL_PIN(168, "GPIO_168"),
> +	PINCTRL_PIN(169, "GPIO_169"),
> +	PINCTRL_PIN(170, "GPIO_170"),
> +	PINCTRL_PIN(171, "GPIO_171"),
> +	PINCTRL_PIN(172, "GPIO_172"),
> +	PINCTRL_PIN(173, "GPIO_173"),
> +	PINCTRL_PIN(174, "GPIO_174"),
> +	PINCTRL_PIN(175, "GPIO_175"),
> +	PINCTRL_PIN(176, "GPIO_176"),
> +	PINCTRL_PIN(177, "GPIO_177"),
> +	PINCTRL_PIN(178, "GPIO_178"),
> +	PINCTRL_PIN(179, "GPIO_179"),
> +	PINCTRL_PIN(180, "GPIO_180"),
> +	PINCTRL_PIN(181, "GPIO_181"),
> +	PINCTRL_PIN(182, "GPIO_182"),
> +	PINCTRL_PIN(183, "GPIO_183"),
> +	PINCTRL_PIN(184, "GPIO_184"),
> +	PINCTRL_PIN(185, "GPIO_185"),
> +	PINCTRL_PIN(186, "GPIO_186"),
> +	PINCTRL_PIN(187, "GPIO_187"),
> +	PINCTRL_PIN(188, "GPIO_188"),
> +	PINCTRL_PIN(189, "GPIO_189"),
> +	PINCTRL_PIN(190, "GPIO_190"),
> +	PINCTRL_PIN(191, "GPIO_191"),
> +	PINCTRL_PIN(192, "GPIO_192"),
> +	PINCTRL_PIN(193, "GPIO_193"),
> +	PINCTRL_PIN(194, "GPIO_194"),
> +	PINCTRL_PIN(195, "GPIO_195"),
> +	PINCTRL_PIN(196, "GPIO_196"),
> +	PINCTRL_PIN(197, "GPIO_197"),
> +	PINCTRL_PIN(198, "GPIO_198"),
> +	PINCTRL_PIN(199, "GPIO_199"),
> +	PINCTRL_PIN(200, "GPIO_200"),
> +	PINCTRL_PIN(201, "GPIO_201"),
> +	PINCTRL_PIN(202, "GPIO_202"),
> +	PINCTRL_PIN(203, "GPIO_203"),
> +	PINCTRL_PIN(204, "GPIO_204"),
> +	PINCTRL_PIN(205, "GPIO_205"),
> +	PINCTRL_PIN(206, "GPIO_206"),
> +	PINCTRL_PIN(207, "GPIO_207"),
> +	PINCTRL_PIN(208, "GPIO_208"),
> +	PINCTRL_PIN(209, "GPIO_209"),
> +	PINCTRL_PIN(210, "GPIO_210"),
> +	PINCTRL_PIN(211, "GPIO_211"),
> +	PINCTRL_PIN(212, "GPIO_212"),
> +	PINCTRL_PIN(213, "GPIO_213"),
> +	PINCTRL_PIN(214, "GPIO_214"),
> +	PINCTRL_PIN(215, "GPIO_215"),
> +	PINCTRL_PIN(216, "GPIO_216"),
> +	PINCTRL_PIN(217, "GPIO_217"),
> +	PINCTRL_PIN(218, "GPIO_218"),
> +	PINCTRL_PIN(219, "GPIO_219"),
> +	PINCTRL_PIN(220, "GPIO_220"),
> +	PINCTRL_PIN(221, "GPIO_221"),
> +	PINCTRL_PIN(222, "GPIO_222"),
> +	PINCTRL_PIN(223, "GPIO_223"),
> +	PINCTRL_PIN(224, "GPIO_224"),
> +	PINCTRL_PIN(225, "GPIO_225"),
> +	PINCTRL_PIN(226, "UFS_RESET"),
> +	PINCTRL_PIN(227, "SDC2_CLK"),
> +	PINCTRL_PIN(228, "SDC2_CMD"),
> +	PINCTRL_PIN(229, "SDC2_DATA"),
> +};
> +
> +#define DECLARE_MSM_GPIO_PINS(pin) \
> +	static const unsigned int gpio##pin##_pins[] = { pin }
> +DECLARE_MSM_GPIO_PINS(0);
> +DECLARE_MSM_GPIO_PINS(1);
> +DECLARE_MSM_GPIO_PINS(2);
> +DECLARE_MSM_GPIO_PINS(3);
> +DECLARE_MSM_GPIO_PINS(4);
> +DECLARE_MSM_GPIO_PINS(5);
> +DECLARE_MSM_GPIO_PINS(6);
> +DECLARE_MSM_GPIO_PINS(7);
> +DECLARE_MSM_GPIO_PINS(8);
> +DECLARE_MSM_GPIO_PINS(9);
> +DECLARE_MSM_GPIO_PINS(10);
> +DECLARE_MSM_GPIO_PINS(11);
> +DECLARE_MSM_GPIO_PINS(12);
> +DECLARE_MSM_GPIO_PINS(13);
> +DECLARE_MSM_GPIO_PINS(14);
> +DECLARE_MSM_GPIO_PINS(15);
> +DECLARE_MSM_GPIO_PINS(16);
> +DECLARE_MSM_GPIO_PINS(17);
> +DECLARE_MSM_GPIO_PINS(18);
> +DECLARE_MSM_GPIO_PINS(19);
> +DECLARE_MSM_GPIO_PINS(20);
> +DECLARE_MSM_GPIO_PINS(21);
> +DECLARE_MSM_GPIO_PINS(22);
> +DECLARE_MSM_GPIO_PINS(23);
> +DECLARE_MSM_GPIO_PINS(24);
> +DECLARE_MSM_GPIO_PINS(25);
> +DECLARE_MSM_GPIO_PINS(26);
> +DECLARE_MSM_GPIO_PINS(27);
> +DECLARE_MSM_GPIO_PINS(28);
> +DECLARE_MSM_GPIO_PINS(29);
> +DECLARE_MSM_GPIO_PINS(30);
> +DECLARE_MSM_GPIO_PINS(31);
> +DECLARE_MSM_GPIO_PINS(32);
> +DECLARE_MSM_GPIO_PINS(33);
> +DECLARE_MSM_GPIO_PINS(34);
> +DECLARE_MSM_GPIO_PINS(35);
> +DECLARE_MSM_GPIO_PINS(36);
> +DECLARE_MSM_GPIO_PINS(37);
> +DECLARE_MSM_GPIO_PINS(38);
> +DECLARE_MSM_GPIO_PINS(39);
> +DECLARE_MSM_GPIO_PINS(40);
> +DECLARE_MSM_GPIO_PINS(41);
> +DECLARE_MSM_GPIO_PINS(42);
> +DECLARE_MSM_GPIO_PINS(43);
> +DECLARE_MSM_GPIO_PINS(44);
> +DECLARE_MSM_GPIO_PINS(45);
> +DECLARE_MSM_GPIO_PINS(46);
> +DECLARE_MSM_GPIO_PINS(47);
> +DECLARE_MSM_GPIO_PINS(48);
> +DECLARE_MSM_GPIO_PINS(49);
> +DECLARE_MSM_GPIO_PINS(50);
> +DECLARE_MSM_GPIO_PINS(51);
> +DECLARE_MSM_GPIO_PINS(52);
> +DECLARE_MSM_GPIO_PINS(53);
> +DECLARE_MSM_GPIO_PINS(54);
> +DECLARE_MSM_GPIO_PINS(55);
> +DECLARE_MSM_GPIO_PINS(56);
> +DECLARE_MSM_GPIO_PINS(57);
> +DECLARE_MSM_GPIO_PINS(58);
> +DECLARE_MSM_GPIO_PINS(59);
> +DECLARE_MSM_GPIO_PINS(60);
> +DECLARE_MSM_GPIO_PINS(61);
> +DECLARE_MSM_GPIO_PINS(62);
> +DECLARE_MSM_GPIO_PINS(63);
> +DECLARE_MSM_GPIO_PINS(64);
> +DECLARE_MSM_GPIO_PINS(65);
> +DECLARE_MSM_GPIO_PINS(66);
> +DECLARE_MSM_GPIO_PINS(67);
> +DECLARE_MSM_GPIO_PINS(68);
> +DECLARE_MSM_GPIO_PINS(69);
> +DECLARE_MSM_GPIO_PINS(70);
> +DECLARE_MSM_GPIO_PINS(71);
> +DECLARE_MSM_GPIO_PINS(72);
> +DECLARE_MSM_GPIO_PINS(73);
> +DECLARE_MSM_GPIO_PINS(74);
> +DECLARE_MSM_GPIO_PINS(75);
> +DECLARE_MSM_GPIO_PINS(76);
> +DECLARE_MSM_GPIO_PINS(77);
> +DECLARE_MSM_GPIO_PINS(78);
> +DECLARE_MSM_GPIO_PINS(79);
> +DECLARE_MSM_GPIO_PINS(80);
> +DECLARE_MSM_GPIO_PINS(81);
> +DECLARE_MSM_GPIO_PINS(82);
> +DECLARE_MSM_GPIO_PINS(83);
> +DECLARE_MSM_GPIO_PINS(84);
> +DECLARE_MSM_GPIO_PINS(85);
> +DECLARE_MSM_GPIO_PINS(86);
> +DECLARE_MSM_GPIO_PINS(87);
> +DECLARE_MSM_GPIO_PINS(88);
> +DECLARE_MSM_GPIO_PINS(89);
> +DECLARE_MSM_GPIO_PINS(90);
> +DECLARE_MSM_GPIO_PINS(91);
> +DECLARE_MSM_GPIO_PINS(92);
> +DECLARE_MSM_GPIO_PINS(93);
> +DECLARE_MSM_GPIO_PINS(94);
> +DECLARE_MSM_GPIO_PINS(95);
> +DECLARE_MSM_GPIO_PINS(96);
> +DECLARE_MSM_GPIO_PINS(97);
> +DECLARE_MSM_GPIO_PINS(98);
> +DECLARE_MSM_GPIO_PINS(99);
> +DECLARE_MSM_GPIO_PINS(100);
> +DECLARE_MSM_GPIO_PINS(101);
> +DECLARE_MSM_GPIO_PINS(102);
> +DECLARE_MSM_GPIO_PINS(103);
> +DECLARE_MSM_GPIO_PINS(104);
> +DECLARE_MSM_GPIO_PINS(105);
> +DECLARE_MSM_GPIO_PINS(106);
> +DECLARE_MSM_GPIO_PINS(107);
> +DECLARE_MSM_GPIO_PINS(108);
> +DECLARE_MSM_GPIO_PINS(109);
> +DECLARE_MSM_GPIO_PINS(110);
> +DECLARE_MSM_GPIO_PINS(111);
> +DECLARE_MSM_GPIO_PINS(112);
> +DECLARE_MSM_GPIO_PINS(113);
> +DECLARE_MSM_GPIO_PINS(114);
> +DECLARE_MSM_GPIO_PINS(115);
> +DECLARE_MSM_GPIO_PINS(116);
> +DECLARE_MSM_GPIO_PINS(117);
> +DECLARE_MSM_GPIO_PINS(118);
> +DECLARE_MSM_GPIO_PINS(119);
> +DECLARE_MSM_GPIO_PINS(120);
> +DECLARE_MSM_GPIO_PINS(121);
> +DECLARE_MSM_GPIO_PINS(122);
> +DECLARE_MSM_GPIO_PINS(123);
> +DECLARE_MSM_GPIO_PINS(124);
> +DECLARE_MSM_GPIO_PINS(125);
> +DECLARE_MSM_GPIO_PINS(126);
> +DECLARE_MSM_GPIO_PINS(127);
> +DECLARE_MSM_GPIO_PINS(128);
> +DECLARE_MSM_GPIO_PINS(129);
> +DECLARE_MSM_GPIO_PINS(130);
> +DECLARE_MSM_GPIO_PINS(131);
> +DECLARE_MSM_GPIO_PINS(132);
> +DECLARE_MSM_GPIO_PINS(133);
> +DECLARE_MSM_GPIO_PINS(134);
> +DECLARE_MSM_GPIO_PINS(135);
> +DECLARE_MSM_GPIO_PINS(136);
> +DECLARE_MSM_GPIO_PINS(137);
> +DECLARE_MSM_GPIO_PINS(138);
> +DECLARE_MSM_GPIO_PINS(139);
> +DECLARE_MSM_GPIO_PINS(140);
> +DECLARE_MSM_GPIO_PINS(141);
> +DECLARE_MSM_GPIO_PINS(142);
> +DECLARE_MSM_GPIO_PINS(143);
> +DECLARE_MSM_GPIO_PINS(144);
> +DECLARE_MSM_GPIO_PINS(145);
> +DECLARE_MSM_GPIO_PINS(146);
> +DECLARE_MSM_GPIO_PINS(147);
> +DECLARE_MSM_GPIO_PINS(148);
> +DECLARE_MSM_GPIO_PINS(149);
> +DECLARE_MSM_GPIO_PINS(150);
> +DECLARE_MSM_GPIO_PINS(151);
> +DECLARE_MSM_GPIO_PINS(152);
> +DECLARE_MSM_GPIO_PINS(153);
> +DECLARE_MSM_GPIO_PINS(154);
> +DECLARE_MSM_GPIO_PINS(155);
> +DECLARE_MSM_GPIO_PINS(156);
> +DECLARE_MSM_GPIO_PINS(157);
> +DECLARE_MSM_GPIO_PINS(158);
> +DECLARE_MSM_GPIO_PINS(159);
> +DECLARE_MSM_GPIO_PINS(160);
> +DECLARE_MSM_GPIO_PINS(161);
> +DECLARE_MSM_GPIO_PINS(162);
> +DECLARE_MSM_GPIO_PINS(163);
> +DECLARE_MSM_GPIO_PINS(164);
> +DECLARE_MSM_GPIO_PINS(165);
> +DECLARE_MSM_GPIO_PINS(166);
> +DECLARE_MSM_GPIO_PINS(167);
> +DECLARE_MSM_GPIO_PINS(168);
> +DECLARE_MSM_GPIO_PINS(169);
> +DECLARE_MSM_GPIO_PINS(170);
> +DECLARE_MSM_GPIO_PINS(171);
> +DECLARE_MSM_GPIO_PINS(172);
> +DECLARE_MSM_GPIO_PINS(173);
> +DECLARE_MSM_GPIO_PINS(174);
> +DECLARE_MSM_GPIO_PINS(175);
> +DECLARE_MSM_GPIO_PINS(176);
> +DECLARE_MSM_GPIO_PINS(177);
> +DECLARE_MSM_GPIO_PINS(178);
> +DECLARE_MSM_GPIO_PINS(179);
> +DECLARE_MSM_GPIO_PINS(180);
> +DECLARE_MSM_GPIO_PINS(181);
> +DECLARE_MSM_GPIO_PINS(182);
> +DECLARE_MSM_GPIO_PINS(183);
> +DECLARE_MSM_GPIO_PINS(184);
> +DECLARE_MSM_GPIO_PINS(185);
> +DECLARE_MSM_GPIO_PINS(186);
> +DECLARE_MSM_GPIO_PINS(187);
> +DECLARE_MSM_GPIO_PINS(188);
> +DECLARE_MSM_GPIO_PINS(189);
> +DECLARE_MSM_GPIO_PINS(190);
> +DECLARE_MSM_GPIO_PINS(191);
> +DECLARE_MSM_GPIO_PINS(192);
> +DECLARE_MSM_GPIO_PINS(193);
> +DECLARE_MSM_GPIO_PINS(194);
> +DECLARE_MSM_GPIO_PINS(195);
> +DECLARE_MSM_GPIO_PINS(196);
> +DECLARE_MSM_GPIO_PINS(197);
> +DECLARE_MSM_GPIO_PINS(198);
> +DECLARE_MSM_GPIO_PINS(199);
> +DECLARE_MSM_GPIO_PINS(200);
> +DECLARE_MSM_GPIO_PINS(201);
> +DECLARE_MSM_GPIO_PINS(202);
> +DECLARE_MSM_GPIO_PINS(203);
> +DECLARE_MSM_GPIO_PINS(204);
> +DECLARE_MSM_GPIO_PINS(205);
> +DECLARE_MSM_GPIO_PINS(206);
> +DECLARE_MSM_GPIO_PINS(207);
> +DECLARE_MSM_GPIO_PINS(208);
> +DECLARE_MSM_GPIO_PINS(209);
> +DECLARE_MSM_GPIO_PINS(210);
> +DECLARE_MSM_GPIO_PINS(211);
> +DECLARE_MSM_GPIO_PINS(212);
> +DECLARE_MSM_GPIO_PINS(213);
> +DECLARE_MSM_GPIO_PINS(214);
> +DECLARE_MSM_GPIO_PINS(215);
> +DECLARE_MSM_GPIO_PINS(216);
> +DECLARE_MSM_GPIO_PINS(217);
> +DECLARE_MSM_GPIO_PINS(218);
> +DECLARE_MSM_GPIO_PINS(219);
> +DECLARE_MSM_GPIO_PINS(220);
> +DECLARE_MSM_GPIO_PINS(221);
> +DECLARE_MSM_GPIO_PINS(222);
> +DECLARE_MSM_GPIO_PINS(223);
> +DECLARE_MSM_GPIO_PINS(224);
> +DECLARE_MSM_GPIO_PINS(225);
> +
> +static const unsigned int ufs_reset_pins[] = { 226 };
> +static const unsigned int sdc2_clk_pins[] = { 227 };
> +static const unsigned int sdc2_cmd_pins[] = { 228 };
> +static const unsigned int sdc2_data_pins[] = { 229 };
> +
> +enum hawi_functions {
> +	msm_mux_gpio,
> +	msm_mux_aoss_cti,
> +	msm_mux_atest_char,
> +	msm_mux_atest_usb,
> +	msm_mux_audio_ext_mclk,
> +	msm_mux_audio_ref_clk,
> +	msm_mux_cam_mclk,
> +	msm_mux_cci_async_in,
> +	msm_mux_cci_i2c0,
> +	msm_mux_cci_i2c1,
> +	msm_mux_cci_i2c2,
> +	msm_mux_cci_i2c3,
> +	msm_mux_cci_i2c4,
> +	msm_mux_cci_i2c5,
> +	msm_mux_cci_timer,
> +	msm_mux_coex_espmi,
> +	msm_mux_coex_uart1_rx,
> +	msm_mux_coex_uart1_tx,
> +	msm_mux_dbg_out_clk,
> +	msm_mux_ddr_bist,
> +	msm_mux_ddr_pxi,
> +	msm_mux_dp_hot,
> +	msm_mux_egpio,
> +	msm_mux_gcc_gp,
> +	msm_mux_gnss_adc,
> +	msm_mux_host_rst,
> +	msm_mux_i2chub0_se0,
> +	msm_mux_i2chub0_se1,
> +	msm_mux_i2chub0_se2,
> +	msm_mux_i2chub0_se3,
> +	msm_mux_i2chub0_se4,
> +	msm_mux_i2s0,
> +	msm_mux_i2s1,
> +	msm_mux_ibi_i3c,
> +	msm_mux_jitter_bist,
> +	msm_mux_mdp_esync0,
> +	msm_mux_mdp_esync1,
> +	msm_mux_mdp_esync2,
> +	msm_mux_mdp_vsync,
> +	msm_mux_mdp_vsync_e,
> +	msm_mux_mdp_vsync_p,
> +	msm_mux_mdp_vsync0_out,
> +	msm_mux_mdp_vsync1_out,
> +	msm_mux_mdp_vsync2_out,
> +	msm_mux_mdp_vsync3_out,
> +	msm_mux_mdp_vsync5_out,
> +	msm_mux_modem_pps_in,
> +	msm_mux_modem_pps_out,
> +	msm_mux_nav_gpio,
> +	msm_mux_nav_gpio0,
> +	msm_mux_nav_gpio3,
> +	msm_mux_nav_rffe,
> +	msm_mux_pcie0_clk_req_n,
> +	msm_mux_pcie0_rst_n,
> +	msm_mux_pcie1_clk_req_n,
> +	msm_mux_phase_flag,
> +	msm_mux_pll_bist_sync,
> +	msm_mux_pll_clk_aux,
> +	msm_mux_qdss_cti,
> +	msm_mux_qlink,
> +	msm_mux_qspi,
> +	msm_mux_qspi_clk,
> +	msm_mux_qspi_cs,
> +	msm_mux_qup1_se0,
> +	msm_mux_qup1_se1,
> +	msm_mux_qup1_se2,
> +	msm_mux_qup1_se3,
> +	msm_mux_qup1_se4,
> +	msm_mux_qup1_se5,
> +	msm_mux_qup1_se6,
> +	msm_mux_qup1_se7,
> +	msm_mux_qup2_se0,
> +	msm_mux_qup2_se1,
> +	msm_mux_qup2_se2,
> +	msm_mux_qup2_se3,
> +	msm_mux_qup2_se4_01,
> +	msm_mux_qup2_se4_23,
> +	msm_mux_qup3_se0_01,
> +	msm_mux_qup3_se0_23,
> +	msm_mux_qup3_se1,
> +	msm_mux_qup3_se2,
> +	msm_mux_qup3_se3,
> +	msm_mux_qup3_se4,
> +	msm_mux_qup3_se5,
> +	msm_mux_qup4_se0,
> +	msm_mux_qup4_se1,
> +	msm_mux_qup4_se2,
> +	msm_mux_qup4_se3_01,
> +	msm_mux_qup4_se3_23,
> +	msm_mux_qup4_se3_l3,
> +	msm_mux_qup4_se4_01,
> +	msm_mux_qup4_se4_23,
> +	msm_mux_qup4_se4_l3,
> +	msm_mux_rng_rosc,
> +	msm_mux_sd_write_protect,
> +	msm_mux_sdc4_clk,
> +	msm_mux_sdc4_cmd,
> +	msm_mux_sdc4_data,
> +	msm_mux_sys_throttle,
> +	msm_mux_tb_trig_sdc,
> +	msm_mux_tmess_rng,
> +	msm_mux_tsense_clm,
> +	msm_mux_tsense_pwm,
> +	msm_mux_uim0,
> +	msm_mux_uim1,
> +	msm_mux_usb0_hs,
> +	msm_mux_usb_phy,
> +	msm_mux_vfr,
> +	msm_mux_vsense_trigger_mirnat,
> +	msm_mux_wcn_sw_ctrl,
> +	msm_mux__,
> +};
> +
> +static const char *const gpio_groups[] = {
> +	"gpio0",   "gpio1",   "gpio2",   "gpio3",   "gpio4",   "gpio5",
> +	"gpio6",   "gpio7",   "gpio8",   "gpio9",   "gpio10",  "gpio11",
> +	"gpio12",  "gpio13",  "gpio14",  "gpio15",  "gpio16",  "gpio17",
> +	"gpio18",  "gpio19",  "gpio20",  "gpio21",  "gpio22",  "gpio23",
> +	"gpio24",  "gpio25",  "gpio26",  "gpio27",  "gpio28",  "gpio29",
> +	"gpio30",  "gpio31",  "gpio32",  "gpio33",  "gpio34",  "gpio35",
> +	"gpio36",  "gpio37",  "gpio38",  "gpio39",  "gpio40",  "gpio41",
> +	"gpio42",  "gpio43",  "gpio44",  "gpio45",  "gpio46",  "gpio47",
> +	"gpio48",  "gpio49",  "gpio50",  "gpio51",  "gpio52",  "gpio53",
> +	"gpio54",  "gpio55",  "gpio56",  "gpio57",  "gpio58",  "gpio59",
> +	"gpio60",  "gpio61",  "gpio62",  "gpio63",  "gpio64",  "gpio65",
> +	"gpio66",  "gpio67",  "gpio68",  "gpio69",  "gpio70",  "gpio71",
> +	"gpio72",  "gpio73",  "gpio74",  "gpio75",  "gpio76",  "gpio77",
> +	"gpio78",  "gpio79",  "gpio80",  "gpio81",  "gpio82",  "gpio83",
> +	"gpio84",  "gpio85",  "gpio86",  "gpio87",  "gpio88",  "gpio89",
> +	"gpio90",  "gpio91",  "gpio92",  "gpio93",  "gpio94",  "gpio95",
> +	"gpio96",  "gpio97",  "gpio98",  "gpio99",  "gpio100", "gpio101",
> +	"gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
> +	"gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
> +	"gpio114", "gpio115", "gpio116", "gpio117", "gpio118", "gpio119",
> +	"gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
> +	"gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131",
> +	"gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137",
> +	"gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
> +	"gpio144", "gpio145", "gpio146", "gpio147", "gpio148", "gpio149",
> +	"gpio150", "gpio151", "gpio152", "gpio153", "gpio154", "gpio155",
> +	"gpio156", "gpio157", "gpio158", "gpio159", "gpio160", "gpio161",
> +	"gpio162", "gpio163", "gpio164", "gpio165", "gpio166", "gpio167",
> +	"gpio168", "gpio169", "gpio170", "gpio171", "gpio172", "gpio173",
> +	"gpio174", "gpio175", "gpio176", "gpio177", "gpio178", "gpio179",
> +	"gpio180", "gpio181", "gpio182", "gpio183", "gpio184", "gpio185",
> +	"gpio186", "gpio187", "gpio188", "gpio189", "gpio190", "gpio191",
> +	"gpio192", "gpio193", "gpio194", "gpio195", "gpio196", "gpio197",
> +	"gpio198", "gpio199", "gpio200", "gpio201", "gpio202", "gpio203",
> +	"gpio204", "gpio205", "gpio206", "gpio207", "gpio208", "gpio209",
> +	"gpio210", "gpio211", "gpio212", "gpio213", "gpio214", "gpio215",
> +	"gpio216", "gpio217", "gpio218", "gpio219", "gpio220", "gpio221",
> +	"gpio222", "gpio223", "gpio224", "gpio225",
> +};
> +
> +static const char *const aoss_cti_groups[] = {
> +	"gpio74", "gpio75", "gpio76", "gpio77",
> +};
> +
> +static const char *const atest_char_groups[] = {
> +	"gpio126", "gpio127", "gpio128", "gpio129", "gpio133",
> +};
> +
> +static const char *const atest_usb_groups[] = {
> +	"gpio70", "gpio71", "gpio72", "gpio73", "gpio129",
> +};
> +
> +static const char *const audio_ext_mclk_groups[] = {
> +	"gpio120", "gpio121",
> +};
> +
> +static const char *const audio_ref_clk_groups[] = {
> +	"gpio120",
> +};
> +
> +static const char *const cam_mclk_groups[] = {
> +	"gpio89", "gpio90", "gpio91", "gpio92", "gpio93", "gpio94",
> +	"gpio95", "gpio96",
> +};
> +
> +static const char *const cci_async_in_groups[] = {
> +	"gpio15", "gpio109", "gpio110",
> +};
> +
> +static const char *const cci_i2c0_groups[] = {
> +	"gpio109", "gpio110",
> +};
> +
> +static const char *const cci_i2c1_groups[] = {
> +	"gpio111", "gpio112",
> +};
> +
> +static const char *const cci_i2c2_groups[] = {
> +	"gpio113", "gpio114",
> +};
> +
> +static const char *const cci_i2c3_groups[] = {
> +	"gpio107", "gpio160",
> +};
> +
> +static const char *const cci_i2c4_groups[] = {
> +	"gpio108", "gpio149",
> +};
> +
> +static const char *const cci_i2c5_groups[] = {
> +	"gpio115", "gpio116",
> +};
> +
> +static const char *const cci_timer_groups[] = {
> +	"gpio105", "gpio106", "gpio107", "gpio159", "gpio160",
> +};
> +
> +static const char *const coex_espmi_groups[] = {
> +	"gpio144", "gpio145",
> +};
> +
> +static const char *const coex_uart1_rx_groups[] = {
> +	"gpio144",
> +};
> +
> +static const char *const coex_uart1_tx_groups[] = {
> +	"gpio145",
> +};
> +
> +static const char *const dbg_out_clk_groups[] = {
> +	"gpio82",
> +};
> +
> +static const char *const ddr_bist_groups[] = {
> +	"gpio40", "gpio41", "gpio44", "gpio45",
> +};
> +
> +static const char *const ddr_pxi_groups[] = {
> +	"gpio43", "gpio44", "gpio45", "gpio46",
> +	"gpio52", "gpio53", "gpio54", "gpio55",
> +};
> +
> +static const char *const dp_hot_groups[] = {
> +	"gpio47",
> +};
> +
> +static const char *const egpio_groups[] = {
> +	"gpio0",   "gpio1",   "gpio2",   "gpio3",   "gpio4",   "gpio5",
> +	"gpio6",   "gpio7",   "gpio28",  "gpio29",  "gpio30",  "gpio31",
> +	"gpio48",  "gpio49",  "gpio50",  "gpio51",  "gpio163", "gpio164",
> +	"gpio165", "gpio166", "gpio167", "gpio168", "gpio169", "gpio170",
> +	"gpio171", "gpio172", "gpio173", "gpio174", "gpio175", "gpio176",
> +	"gpio177", "gpio178", "gpio179", "gpio180", "gpio181", "gpio182",
> +	"gpio183", "gpio184", "gpio185", "gpio186", "gpio187", "gpio188",
> +	"gpio189", "gpio190", "gpio191", "gpio192", "gpio193", "gpio194",
> +	"gpio195", "gpio196", "gpio197", "gpio198", "gpio199", "gpio200",
> +	"gpio201", "gpio202", "gpio203", "gpio204", "gpio205", "gpio206",
> +	"gpio207", "gpio208", "gpio209", "gpio212", "gpio213", "gpio214",
> +	"gpio215", "gpio216", "gpio217", "gpio218",
> +};
> +
> +static const char *const gcc_gp_groups[] = {
> +	"gpio86", "gpio87", "gpio130", "gpio131", "gpio132", "gpio158",
> +};
> +
> +static const char *const gnss_adc_groups[] = {
> +	"gpio40", "gpio41", "gpio42", "gpio77",
> +};
> +
> +static const char *const host_rst_groups[] = {
> +	"gpio106",
> +};
> +
> +static const char *const i2chub0_se0_groups[] = {
> +	"gpio66", "gpio67",
> +};
> +
> +static const char *const i2chub0_se1_groups[] = {
> +	"gpio78", "gpio79",
> +};
> +
> +static const char *const i2chub0_se2_groups[] = {
> +	"gpio68", "gpio69",
> +};
> +
> +static const char *const i2chub0_se3_groups[] = {
> +	"gpio70", "gpio71",
> +};
> +
> +static const char *const i2chub0_se4_groups[] = {
> +	"gpio72", "gpio73",
> +};
> +
> +static const char *const i2s0_groups[] = {
> +	"gpio122", "gpio123", "gpio124", "gpio125",
> +};
> +
> +static const char *const i2s1_groups[] = {
> +	"gpio117", "gpio118", "gpio119", "gpio120",
> +};
> +
> +static const char *const ibi_i3c_groups[] = {
> +	"gpio0",  "gpio1",  "gpio4",  "gpio5",  "gpio8",  "gpio9",
> +	"gpio12", "gpio13", "gpio28", "gpio29", "gpio32", "gpio33",
> +	"gpio36", "gpio37", "gpio48", "gpio49", "gpio60", "gpio61",
> +};
> +
> +static const char *const jitter_bist_groups[] = {
> +	"gpio73",
> +};
> +
> +static const char *const mdp_esync0_groups[] = {
> +	"gpio88", "gpio100",
> +};
> +
> +static const char *const mdp_esync1_groups[] = {
> +	"gpio86", "gpio100",
> +};
> +
> +static const char *const mdp_esync2_groups[] = {
> +	"gpio87", "gpio97",
> +};
> +
> +static const char *const mdp_vsync_groups[] = {
> +	"gpio86", "gpio87", "gpio88", "gpio97",
> +};
> +
> +static const char *const mdp_vsync_e_groups[] = {
> +	"gpio98",
> +};
> +
> +static const char *const mdp_vsync_p_groups[] = {
> +	"gpio98",
> +};
> +
> +static const char *const mdp_vsync0_out_groups[] = {
> +	"gpio86",
> +};
> +
> +static const char *const mdp_vsync1_out_groups[] = {
> +	"gpio86",
> +};
> +
> +static const char *const mdp_vsync2_out_groups[] = {
> +	"gpio87",
> +};
> +
> +static const char *const mdp_vsync3_out_groups[] = {
> +	"gpio87",
> +};
> +
> +static const char *const mdp_vsync5_out_groups[] = {
> +	"gpio87",
> +};
> +
> +static const char *const modem_pps_in_groups[] = {
> +	"gpio151",
> +};
> +
> +static const char *const modem_pps_out_groups[] = {
> +	"gpio151",
> +};
> +
> +static const char *const nav_gpio_groups[] = {
> +	"gpio146", "gpio147", "gpio148", "gpio151",
> +};
> +
> +static const char *const nav_gpio0_groups[] = {
> +	"gpio150",
> +};
> +
> +static const char *const nav_gpio3_groups[] = {
> +	"gpio150",
> +};
> +
> +static const char *const nav_rffe_groups[] = {
> +	"gpio134", "gpio135", "gpio138", "gpio139",
> +};
> +
> +static const char *const pcie0_clk_req_n_groups[] = {
> +	"gpio103",
> +};
> +
> +static const char *const pcie0_rst_n_groups[] = {
> +	"gpio102",
> +};
> +
> +static const char *const pcie1_clk_req_n_groups[] = {
> +	"gpio221",
> +};
> +
> +static const char *const phase_flag_groups[] = {
> +	"gpio117", "gpio118", "gpio119", "gpio123", "gpio124", "gpio125",
> +	"gpio169", "gpio170", "gpio171", "gpio172", "gpio173", "gpio175",
> +	"gpio176", "gpio179", "gpio180", "gpio181", "gpio184", "gpio185",
> +	"gpio192", "gpio196", "gpio197", "gpio198", "gpio199", "gpio204",
> +	"gpio206", "gpio207", "gpio208", "gpio210", "gpio211", "gpio214",
> +	"gpio215", "gpio216",
> +};
> +
> +static const char *const pll_bist_sync_groups[] = {
> +	"gpio104",
> +};
> +
> +static const char *const pll_clk_aux_groups[] = {
> +	"gpio94",
> +};
> +
> +static const char *const qdss_cti_groups[] = {
> +	"gpio27",  "gpio31", "gpio72", "gpio73", "gpio82", "gpio83",
> +	"gpio152", "gpio158",
> +};
> +
> +static const char *const qlink_groups[] = {
> +	"gpio152", "gpio153", "gpio154",
> +};
> +
> +static const char *const qspi_groups[] = {
> +	"gpio80", "gpio81", "gpio82", "gpio147",
> +};
> +
> +static const char *const qspi_clk_groups[] = {
> +	"gpio83",
> +};
> +
> +static const char *const qspi_cs_groups[] = {
> +	"gpio146", "gpio148",
> +};
> +
> +static const char *const qup1_se0_groups[] = {
> +	"gpio80", "gpio81", "gpio82", "gpio83",
> +};
> +
> +static const char *const qup1_se1_groups[] = {
> +	"gpio74", "gpio75", "gpio76", "gpio77",
> +};
> +
> +static const char *const qup1_se2_groups[] = {
> +	"gpio40", "gpio41", "gpio42", "gpio43", "gpio130", "gpio131", "gpio132",
> +};
> +
> +static const char *const qup1_se3_groups[] = {
> +	"gpio44", "gpio45", "gpio46", "gpio47",
> +};
> +
> +static const char *const qup1_se4_groups[] = {
> +	"gpio36", "gpio37", "gpio38", "gpio39",
> +};
> +
> +static const char *const qup1_se5_groups[] = {
> +	"gpio52", "gpio53", "gpio54", "gpio55",
> +};
> +
> +static const char *const qup1_se6_groups[] = {
> +	"gpio56", "gpio57", "gpio58", "gpio59",
> +};
> +
> +static const char *const qup1_se7_groups[] = {
> +	"gpio60", "gpio61", "gpio62", "gpio63",
> +};
> +
> +static const char *const qup2_se0_groups[] = {
> +	"gpio0", "gpio1", "gpio2", "gpio3",
> +};
> +
> +static const char *const qup2_se1_groups[] = {
> +	"gpio4", "gpio5", "gpio6", "gpio7",
> +};
> +
> +static const char *const qup2_se2_groups[] = {
> +	"gpio117", "gpio118", "gpio119", "gpio120",
> +};
> +
> +static const char *const qup2_se3_groups[] = {
> +	"gpio97", "gpio122", "gpio123", "gpio124", "gpio125",
> +};
> +
> +static const char *const qup2_se4_01_groups[] = {
> +	"gpio208", "gpio209",
> +};
> +
> +static const char *const qup2_se4_23_groups[] = {
> +	"gpio208", "gpio209",
> +};
> +
> +static const char *const qup3_se0_01_groups[] = {
> +	"gpio64", "gpio65",
> +};
> +
> +static const char *const qup3_se0_23_groups[] = {
> +	"gpio64", "gpio65",
> +};
> +
> +static const char *const qup3_se1_groups[] = {
> +	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio15",
> +};
> +
> +static const char *const qup3_se2_groups[] = {
> +	"gpio12", "gpio13", "gpio14", "gpio15",
> +};
> +
> +static const char *const qup3_se3_groups[] = {
> +	"gpio16", "gpio17", "gpio18", "gpio19",
> +};
> +
> +static const char *const qup3_se4_groups[] = {
> +	"gpio20", "gpio21", "gpio22", "gpio23",
> +};
> +
> +static const char *const qup3_se5_groups[] = {
> +	"gpio24", "gpio25", "gpio26", "gpio27",
> +};
> +
> +static const char *const qup4_se0_groups[] = {
> +	"gpio48", "gpio49", "gpio50", "gpio51",
> +};
> +
> +static const char *const qup4_se1_groups[] = {
> +	"gpio28", "gpio29", "gpio30", "gpio31",
> +};
> +
> +static const char *const qup4_se2_groups[] = {
> +	"gpio32", "gpio33", "gpio34", "gpio35",
> +};
> +
> +static const char *const qup4_se3_01_groups[] = {
> +	"gpio84", "gpio121",
> +};
> +
> +static const char *const qup4_se3_23_groups[] = {
> +	"gpio84", "gpio121",
> +};
> +
> +static const char *const qup4_se3_l3_groups[] = {
> +	"gpio98",
> +};
> +
> +static const char *const qup4_se4_01_groups[] = {
> +	"gpio161", "gpio162",
> +};
> +
> +static const char *const qup4_se4_23_groups[] = {
> +	"gpio161", "gpio162",
> +};
> +
> +static const char *const qup4_se4_l3_groups[] = {
> +	"gpio88",
> +};
> +
> +static const char *const rng_rosc_groups[] = {
> +	"gpio64", "gpio65", "gpio66", "gpio84",
> +};
> +
> +static const char *const sd_write_protect_groups[] = {
> +	"gpio85",
> +};
> +
> +static const char *const sdc4_clk_groups[] = {
> +	"gpio83",
> +};
> +
> +static const char *const sdc4_cmd_groups[] = {
> +	"gpio148",
> +};
> +
> +static const char *const sdc4_data_groups[] = {
> +	"gpio80", "gpio81", "gpio82", "gpio147",
> +};
> +
> +static const char *const sys_throttle_groups[] = {
> +	"gpio99",
> +};
> +
> +static const char *const tb_trig_sdc_groups[] = {
> +	"gpio88", "gpio146",
> +};
> +
> +static const char *const tmess_rng_groups[] = {
> +	"gpio64", "gpio65", "gpio66", "gpio84",
> +};
> +
> +static const char *const tsense_clm_groups[] = {
> +	"gpio10", "gpio87", "gpio97", "gpio99", "gpio105", "gpio106",
> +	"gpio159",
> +};
> +
> +static const char *const tsense_pwm_groups[] = {
> +	"gpio10", "gpio87", "gpio97", "gpio99", "gpio223", "gpio224",
> +	"gpio225",
> +};
> +
> +static const char *const uim0_groups[] = {
> +	"gpio126", "gpio127", "gpio128", "gpio129",
> +};
> +
> +static const char *const uim1_groups[] = {
> +	"gpio36", "gpio37", "gpio39", "gpio54", "gpio55", "gpio56",
> +	"gpio70", "gpio71", "gpio72", "gpio130", "gpio131", "gpio132",
> +	"gpio133",
> +};
> +
> +static const char *const usb0_hs_groups[] = {
> +	"gpio79",
> +};
> +
> +static const char *const usb_phy_groups[] = {
> +	"gpio59", "gpio60",
> +};
> +
> +static const char *const vfr_groups[] = {
> +	"gpio146", "gpio151",
> +};
> +
> +static const char *const vsense_trigger_mirnat_groups[] = {
> +	"gpio59",
> +};
> +
> +static const char *const wcn_sw_ctrl_groups[] = {
> +	"gpio18", "gpio19", "gpio155", "gpio156",
> +};
> +
> +static const struct pinfunction hawi_functions[] = {
> +	MSM_GPIO_PIN_FUNCTION(gpio),
> +	MSM_PIN_FUNCTION(aoss_cti),
> +	MSM_PIN_FUNCTION(atest_char),
> +	MSM_PIN_FUNCTION(atest_usb),
> +	MSM_PIN_FUNCTION(audio_ext_mclk),
> +	MSM_PIN_FUNCTION(audio_ref_clk),
> +	MSM_PIN_FUNCTION(cam_mclk),
> +	MSM_PIN_FUNCTION(cci_async_in),
> +	MSM_PIN_FUNCTION(cci_i2c0),
> +	MSM_PIN_FUNCTION(cci_i2c1),
> +	MSM_PIN_FUNCTION(cci_i2c2),
> +	MSM_PIN_FUNCTION(cci_i2c3),
> +	MSM_PIN_FUNCTION(cci_i2c4),
> +	MSM_PIN_FUNCTION(cci_i2c5),
> +	MSM_PIN_FUNCTION(cci_timer),
> +	MSM_PIN_FUNCTION(coex_espmi),
> +	MSM_PIN_FUNCTION(coex_uart1_rx),
> +	MSM_PIN_FUNCTION(coex_uart1_tx),
> +	MSM_PIN_FUNCTION(dbg_out_clk),
> +	MSM_PIN_FUNCTION(ddr_bist),
> +	MSM_PIN_FUNCTION(ddr_pxi),
> +	MSM_PIN_FUNCTION(dp_hot),
> +	MSM_PIN_FUNCTION(egpio),
> +	MSM_PIN_FUNCTION(gcc_gp),
> +	MSM_PIN_FUNCTION(gnss_adc),
> +	MSM_PIN_FUNCTION(host_rst),
> +	MSM_PIN_FUNCTION(i2chub0_se0),
> +	MSM_PIN_FUNCTION(i2chub0_se1),
> +	MSM_PIN_FUNCTION(i2chub0_se2),
> +	MSM_PIN_FUNCTION(i2chub0_se3),
> +	MSM_PIN_FUNCTION(i2chub0_se4),
> +	MSM_PIN_FUNCTION(i2s0),
> +	MSM_PIN_FUNCTION(i2s1),
> +	MSM_PIN_FUNCTION(ibi_i3c),
> +	MSM_PIN_FUNCTION(jitter_bist),
> +	MSM_PIN_FUNCTION(mdp_esync0),
> +	MSM_PIN_FUNCTION(mdp_esync1),
> +	MSM_PIN_FUNCTION(mdp_esync2),
> +	MSM_PIN_FUNCTION(mdp_vsync),
> +	MSM_PIN_FUNCTION(mdp_vsync_e),
> +	MSM_PIN_FUNCTION(mdp_vsync_p),
> +	MSM_PIN_FUNCTION(mdp_vsync0_out),
> +	MSM_PIN_FUNCTION(mdp_vsync1_out),
> +	MSM_PIN_FUNCTION(mdp_vsync2_out),
> +	MSM_PIN_FUNCTION(mdp_vsync3_out),
> +	MSM_PIN_FUNCTION(mdp_vsync5_out),
> +	MSM_PIN_FUNCTION(modem_pps_in),
> +	MSM_PIN_FUNCTION(modem_pps_out),
> +	MSM_PIN_FUNCTION(nav_gpio),
> +	MSM_PIN_FUNCTION(nav_gpio0),
> +	MSM_PIN_FUNCTION(nav_gpio3),
> +	MSM_PIN_FUNCTION(nav_rffe),
> +	MSM_PIN_FUNCTION(pcie0_clk_req_n),
> +	MSM_PIN_FUNCTION(pcie0_rst_n),
> +	MSM_PIN_FUNCTION(pcie1_clk_req_n),
> +	MSM_PIN_FUNCTION(phase_flag),
> +	MSM_PIN_FUNCTION(pll_bist_sync),
> +	MSM_PIN_FUNCTION(pll_clk_aux),
> +	MSM_PIN_FUNCTION(qdss_cti),
> +	MSM_PIN_FUNCTION(qlink),
> +	MSM_PIN_FUNCTION(qspi),
> +	MSM_PIN_FUNCTION(qspi_clk),
> +	MSM_PIN_FUNCTION(qspi_cs),
> +	MSM_PIN_FUNCTION(qup1_se0),
> +	MSM_PIN_FUNCTION(qup1_se1),
> +	MSM_PIN_FUNCTION(qup1_se2),
> +	MSM_PIN_FUNCTION(qup1_se3),
> +	MSM_PIN_FUNCTION(qup1_se4),
> +	MSM_PIN_FUNCTION(qup1_se5),
> +	MSM_PIN_FUNCTION(qup1_se6),
> +	MSM_PIN_FUNCTION(qup1_se7),
> +	MSM_PIN_FUNCTION(qup2_se0),
> +	MSM_PIN_FUNCTION(qup2_se1),
> +	MSM_PIN_FUNCTION(qup2_se2),
> +	MSM_PIN_FUNCTION(qup2_se3),
> +	MSM_PIN_FUNCTION(qup2_se4_01),
> +	MSM_PIN_FUNCTION(qup2_se4_23),
> +	MSM_PIN_FUNCTION(qup3_se0_01),
> +	MSM_PIN_FUNCTION(qup3_se0_23),
> +	MSM_PIN_FUNCTION(qup3_se1),
> +	MSM_PIN_FUNCTION(qup3_se2),
> +	MSM_PIN_FUNCTION(qup3_se3),
> +	MSM_PIN_FUNCTION(qup3_se4),
> +	MSM_PIN_FUNCTION(qup3_se5),
> +	MSM_PIN_FUNCTION(qup4_se0),
> +	MSM_PIN_FUNCTION(qup4_se1),
> +	MSM_PIN_FUNCTION(qup4_se2),
> +	MSM_PIN_FUNCTION(qup4_se3_01),
> +	MSM_PIN_FUNCTION(qup4_se3_23),
> +	MSM_PIN_FUNCTION(qup4_se3_l3),
> +	MSM_PIN_FUNCTION(qup4_se4_01),
> +	MSM_PIN_FUNCTION(qup4_se4_23),
> +	MSM_PIN_FUNCTION(qup4_se4_l3),
> +	MSM_PIN_FUNCTION(rng_rosc),
> +	MSM_PIN_FUNCTION(sd_write_protect),
> +	MSM_PIN_FUNCTION(sdc4_clk),
> +	MSM_PIN_FUNCTION(sdc4_cmd),
> +	MSM_PIN_FUNCTION(sdc4_data),
> +	MSM_PIN_FUNCTION(sys_throttle),
> +	MSM_PIN_FUNCTION(tb_trig_sdc),
> +	MSM_PIN_FUNCTION(tmess_rng),
> +	MSM_PIN_FUNCTION(tsense_clm),
> +	MSM_PIN_FUNCTION(tsense_pwm),
> +	MSM_PIN_FUNCTION(uim0),
> +	MSM_PIN_FUNCTION(uim1),
> +	MSM_PIN_FUNCTION(usb0_hs),
> +	MSM_PIN_FUNCTION(usb_phy),
> +	MSM_PIN_FUNCTION(vfr),
> +	MSM_PIN_FUNCTION(vsense_trigger_mirnat),
> +	MSM_PIN_FUNCTION(wcn_sw_ctrl),
> +};
> +
> +/*
> + * Every pin is maintained as a single group, and missing or non-existing pin
> + * would be maintained as dummy group to synchronize pin group index with
> + * pin descriptor registered with pinctrl core.
> + * Clients would not be able to request these dummy pin groups.
> + */
> +static const struct msm_pingroup hawi_groups[] = {
> +	[0] = PINGROUP(0, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[1] = PINGROUP(1, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[2] = PINGROUP(2, qup2_se0, _, _, _, _, _, _, _, _, _, egpio),
> +	[3] = PINGROUP(3, qup2_se0, _, _, _, _, _, _, _, _, _, egpio),
> +	[4] = PINGROUP(4, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[5] = PINGROUP(5, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[6] = PINGROUP(6, qup2_se1, _, _, _, _, _, _, _, _, _, egpio),
> +	[7] = PINGROUP(7, qup2_se1, _, _, _, _, _, _, _, _, _, egpio),
> +	[8] = PINGROUP(8, qup3_se1, ibi_i3c, _, _, _, _, _, _, _, _, _),
> +	[9] = PINGROUP(9, qup3_se1, ibi_i3c, _, _, _, _, _, _, _, _, _),
> +	[10] = PINGROUP(10, qup3_se1, _, tsense_clm, tsense_pwm, _, _, _, _, _, _, _),
> +	[11] = PINGROUP(11, qup3_se1, _, _, _, _, _, _, _, _, _, _),
> +	[12] = PINGROUP(12, qup3_se2, ibi_i3c, qup3_se1, _, _, _, _, _, _, _, _),
> +	[13] = PINGROUP(13, qup3_se2, ibi_i3c, qup3_se1, _, _, _, _, _, _, _, _),
> +	[14] = PINGROUP(14, qup3_se2, _, _, _, _, _, _, _, _, _, _),
> +	[15] = PINGROUP(15, qup3_se2, cci_async_in, qup3_se1, _, _, _, _, _, _, _, _),
> +	[16] = PINGROUP(16, qup3_se3, _, _, _, _, _, _, _, _, _, _),
> +	[17] = PINGROUP(17, qup3_se3, _, _, _, _, _, _, _, _, _, _),
> +	[18] = PINGROUP(18, wcn_sw_ctrl, qup3_se3, _, _, _, _, _, _, _, _, _),
> +	[19] = PINGROUP(19, wcn_sw_ctrl, qup3_se3, _, _, _, _, _, _, _, _, _),
> +	[20] = PINGROUP(20, qup3_se4, _, _, _, _, _, _, _, _, _, _),
> +	[21] = PINGROUP(21, qup3_se4, _, _, _, _, _, _, _, _, _, _),
> +	[22] = PINGROUP(22, qup3_se4, _, _, _, _, _, _, _, _, _, _),
> +	[23] = PINGROUP(23, qup3_se4, _, _, _, _, _, _, _, _, _, _),
> +	[24] = PINGROUP(24, qup3_se5, _, _, _, _, _, _, _, _, _, _),
> +	[25] = PINGROUP(25, qup3_se5, _, _, _, _, _, _, _, _, _, _),
> +	[26] = PINGROUP(26, qup3_se5, _, _, _, _, _, _, _, _, _, _),
> +	[27] = PINGROUP(27, qup3_se5, qdss_cti, _, _, _, _, _, _, _, _, _),
> +	[28] = PINGROUP(28, qup4_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[29] = PINGROUP(29, qup4_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[30] = PINGROUP(30, qup4_se1, _, _, _, _, _, _, _, _, _, egpio),
> +	[31] = PINGROUP(31, qup4_se1, qdss_cti, _, _, _, _, _, _, _, _, egpio),
> +	[32] = PINGROUP(32, qup4_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
> +	[33] = PINGROUP(33, qup4_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
> +	[34] = PINGROUP(34, qup4_se2, _, _, _, _, _, _, _, _, _, _),
> +	[35] = PINGROUP(35, qup4_se2, _, _, _, _, _, _, _, _, _, _),
> +	[36] = PINGROUP(36, qup1_se4, uim1, ibi_i3c, _, _, _, _, _, _, _, _),
> +	[37] = PINGROUP(37, qup1_se4, uim1, ibi_i3c, _, _, _, _, _, _, _, _),
> +	[38] = PINGROUP(38, qup1_se4, _, _, _, _, _, _, _, _, _, _),
> +	[39] = PINGROUP(39, qup1_se4, uim1, _, _, _, _, _, _, _, _, _),
> +	[40] = PINGROUP(40, qup1_se2, ddr_bist, _, gnss_adc, _, _, _, _, _, _, _),
> +	[41] = PINGROUP(41, qup1_se2, ddr_bist, _, gnss_adc, _, _, _, _, _, _, _),
> +	[42] = PINGROUP(42, qup1_se2, gnss_adc, _, _, _, _, _, _, _, _, _),
> +	[43] = PINGROUP(43, qup1_se2, _, ddr_pxi, _, _, _, _, _, _, _, _),
> +	[44] = PINGROUP(44, qup1_se3, ddr_bist, ddr_pxi, _, _, _, _, _, _, _, _),
> +	[45] = PINGROUP(45, qup1_se3, ddr_bist, ddr_pxi, _, _, _, _, _, _, _, _),
> +	[46] = PINGROUP(46, qup1_se3, ddr_pxi, _, _, _, _, _, _, _, _, _),
> +	[47] = PINGROUP(47, qup1_se3, dp_hot, _, _, _, _, _, _, _, _, _),
> +	[48] = PINGROUP(48, qup4_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[49] = PINGROUP(49, qup4_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
> +	[50] = PINGROUP(50, qup4_se0, _, _, _, _, _, _, _, _, _, egpio),
> +	[51] = PINGROUP(51, qup4_se0, _, _, _, _, _, _, _, _, _, egpio),
> +	[52] = PINGROUP(52, qup1_se5, ddr_pxi, _, _, _, _, _, _, _, _, _),
> +	[53] = PINGROUP(53, qup1_se5, _, ddr_pxi, _, _, _, _, _, _, _, _),
> +	[54] = PINGROUP(54, qup1_se5, uim1, ddr_pxi, _, _, _, _, _, _, _, _),
> +	[55] = PINGROUP(55, qup1_se5, uim1, ddr_pxi, _, _, _, _, _, _, _, _),
> +	[56] = PINGROUP(56, qup1_se6, uim1, _, _, _, _, _, _, _, _, _),
> +	[57] = PINGROUP(57, qup1_se6, _, _, _, _, _, _, _, _, _, _),
> +	[58] = PINGROUP(58, qup1_se6, _, _, _, _, _, _, _, _, _, _),
> +	[59] = PINGROUP(59, qup1_se6, usb_phy, vsense_trigger_mirnat, _, _, _, _, _, _, _, _),
> +	[60] = PINGROUP(60, qup1_se7, usb_phy, ibi_i3c, _, _, _, _, _, _, _, _),
> +	[61] = PINGROUP(61, qup1_se7, ibi_i3c, _, _, _, _, _, _, _, _, _),
> +	[62] = PINGROUP(62, qup1_se7, _, _, _, _, _, _, _, _, _, _),
> +	[63] = PINGROUP(63, qup1_se7, _, _, _, _, _, _, _, _, _, _),
> +	[64] = PINGROUP(64, qup3_se0_01, qup3_se0_23, rng_rosc, tmess_rng, _, _, _, _, _, _, _),
> +	[65] = PINGROUP(65, qup3_se0_01, qup3_se0_23, rng_rosc, tmess_rng, _, _, _, _, _, _, _),
> +	[66] = PINGROUP(66, i2chub0_se0, rng_rosc, tmess_rng, _, _, _, _, _, _, _, _),
> +	[67] = PINGROUP(67, i2chub0_se0, _, _, _, _, _, _, _, _, _, _),
> +	[68] = PINGROUP(68, i2chub0_se2, _, _, _, _, _, _, _, _, _, _),
> +	[69] = PINGROUP(69, i2chub0_se2, _, _, _, _, _, _, _, _, _, _),
> +	[70] = PINGROUP(70, i2chub0_se3, uim1, _, atest_usb, _, _, _, _, _, _, _),
> +	[71] = PINGROUP(71, i2chub0_se3, uim1, _, atest_usb, _, _, _, _, _, _, _),
> +	[72] = PINGROUP(72, i2chub0_se4, uim1, qdss_cti, _, atest_usb, _, _, _, _, _, _),
> +	[73] = PINGROUP(73, i2chub0_se4, qdss_cti, jitter_bist, atest_usb, _, _, _, _, _, _, _),
> +	[74] = PINGROUP(74, qup1_se1, aoss_cti, _, _, _, _, _, _, _, _, _),
> +	[75] = PINGROUP(75, qup1_se1, aoss_cti, _, _, _, _, _, _, _, _, _),
> +	[76] = PINGROUP(76, qup1_se1, aoss_cti, _, _, _, _, _, _, _, _, _),
> +	[77] = PINGROUP(77, qup1_se1, aoss_cti, gnss_adc, _, _, _, _, _, _, _, _),
> +	[78] = PINGROUP(78, i2chub0_se1, _, _, _, _, _, _, _, _, _, _),
> +	[79] = PINGROUP(79, i2chub0_se1, usb0_hs, _, _, _, _, _, _, _, _, _),
> +	[80] = PINGROUP(80, qup1_se0, sdc4_data, qspi, _, _, _, _, _, _, _, _),
> +	[81] = PINGROUP(81, qup1_se0, sdc4_data, qspi, _, _, _, _, _, _, _, _),
> +	[82] = PINGROUP(82, qup1_se0, sdc4_data, qdss_cti, qspi, dbg_out_clk, _, _, _, _, _, _),
> +	[83] = PINGROUP(83, qup1_se0, sdc4_clk, qdss_cti, qspi_clk, _, _, _, _, _, _, _),
> +	[84] = PINGROUP(84, qup4_se3_01, qup4_se3_23, rng_rosc, tmess_rng, _, _, _, _, _, _, _),
> +	[85] = PINGROUP(85, sd_write_protect, _, _, _, _, _, _, _, _, _, _),
> +	[86] = PINGROUP(86, mdp_vsync, mdp_vsync0_out, mdp_vsync1_out, mdp_esync1, gcc_gp,
> +			_, _, _, _, _, _),
> +	[87] = PINGROUP(87, mdp_vsync, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out,
> +			mdp_esync2, gcc_gp, _, tsense_clm, tsense_pwm, _, _),
> +	[88] = PINGROUP(88, mdp_esync0, mdp_vsync, qup4_se4_l3, tb_trig_sdc, _, _, _, _, _, _, _),
> +	[89] = PINGROUP(89, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[90] = PINGROUP(90, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[91] = PINGROUP(91, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[92] = PINGROUP(92, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[93] = PINGROUP(93, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[94] = PINGROUP(94, cam_mclk, pll_clk_aux, _, _, _, _, _, _, _, _, _),
> +	[95] = PINGROUP(95, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[96] = PINGROUP(96, cam_mclk, _, _, _, _, _, _, _, _, _, _),
> +	[97] = PINGROUP(97, mdp_esync2, qup2_se3, mdp_vsync, tsense_clm, tsense_pwm, _, _,
> +			_, _, _, _),
> +	[98] = PINGROUP(98, mdp_vsync_e, qup4_se3_l3, mdp_vsync_p, _, _, _, _, _, _, _, _),
> +	[99] = PINGROUP(99, sys_throttle, tsense_clm, tsense_pwm, _, _, _, _, _, _, _, _),
> +	[100] = PINGROUP(100, mdp_esync1, mdp_esync0, _, _, _, _, _, _, _, _, _),
> +	[101] = PINGROUP(101, _, _, _, _, _, _, _, _, _, _, _),
> +	[102] = PINGROUP(102, pcie0_rst_n, _, _, _, _, _, _, _, _, _, _),
> +	[103] = PINGROUP(103, pcie0_clk_req_n, _, _, _, _, _, _, _, _, _, _),
> +	[104] = PINGROUP(104, pll_bist_sync, _, _, _, _, _, _, _, _, _, _),
> +	[105] = PINGROUP(105, cci_timer, tsense_clm, _, _, _, _, _, _, _, _, _),
> +	[106] = PINGROUP(106, host_rst, cci_timer, tsense_clm, _, _, _, _, _, _, _, _),
> +	[107] = PINGROUP(107, cci_i2c3, cci_timer, _, _, _, _, _, _, _, _, _),
> +	[108] = PINGROUP(108, cci_i2c4, _, _, _, _, _, _, _, _, _, _),
> +	[109] = PINGROUP(109, cci_i2c0, cci_async_in, _, _, _, _, _, _, _, _, _),
> +	[110] = PINGROUP(110, cci_i2c0, cci_async_in, _, _, _, _, _, _, _, _, _),
> +	[111] = PINGROUP(111, cci_i2c1, _, _, _, _, _, _, _, _, _, _),
> +	[112] = PINGROUP(112, cci_i2c1, _, _, _, _, _, _, _, _, _, _),
> +	[113] = PINGROUP(113, cci_i2c2, _, _, _, _, _, _, _, _, _, _),
> +	[114] = PINGROUP(114, cci_i2c2, _, _, _, _, _, _, _, _, _, _),
> +	[115] = PINGROUP(115, cci_i2c5, _, _, _, _, _, _, _, _, _, _),
> +	[116] = PINGROUP(116, cci_i2c5, _, _, _, _, _, _, _, _, _, _),
> +	[117] = PINGROUP(117, i2s1, qup2_se2, phase_flag, _, _, _, _, _, _, _, _),
> +	[118] = PINGROUP(118, i2s1, qup2_se2, phase_flag, _, _, _, _, _, _, _, _),
> +	[119] = PINGROUP(119, i2s1, qup2_se2, phase_flag, _, _, _, _, _, _, _, _),
> +	[120] = PINGROUP(120, i2s1, qup2_se2, audio_ext_mclk, audio_ref_clk, _, _,
> +			_, _, _, _, _),
> +	[121] = PINGROUP(121, audio_ext_mclk, qup4_se3_01, qup4_se3_23, _, _, _, _, _, _, _, _),
> +	[122] = PINGROUP(122, i2s0, qup2_se3, _, _, _, _, _, _, _, _, _),
> +	[123] = PINGROUP(123, i2s0, qup2_se3, _, phase_flag, _, _, _, _, _, _, _),
> +	[124] = PINGROUP(124, i2s0, qup2_se3, _, phase_flag, _, _, _, _, _, _, _),
> +	[125] = PINGROUP(125, i2s0, qup2_se3, phase_flag, _, _, _, _, _, _, _, _),
> +	[126] = PINGROUP(126, uim0, atest_char, _, _, _, _, _, _, _, _, _),
> +	[127] = PINGROUP(127, uim0, atest_char, _, _, _, _, _, _, _, _, _),
> +	[128] = PINGROUP(128, uim0, atest_char, _, _, _, _, _, _, _, _, _),
> +	[129] = PINGROUP(129, uim0, atest_usb, atest_char, _, _, _, _, _, _, _, _),
> +	[130] = PINGROUP(130, uim1, qup1_se2, gcc_gp, _, _, _, _, _, _, _, _),
> +	[131] = PINGROUP(131, uim1, qup1_se2, gcc_gp, _, _, _, _, _, _, _, _),
> +	[132] = PINGROUP(132, uim1, qup1_se2, gcc_gp, _, _, _, _, _, _, _, _),
> +	[133] = PINGROUP(133, uim1, atest_char, _, _, _, _, _, _, _, _, _),
> +	[134] = PINGROUP(134, _, _, nav_rffe, _, _, _, _, _, _, _, _),
> +	[135] = PINGROUP(135, _, _, nav_rffe, _, _, _, _, _, _, _, _),
> +	[136] = PINGROUP(136, _, _, _, _, _, _, _, _, _, _, _),
> +	[137] = PINGROUP(137, _, _, _, _, _, _, _, _, _, _, _),
> +	[138] = PINGROUP(138, _, _, nav_rffe, _, _, _, _, _, _, _, _),
> +	[139] = PINGROUP(139, _, _, nav_rffe, _, _, _, _, _, _, _, _),
> +	[140] = PINGROUP(140, _, _, _, _, _, _, _, _, _, _, _),
> +	[141] = PINGROUP(141, _, _, _, _, _, _, _, _, _, _, _),
> +	[142] = PINGROUP(142, _, _, _, _, _, _, _, _, _, _, _),
> +	[143] = PINGROUP(143, _, _, _, _, _, _, _, _, _, _, _),
> +	[144] = PINGROUP(144, coex_uart1_rx, coex_espmi, _, _, _, _, _, _, _, _, _),
> +	[145] = PINGROUP(145, coex_uart1_tx, coex_espmi, _, _, _, _, _, _, _, _, _),
> +	[146] = PINGROUP(146, _, vfr, nav_gpio, tb_trig_sdc, qspi_cs, _, _, _, _, _, _),
> +	[147] = PINGROUP(147, _, nav_gpio, sdc4_data, qspi, _, _, _, _, _, _, _),
> +	[148] = PINGROUP(148, nav_gpio, _, sdc4_cmd, qspi_cs, _, _, _, _, _, _, _),
> +	[149] = PINGROUP(149, cci_i2c4, _, _, _, _, _, _, _, _, _, _),
> +	[150] = PINGROUP(150, nav_gpio0, nav_gpio3, _, _, _, _, _, _, _, _, _),
> +	[151] = PINGROUP(151, nav_gpio, vfr, modem_pps_in, modem_pps_out, _, _, _, _, _, _, _),
> +	[152] = PINGROUP(152, qlink, qdss_cti, _, _, _, _, _, _, _, _, _),
> +	[153] = PINGROUP(153, qlink, _, _, _, _, _, _, _, _, _, _),
> +	[154] = PINGROUP(154, qlink, _, _, _, _, _, _, _, _, _, _),
> +	[155] = PINGROUP(155, wcn_sw_ctrl, _, _, _, _, _, _, _, _, _, _),
> +	[156] = PINGROUP(156, wcn_sw_ctrl, _, _, _, _, _, _, _, _, _, _),
> +	[157] = PINGROUP(157, _, _, _, _, _, _, _, _, _, _, _),
> +	[158] = PINGROUP(158, qdss_cti, gcc_gp, _, _, _, _, _, _, _, _, _),
> +	[159] = PINGROUP(159, cci_timer, tsense_clm, _, _, _, _, _, _, _, _, _),
> +	[160] = PINGROUP(160, cci_timer, cci_i2c3, _, _, _, _, _, _, _, _, _),
> +	[161] = PINGROUP(161, qup4_se4_01, qup4_se4_23, _, _, _, _, _, _, _, _, _),
> +	[162] = PINGROUP(162, qup4_se4_01, qup4_se4_23, _, _, _, _, _, _, _, _, _),
> +	[163] = PINGROUP(163, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[164] = PINGROUP(164, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[165] = PINGROUP(165, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[166] = PINGROUP(166, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[167] = PINGROUP(167, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[168] = PINGROUP(168, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[169] = PINGROUP(169, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[170] = PINGROUP(170, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[171] = PINGROUP(171, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[172] = PINGROUP(172, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[173] = PINGROUP(173, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[174] = PINGROUP(174, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[175] = PINGROUP(175, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[176] = PINGROUP(176, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[177] = PINGROUP(177, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[178] = PINGROUP(178, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[179] = PINGROUP(179, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[180] = PINGROUP(180, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[181] = PINGROUP(181, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[182] = PINGROUP(182, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[183] = PINGROUP(183, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[184] = PINGROUP(184, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[185] = PINGROUP(185, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[186] = PINGROUP(186, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[187] = PINGROUP(187, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[188] = PINGROUP(188, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[189] = PINGROUP(189, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[190] = PINGROUP(190, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[191] = PINGROUP(191, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[192] = PINGROUP(192, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[193] = PINGROUP(193, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[194] = PINGROUP(194, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[195] = PINGROUP(195, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[196] = PINGROUP(196, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[197] = PINGROUP(197, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[198] = PINGROUP(198, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[199] = PINGROUP(199, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[200] = PINGROUP(200, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[201] = PINGROUP(201, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[202] = PINGROUP(202, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[203] = PINGROUP(203, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[204] = PINGROUP(204, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[205] = PINGROUP(205, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[206] = PINGROUP(206, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[207] = PINGROUP(207, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[208] = PINGROUP(208, qup2_se4_01, qup2_se4_23, phase_flag, _, _, _, _, _, _, _, egpio),
> +	[209] = PINGROUP(209, qup2_se4_01, qup2_se4_23, _, _, _, _, _, _, _, _, egpio),
> +	[210] = PINGROUP(210, phase_flag, _, _, _, _, _, _, _, _, _, _),
> +	[211] = PINGROUP(211, phase_flag, _, _, _, _, _, _, _, _, _, _),
> +	[212] = PINGROUP(212, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[213] = PINGROUP(213, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[214] = PINGROUP(214, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[215] = PINGROUP(215, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[216] = PINGROUP(216, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
> +	[217] = PINGROUP(217, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[218] = PINGROUP(218, _, _, _, _, _, _, _, _, _, _, egpio),
> +	[219] = PINGROUP(219, _, _, _, _, _, _, _, _, _, _, _),
> +	[220] = PINGROUP(220, _, _, _, _, _, _, _, _, _, _, _),
> +	[221] = PINGROUP(221, pcie1_clk_req_n, _, _, _, _, _, _, _, _, _, _),
> +	[222] = PINGROUP(222, _, _, _, _, _, _, _, _, _, _, _),
> +	[223] = PINGROUP(223, tsense_pwm, _, _, _, _, _, _, _, _, _, _),
> +	[224] = PINGROUP(224, tsense_pwm, _, _, _, _, _, _, _, _, _, _),
> +	[225] = PINGROUP(225, tsense_pwm, _, _, _, _, _, _, _, _, _, _),
> +	[226] = UFS_RESET(ufs_reset, 0xf1004, 0xf2000),
> +	[227] = SDC_QDSD_PINGROUP(sdc2_clk, 0xe6000, 14, 6),
> +	[228] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xe6000, 11, 3),
> +	[229] = SDC_QDSD_PINGROUP(sdc2_data, 0xe6000, 9, 0),
> +};
> +
> +static const struct msm_gpio_wakeirq_map hawi_pdc_map[] = {
> +	{ 0, 105 },   { 3, 113 },   { 4, 106 },   { 7, 107 },   { 8, 108 },   { 11, 109 },
> +	{ 12, 115 },  { 15, 131 },  { 16, 116 },  { 17, 141 },  { 18, 143 },  { 19, 112 },
> +	{ 23, 117 },  { 24, 118 },  { 27, 119 },  { 28, 125 },  { 31, 126 },  { 32, 127 },
> +	{ 35, 101 },  { 36, 128 },  { 39, 129 },  { 43, 130 },  { 47, 154 },  { 48, 135 },
> +	{ 51, 114 },  { 55, 104 },  { 57, 136 },  { 58, 137 },  { 59, 138 },  { 60, 139 },
> +	{ 61, 145 },  { 63, 124 },  { 64, 110 },  { 65, 123 },  { 67, 132 },  { 68, 146 },
> +	{ 69, 147 },  { 75, 151 },  { 77, 148 },  { 78, 149 },  { 79, 155 },  { 80, 156 },
> +	{ 81, 157 },  { 82, 158 },  { 84, 134 },  { 85, 159 },  { 86, 160 },  { 87, 161 },
> +	{ 88, 162 },  { 95, 163 },  { 96, 164 },  { 97, 133 },  { 98, 150 },  { 99, 111 },
> +	{ 101, 165 }, { 102, 166 }, { 103, 167 }, { 104, 168 }, { 120, 169 }, { 123, 170 },
> +	{ 125, 171 }, { 129, 153 }, { 133, 100 }, { 144, 172 }, { 146, 173 }, { 151, 174 },
> +	{ 152, 175 }, { 155, 122 }, { 158, 120 }, { 162, 142 }, { 164, 176 }, { 165, 177 },
> +	{ 167, 178 }, { 168, 179 }, { 174, 180 }, { 177, 181 }, { 179, 182 }, { 183, 183 },
> +	{ 184, 184 }, { 185, 185 }, { 186, 152 }, { 188, 144 }, { 202, 102 }, { 203, 103 },
> +	{ 205, 140 }, { 209, 186 }, { 213, 121 }, { 216, 187 }, { 221, 188 }, { 222, 189 },
> +	{ 223, 190 }, { 224, 191 }, { 225, 192 },
> +};
> +
> +static const struct msm_pinctrl_soc_data hawi_tlmm = {
> +	.pins = hawi_pins,
> +	.npins = ARRAY_SIZE(hawi_pins),
> +	.functions = hawi_functions,
> +	.nfunctions = ARRAY_SIZE(hawi_functions),
> +	.groups = hawi_groups,
> +	.ngroups = ARRAY_SIZE(hawi_groups),
> +	.ngpios = 227,
> +	.wakeirq_map = hawi_pdc_map,
> +	.nwakeirq_map = ARRAY_SIZE(hawi_pdc_map),
> +	.egpio_func = 11,
> +};
> +
> +static int hawi_tlmm_probe(struct platform_device *pdev)
> +{
> +	return msm_pinctrl_probe(pdev, &hawi_tlmm);
> +}
> +
> +static const struct of_device_id hawi_tlmm_of_match[] = {
> +	{ .compatible = "qcom,hawi-tlmm", },
> +	{},
> +};
> +
> +static struct platform_driver hawi_tlmm_driver = {
> +	.driver = {
> +		.name = "hawi-tlmm",
> +		.of_match_table = hawi_tlmm_of_match,
> +	},
> +	.probe = hawi_tlmm_probe,
> +};
> +
> +static int __init hawi_tlmm_init(void)
> +{
> +	return platform_driver_register(&hawi_tlmm_driver);
> +}
> +arch_initcall(hawi_tlmm_init);
> +
> +static void __exit hawi_tlmm_exit(void)
> +{
> +	platform_driver_unregister(&hawi_tlmm_driver);
> +}
> +module_exit(hawi_tlmm_exit);
> +
> +MODULE_DESCRIPTION("QTI Hawi TLMM driver");
> +MODULE_LICENSE("GPL");
> +MODULE_DEVICE_TABLE(of, hawi_tlmm_of_match);
> 
> -- 
> 2.53.0
> 

^ permalink raw reply

* Re: [PATCH v2 3/5] arm64: dts: qcom: sm8550: move IPA properties to SoC device tree
From: Dmitry Baryshkov @ 2026-04-09  1:45 UTC (permalink / raw)
  To: Joe Sandom
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260407-rb5gen2-dts-v2-3-d0c7f447ee73@axon.com>

On Tue, Apr 07, 2026 at 04:46:46PM +0100, Joe Sandom wrote:
> Move qcom,gsi-loader and memory-region properties from individual board
> DTS files into the SoC DTSI, since these are common to all SM8550-based
> boards.
> 
> Signed-off-by: Joe Sandom <jsandom@axon.com>
> ---
>  arch/arm64/boot/dts/qcom/sm8550-hdk.dts | 2 --
>  arch/arm64/boot/dts/qcom/sm8550-qrd.dts | 2 --
>  arch/arm64/boot/dts/qcom/sm8550.dtsi    | 2 ++
>  3 files changed, 2 insertions(+), 4 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v2 2/5] arm64: dts: qcom: sm8550: add PCIe port labels
From: Dmitry Baryshkov @ 2026-04-09  1:45 UTC (permalink / raw)
  To: Joe Sandom
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260407-rb5gen2-dts-v2-2-d0c7f447ee73@axon.com>

On Tue, Apr 07, 2026 at 04:46:45PM +0100, Joe Sandom wrote:
> Add labels to the root port nodes (pcie0_port0, pcie1_port0) to
> allow board DTS files to reference them for adding endpoint devices
> to each pcie root port.
> 
> Update the pcieport0 reference to pcie0_port0 in sm8550-hdk.dts and
> sm8550-qrd.dts to match the label rename in sm8550.dtsi.
> 
> Signed-off-by: Joe Sandom <jsandom@axon.com>
> ---
>  arch/arm64/boot/dts/qcom/sm8550-hdk.dts | 2 +-
>  arch/arm64/boot/dts/qcom/sm8550-qrd.dts | 2 +-
>  arch/arm64/boot/dts/qcom/sm8550.dtsi    | 4 ++--
>  3 files changed, 4 insertions(+), 4 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH 19/19] gpio: add GPIO controller found on Waveshare DSI TOUCH panels
From: Dmitry Baryshkov @ 2026-04-09  1:26 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: dri-devel, devicetree, linux-kernel, linux-gpio, Neil Armstrong,
	Jessica Zhang, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
	Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
	Linus Walleij
In-Reply-To: <CAMRc=Mcusnm-k76e6jTiwrw5xJL7f-nWBsg4=QpD08cv8pPgMw@mail.gmail.com>

On Fri, Apr 03, 2026 at 08:30:22AM -0400, Bartosz Golaszewski wrote:
> On Wed, 1 Apr 2026 09:26:38 +0200, Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com> said:
> > The Waveshare DSI TOUCH family of panels has separate on-board GPIO
> > controller, which controls power supplies to the panel and the touch
> > screen and provides reset pins for both the panel and the touchscreen.
> > Also it provides a simple PWM controller for panel backlight. Add
> > support for this GPIO controller.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> > ---
> >  drivers/gpio/Kconfig              |  10 ++
> >  drivers/gpio/Makefile             |   1 +
> >  drivers/gpio/gpio-waveshare-dsi.c | 220 ++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 231 insertions(+)
> >
> > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> > index 4c3f6ec336c1..f0bb5cdebf9b 100644
> > --- a/drivers/gpio/Kconfig
> > +++ b/drivers/gpio/Kconfig
> > @@ -804,6 +804,16 @@ config GPIO_VISCONTI
> >  	help
> >  	  Say yes here to support GPIO on Tohisba Visconti.
> >
> > +config GPIO_WAVESHARE_DSI_TOUCH
> > +	tristate "Waveshare GPIO controller for DSI panels"
> > +	depends on BACKLIGHT_CLASS_DEVICE
> > +	depends on I2C
> > +	select REGMAP_I2C
> > +	help
> > +	  Enable support for the GPIO and PWM controller found on Waveshare DSI
> > +	  TOUCH panel kits. It provides GPIOs (used for regulator control and
> > +          resets) and backlight support.
> > +
> >  config GPIO_WCD934X
> >  	tristate "Qualcomm Technologies Inc WCD9340/WCD9341 GPIO controller driver"
> >  	depends on MFD_WCD934X
> > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> > index 20d4a57afdaa..75ce89fc3b93 100644
> > --- a/drivers/gpio/Makefile
> > +++ b/drivers/gpio/Makefile
> > @@ -207,6 +207,7 @@ obj-$(CONFIG_GPIO_VIRTUSER)		+= gpio-virtuser.o
> >  obj-$(CONFIG_GPIO_VIRTIO)		+= gpio-virtio.o
> >  obj-$(CONFIG_GPIO_VISCONTI)		+= gpio-visconti.o
> >  obj-$(CONFIG_GPIO_VX855)		+= gpio-vx855.o
> > +obj-$(CONFIG_GPIO_WAVESHARE_DSI_TOUCH)	+= gpio-waveshare-dsi.o
> >  obj-$(CONFIG_GPIO_WCD934X)		+= gpio-wcd934x.o
> >  obj-$(CONFIG_GPIO_WHISKEY_COVE)		+= gpio-wcove.o
> >  obj-$(CONFIG_GPIO_WINBOND)		+= gpio-winbond.o
> > diff --git a/drivers/gpio/gpio-waveshare-dsi.c b/drivers/gpio/gpio-waveshare-dsi.c
> > new file mode 100644
> > index 000000000000..30fe7569c150
> > --- /dev/null
> > +++ b/drivers/gpio/gpio-waveshare-dsi.c
> > @@ -0,0 +1,220 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2024 Waveshare International Limited
> > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > + */
> > +
> > +#include <linux/backlight.h>
> > +#include <linux/err.h>
> > +#include <linux/fb.h>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/regmap.h>
> > +
> > +/* I2C registers of the microcontroller. */
> > +#define REG_TP		0x94
> > +#define REG_LCD		0x95
> > +#define REG_PWM		0x96
> > +#define REG_SIZE	0x97
> > +#define REG_ID		0x98
> > +#define REG_VERSION	0x99
> > +
> > +enum {
> > +	GPIO_AVDD = 0,
> > +	GPIO_PANEL_RESET = 1,
> > +	GPIO_BL_ENABLE = 2,
> > +	GPIO_IOVCC = 4,
> > +	GPIO_VCC = 8,
> > +	GPIO_TS_RESET = 9,
> > +	NUM_GPIO = 16,
> 
> Why is this part of an enum?

I'll move this out of the enum.

> 
> > +static int waveshare_gpio_set(struct waveshare_gpio *state, unsigned int offset, int value)
> > +{
> > +	u16 last_val;
> > +
> > +	mutex_lock(&state->pwr_lock);
> 
> Can you use guards for locks?

Yes

> 
> > +
> > +	last_val = state->poweron_state;
> > +	if (value)
> > +		last_val |= BIT(offset);
> > +	else
> > +		last_val &= ~BIT(offset);
> > +
> > +	state->poweron_state = last_val;
> > +
> > +	regmap_write(state->regmap, REG_TP, last_val >> 8);
> > +	regmap_write(state->regmap, REG_LCD, last_val & 0xff);
> 
> I2C regmap writes can fail and their return value should be checked.

Ack.

> 
> > +
> > +	mutex_unlock(&state->pwr_lock);
> > +
> > +	return 0;
> > +}
> > +

[...]

> > +
> > +static int waveshare_gpio_update_status(struct backlight_device *bl)
> > +{
> > +	struct waveshare_gpio *state = bl_get_data(bl);
> > +	int brightness = backlight_get_brightness(bl);
> > +
> > +	waveshare_gpio_set(state, GPIO_BL_ENABLE, brightness);
> > +
> > +	return regmap_write(state->regmap, REG_PWM, brightness);
> > +}
> > +

[...]

> > +static int waveshare_gpio_probe(struct i2c_client *i2c)
> > +{

[...]
> > +
> > +	dev_dbg(dev, "waveshare panel mcu version = 0x%x\n", data);
> > +
> > +	state->poweron_state = BIT(GPIO_TS_RESET);
> > +	regmap_write(regmap, REG_TP, state->poweron_state >> 8);
> > +	regmap_write(regmap, REG_LCD, state->poweron_state & 0xff);

And this can become waveshare_gpio_set().

> > +	msleep(20);
> > +
> > +	state->regmap = regmap;
> > +	state->gc.parent = dev;
> > +	state->gc.label = i2c->name;
> > +	state->gc.owner = THIS_MODULE;
> > +	state->gc.base = -1;
> > +	state->gc.ngpio = NUM_GPIO;
> > +
> > +	/* it is output only */
> > +	state->gc.get = waveshare_gpio_gpio_get;
> > +	state->gc.set = waveshare_gpio_gpio_set;
> > +	state->gc.get_direction = waveshare_gpio_gpio_get_direction;
> > +	state->gc.can_sleep = true;
> > +
> > +	ret = devm_gpiochip_add_data(dev, &state->gc, state);
> > +	if (ret)
> > +		return dev_err_probe(dev, ret, "Failed to create gpiochip\n");
> > +
> 
> This driver looks like it could be easily converted to use gpio-regmap and
> become much shorter in the process. Could you please take a look at
> linux/gpio/regmap.h?

I took a glance. It is a nice wrapper, but I think being able to call
waveshare_gpio_set() internally without extra troubles overweights the
bonuses of the wrapper. Also, I'd agree if there were extra complexity
here (e.g. the stride or the in/out handling), but having just the out
GPIOs doesn't seem to warrant it.

An alternative would be to split away the backlight into a separate
pwm-backlight device. Then having waveshare_gpio_set() isn't that
important and thus I could switch to GPIO_REGMAP. But then... We don't
have real control over the PWM. We are really programming some values,
with the actual PWM duty cycle calculations being handled internally.

With all that in mind, unless you really insist, I'd prefer to leave
this part the driver as is.

> 
> > +	props.type = BACKLIGHT_RAW;
> > +	props.max_brightness = 255;
> > +	props.brightness = 255;
> > +	bl = devm_backlight_device_register(dev, dev_name(dev), dev, state,
> > +					    &waveshare_gpio_bl, &props);
> > +	return PTR_ERR_OR_ZERO(bl);
> > +}
> > +

-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
From: Marek Vasut @ 2026-04-09  1:04 UTC (permalink / raw)
  To: Fidelio Lawson, Woojung Huh, UNGLinuxDriver, Andrew Lunn,
	Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Marek Vasut, Maxime Chevallier
  Cc: netdev, devicetree, linux-kernel, Fidelio Lawson
In-Reply-To: <20260408-ksz87xx_errata_low_loss_connections-v2-1-9cfe38691713@exotec.com>

On 4/8/26 1:57 PM, Fidelio Lawson wrote:
> Implement the "Module 3: Equalizer fix for short cables" erratum from
> Microchip document DS80000687C for KSZ87xx switches.
> 
> The issue affects short or low-loss cable links (e.g. CAT5e/CAT6),
> where the PHY receiver equalizer may amplify high-amplitude signals
> excessively, resulting in internal distortion and link establishment
> failures.
> 
> KSZ87xx devices require a workaround for the Module 3 low-loss cable
> condition, controlled through the switch TABLE_LINK_MD_V indirect
> registers.
> 
> The affected registers are part of the switch address space and are not
> directly accessible from the PHY driver. To keep the PHY-facing API
> clean and avoid leaking switch-specific details, model this errata
> control as vendor-specific Clause 22 PHY registers.
> 
> Two vendor-defined bits are introduced in PHY_REG_LOW_LOSS_CTRL,
> and ksz8_r_phy() / ksz8_w_phy() translate accesses to these bits
> into the appropriate indirect TABLE_LINK_MD_V accesses.
> 
> The control register defines the following modes:
>    bits [1:0]:
>      00 = workaround disabled
>      01 = workaround 1 (DSP EQ training adjustment, LinkMD reg 0x3c)
>      10 = workaround 2 (receiver LPF bandwidth, LinkMD reg 0x4c)
> 
> Workaround 1: Adjusts the DSP EQ training behavior via LinkMD register
> 0x3C. Widens and optimizes the DSP EQ compensation range,
> and is expected to solve most short/low-loss cable issues.
> 
> Workaround 2: for the cases where Workaround 1 is not sufficient.
> This one adjusts the receiver low-pass filter bandwidth, effectively
> reducing the high-frequency component of the received signal
> 
> The register is accessible through standard PHY read/write operations
> (e.g. phytool), without requiring any switch-specific userspace
> interface. This allows robust link establishment on short or
> low-loss cabling without requiring DTS properties and without
> constraining hardware design choices.
> 
> The erratum affects the shared PHY analog front-end and therefore
> applies globally to the switch.
> 
> Signed-off-by: Fidelio Lawson <fidelio.lawson@exotec.com>
> ---
> Hello,
> 
> This patch implements the “Module 3: Equalizer fix for short cables” erratum
> described in Microchip document DS80000687C for KSZ87xx switches.
> 
> According to the erratum, the embedded PHY receiver in KSZ87xx switches is
> tuned by default for long, high-loss Ethernet cables. When operating with
> short or low-loss cables (for example CAT5e or CAT6), the PHY equalizer may
> over-amplify the incoming signal, leading to internal distortion and link
> establishment failures.
> 
> Microchip provides two workarounds, each requiring a write to a different
> indirect PHY register access mechanism.
> 
> The workaround requires programming internal PHY/DSP registers located in the
> LinkMD table, accessed through the KSZ8 indirect register mechanism. Since these
> registers belong to the switch address space and are not directly accessible
> from a standalone PHY driver, the erratum control is modeled as a vendor-specific
> Clause 22 PHY register, virtualized by the KSZ8 DSA driver.
> 
> Reads and writes to this register are intercepted by ksz8_r_phy() /
> ksz8_w_phy() and translated into the required TABLE_LINK_MD_V indirect accesses.
> The erratum affects the shared PHY analog front-end and therefore applies
> globally to the switch.
> 
> The register defines three modes:
>    - 0x0: workaround disabled
>    - 0x1: workaround 1 (DSP EQ training adjustment)
>    - 0x2: workaround 2 (receiver low-pass filter bandwidth reduction)
> 
> The register can be read and written from userspace via standard Clause 22 PHY
> accesses (for example using phytool) on DSA user ports.
> 
> This series is based on Linux v7.0-rc1.
> ---
> Changes in v2:
> - Dropped the device tree approache based on review feedback
> - Modeled the errata control as a vendor-specific Clause 22 PHY register
> - Added KSZ87xx-specific guards and replaced magic values with named macros
> - Rebased on Linux v7.0-rc1
> - Link to v1: https://patch.msgid.link/20260326-ksz87xx_errata_low_loss_connections-v1-0-79a698f43626@exotec.com
> ---
>   drivers/net/dsa/microchip/ksz8.c       | 33 +++++++++++++++++++++++++++++++++
>   drivers/net/dsa/microchip/ksz8_reg.h   | 20 +++++++++++++++++++-
>   drivers/net/dsa/microchip/ksz_common.h |  3 +++
>   3 files changed, 55 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
> index c354abdafc1b..d11da6e9ff54 100644
> --- a/drivers/net/dsa/microchip/ksz8.c
> +++ b/drivers/net/dsa/microchip/ksz8.c
> @@ -1058,6 +1058,11 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
>   		if (ret)
>   			return ret;
>   
> +		break;
> +	case PHY_REG_KSZ87XX_LOW_LOSS:
> +		if (!ksz_is_ksz87xx(dev))
> +			return -EOPNOTSUPP;
> +		data = dev->low_loss_wa_mode;
>   		break;
>   	default:
>   		processed = false;
> @@ -1271,6 +1276,34 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
>   		if (ret)
>   			return ret;
>   		break;
> +	case PHY_REG_KSZ87XX_LOW_LOSS:
> +		if (!ksz_is_ksz87xx(dev))
> +			return -EOPNOTSUPP;
> +
> +		switch (val & PHY_KSZ87XX_LOW_LOSS_MASK) {
> +		case PHY_LOW_LOSS_ERRATA_DISABLED:
> +			ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_EQ_TRAIN,
> +					      KSZ87XX_EQ_TRAIN_DEFAULT);
> +			if (!ret)
> +				ret = ksz8_ind_write8(dev, TABLE_LINK_MD,
> +						      KSZ87XX_REG_PHY_LPF,
> +						      KSZ87XX_PHY_LPF_DEFAULT);
> +			break;
> +		case KSZ87XX_LOW_LOSS_WA_EQ:
> +			ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_EQ_TRAIN,
> +					      KSZ87XX_EQ_TRAIN_LOW_LOSS);
> +			break;
> +		case KSZ87XX_LOW_LOSS_WA_LPF:
> +			ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_PHY_LPF,
> +					      KSZ87XX_PHY_LPF_62MHZ);

Please adjust this and make the low pass filter bandwidth actually 
configurable according to the values supported by the hardware, see this 
article:

https://microchip.my.site.com/s/article/Solution-for-Using-CAT-5E-or-CAT-6-Short-Cable-with-a-Link-Issue-for-the-KSZ8795-Family

The indirect register (0x4C) is an 8-bit register. The bits [7:6] are 
described in the table below.

Low pass filter bandwidth
00 = 90MHz
01 = 62MHz
10 = 55MHz
11 = 44MHz

...

^ permalink raw reply

* Re: [PATCH 14/19] drm/panel: jadard-jd9365da-h3: support Waveshare DSI panels
From: Dmitry Baryshkov @ 2026-04-09  0:49 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
	Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
	linux-gpio
In-Reply-To: <CAD++jL=jUd4sQ1bhwcBRYpFFApP6vdJw2BoQwxoWShUKdEb9oA@mail.gmail.com>

On Wed, Apr 08, 2026 at 10:24:17AM +0200, Linus Walleij wrote:
> Hi Dmitry,
> 
> thanks for your patch!
> 
> On Wed, Apr 1, 2026 at 9:27 AM Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com> wrote:
> 
> > Add configuration for Waveshare DSI panels using JD9365 controller.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> 
> Some more words with details on all the panels added perhaps?

:D

> 
> > -       desc = of_device_get_match_data(dev);
> > +       jd9365da_switch_page(&dsi_ctx, 0x01);
> > +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
> > +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x41);
> 
> Predictably I'm not very happy with all the unexplained magic and nonestisting
> defines used here. Do you have some info/defines?

No, unfortunately.

> 
> But there is also one more thing, this looks like a big "jam table"
> with just register+value tuples, so construct something like:
> 
> struct jadard_jam_tbl_entry {
>         u8 reg;
>         u8 val;
> };
> 
> static const struct jadard_jam_tbl_entry jd_3_4_c_init_jam[] = {
>         {0x00, 0x00}, {0x01, 0x41}, ...};
> 
> (Ideas taken from drivers/net/dsa/realtek/rtl8366rb.c, take a look
> for code and all, you get the picture.)

Few months ago the code was moved exactly in the opposite direction. We
added all _multi() functions and made shure that the code is as
efficient as the register tables. On the other hand, having it as a code
allows better control. E.g. handling 2/4 lane case would require extra
hacks to the register tables, while the code handles that without extra
hacks and without loosing effectiveness.

> 
> Yours,
> Linus Walleij

-- 
With best wishes
Dmitry

^ permalink raw reply

* [PATCH 2/2] pwm: pxa: Add optional bus clock
From: Yixun Lan @ 2026-04-09  0:45 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Duje Mihanović
  Cc: linux-pwm, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan
In-Reply-To: <20260409-03-k3-pwm-drv-v1-0-1307a06fba38@kernel.org>

Add one secondary optional bus clock for the PWM PXA driver, also keep it
compatible with old single clock.

The SpacemiT K3 SoC require one bus clock for PWM controller, acquire
and enable it during probe phase.

Signed-off-by: Yixun Lan <dlan@kernel.org>
---
 drivers/pwm/pwm-pxa.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 0f5bdb0e395e..2ace31405c2d 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -53,6 +53,7 @@ struct pxa_pwm_chip {
 	struct device	*dev;
 
 	struct clk	*clk;
+	struct clk	*bus_clk;
 	void __iomem	*mmio_base;
 };
 
@@ -177,7 +178,12 @@ static int pwm_probe(struct platform_device *pdev)
 		return PTR_ERR(chip);
 	pc = to_pxa_pwm_chip(chip);
 
-	pc->clk = devm_clk_get(dev, NULL);
+	pc->bus_clk = devm_clk_get_optional_enabled(dev, "bus");
+	if (IS_ERR(pc->bus_clk))
+		return dev_err_probe(dev, PTR_ERR(pc->bus_clk), "Failed to get bus clock\n");
+
+	/* Get named func clk if bus clock is valid */
+	pc->clk = devm_clk_get(dev, pc->bus_clk ? "func" : NULL);
 	if (IS_ERR(pc->clk))
 		return dev_err_probe(dev, PTR_ERR(pc->clk), "Failed to get clock\n");
 

-- 
2.53.0


^ permalink raw reply related

* [PATCH 1/2] dt-bindings: pwm: marvell,pxa-pwm: Add SpacemiT K3 PWM support
From: Yixun Lan @ 2026-04-09  0:45 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Duje Mihanović
  Cc: linux-pwm, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan
In-Reply-To: <20260409-03-k3-pwm-drv-v1-0-1307a06fba38@kernel.org>

The PWM controller in SpacemiT K3 SoC reuse the same IP as previous K1
generation, while the difference is that one additional bus clock is
added.

Signed-off-by: Yixun Lan <dlan@kernel.org>
---
 .../devicetree/bindings/pwm/marvell,pxa-pwm.yaml   | 53 ++++++++++++++++++++--
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml b/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
index 8df327e52810..3427c8ef3945 100644
--- a/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
@@ -15,7 +15,9 @@ allOf:
       properties:
         compatible:
           contains:
-            const: spacemit,k1-pwm
+            enum:
+              - spacemit,k1-pwm
+              - spacemit,k3-pwm
     then:
       properties:
         "#pwm-cells":
@@ -26,6 +28,38 @@ allOf:
           const: 1
           description: |
             Used for specifying the period length in nanoseconds.
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - spacemit,k3-pwm
+    then:
+      properties:
+        clock-names:
+          items:
+            - const: func
+            - const: bus
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - spacemit,k3-pwm
+    then:
+      required:
+        - clock-names
+      properties:
+        clocks:
+          minItems: 2
+        clock-names:
+          minItems: 2
+    else:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names:
+          maxItems: 1
 
 properties:
   compatible:
@@ -36,7 +70,9 @@ properties:
           - marvell,pxa168-pwm
           - marvell,pxa910-pwm
       - items:
-          - const: spacemit,k1-pwm
+          - enum:
+              - spacemit,k1-pwm
+              - spacemit,k3-pwm
           - const: marvell,pxa910-pwm
 
   reg:
@@ -47,7 +83,18 @@ properties:
     description: Number of cells in a pwm specifier.
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    items:
+      - description: The function clock
+      - description: An optional bus clock
+
+  clock-names:
+    minItems: 1
+    maxItems: 2
+    oneOf:
+      - items:
+          - const: func
+          - const: bus
 
   resets:
     maxItems: 1

-- 
2.53.0


^ permalink raw reply related

* [PATCH 0/2] pwm: spacemit: Add Support for K3 SoC
From: Yixun Lan @ 2026-04-09  0:45 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Duje Mihanović
  Cc: linux-pwm, devicetree, linux-kernel, linux-riscv, spacemit,
	Yixun Lan

The PWM controller in SpacemiT K3 SoC reuse the same IP as previous K1
generation, while the difference is that one additional bus clock is
added. Introduce a new compatible string and also adjust driver code to
support it.

Signed-off-by: Yixun Lan <dlan@kernel.org>
---
Yixun Lan (2):
      dt-bindings: pwm: marvell,pxa-pwm: Add SpacemiT K3 PWM support
      pwm: pxa: Add optional bus clock

 .../devicetree/bindings/pwm/marvell,pxa-pwm.yaml   | 53 ++++++++++++++++++++--
 drivers/pwm/pwm-pxa.c                              |  8 +++-
 2 files changed, 57 insertions(+), 4 deletions(-)
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260401-03-k3-pwm-drv-4ea99ae355d6

Best regards,
-- 
Yixun Lan <dlan@kernel.org>


^ permalink raw reply

* Re: [PATCH v6 6/6] clk: fsl-sai: Add MCLK generation support
From: Brian Masney @ 2026-04-09  0:41 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-clk, Michael Walle, Conor Dooley, Krzysztof Kozlowski,
	Michael Turquette, Michael Walle, Rob Herring, Stephen Boyd,
	devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-6-marex@nabladev.com>

On Thu, Apr 09, 2026 at 02:29:06AM +0200, Marek Vasut wrote:
> The driver currently supports generating BCLK. There are systems which
> require generation of MCLK instead. Register new MCLK clock and handle
> clock-cells = <1> to differentiate between BCLK and MCLK. In case of a
> legacy system with clock-cells = <0>, the driver behaves as before, i.e.
> always returns BCLK.
> 
> Note that it is not possible re-use the current SAI audio driver to
> generate MCLK and correctly enable and disable the MCLK.
> 
> If SAI (audio driver) is used to control the MCLK enablement, then MCLK
> clock is not always enabled, and it is not necessarily enabled when the
> codec may need the clock to be enabled. There is also no way for the
> codec node to specify phandle to clock provider in DT, because the SAI
> (audio driver) is not clock provider.
> 
> If SAI (clock driver) is used to control the MCLK enablement, then MCLK
> clock is enabled when the codec needs the clock enabled, because the
> codec is the clock consumer and the SAI (clock driver) is the clock
> provider, and the codec driver can request the clock to be enabled when
> needed. There is also the usual phandle to clock provider in DT, because
> the SAI (clock driver) is clock provider.
> 
> Acked-by: Michael Walle <mwalle@kernel.org>
> Signed-off-by: Marek Vasut <marex@nabladev.com>

Reviewed-by: Brian Masney <bmasney@redhat.com>


^ permalink raw reply

* Re: [PATCH v6 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Brian Masney @ 2026-04-09  0:41 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-clk, Conor Dooley, Krzysztof Kozlowski, Michael Turquette,
	Michael Walle, Rob Herring, Stephen Boyd, devicetree,
	linux-kernel
In-Reply-To: <20260409002952.319668-5-marex@nabladev.com>

On Thu, Apr 09, 2026 at 02:29:05AM +0200, Marek Vasut wrote:
> Create helper function fsl_sai_clk_register() to set up and register
> SAI clock. Rename BCLK specific struct fsl_sai_clk members with bclk_
> prefix. Use of_node_full_name(dev->of_node) and clock name to register
> uniquely named clock. This is done in preparation for the follow up
> patch, which adds MCLK support.
> 
> Signed-off-by: Marek Vasut <marex@nabladev.com>

Reviewed-by: Brian Masney <bmasney@redhat.com>


^ permalink raw reply

* Re: [PATCH 12/19] drm/panel: jadard-jd9365da-h3: support variable DSI configuration
From: Dmitry Baryshkov @ 2026-04-09  0:35 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
	Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
	linux-gpio
In-Reply-To: <CAD++jLnAaUzHun-i7PBLzFQmsKCXXfRO+4hAgTFCZtLm_Bu6iw@mail.gmail.com>

On Wed, Apr 08, 2026 at 10:15:13AM +0200, Linus Walleij wrote:
> Hi Dmitry,
> 
> thanks for your patch!
> 
> On Wed, Apr 1, 2026 at 9:27 AM Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com> wrote:
> 
> > Several panels support attachment either using 4 DSI lanes or just 2. In
> > some cases, this requires a different panel mode to fulfill clock
> > requirements. Extend the driver to handle such cases by letting the
> > panel description to omit lanes specification and parsing number of
> > lanes from the DT.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> (...)
> 
> > +       if (dsi_ctx->dsi->lanes == 2)
> > +               mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x80, 0x01);
> > +       else
> > +               mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x80, 0x03);
> 
> If lanes 2 we do unexplicable magic A else we do unexplicable magic B?
> 
> Do we know more about what is actually going on here?
> 
> Can you check the datasheet?

The datasheet (you can find it) is pretty useless here. Unfortunately I
don't have a second source of information. As far as I know, this
value maps directly to the number of lanes and nothing else.

> 
> The patch is nice anyway and no big deal so, so +/- that fixup:
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> 
> Yours,
> Linus Walleij

-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH 10/19] drm/panel: himax-hx8394: support Waveshare DSI panels
From: Dmitry Baryshkov @ 2026-04-09  0:33 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
	Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
	linux-gpio
In-Reply-To: <CAD++jLmG_y2dunkyzH7KDtphN6WORzt87f5CpqzAtCUtALv8CA@mail.gmail.com>

On Wed, Apr 08, 2026 at 10:10:13AM +0200, Linus Walleij wrote:
> On Wed, Apr 1, 2026 at 9:27 AM Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com> wrote:
> 
> > Enable support for Waveshare 5.0" and 5.5" DSI TOUCH-A panels.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> 
> This looks excellent, good documentation and references to (incomplete...)
> datasheet. Maybe this datasheet has the defs I was complaining about
> in the other patch?

No :-(

> Reviewed-by: Linus Walleij <linusw@kernel.org>
> 
> Yours,
> Linus Walleij

-- 
With best wishes
Dmitry

^ permalink raw reply

* [PATCH v6 6/6] clk: fsl-sai: Add MCLK generation support
From: Marek Vasut @ 2026-04-09  0:29 UTC (permalink / raw)
  To: linux-clk
  Cc: Marek Vasut, Michael Walle, Brian Masney, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, Stephen Boyd, devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-1-marex@nabladev.com>

The driver currently supports generating BCLK. There are systems which
require generation of MCLK instead. Register new MCLK clock and handle
clock-cells = <1> to differentiate between BCLK and MCLK. In case of a
legacy system with clock-cells = <0>, the driver behaves as before, i.e.
always returns BCLK.

Note that it is not possible re-use the current SAI audio driver to
generate MCLK and correctly enable and disable the MCLK.

If SAI (audio driver) is used to control the MCLK enablement, then MCLK
clock is not always enabled, and it is not necessarily enabled when the
codec may need the clock to be enabled. There is also no way for the
codec node to specify phandle to clock provider in DT, because the SAI
(audio driver) is not clock provider.

If SAI (clock driver) is used to control the MCLK enablement, then MCLK
clock is enabled when the codec needs the clock enabled, because the
codec is the clock consumer and the SAI (clock driver) is the clock
provider, and the codec driver can request the clock to be enabled when
needed. There is also the usual phandle to clock provider in DT, because
the SAI (clock driver) is clock provider.

Acked-by: Michael Walle <mwalle@kernel.org>
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Brian Masney <bmasney@redhat.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Rob Herring <robh@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
V2: No change
V3: - Rebase on current next, update mail address
    - Update commit message according to clarify the difference between
      SAI audio and SAI clock driver
    - Pick ancient AB from Michael, although this may be outdated
      https://patchwork.kernel.org/project/alsa-devel/patch/20241226162234.40141-4-marex@denx.de/
V4: Use the fsl_sai_clk_register() helper.
V5: - Move include clk.h into 3/6
    - Validate clock cells in fsl_sai_of_clk_get()
V6: No change
---
 drivers/clk/clk-fsl-sai.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c
index c595d340e00f1..eded6a5fac216 100644
--- a/drivers/clk/clk-fsl-sai.c
+++ b/drivers/clk/clk-fsl-sai.c
@@ -16,19 +16,27 @@
 
 #define I2S_CSR		0x00
 #define I2S_CR2		0x08
+#define I2S_MCR		0x100
 #define CSR_BCE_BIT	28
+#define CSR_TE_BIT	31
 #define CR2_BCD		BIT(24)
 #define CR2_DIV_SHIFT	0
 #define CR2_DIV_WIDTH	8
+#define MCR_MOE		BIT(30)
 
 struct fsl_sai_data {
 	unsigned int	offset;	/* Register offset */
+	bool		have_mclk; /* Have MCLK control */
 };
 
 struct fsl_sai_clk {
+	const struct fsl_sai_data *data;
 	struct clk_divider bclk_div;
+	struct clk_divider mclk_div;
 	struct clk_gate bclk_gate;
+	struct clk_gate mclk_gate;
 	struct clk_hw *bclk_hw;
+	struct clk_hw *mclk_hw;
 	spinlock_t lock;
 };
 
@@ -37,7 +45,17 @@ fsl_sai_of_clk_get(struct of_phandle_args *clkspec, void *data)
 {
 	struct fsl_sai_clk *sai_clk = data;
 
-	return sai_clk->bclk_hw;
+	if (clkspec->args_count == 0)
+		return sai_clk->bclk_hw;
+
+	if (clkspec->args_count == 1) {
+		if (clkspec->args[0] == 0)
+			return sai_clk->bclk_hw;
+		if (sai_clk->data->have_mclk && clkspec->args[0] == 1)
+			return sai_clk->mclk_hw;
+	}
+
+	return ERR_PTR(-EINVAL);
 }
 
 static int fsl_sai_clk_register(struct device *dev, void __iomem *base,
@@ -104,6 +122,7 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
 	if (IS_ERR(clk_bus))
 		return PTR_ERR(clk_bus);
 
+	sai_clk->data = data;
 	spin_lock_init(&sai_clk->lock);
 
 	ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
@@ -113,15 +132,28 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	if (data->have_mclk) {
+		ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
+					   &sai_clk->mclk_div,
+					   &sai_clk->mclk_gate,
+					   &sai_clk->mclk_hw,
+					   CSR_TE_BIT, MCR_MOE, I2S_MCR,
+					   "MCLK");
+		if (ret)
+			return ret;
+	}
+
 	return devm_of_clk_add_hw_provider(dev, fsl_sai_of_clk_get, sai_clk);
 }
 
 static const struct fsl_sai_data fsl_sai_vf610_data = {
 	.offset	= 0,
+	.have_mclk = false,
 };
 
 static const struct fsl_sai_data fsl_sai_imx8mq_data = {
 	.offset	= 8,
+	.have_mclk = true,
 };
 
 static const struct of_device_id of_fsl_sai_clk_ids[] = {
-- 
2.53.0


^ permalink raw reply related

* [PATCH v6 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Marek Vasut @ 2026-04-09  0:29 UTC (permalink / raw)
  To: linux-clk
  Cc: Marek Vasut, Brian Masney, Conor Dooley, Krzysztof Kozlowski,
	Michael Turquette, Michael Walle, Rob Herring, Stephen Boyd,
	devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-1-marex@nabladev.com>

Create helper function fsl_sai_clk_register() to set up and register
SAI clock. Rename BCLK specific struct fsl_sai_clk members with bclk_
prefix. Use of_node_full_name(dev->of_node) and clock name to register
uniquely named clock. This is done in preparation for the follow up
patch, which adds MCLK support.

Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Brian Masney <bmasney@redhat.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Rob Herring <robh@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
V4: New patch
V5: - Include fsl_sai_of_clk_get() which returns only BCLK in here already
    - s/hw/chw/ in fsl_sai_clk_register
V6: Move register initialization before devm_clk_hw_register_composite_pdata()
---
 drivers/clk/clk-fsl-sai.c | 90 +++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 27 deletions(-)

diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c
index 27925893c4c27..c595d340e00f1 100644
--- a/drivers/clk/clk-fsl-sai.c
+++ b/drivers/clk/clk-fsl-sai.c
@@ -26,20 +26,71 @@ struct fsl_sai_data {
 };
 
 struct fsl_sai_clk {
-	struct clk_divider div;
-	struct clk_gate gate;
+	struct clk_divider bclk_div;
+	struct clk_gate bclk_gate;
+	struct clk_hw *bclk_hw;
 	spinlock_t lock;
 };
 
+static struct clk_hw *
+fsl_sai_of_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct fsl_sai_clk *sai_clk = data;
+
+	return sai_clk->bclk_hw;
+}
+
+static int fsl_sai_clk_register(struct device *dev, void __iomem *base,
+				spinlock_t *lock, struct clk_divider *div,
+				struct clk_gate *gate, struct clk_hw **hw,
+				const int gate_bit, const int dir_bit,
+				const int div_reg, char *name)
+{
+	const struct fsl_sai_data *data = device_get_match_data(dev);
+	struct clk_parent_data pdata = { .index = 0 };
+	struct clk_hw *chw;
+	char *cname;
+
+	gate->reg = base + data->offset + I2S_CSR;
+	gate->bit_idx = gate_bit;
+	gate->lock = lock;
+
+	div->reg = base + div_reg;
+	div->shift = CR2_DIV_SHIFT;
+	div->width = CR2_DIV_WIDTH;
+	div->lock = lock;
+
+	cname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s",
+			       of_node_full_name(dev->of_node), name);
+	if (!cname)
+		return -ENOMEM;
+
+	/* Set clock direction */
+	writel(dir_bit, base + div_reg);
+
+	chw = devm_clk_hw_register_composite_pdata(dev, cname,
+						   &pdata, 1, NULL, NULL,
+						   &div->hw,
+						   &clk_divider_ops,
+						   &gate->hw,
+						   &clk_gate_ops,
+						   CLK_SET_RATE_GATE);
+	if (IS_ERR(chw))
+		return PTR_ERR(chw);
+
+	*hw = chw;
+
+	return 0;
+}
+
 static int fsl_sai_clk_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct fsl_sai_data *data = device_get_match_data(dev);
 	struct fsl_sai_clk *sai_clk;
-	struct clk_parent_data pdata = { .index = 0 };
 	struct clk *clk_bus;
 	void __iomem *base;
-	struct clk_hw *hw;
+	int ret;
 
 	sai_clk = devm_kzalloc(dev, sizeof(*sai_clk), GFP_KERNEL);
 	if (!sai_clk)
@@ -55,29 +106,14 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
 
 	spin_lock_init(&sai_clk->lock);
 
-	sai_clk->gate.reg = base + data->offset + I2S_CSR;
-	sai_clk->gate.bit_idx = CSR_BCE_BIT;
-	sai_clk->gate.lock = &sai_clk->lock;
-
-	sai_clk->div.reg = base + data->offset + I2S_CR2;
-	sai_clk->div.shift = CR2_DIV_SHIFT;
-	sai_clk->div.width = CR2_DIV_WIDTH;
-	sai_clk->div.lock = &sai_clk->lock;
-
-	/* set clock direction, we are the BCLK master */
-	writel(CR2_BCD, base + data->offset + I2S_CR2);
-
-	hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
-						  &pdata, 1, NULL, NULL,
-						  &sai_clk->div.hw,
-						  &clk_divider_ops,
-						  &sai_clk->gate.hw,
-						  &clk_gate_ops,
-						  CLK_SET_RATE_GATE);
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
+	ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
+				   &sai_clk->bclk_div, &sai_clk->bclk_gate,
+				   &sai_clk->bclk_hw, CSR_BCE_BIT, CR2_BCD,
+				   data->offset + I2S_CR2, "BCLK");
+	if (ret)
+		return ret;
+
+	return devm_of_clk_add_hw_provider(dev, fsl_sai_of_clk_get, sai_clk);
 }
 
 static const struct fsl_sai_data fsl_sai_vf610_data = {
-- 
2.53.0


^ permalink raw reply related

* [PATCH v6 4/6] dt-bindings: clock: fsl-sai: Document clock-cells = <1> support
From: Marek Vasut @ 2026-04-09  0:29 UTC (permalink / raw)
  To: linux-clk
  Cc: Marek Vasut, Conor Dooley, Brian Masney, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, Stephen Boyd, devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-1-marex@nabladev.com>

The driver now supports generation of both BCLK and MCLK, document
support for #clock-cells = <0> for legacy case and #clock-cells = <1>
for the new case which can differentiate between BCLK and MCLK.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Brian Masney <bmasney@redhat.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Rob Herring <robh@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
V2: Update commit message, align it with the bindings one
V3: - Rebase on current next, update mail address
    - Pick ancient AB from Conor, although this may be outdated
      https://patchwork.kernel.org/project/alsa-devel/patch/20241226162234.40141-3-marex@denx.de/
V4: No change
V5: No change
V6: No change
---
 Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml b/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml
index 90799b3b505ee..041a63fa2d2b0 100644
--- a/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml
@@ -10,7 +10,7 @@ maintainers:
   - Michael Walle <michael@walle.cc>
 
 description: |
-  It is possible to use the BCLK pin of a SAI module as a generic
+  It is possible to use the BCLK or MCLK pin of a SAI module as a generic
   clock output. Some SoC are very constrained in their pin multiplexer
   configuration. E.g. pins can only be changed in groups. For example, on
   the LS1028A SoC you can only enable SAIs in pairs. If you use only one SAI,
@@ -47,7 +47,7 @@ properties:
       - const: mclk1
 
   '#clock-cells':
-    const: 0
+    maximum: 1
 
 allOf:
   - if:
-- 
2.53.0


^ permalink raw reply related

* [PATCH v6 3/6] clk: fsl-sai: Add i.MX8M support with 8 byte register offset
From: Marek Vasut @ 2026-04-09  0:29 UTC (permalink / raw)
  To: linux-clk
  Cc: Marek Vasut, Brian Masney, Peng Fan, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, Stephen Boyd, devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-1-marex@nabladev.com>

The i.MX8M/Mini/Nano/Plus variant of the SAI IP has control registers
shifted by +8 bytes and requires additional bus clock. Add support for
the i.MX8M variant of the IP with this register shift and additional
clock.

Reviewed-by: Brian Masney <bmasney@redhat.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Brian Masney <bmasney@redhat.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Rob Herring <robh@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
V2: Update commit message, align it with the bindings one
V3: - Rebase on current next, update mail address
    - Pick ancient RB from Peng, although this may be outdated
      https://patchwork.kernel.org/project/alsa-devel/patch/20241226162234.40141-2-marex@denx.de/
    - Optionally enable "bus" clock, which are needed on MX8M to operate
      register file
V4: Add RB from Brian
V5: Include clk.h
V6: No change
---
 drivers/clk/Kconfig       |  2 +-
 drivers/clk/clk-fsl-sai.c | 28 ++++++++++++++++++++++++----
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index cc8743b11bb1f..9f7f391a5615a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -255,7 +255,7 @@ config COMMON_CLK_FSL_FLEXSPI
 
 config COMMON_CLK_FSL_SAI
 	bool "Clock driver for BCLK of Freescale SAI cores"
-	depends on ARCH_LAYERSCAPE || COMPILE_TEST
+	depends on ARCH_LAYERSCAPE || ARCH_MXC || COMPILE_TEST
 	help
 	  This driver supports the Freescale SAI (Synchronous Audio Interface)
 	  to be used as a generic clock output. Some SoCs have restrictions
diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c
index c59ddd519f9f5..27925893c4c27 100644
--- a/drivers/clk/clk-fsl-sai.c
+++ b/drivers/clk/clk-fsl-sai.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -20,6 +21,10 @@
 #define CR2_DIV_SHIFT	0
 #define CR2_DIV_WIDTH	8
 
+struct fsl_sai_data {
+	unsigned int	offset;	/* Register offset */
+};
+
 struct fsl_sai_clk {
 	struct clk_divider div;
 	struct clk_gate gate;
@@ -29,8 +34,10 @@ struct fsl_sai_clk {
 static int fsl_sai_clk_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	const struct fsl_sai_data *data = device_get_match_data(dev);
 	struct fsl_sai_clk *sai_clk;
 	struct clk_parent_data pdata = { .index = 0 };
+	struct clk *clk_bus;
 	void __iomem *base;
 	struct clk_hw *hw;
 
@@ -42,19 +49,23 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
+	clk_bus = devm_clk_get_optional_enabled(dev, "bus");
+	if (IS_ERR(clk_bus))
+		return PTR_ERR(clk_bus);
+
 	spin_lock_init(&sai_clk->lock);
 
-	sai_clk->gate.reg = base + I2S_CSR;
+	sai_clk->gate.reg = base + data->offset + I2S_CSR;
 	sai_clk->gate.bit_idx = CSR_BCE_BIT;
 	sai_clk->gate.lock = &sai_clk->lock;
 
-	sai_clk->div.reg = base + I2S_CR2;
+	sai_clk->div.reg = base + data->offset + I2S_CR2;
 	sai_clk->div.shift = CR2_DIV_SHIFT;
 	sai_clk->div.width = CR2_DIV_WIDTH;
 	sai_clk->div.lock = &sai_clk->lock;
 
 	/* set clock direction, we are the BCLK master */
-	writel(CR2_BCD, base + I2S_CR2);
+	writel(CR2_BCD, base + data->offset + I2S_CR2);
 
 	hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
 						  &pdata, 1, NULL, NULL,
@@ -69,8 +80,17 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
 	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
 }
 
+static const struct fsl_sai_data fsl_sai_vf610_data = {
+	.offset	= 0,
+};
+
+static const struct fsl_sai_data fsl_sai_imx8mq_data = {
+	.offset	= 8,
+};
+
 static const struct of_device_id of_fsl_sai_clk_ids[] = {
-	{ .compatible = "fsl,vf610-sai-clock" },
+	{ .compatible = "fsl,vf610-sai-clock", .data = &fsl_sai_vf610_data },
+	{ .compatible = "fsl,imx8mq-sai-clock", .data = &fsl_sai_imx8mq_data },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, of_fsl_sai_clk_ids);
-- 
2.53.0


^ permalink raw reply related

* [PATCH v6 2/6] clk: fsl-sai: Sort the headers
From: Marek Vasut @ 2026-04-09  0:29 UTC (permalink / raw)
  To: linux-clk
  Cc: Marek Vasut, Brian Masney, Conor Dooley, Krzysztof Kozlowski,
	Michael Turquette, Michael Walle, Rob Herring, Stephen Boyd,
	devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-1-marex@nabladev.com>

Sort the headers. No functional change.

Reviewed-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Brian Masney <bmasney@redhat.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Rob Herring <robh@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
V4: New patch
V5: - Reorder this into 2/6 position
    - Add RB from Brian
V6: No change
---
 drivers/clk/clk-fsl-sai.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c
index cba45e07562da..c59ddd519f9f5 100644
--- a/drivers/clk/clk-fsl-sai.c
+++ b/drivers/clk/clk-fsl-sai.c
@@ -5,12 +5,12 @@
  * Copyright 2020 Michael Walle <michael@walle.cc>
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 
 #define I2S_CSR		0x00
-- 
2.53.0


^ permalink raw reply related

* [PATCH v6 1/6] dt-bindings: clock: fsl-sai: Document i.MX8M support
From: Marek Vasut @ 2026-04-09  0:29 UTC (permalink / raw)
  To: linux-clk
  Cc: Marek Vasut, Conor Dooley, Brian Masney, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, Stephen Boyd, devicetree, linux-kernel

The i.MX8M/Mini/Nano/Plus variant of the SAI IP has control registers
shifted by +8 bytes and requires additional bus clock. Document support
for the i.MX8M variant of the IP with this register shift and additional
clock. Update the description slightly.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Brian Masney <bmasney@redhat.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Rob Herring <robh@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
V2: No change
V3: - Rebase on current next, update mail address
    - Pick ancient AB from Conor, although this may be outdated
      https://patchwork.kernel.org/project/alsa-devel/patch/20241226162234.40141-1-marex@denx.de/
    - Invert the allOf conditional to match on VF610 and limit
      the clocks/clock-names there. MX8M can have one or two
      input clock, "bus" is mandatory and "mclk1" is optional.
      The "mclk1" are used by the driver in 4/4 .
V4: No change
V5: No change
V6: No change
---
 .../bindings/clock/fsl,sai-clock.yaml         | 41 ++++++++++++++++---
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml b/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml
index 3bca9d11c148f..90799b3b505ee 100644
--- a/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/fsl,sai-clock.yaml
@@ -10,10 +10,10 @@ maintainers:
   - Michael Walle <michael@walle.cc>
 
 description: |
-  It is possible to use the BCLK pin of a SAI module as a generic clock
-  output. Some SoC are very constrained in their pin multiplexer
-  configuration. Eg. pins can only be changed groups. For example, on the
-  LS1028A SoC you can only enable SAIs in pairs. If you use only one SAI,
+  It is possible to use the BCLK pin of a SAI module as a generic
+  clock output. Some SoC are very constrained in their pin multiplexer
+  configuration. E.g. pins can only be changed in groups. For example, on
+  the LS1028A SoC you can only enable SAIs in pairs. If you use only one SAI,
   the second pins are wasted. Using this binding it is possible to use the
   clock of the second SAI as a MCLK clock for an audio codec, for example.
 
@@ -21,17 +21,46 @@ description: |
 
 properties:
   compatible:
-    const: fsl,vf610-sai-clock
+    oneOf:
+      - items:
+          - enum:
+              - fsl,imx8mm-sai-clock
+              - fsl,imx8mn-sai-clock
+              - fsl,imx8mp-sai-clock
+          - const: fsl,imx8mq-sai-clock
+      - items:
+          - enum:
+              - fsl,imx8mq-sai-clock
+              - fsl,vf610-sai-clock
 
   reg:
     maxItems: 1
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    minItems: 1
+    items:
+      - const: bus
+      - const: mclk1
 
   '#clock-cells':
     const: 0
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,vf610-sai-clock
+    then:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names: false
+
 required:
   - compatible
   - reg
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
From: Peng Fan @ 2026-04-09  0:30 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Peng Fan, Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Daniel Baluta, linux-remoteproc@vger.kernel.org,
	devicetree@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <adZ4WIaC6WN97JhR@p14s>

On Wed, Apr 08, 2026 at 09:46:32AM -0600, Mathieu Poirier wrote:
>On Wed, Apr 08, 2026 at 01:30:16AM +0000, Peng Fan wrote:
>> > Subject: Re: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to
>> > SM CPU/LMM reset vector
>> > 
>> [...]
>> > 
>> > >
>> > > Aligning the ELF entry point with the hardware reset base on
>> > Cortex‑M
>> > > systems is possible, but it comes with several risks.
>> > 
>> > I'm not asking to align the ELF entry point with the hardware reset base.
>> > All I want is to have the correct start address embedded in the ELF file
>> > to avoid having to use a mask.
>> 
>> I see, per my understanding:
>> FreeRTOS typically exposes __isr_vector, which corresponds to the hardware
>> reset / vector table base.
>> Zephyr (Cortex‑M) exposes _vector_table, which serves the same purpose.
>> I am not certain about other RTOSes, but the pattern seems consistent:
>> the vector table base is already available as a named ELF symbol.
>> 
>> Given that, if the preferred approach is to parse the ELF and explicitly
>> retrieve the hardware reset base, I can update the implementation accordingly.
>> If you prefer to parse the elf file to get the hardware reset base,
>> I could update to use them.
>> 
>> Options1: Something as below:
>> 1. Include rproc_elf_find_symbol in remoteproc_elf_loader.c
>> 2. Use below in imx_rproc.c
>> ret = rproc_elf_find_symbol(rproc, fw, "__isr_vector", &vector_base);
>> if (ret)
>>     ret = rproc_elf_find_symbol(rproc, fw, "__vector_table", &vector_base);
>> 
>> if (!ret)
>>     rproc->bootaddr = vector_base
>> else
>>    dev_info(dev, "no __isr_vector or __vector_table\n")
>
>No

If your concern is about rproc->bootaddr, I could introduce
imx_rproc->vector_base for i.MX.  Please help detail a bit.

>
>> 
>> This makes the hardware reset base explicit, avoids masking e_entry.
>> 
>> Option 2: User‑provided reset symbol via sysfs 
>> As an alternative, we could expose a sysfs attribute,
>> e.g. reset_symbol, allowing users to specify the symbol name
>> to be used as the reset base:
>> 
>> echo __isr_vector > /sys/class/remoteproc/remoteprocX/reset_symbol
>> 
>
>Definitely not.
>
>The definition of e_entry in the specification is clear, i.e "the address of the
>entry point from where the process starts executing".  If masking is required
>because the tool that puts the image together gets the wrong address, then it
>should be fixed.

The hardware reset base is the address from which the hardware fetches the
initial stack pointer and program counter values and loads them into the SP
and PC registers.  In contrast, bootaddr (i.e. e_entry) represents the address
at which the CPU starts executing code (the PC value after reset). As you
pointed out earlier, this distinction is clear.

In our case, we need to obtain the hardware reset base and pass that value to
the system firmware. However, e_entry should not be set to the hardware reset
base. Doing so would introduce the issues I described in [1]. This means we
should not modify the Zephyr or FreeRTOS build outputs to make e_entry equal
to the hardware reset base.

Given these constraints, the feasible solutions I can see are either:
- option 1 (explicitly retrieving the hardware reset base), or
- continuing to use masking.

Please suggest.

[1] https://lore.kernel.org/all/acs2PAZq2k3zjmDW@shlinux89/

Thanks,
Peng

>
>> The remoteproc core would then resolve that symbol from
>> the ELF and set rproc->bootaddr accordingly.
>> This provides maximum flexibility but does introduce a new user‑visible ABI,
>> so I see it more as an opt‑in or fallback mechanism.
>> 
>> Please let me know which approach you prefer, and I will update
>> this series accordingly in v3..
>> 
>> Thanks,
>> Peng.
>> 
>> 
>> > 
>> > > 1, Semantic mismatch (ELF vs. hardware behavior) 2, Debuggers may
>> > > attempt to set breakpoints or start execution at the entry symbol
>> > >

^ permalink raw reply

* Re: [PATCH v5 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Marek Vasut @ 2026-04-09  0:24 UTC (permalink / raw)
  To: Brian Masney
  Cc: linux-clk, Conor Dooley, Krzysztof Kozlowski, Michael Turquette,
	Michael Walle, Rob Herring, Stephen Boyd, devicetree,
	linux-kernel
In-Reply-To: <adbSxmeJDf14EtS0@redhat.com>

On 4/9/26 12:12 AM, Brian Masney wrote:

Hi,

>> -	hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
>> -						  &pdata, 1, NULL, NULL,
>> -						  &sai_clk->div.hw,
>> -						  &clk_divider_ops,
>> -						  &sai_clk->gate.hw,
>> -						  &clk_gate_ops,
>> -						  CLK_SET_RATE_GATE);
>> -	if (IS_ERR(hw))
>> -		return PTR_ERR(hw);
>> -
>> -	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
>> +	ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
>> +				   &sai_clk->bclk_div, &sai_clk->bclk_gate,
>> +				   &sai_clk->bclk_hw, CSR_BCE_BIT, CR2_BCD,
>> +				   data->offset + I2S_CR2, "BCLK");
>                                     ^^^^^^^^^^^^^^^^^^^^^^
> Sashiko reports the following:
> https://sashiko.dev/#/patchset/20260407211123.77602-1-marex%40nabladev.com
> 
>      For MCLK, this evaluates to writel(MCR_MOE, base + I2S_MCR). Does this
>      overwrite the entire register and clear all other bits to 0? This could zero
>      out fields like the MCLK Divider Enable and Clock Source Select, breaking
>      the MCLK hardware divider.
> 
> It's the same behavior as what was there previously. There's a lot more
> to the comment. Can you look and see if there's anything else valid in
> Sashiko's comment that should be addressed while changes are being made
> here?
> 
> Otherwise, based on what was there previously, this looks good to me.
I'll move the writel() before devm_clk_hw_register_composite_pdata() 
even if it makes no difference in this particular case.

^ permalink raw reply

* Re: [PATCH v5 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Marek Vasut @ 2026-04-09  0:13 UTC (permalink / raw)
  To: Brian Masney
  Cc: linux-clk, Conor Dooley, Krzysztof Kozlowski, Michael Turquette,
	Michael Walle, Rob Herring, Stephen Boyd, devicetree,
	linux-kernel
In-Reply-To: <adbPlFzI7jrU9pCq@redhat.com>

On 4/8/26 11:58 PM, Brian Masney wrote:

Hi,

>> +static int fsl_sai_clk_register(struct device *dev, void __iomem *base,
>> +				spinlock_t *lock, struct clk_divider *div,
>> +				struct clk_gate *gate, struct clk_hw **hw,
>> +				const int gate_bit, const int dir_bit,
>> +				const int div_reg, char *name)
>> +{
>> +	const struct fsl_sai_data *data = device_get_match_data(dev);
>> +	struct clk_parent_data pdata = { .index = 0 };
>> +	struct clk_hw *chw;
>> +	char *cname;
>> +
>> +	gate->reg = base + data->offset + I2S_CSR;
>> +	gate->bit_idx = gate_bit;
>> +	gate->lock = lock;
>> +
>> +	div->reg = base + div_reg;
>> +	div->shift = CR2_DIV_SHIFT;
>> +	div->width = CR2_DIV_WIDTH;
>> +	div->lock = lock;
>> +
>> +	cname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s",
>> +			       of_node_full_name(dev->of_node), name);
> 
> Sashiko has the following feedback:
> https://sashiko.dev/#/patchset/20260407211123.77602-1-marex%40nabladev.com
> 
>      Does using of_node_full_name() break debugfs directory creation?
>      
>      The full node name usually contains slashes (e.g., soc/bus@1000/sai@2000),
>      which causes lookup_one_len() to reject the name with -EACCES when the CCF
>      tries to create the directories.

This is nonsense, the node name is clock-controller@12340000 or 
something like that .

>      Also, if the device is instantiated without Device Tree, this evaluates to
>      "<no-node>", potentially causing collisions if multiple instances exist.
>      Would dev_name(dev) be more appropriate here?

This driver is always instantiated from DT.

>> +	if (!cname)
>> +		return -ENOMEM;
>> +
>> +	chw = devm_clk_hw_register_composite_pdata(dev, cname,
>> +						   &pdata, 1, NULL, NULL,
>> +						   &div->hw,
>> +						   &clk_divider_ops,
>> +						   &gate->hw,
>> +						   &clk_gate_ops,
>> +						   CLK_SET_RATE_GATE);
>> +	if (IS_ERR(chw))
>> +		return PTR_ERR(chw);
>> +
>> +	*hw = chw;
>> +
>> +	/* Set clock direction */
>> +	writel(dir_bit, base + div_reg);
> 
> Sashiko also has the following feedback:
> 
>      Is it safe to initialize the hardware register after registering the clock
>      with the CCF?
The BCD/MOE/DIVEN/DIV fields of the CR2/MCR registers are all zeroes, so 
yes, either order is safe.

^ permalink raw reply

* Re: [PATCH v4 11/11] arm64: dts: qcom: sdm845-google: Add STM FTS touchscreen support
From: Dmitry Baryshkov @ 2026-04-08 23:56 UTC (permalink / raw)
  To: david
  Cc: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
	Bjorn Andersson, Konrad Dybcio, Petr Hodina, linux-input,
	linux-stm32, linux-arm-kernel, linux-kernel, Krzysztof Kozlowski,
	devicetree, linux-arm-msm, phone-devel, Konrad Dybcio
In-Reply-To: <20260409-stmfts5-v4-11-64fe62027db5@ixit.cz>

On Thu, Apr 09, 2026 at 12:15:54AM +0200, David Heidelberg via B4 Relay wrote:
> From: Petr Hodina <petr.hodina@protonmail.com>
> 
> Basic touchscreen connected to second i2c bus.
> 
> Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Co-developed-by: David Heidelberg <david@ixit.cz>
> Signed-off-by: David Heidelberg <david@ixit.cz>
> ---
>  arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts | 19 ++++++++++++++++++-
>  arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi  |  2 +-
>  2 files changed, 19 insertions(+), 2 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* [PATCH v4 10/11] Input: stmfts - support FTS5
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
  To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
	Bjorn Andersson, Konrad Dybcio
  Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
	linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
	phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>

From: Petr Hodina <petr.hodina@protonmail.com>

FTS support SLPI and AP mode, introduce mode-switch GPIO to switch between
those two. Currently we can handle only full power AP mode, so we just
keep the AP on.

Useful for devices like Pixel 3 (blueline) and many others.

Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/touchscreen/stmfts.c | 494 ++++++++++++++++++++++++++++++++++---
 1 file changed, 466 insertions(+), 28 deletions(-)

diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 1e6d9a287cd0c..e613299e37557 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -1,8 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
-// STMicroelectronics FTS Touchscreen device driver
-//
-// Copyright (c) 2017 Samsung Electronics Co., Ltd.
-// Copyright (c) 2017 Andi Shyti <andi@etezian.org>
+/* STMicroelectronics FTS Touchscreen device driver
+ *
+ * Copyright 2017 Samsung Electronics Co., Ltd.
+ * Copyright 2017 Andi Shyti <andi@etezian.org>
+ * Copyright David Heidelberg <david@ixit.cz>
+ * Copyright Petr Hodina <petr.hodina@protonmail.com>
+ */
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -12,6 +15,7 @@
 #include <linux/irq.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 
@@ -34,6 +38,7 @@
 #define STMFTS_FULL_FORCE_CALIBRATION		0xa2
 #define STMFTS_MS_CX_TUNING			0xa3
 #define STMFTS_SS_CX_TUNING			0xa4
+#define STMFTS5_SET_SCAN_MODE			0xa0
 
 /* events */
 #define STMFTS_EV_NO_EVENT			0x00
@@ -51,12 +56,32 @@
 #define STMFTS_EV_STATUS			0x16
 #define STMFTS_EV_DEBUG				0xdb
 
+/* events FTS5 */
+#define STMFTS5_EV_CONTROLLER_READY		0x03
+/* FTM5 event IDs (full byte, not masked) */
+#define STMFTS5_EV_MULTI_TOUCH_ENTER		0x13
+#define STMFTS5_EV_MULTI_TOUCH_MOTION		0x23
+#define STMFTS5_EV_MULTI_TOUCH_LEAVE		0x33
+#define STMFTS5_EV_STATUS_UPDATE		0x43
+#define STMFTS5_EV_USER_REPORT			0x53
+#define STMFTS5_EV_DEBUG			0xe3
+#define STMFTS5_EV_ERROR			0xf3
+
 /* multi touch related event masks */
 #define STMFTS_MASK_EVENT_ID			0x0f
 #define STMFTS_MASK_TOUCH_ID			0xf0
 #define STMFTS_MASK_LEFT_EVENT			0x0f
 #define STMFTS_MASK_X_MSB			0x0f
 #define STMFTS_MASK_Y_LSB			0xf0
+#define STMFTS5_MASK_TOUCH_TYPE			0x0f
+
+/* touch type classifications */
+#define STMFTS_TOUCH_TYPE_INVALID		0x00
+#define STMFTS_TOUCH_TYPE_FINGER		0x01
+#define STMFTS_TOUCH_TYPE_GLOVE			0x02
+#define STMFTS_TOUCH_TYPE_STYLUS		0x03
+#define STMFTS_TOUCH_TYPE_PALM			0x04
+#define STMFTS_TOUCH_TYPE_HOVER			0x05
 
 /* key related event masks */
 #define STMFTS_MASK_KEY_NO_TOUCH		0x00
@@ -75,9 +100,12 @@ static const struct regulator_bulk_data stmfts_supplies[] = {
 };
 
 struct stmfts_data {
+	const struct stmfts_chip_ops *ops;
+
 	struct i2c_client *client;
 	struct input_dev *input;
 	struct gpio_desc *reset_gpio;
+	struct gpio_desc *mode_switch_gpio;
 	struct led_classdev led_cdev;
 	struct mutex mutex;
 
@@ -101,12 +129,27 @@ struct stmfts_data {
 
 	struct completion cmd_done;
 
+	unsigned long touch_id;
+	unsigned long stylus_id;
+
 	bool use_key;
 	bool led_status;
 	bool hover_enabled;
+	bool stylus_enabled;
 	bool running;
 };
 
+struct stmfts_chip_ops {
+	int  (*configure)(struct stmfts_data *sdata);
+	void (*power_off)(struct stmfts_data *sdata);
+	int  (*setup_input)(struct stmfts_data *sdata);
+	int  (*input_open)(struct input_dev *dev);
+	void (*input_close)(struct input_dev *dev);
+	void (*parse_events)(struct stmfts_data *sdata);
+	int  (*set_hover)(struct stmfts_data *sdata, bool enable);
+	int  (*runtime_resume)(struct stmfts_data *sdata);
+};
+
 static int stmfts_brightness_set(struct led_classdev *led_cdev,
 					enum led_brightness value)
 {
@@ -169,6 +212,7 @@ static int stmfts_read_events(struct stmfts_data *sdata)
 	return ret == ARRAY_SIZE(msgs) ? 0 : -EIO;
 }
 
+/* FTS4 event handling functions */
 static void stmfts_report_contact_event(struct stmfts_data *sdata,
 					const u8 event[])
 {
@@ -204,6 +248,157 @@ static void stmfts_report_contact_release(struct stmfts_data *sdata,
 	input_sync(sdata->input);
 }
 
+/* FTS5 event handling functions */
+static void stmfts5_report_contact_event(struct stmfts_data *sdata,
+					 const u8 event[])
+{
+	u8 area;
+	u8 maj;
+	u8 min;
+	/* FTM5 event format:
+	 * event[0] = event ID (0x13/0x23)
+	 * event[1] = touch type (low 4 bits) | touch ID (high 4 bits)
+	 * event[2] = X LSB
+	 * event[3] = X MSB (low 4 bits) | Y MSB (high 4 bits)
+	 * event[4] = Y LSB
+	 * event[5] = pressure
+	 * event[6] = major (low 4 bits) | minor (high 4 bits)
+	 * event[7] = minor (high 2 bits)
+	 */
+	u8 touch_id = (event[1] & STMFTS_MASK_TOUCH_ID) >> 4;
+	u8 touch_type = event[1] & STMFTS5_MASK_TOUCH_TYPE;
+	int x, y, distance;
+	unsigned int tool = MT_TOOL_FINGER;
+	bool touch_condition = true;
+
+	/* Parse coordinates with better precision */
+	x = (((int)event[3] & STMFTS_MASK_X_MSB) << 8) | event[2];
+	y = ((int)event[4] << 4) | ((event[3] & STMFTS_MASK_Y_LSB) >> 4);
+
+	/* Parse pressure - ensure non-zero for active touch */
+	area = event[5];
+	if (area <= 0 && touch_type != STMFTS_TOUCH_TYPE_HOVER) {
+		/* Should not happen for contact events. Set minimum pressure
+		 * to prevent touch from being dropped
+		 */
+		dev_warn_once(&sdata->client->dev,
+			      "zero pressure on contact event, slot %d\n", touch_id);
+		area = 1;
+	}
+
+	/* Parse touch area with improved bit extraction */
+	maj = (((event[0] & 0x0C) << 2) | ((event[6] & 0xF0) >> 4));
+	min = (((event[7] & 0xC0) >> 2) | (event[6] & 0x0F));
+
+	/* Distance is 0 for touching, max for hovering */
+	distance = 0;
+
+	/* Classify touch type and set appropriate tool and parameters */
+	switch (touch_type) {
+	case STMFTS_TOUCH_TYPE_STYLUS:
+		if (sdata->stylus_enabled) {
+			tool = MT_TOOL_PEN;
+			__set_bit(touch_id, &sdata->stylus_id);
+			__clear_bit(touch_id, &sdata->touch_id);
+			break;
+		}
+		fallthrough; /* Report as finger if stylus not enabled */
+
+	case STMFTS_TOUCH_TYPE_FINGER:
+	case STMFTS_TOUCH_TYPE_GLOVE:
+		tool = MT_TOOL_FINGER;
+		__set_bit(touch_id, &sdata->touch_id);
+		__clear_bit(touch_id, &sdata->stylus_id);
+		break;
+
+	case STMFTS_TOUCH_TYPE_PALM:
+		/* Palm touch - report but can be filtered by userspace */
+		tool = MT_TOOL_PALM;
+		__set_bit(touch_id, &sdata->touch_id);
+		__clear_bit(touch_id, &sdata->stylus_id);
+		break;
+
+	case STMFTS_TOUCH_TYPE_HOVER:
+		tool = MT_TOOL_FINGER;
+		touch_condition = false;
+		area = 0;
+		distance = 255;
+		__set_bit(touch_id, &sdata->touch_id);
+		__clear_bit(touch_id, &sdata->stylus_id);
+		break;
+
+	case STMFTS_TOUCH_TYPE_INVALID:
+	default:
+		dev_warn(&sdata->client->dev,
+			 "invalid touch type %d for slot %d\n",
+			 touch_type, touch_id);
+		return;
+	}
+
+	/* Boundary check - some devices report max value, adjust */
+	if (x >= sdata->prop.max_x)
+		x = sdata->prop.max_x - 1;
+	if (y >= sdata->prop.max_y)
+		y = sdata->prop.max_y - 1;
+
+	input_mt_slot(sdata->input, touch_id);
+	input_report_key(sdata->input, BTN_TOUCH, touch_condition);
+	input_mt_report_slot_state(sdata->input, tool, true);
+
+	input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
+	input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
+	input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, maj);
+	input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, min);
+	input_report_abs(sdata->input, ABS_MT_PRESSURE, area);
+	input_report_abs(sdata->input, ABS_MT_DISTANCE, distance);
+
+	input_sync(sdata->input);
+}
+
+static void stmfts5_report_contact_release(struct stmfts_data *sdata,
+					   const u8 event[])
+{
+	/* FTM5 format: touch ID is in high 4 bits of event[1] */
+	u8 touch_id = (event[1] & STMFTS_MASK_TOUCH_ID) >> 4;
+	u8 touch_type = event[1] & STMFTS5_MASK_TOUCH_TYPE;
+	unsigned int tool = MT_TOOL_FINGER;
+
+	/* Determine tool type based on touch classification */
+	switch (touch_type) {
+	case STMFTS_TOUCH_TYPE_STYLUS:
+		if (sdata->stylus_enabled) {
+			tool = MT_TOOL_PEN;
+			__clear_bit(touch_id, &sdata->stylus_id);
+		} else {
+			__clear_bit(touch_id, &sdata->touch_id);
+		}
+		break;
+
+	case STMFTS_TOUCH_TYPE_PALM:
+		tool = MT_TOOL_PALM;
+		__clear_bit(touch_id, &sdata->touch_id);
+		break;
+
+	case STMFTS_TOUCH_TYPE_FINGER:
+	case STMFTS_TOUCH_TYPE_GLOVE:
+	case STMFTS_TOUCH_TYPE_HOVER:
+	default:
+		tool = MT_TOOL_FINGER;
+		__clear_bit(touch_id, &sdata->touch_id);
+		break;
+	}
+
+	input_mt_slot(sdata->input, touch_id);
+	input_report_abs(sdata->input, ABS_MT_PRESSURE, 0);
+	input_mt_report_slot_state(sdata->input, tool, false);
+
+	/* Report BTN_TOUCH only if no touches remain */
+	if (!sdata->touch_id && !sdata->stylus_id)
+		input_report_key(sdata->input, BTN_TOUCH, 0);
+
+	input_sync(sdata->input);
+}
+
 static void stmfts_report_hover_event(struct stmfts_data *sdata,
 				      const u8 event[])
 {
@@ -251,7 +446,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
 		u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
 
 		switch (event[0]) {
-
 		case STMFTS_EV_CONTROLLER_READY:
 		case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY:
 		case STMFTS_EV_STATUS:
@@ -264,7 +458,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
 		}
 
 		switch (event[0] & STMFTS_MASK_EVENT_ID) {
-
 		case STMFTS_EV_MULTI_TOUCH_ENTER:
 		case STMFTS_EV_MULTI_TOUCH_MOTION:
 			stmfts_report_contact_event(sdata, event);
@@ -298,6 +491,45 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
 	}
 }
 
+static void stmfts5_parse_events(struct stmfts_data *sdata)
+{
+	for (int i = 0; i < STMFTS_STACK_DEPTH; i++) {
+		u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
+
+		switch (event[0]) {
+		case STMFTS5_EV_CONTROLLER_READY:
+			complete(&sdata->cmd_done);
+			fallthrough;
+
+		case STMFTS_EV_NO_EVENT:
+		case STMFTS5_EV_STATUS_UPDATE:
+		case STMFTS5_EV_USER_REPORT:
+		case STMFTS5_EV_DEBUG:
+			return;
+
+		case STMFTS5_EV_MULTI_TOUCH_ENTER:
+		case STMFTS5_EV_MULTI_TOUCH_MOTION:
+			stmfts5_report_contact_event(sdata, event);
+			break;
+
+		case STMFTS5_EV_MULTI_TOUCH_LEAVE:
+			stmfts5_report_contact_release(sdata, event);
+			break;
+
+		case STMFTS5_EV_ERROR:
+			dev_warn(&sdata->client->dev,
+				 "error code: 0x%x%x%x%x%x%x",
+				 event[6], event[5], event[4],
+				 event[3], event[2], event[1]);
+			break;
+
+		default:
+			dev_err(&sdata->client->dev,
+				"unknown FTS5 event %#02x\n", event[0]);
+		}
+	}
+}
+
 static irqreturn_t stmfts_irq_handler(int irq, void *dev)
 {
 	struct stmfts_data *sdata = dev;
@@ -310,7 +542,7 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
 		dev_err(&sdata->client->dev,
 			"failed to read events: %d\n", err);
 	else
-		stmfts_parse_events(sdata);
+		sdata->ops->parse_events(sdata);
 
 	return IRQ_HANDLED;
 }
@@ -332,6 +564,25 @@ static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
 	return 0;
 }
 
+static int stmfts5_set_scan_mode(struct stmfts_data *sdata, const u8 val)
+{
+	int err;
+
+	u8 scan_mode_cmd[3] = { STMFTS5_SET_SCAN_MODE, 0x00, val };
+	struct i2c_msg msg = {
+		.addr = sdata->client->addr,
+		.len = sizeof(scan_mode_cmd),
+		.buf = scan_mode_cmd,
+	};
+
+	err = i2c_transfer(sdata->client->adapter, &msg, 1);
+	if (err != 1)
+		return err < 0 ? err : -EIO;
+
+	return 0;
+
+}
+
 static int stmfts_input_open(struct input_dev *dev)
 {
 	struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -371,6 +622,28 @@ static int stmfts_input_open(struct input_dev *dev)
 	return 0;
 }
 
+static int stmfts5_input_open(struct input_dev *dev)
+{
+	struct stmfts_data *sdata = input_get_drvdata(dev);
+	int err;
+
+	err = pm_runtime_resume_and_get(&sdata->client->dev);
+	if (err)
+		return err;
+
+	mutex_lock(&sdata->mutex);
+	sdata->running = true;
+	mutex_unlock(&sdata->mutex);
+
+	err = stmfts5_set_scan_mode(sdata, 0xff);
+	if (err) {
+		pm_runtime_put_sync(&sdata->client->dev);
+		return err;
+	}
+
+	return 0;
+}
+
 static void stmfts_input_close(struct input_dev *dev)
 {
 	struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -404,6 +677,23 @@ static void stmfts_input_close(struct input_dev *dev)
 	pm_runtime_put_sync(&sdata->client->dev);
 }
 
+static void stmfts5_input_close(struct input_dev *dev)
+{
+	struct stmfts_data *sdata = input_get_drvdata(dev);
+	int err;
+
+	err = stmfts5_set_scan_mode(sdata, 0x00);
+	if (err)
+		dev_warn(&sdata->client->dev,
+			 "failed to disable touchscreen: %d\n", err);
+
+	mutex_lock(&sdata->mutex);
+	sdata->running = false;
+	mutex_unlock(&sdata->mutex);
+
+	pm_runtime_put_sync(&sdata->client->dev);
+}
+
 static ssize_t stmfts_sysfs_chip_id(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -484,10 +774,8 @@ static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
 	guard(mutex)(&sdata->mutex);
 
 	if (hover != sdata->hover_enabled) {
-		if (sdata->running) {
-			err = i2c_smbus_write_byte(sdata->client,
-					   value ? STMFTS_SS_HOVER_SENSE_ON :
-						   STMFTS_SS_HOVER_SENSE_OFF);
+		if (sdata->running && sdata->ops->set_hover) {
+			err = sdata->ops->set_hover(sdata, hover);
 			if (err)
 				return err;
 		}
@@ -612,7 +900,7 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 	if (sdata->reset_gpio)
 		stmfts_reset(sdata);
 
-	err = stmfts_configure(sdata);
+	err = sdata->ops->configure(sdata);
 	if (err)
 		regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
 				       sdata->supplies);
@@ -620,6 +908,29 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 	return err;
 }
 
+static int stmfts5_configure(struct stmfts_data *sdata)
+{
+	u8 event[STMFTS_EVENT_SIZE];
+	int ret;
+
+	/* Verify I2C communication */
+	ret = i2c_smbus_read_i2c_block_data(sdata->client,
+					    STMFTS_READ_ALL_EVENT,
+					    sizeof(event), event);
+	if (ret < 0)
+		return ret;
+
+	enable_irq(sdata->client->irq);
+
+	return 0;
+}
+
+static void stmfts5_chip_power_off(struct stmfts_data *sdata)
+{
+	i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
+	msleep(20);
+}
+
 static void stmfts_power_off(void *data)
 {
 	struct stmfts_data *sdata = data;
@@ -629,10 +940,73 @@ static void stmfts_power_off(void *data)
 	if (sdata->reset_gpio)
 		gpiod_set_value_cansleep(sdata->reset_gpio, 1);
 
+	if (sdata->ops->power_off)
+		sdata->ops->power_off(sdata);
+
 	regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
 			       sdata->supplies);
 }
 
+static int stmfts_setup_input(struct stmfts_data *sdata)
+{
+	struct device *dev = &sdata->client->dev;
+
+	input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);
+	input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
+
+	sdata->use_key = device_property_read_bool(dev, "touch-key-connected");
+	if (sdata->use_key) {
+		input_set_capability(sdata->input, EV_KEY, KEY_MENU);
+		input_set_capability(sdata->input, EV_KEY, KEY_BACK);
+	}
+
+	return input_mt_init_slots(sdata->input, STMFTS_MAX_FINGERS,
+				   INPUT_MT_DIRECT);
+}
+
+static int stmfts5_setup_input(struct stmfts_data *sdata)
+{
+	struct device *dev = &sdata->client->dev;
+
+	sdata->mode_switch_gpio = devm_gpiod_get_optional(dev, "mode-switch",
+							  GPIOD_OUT_HIGH);
+	if (IS_ERR(sdata->mode_switch_gpio))
+		return dev_err_probe(dev, PTR_ERR(sdata->mode_switch_gpio),
+				     "Failed to get GPIO 'switch'\n");
+
+	/* Mark as direct input device for calibration support */
+	__set_bit(INPUT_PROP_DIRECT, sdata->input->propbit);
+
+	/* Set up basic touch capabilities */
+	input_set_capability(sdata->input, EV_KEY, BTN_TOUCH);
+
+	/* Set resolution for accurate calibration */
+	if (!input_abs_get_res(sdata->input, ABS_MT_POSITION_X)) {
+		input_abs_set_res(sdata->input, ABS_MT_POSITION_X, 10);
+		input_abs_set_res(sdata->input, ABS_MT_POSITION_Y, 10);
+	}
+
+	input_set_abs_params(sdata->input, ABS_MT_DISTANCE, 0, 255, 0, 0);
+
+	/* Enable stylus support if requested */
+	sdata->stylus_enabled = device_property_read_bool(dev, "stylus-enabled");
+
+	/* Initialize touch tracking bitmaps */
+	sdata->touch_id = 0;
+	sdata->stylus_id = 0;
+
+	/* Initialize MT slots with support for pen tool type */
+	return input_mt_init_slots(sdata->input, STMFTS_MAX_FINGERS,
+				   INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+}
+
+static int stmfts_set_hover(struct stmfts_data *sdata, bool enable)
+{
+	return i2c_smbus_write_byte(sdata->client,
+				    enable ? STMFTS_SS_HOVER_SENSE_ON :
+					     STMFTS_SS_HOVER_SENSE_OFF);
+}
+
 static int stmfts_enable_led(struct stmfts_data *sdata)
 {
 	int err;
@@ -678,6 +1052,8 @@ static int stmfts_probe(struct i2c_client *client)
 	mutex_init(&sdata->mutex);
 	init_completion(&sdata->cmd_done);
 
+	sdata->ops = of_device_get_match_data(dev);
+
 	err = devm_regulator_bulk_get_const(dev,
 					    ARRAY_SIZE(stmfts_supplies),
 					    stmfts_supplies,
@@ -697,8 +1073,8 @@ static int stmfts_probe(struct i2c_client *client)
 
 	sdata->input->name = STMFTS_DEV_NAME;
 	sdata->input->id.bustype = BUS_I2C;
-	sdata->input->open = stmfts_input_open;
-	sdata->input->close = stmfts_input_close;
+	sdata->input->open = sdata->ops->input_open;
+	sdata->input->close = sdata->ops->input_close;
 
 	input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_X);
 	input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_Y);
@@ -706,19 +1082,9 @@ static int stmfts_probe(struct i2c_client *client)
 
 	input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
 	input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
-	input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);
 	input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
-	input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
-
-	sdata->use_key = device_property_read_bool(dev,
-						   "touch-key-connected");
-	if (sdata->use_key) {
-		input_set_capability(sdata->input, EV_KEY, KEY_MENU);
-		input_set_capability(sdata->input, EV_KEY, KEY_BACK);
-	}
 
-	err = input_mt_init_slots(sdata->input,
-				  STMFTS_MAX_FINGERS, INPUT_MT_DIRECT);
+	err = sdata->ops->setup_input(sdata);
 	if (err)
 		return err;
 
@@ -789,13 +1155,62 @@ static int stmfts_runtime_suspend(struct device *dev)
 	return ret;
 }
 
-static int stmfts_runtime_resume(struct device *dev)
+static int stmfts_chip_runtime_resume(struct stmfts_data *sdata)
+{
+	return i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT);
+}
+
+static int stmfts5_chip_runtime_resume(struct stmfts_data *sdata)
 {
-	struct stmfts_data *sdata = dev_get_drvdata(dev);
 	struct i2c_client *client = sdata->client;
+	struct device *dev = &client->dev;
+	u8 int_enable_cmd[4] = {0xB6, 0x00, 0x2C, 0x01};
+	struct i2c_msg msg = {
+		.addr = client->addr,
+		.len = sizeof(int_enable_cmd),
+		.buf = int_enable_cmd,
+	};
 	int ret;
 
 	ret = i2c_smbus_write_byte(client, STMFTS_SLEEP_OUT);
+	if (ret)
+		return ret;
+
+	msleep(20);
+
+	/* Perform capacitance tuning after wakeup */
+	ret = i2c_smbus_write_byte(client, STMFTS_MS_CX_TUNING);
+	if (ret)
+		dev_warn(dev, "MS_CX_TUNING failed: %d\n", ret);
+	msleep(20);
+
+	ret = i2c_smbus_write_byte(client, STMFTS_SS_CX_TUNING);
+	if (ret)
+		dev_warn(dev, "SS_CX_TUNING failed: %d\n", ret);
+	msleep(20);
+
+	/* Force calibration */
+	ret = i2c_smbus_write_byte(client, STMFTS_FULL_FORCE_CALIBRATION);
+	if (ret)
+		dev_warn(dev, "FORCE_CALIBRATION failed: %d\n", ret);
+	msleep(50);
+
+	/* Enable controller interrupts */
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret != 1)
+		return ret < 0 ? ret : -EIO;
+
+	msleep(20);
+
+	return 0;
+}
+
+static int stmfts_runtime_resume(struct device *dev)
+{
+	struct stmfts_data *sdata = dev_get_drvdata(dev);
+	int ret;
+
+	ret = sdata->ops->runtime_resume(sdata);
 	if (ret)
 		dev_err(dev, "failed to resume device: %d\n", ret);
 
@@ -824,8 +1239,29 @@ static const struct dev_pm_ops stmfts_pm_ops = {
 };
 
 #ifdef CONFIG_OF
+static const struct stmfts_chip_ops stmfts4_ops = {
+	.configure	= stmfts_configure,
+	.setup_input	= stmfts_setup_input,
+	.input_open	= stmfts_input_open,
+	.input_close	= stmfts_input_close,
+	.parse_events	= stmfts_parse_events,
+	.set_hover	= stmfts_set_hover,
+	.runtime_resume	= stmfts_chip_runtime_resume,
+};
+
+static const struct stmfts_chip_ops stmfts5_ops = {
+	.configure	= stmfts5_configure,
+	.power_off	= stmfts5_chip_power_off,
+	.setup_input	= stmfts5_setup_input,
+	.input_open	= stmfts5_input_open,
+	.input_close	= stmfts5_input_close,
+	.parse_events	= stmfts5_parse_events,
+	.runtime_resume	= stmfts5_chip_runtime_resume,
+};
+
 static const struct of_device_id stmfts_of_match[] = {
-	{ .compatible = "st,stmfts", },
+	{ .compatible = "st,stmfts",	.data = &stmfts4_ops },
+	{ .compatible = "st,stmfts5",	.data = &stmfts5_ops },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, stmfts_of_match);
@@ -853,5 +1289,7 @@ static struct i2c_driver stmfts_driver = {
 module_i2c_driver(stmfts_driver);
 
 MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
+MODULE_AUTHOR("David Heidelberg <david@ixit.cz>");
+MODULE_AUTHOR("Petr Hodina <petr.hodina@protonmail.com>");
 MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen");
 MODULE_LICENSE("GPL");

-- 
2.53.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox