* [PATCH v12 2/2] hwmon: add support for MCP998X
From: Victor Duicu @ 2026-04-03 13:32 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet
Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, marius.cristea,
victor.duicu
In-Reply-To: <20260403-add-mcp9982-hwmon-v12-0-b3bfb26ff136@microchip.com>
Add driver for Microchip MCP998X/33 and MCP998XD/33D
Multichannel Automotive Temperature Monitor Family.
Signed-off-by: Victor Duicu <victor.duicu@microchip.com>
---
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/mcp9982.rst | 111 +++++
MAINTAINERS | 2 +
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/mcp9982.c | 997 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 1123 insertions(+)
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 85d7a686883e..b02709fc216e 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -173,6 +173,7 @@ Hardware Monitoring Kernel Drivers
mc33xs2410_hwmon
mc34vr500
mcp3021
+ mcp9982
menf21bmc
mlxreg-fan
mp2856
diff --git a/Documentation/hwmon/mcp9982.rst b/Documentation/hwmon/mcp9982.rst
new file mode 100644
index 000000000000..790ee1697b45
--- /dev/null
+++ b/Documentation/hwmon/mcp9982.rst
@@ -0,0 +1,111 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Kernel driver MCP998X
+=====================
+
+Supported chips:
+
+ * Microchip Technology MCP998X/MCP9933 and MCP998XD/MCP9933D
+
+ Prefix: 'mcp9982'
+
+ Datasheet:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP998X-Family-Data-Sheet-DS20006827.pdf
+
+Authors:
+
+ - Victor Duicu <victor.duicu@microchip.com>
+
+Description
+-----------
+
+This driver implements support for the MCP998X family containing: MCP9982,
+MCP9982D, MCP9983, MCP9983D, MCP9984, MCP9984D, MCP9985, MCP9985D,
+MCP9933 and MCP9933D.
+
+The MCP998X Family is a high accuracy 2-wire multichannel automotive
+temperature monitor.
+
+The chips in the family have different numbers of external channels,
+ranging from 1 (MCP9982) to 4 channels (MCP9985). Reading diodes in
+anti-parallel connection is supported by MCP9984/85/33 and
+MCP9984D/85D/33D. Dedicated hardware shutdown circuitry is present
+only in MCP998XD and MCP9933D.
+
+Temperatures are read in millidegrees Celsius, ranging from -64 to
+191.875 with 0.125 precision.
+
+Each channel has a minimum, maximum, and critical limit alongside associated alarms.
+The chips also implement a hysteresis mechanism which applies only to the maximum
+and critical limits. The relative difference between a limit and its hysteresis
+is the same for both and the value is kept in a single register.
+
+The chips measure temperatures with a variable conversion rate.
+Update_interval = Conversion/Second, so the available options are:
+- 16000 (ms) = 1 conv/16 sec
+- 8000 (ms) = 1 conv/8 sec
+- 4000 (ms) = 1 conv/4 sec
+- 2000 (ms) = 1 conv/2 sec
+- 1000 (ms) = 1 conv/sec
+- 500 (ms) = 2 conv/sec
+- 250 (ms) = 4 conv/sec
+- 125 (ms) = 8 conv/sec
+- 64 (ms) = 16 conv/sec
+- 32 (ms) = 32 conv/sec
+- 16 (ms) = 64 conv/sec
+
+Usage Notes
+-----------
+
+Parameters that can be configured in devicetree:
+- anti-parallel diode mode operation
+- resistance error correction on channels 1 and 2
+- resistance error correction on channels 3 and 4
+- power state
+
+Chips 82/83 and 82D/83D do not support anti-parallel diode mode.
+For chips with "D" in the name resistance error correction must be on.
+Please see Documentation/devicetree/bindings/hwmon/microchip,mcp9982.yaml
+for details.
+
+There are two power states:
+- Active state: in which the chip is converting on all channels at the
+programmed rate.
+
+- Standby state: in which the host must initiate a conversion cycle.
+
+Chips with "D" in the name work in Active state only and those without
+can work in either state.
+
+Chips with "D" in the name can't set update interval slower than 1 second.
+
+Among the hysteresis attributes, only the tempX_crit_hyst ones are writeable
+while the others are read only. Setting tempX_crit_hyst writes the difference
+between tempX_crit and tempX_crit_hyst in the hysteresis register. The new value
+applies automatically to the other limits. At power up the device starts with
+a 10 degree hysteresis.
+
+Sysfs entries
+-------------
+
+The following attributes are supported. The temperature limits and
+update_interval are read-write. The attribute tempX_crit_hyst is read-write,
+while tempX_max_hyst is read only. All other attributes are read only.
+
+======================= ==================================================
+temp[1-5]_label User name for channel.
+temp[1-5]_input Measured temperature for channel.
+
+temp[1-5]_crit Critical temperature limit.
+temp[1-5]_crit_alarm Critical temperature limit alarm.
+temp[1-5]_crit_hyst Critical temperature limit hysteresis.
+
+temp[1-5]_max High temperature limit.
+temp[1-5]_max_alarm High temperature limit alarm.
+temp[1-5]_max_hyst High temperature limit hysteresis.
+
+temp[1-5]_min Low temperature limit.
+temp[1-5]_min_alarm Low temperature limit alarm.
+
+update_interval The interval at which the chip will update readings.
+======================= ==================================================
diff --git a/MAINTAINERS b/MAINTAINERS
index 026510a4129c..5c6662e10b04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17165,6 +17165,8 @@ M: Victor Duicu <victor.duicu@microchip.com>
L: linux-hwmon@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/hwmon/microchip,mcp9982.yaml
+F: Documentation/hwmon/mcp9982.rst
+F: drivers/hwmon/mcp9982.c
MICROCHIP MMC/SD/SDIO MCI DRIVER
M: Aubin Constans <aubin.constans@microchip.com>
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 157678b821fc..c758ab2d5fdf 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1388,6 +1388,17 @@ config SENSORS_MCP3021
This driver can also be built as a module. If so, the module
will be called mcp3021.
+config SENSORS_MCP9982
+ tristate "Microchip Technology MCP9982 driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say yes here to include support for Microchip Technology's MCP998X/33
+ and MCP998XD/33D Multichannel Automotive Temperature Monitor Family.
+
+ This driver can also be built as a module. If so, the module
+ will be called mcp9982.
+
config SENSORS_MLXREG_FAN
tristate "Mellanox FAN driver"
depends on MELLANOX_PLATFORM
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index eade8e3b1bde..cec33da29a68 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -170,6 +170,7 @@ obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_MC33XS2410) += mc33xs2410_hwmon.o
obj-$(CONFIG_SENSORS_MC34VR500) += mc34vr500.o
obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
+obj-$(CONFIG_SENSORS_MCP9982) += mcp9982.o
obj-$(CONFIG_SENSORS_TC654) += tc654.o
obj-$(CONFIG_SENSORS_TPS23861) += tps23861.o
obj-$(CONFIG_SENSORS_MLXREG_FAN) += mlxreg-fan.o
diff --git a/drivers/hwmon/mcp9982.c b/drivers/hwmon/mcp9982.c
new file mode 100644
index 000000000000..f0b836a3f256
--- /dev/null
+++ b/drivers/hwmon/mcp9982.c
@@ -0,0 +1,997 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * HWMON driver for MCP998X/33 and MCP998XD/33D Multichannel Automotive
+ * Temperature Monitor Family
+ *
+ * Copyright (C) 2026 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Victor Duicu <victor.duicu@microchip.com>
+ *
+ * Datasheet can be found here:
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP998X-Family-Data-Sheet-DS20006827.pdf
+ */
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/bits.h>
+#include <linux/byteorder/generic.h>
+#include <linux/delay.h>
+#include <linux/device/devres.h>
+#include <linux/device.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/math.h>
+#include <linux/minmax.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/time64.h>
+#include <linux/util_macros.h>
+
+/* MCP9982 Registers */
+#define MCP9982_HIGH_BYTE_ADDR(index) (2 * (index))
+#define MCP9982_ONE_SHOT_ADDR 0x0A
+#define MCP9982_INTERNAL_HIGH_LIMIT_ADDR 0x0B
+#define MCP9982_INTERNAL_LOW_LIMIT_ADDR 0x0C
+#define MCP9982_EXT_HIGH_LIMIT_ADDR(index) (4 * ((index) - 1) + 0x0D)
+#define MCP9982_EXT_LOW_LIMIT_ADDR(index) (4 * ((index) - 1) + 0x0F)
+#define MCP9982_THERM_LIMIT_ADDR(index) ((index) + 0x1D)
+#define MCP9982_CFG_ADDR 0x22
+#define MCP9982_CONV_ADDR 0x24
+#define MCP9982_HYS_ADDR 0x25
+#define MCP9982_CONSEC_ALRT_ADDR 0x26
+#define MCP9982_ALRT_CFG_ADDR 0x27
+#define MCP9982_RUNNING_AVG_ADDR 0x28
+#define MCP9982_HOTTEST_CFG_ADDR 0x29
+#define MCP9982_STATUS_ADDR 0x2A
+#define MCP9982_EXT_FAULT_STATUS_ADDR 0x2B
+#define MCP9982_HIGH_LIMIT_STATUS_ADDR 0x2C
+#define MCP9982_LOW_LIMIT_STATUS_ADDR 0x2D
+#define MCP9982_THERM_LIMIT_STATUS_ADDR 0x2E
+#define MCP9982_HOTTEST_HIGH_BYTE_ADDR 0x2F
+#define MCP9982_HOTTEST_LOW_BYTE_ADDR 0x30
+#define MCP9982_HOTTEST_STATUS_ADDR 0x31
+#define MCP9982_THERM_SHTDWN_CFG_ADDR 0x32
+#define MCP9982_HRDW_THERM_SHTDWN_LIMIT_ADDR 0x33
+#define MCP9982_EXT_BETA_CFG_ADDR(index) ((index) + 0x33)
+#define MCP9982_EXT_IDEAL_ADDR(index) ((index) + 0x35)
+
+/* MCP9982 Bits */
+#define MCP9982_CFG_MSKAL BIT(7)
+#define MCP9982_CFG_RS BIT(6)
+#define MCP9982_CFG_ATTHM BIT(5)
+#define MCP9982_CFG_RECD12 BIT(4)
+#define MCP9982_CFG_RECD34 BIT(3)
+#define MCP9982_CFG_RANGE BIT(2)
+#define MCP9982_CFG_DA_ENA BIT(1)
+#define MCP9982_CFG_APDD BIT(0)
+
+#define MCP9982_STATUS_BUSY BIT(5)
+
+/* Constants and default values */
+#define MCP9982_MAX_NUM_CHANNELS 5
+#define MCP9982_BETA_AUTODETECT 16
+#define MCP9982_IDEALITY_DEFAULT 18
+#define MCP9982_OFFSET 64
+#define MCP9982_DEFAULT_CONSEC_ALRT_VAL 112
+#define MCP9982_DEFAULT_HYS_VAL 10
+#define MCP9982_DEFAULT_CONV_VAL 6
+#define MCP9982_WAKE_UP_TIME_US 125000
+#define MCP9982_WAKE_UP_TIME_MAX_US 130000
+#define MCP9982_HIGH_LIMIT_DEFAULT 85000
+#define MCP9982_LOW_LIMIT_DEFAULT 0
+
+static const struct hwmon_channel_info * const mcp9985_info[] = {
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_MIN |
+ HWMON_T_MIN_ALARM | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_MAX_HYST | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_MIN |
+ HWMON_T_MIN_ALARM | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_MAX_HYST | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_MIN |
+ HWMON_T_MIN_ALARM | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_MAX_HYST | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_MIN |
+ HWMON_T_MIN_ALARM | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_MAX_HYST | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
+ HWMON_T_CRIT_HYST,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_MIN |
+ HWMON_T_MIN_ALARM | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_MAX_HYST | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
+ HWMON_T_CRIT_HYST),
+ HWMON_CHANNEL_INFO(chip,
+ HWMON_C_UPDATE_INTERVAL),
+ NULL
+};
+
+/**
+ * struct mcp9982_features - features of a mcp9982 instance
+ * @name: chip's name
+ * @phys_channels: number of physical channels supported by the chip
+ * @hw_thermal_shutdown: presence of hardware thermal shutdown circuitry
+ * @allow_apdd: whether the chip supports enabling APDD
+ * @has_recd34: whether the chip has the channels that are affected by recd34
+ */
+struct mcp9982_features {
+ const char *name;
+ u8 phys_channels;
+ bool hw_thermal_shutdown;
+ bool allow_apdd;
+ bool has_recd34;
+};
+
+static const struct mcp9982_features mcp9933_chip_config = {
+ .name = "mcp9933",
+ .phys_channels = 3,
+ .hw_thermal_shutdown = false,
+ .allow_apdd = true,
+ .has_recd34 = false,
+};
+
+static const struct mcp9982_features mcp9933d_chip_config = {
+ .name = "mcp9933d",
+ .phys_channels = 3,
+ .hw_thermal_shutdown = true,
+ .allow_apdd = true,
+ .has_recd34 = false,
+};
+
+static const struct mcp9982_features mcp9982_chip_config = {
+ .name = "mcp9982",
+ .phys_channels = 2,
+ .hw_thermal_shutdown = false,
+ .allow_apdd = false,
+ .has_recd34 = false,
+};
+
+static const struct mcp9982_features mcp9982d_chip_config = {
+ .name = "mcp9982d",
+ .phys_channels = 2,
+ .hw_thermal_shutdown = true,
+ .allow_apdd = false,
+ .has_recd34 = false,
+};
+
+static const struct mcp9982_features mcp9983_chip_config = {
+ .name = "mcp9983",
+ .phys_channels = 3,
+ .hw_thermal_shutdown = false,
+ .allow_apdd = false,
+ .has_recd34 = true,
+};
+
+static const struct mcp9982_features mcp9983d_chip_config = {
+ .name = "mcp9983d",
+ .phys_channels = 3,
+ .hw_thermal_shutdown = true,
+ .allow_apdd = false,
+ .has_recd34 = true,
+};
+
+static const struct mcp9982_features mcp9984_chip_config = {
+ .name = "mcp9984",
+ .phys_channels = 4,
+ .hw_thermal_shutdown = false,
+ .allow_apdd = true,
+ .has_recd34 = true,
+};
+
+static const struct mcp9982_features mcp9984d_chip_config = {
+ .name = "mcp9984d",
+ .phys_channels = 4,
+ .hw_thermal_shutdown = true,
+ .allow_apdd = true,
+ .has_recd34 = true,
+};
+
+static const struct mcp9982_features mcp9985_chip_config = {
+ .name = "mcp9985",
+ .phys_channels = 5,
+ .hw_thermal_shutdown = false,
+ .allow_apdd = true,
+ .has_recd34 = true,
+};
+
+static const struct mcp9982_features mcp9985d_chip_config = {
+ .name = "mcp9985d",
+ .phys_channels = 5,
+ .hw_thermal_shutdown = true,
+ .allow_apdd = true,
+ .has_recd34 = true,
+};
+
+static const unsigned int mcp9982_update_interval[11] = {
+ 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 64, 32, 16
+};
+
+/* MCP9982 regmap configuration */
+static const struct regmap_range mcp9982_regmap_wr_ranges[] = {
+ regmap_reg_range(MCP9982_ONE_SHOT_ADDR, MCP9982_CFG_ADDR),
+ regmap_reg_range(MCP9982_CONV_ADDR, MCP9982_HOTTEST_CFG_ADDR),
+ regmap_reg_range(MCP9982_THERM_SHTDWN_CFG_ADDR, MCP9982_THERM_SHTDWN_CFG_ADDR),
+ regmap_reg_range(MCP9982_EXT_BETA_CFG_ADDR(1), MCP9982_EXT_IDEAL_ADDR(4)),
+};
+
+static const struct regmap_access_table mcp9982_regmap_wr_table = {
+ .yes_ranges = mcp9982_regmap_wr_ranges,
+ .n_yes_ranges = ARRAY_SIZE(mcp9982_regmap_wr_ranges),
+};
+
+static const struct regmap_range mcp9982_regmap_rd_ranges[] = {
+ regmap_reg_range(MCP9982_HIGH_BYTE_ADDR(0), MCP9982_CFG_ADDR),
+ regmap_reg_range(MCP9982_CONV_ADDR, MCP9982_EXT_IDEAL_ADDR(4)),
+};
+
+static const struct regmap_access_table mcp9982_regmap_rd_table = {
+ .yes_ranges = mcp9982_regmap_rd_ranges,
+ .n_yes_ranges = ARRAY_SIZE(mcp9982_regmap_rd_ranges),
+};
+
+static bool mcp9982_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MCP9982_ONE_SHOT_ADDR:
+ case MCP9982_INTERNAL_HIGH_LIMIT_ADDR:
+ case MCP9982_INTERNAL_LOW_LIMIT_ADDR:
+ case MCP9982_EXT_LOW_LIMIT_ADDR(1):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(1) + 1:
+ case MCP9982_EXT_LOW_LIMIT_ADDR(2):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(2) + 1:
+ case MCP9982_EXT_LOW_LIMIT_ADDR(3):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(3) + 1:
+ case MCP9982_EXT_LOW_LIMIT_ADDR(4):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(4) + 1:
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(1):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(1) + 1:
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(2):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(2) + 1:
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(3):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(3) + 1:
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(4):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(4) + 1:
+ case MCP9982_THERM_LIMIT_ADDR(0):
+ case MCP9982_THERM_LIMIT_ADDR(1):
+ case MCP9982_THERM_LIMIT_ADDR(2):
+ case MCP9982_THERM_LIMIT_ADDR(3):
+ case MCP9982_THERM_LIMIT_ADDR(4):
+ case MCP9982_CFG_ADDR:
+ case MCP9982_CONV_ADDR:
+ case MCP9982_HYS_ADDR:
+ case MCP9982_CONSEC_ALRT_ADDR:
+ case MCP9982_ALRT_CFG_ADDR:
+ case MCP9982_RUNNING_AVG_ADDR:
+ case MCP9982_HOTTEST_CFG_ADDR:
+ case MCP9982_THERM_SHTDWN_CFG_ADDR:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static const struct regmap_config mcp9982_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .rd_table = &mcp9982_regmap_rd_table,
+ .wr_table = &mcp9982_regmap_wr_table,
+ .volatile_reg = mcp9982_is_volatile_reg,
+ .max_register = MCP9982_EXT_IDEAL_ADDR(4),
+ .cache_type = REGCACHE_MAPLE,
+};
+
+/**
+ * struct mcp9982_priv - information about chip parameters
+ * @regmap: device register map
+ * @chip: pointer to structure holding chip features
+ * @labels: labels of the channels
+ * @interval_idx: index representing the current update interval
+ * @enabled_channel_mask: mask containing which channels should be enabled
+ * @num_channels: number of active physical channels
+ * @recd34_enable: state of Resistance Error Correction(REC) on channels 3 and 4
+ * @recd12_enable: state of Resistance Error Correction(REC) on channels 1 and 2
+ * @apdd_enable: state of anti-parallel diode mode
+ * @run_state: chip is in Run state, otherwise is in Standby state
+ */
+struct mcp9982_priv {
+ struct regmap *regmap;
+ const struct mcp9982_features *chip;
+ const char *labels[MCP9982_MAX_NUM_CHANNELS];
+ unsigned int interval_idx;
+ unsigned long enabled_channel_mask;
+ u8 num_channels;
+ bool recd34_enable;
+ bool recd12_enable;
+ bool apdd_enable;
+ bool run_state;
+};
+
+static int mcp9982_read_limit(struct mcp9982_priv *priv, u8 address, long *val)
+{
+ unsigned int limit, reg_high, reg_low;
+ int ret;
+
+ switch (address) {
+ case MCP9982_INTERNAL_HIGH_LIMIT_ADDR:
+ case MCP9982_INTERNAL_LOW_LIMIT_ADDR:
+ case MCP9982_THERM_LIMIT_ADDR(0):
+ case MCP9982_THERM_LIMIT_ADDR(1):
+ case MCP9982_THERM_LIMIT_ADDR(2):
+ case MCP9982_THERM_LIMIT_ADDR(3):
+ case MCP9982_THERM_LIMIT_ADDR(4):
+ ret = regmap_read(priv->regmap, address, &limit);
+ if (ret)
+ return ret;
+
+ *val = ((int)limit - MCP9982_OFFSET) * 1000;
+
+ return 0;
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(1):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(2):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(3):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(4):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(1):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(2):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(3):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(4):
+ /*
+ * In order to keep consistency with reading temperature memory region we will use
+ * single byte I2C read.
+ */
+ ret = regmap_read(priv->regmap, address, ®_high);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(priv->regmap, address + 1, ®_low);
+ if (ret)
+ return ret;
+
+ *val = ((reg_high << 8) + reg_low) >> 5;
+ *val = (*val - (MCP9982_OFFSET << 3)) * 125;
+
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp9982_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
+ long *val)
+{
+ struct mcp9982_priv *priv = dev_get_drvdata(dev);
+ unsigned int reg_high, reg_low, hyst, reg_status;
+ int ret;
+ u8 addr;
+
+ /*
+ * In Standby State the conversion cycle must be initated manually in
+ * order to read fresh temperature values and the status of the alarms.
+ */
+ if (!priv->run_state) {
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_crit_alarm:
+ ret = regmap_write(priv->regmap, MCP9982_ONE_SHOT_ADDR, 1);
+ if (ret)
+ return ret;
+ /*
+ * When the device is in Standby mode, 125 ms need
+ * to pass from writing in One Shot register before
+ * the conversion cycle begins.
+ */
+ usleep_range(MCP9982_WAKE_UP_TIME_US, MCP9982_WAKE_UP_TIME_MAX_US);
+ ret = regmap_read_poll_timeout
+ (priv->regmap, MCP9982_STATUS_ADDR,
+ reg_status, !(reg_status & MCP9982_STATUS_BUSY),
+ MCP9982_WAKE_UP_TIME_US,
+ MCP9982_WAKE_UP_TIME_US * 10);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ /*
+ * The only areas of memory that support SMBus block read are 80h->89h
+ * (temperature memory block) and 90h->97h(status memory block).
+ * In this context the read operation uses SMBus protocol and the first
+ * value returned will be the number of addresses that can be read.
+ * Temperature memory block is 10 bytes long and status memory block is 8
+ * bytes long.
+ *
+ * Depending on the read instruction used, the chip behaves differently:
+ * - regmap_bulk_read() when applied to the temperature memory block
+ * (80h->89h), the chip replies with SMBus block read, including count,
+ * additionally to the high and the low bytes. This function cannot be
+ * applied on the memory region 00h->09h(memory area which does not support
+ * block reads, returns wrong data) unless use_single_read is set in
+ * regmap_config.
+ *
+ * - regmap_multi_reg_read() when applied to the 00h->09h area uses I2C
+ * and returns only the high and low temperature bytes. When applied to
+ * the temperature memory block (80h->89h) returns the count till the end of
+ * the temperature memory block(aka SMBus count).
+ *
+ * - i2c_smbus_read_block_data() is not supported by all drivers.
+ *
+ * In order to keep consistency with reading limit memory region we will
+ * use single byte I2C read.
+ *
+ * Low register is latched when high temperature register is read.
+ */
+ ret = regmap_read(priv->regmap, MCP9982_HIGH_BYTE_ADDR(channel), ®_high);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(priv->regmap, MCP9982_HIGH_BYTE_ADDR(channel) + 1,
+ ®_low);
+ if (ret)
+ return ret;
+
+ *val = ((reg_high << 8) + reg_low) >> 5;
+ *val = (*val - (MCP9982_OFFSET << 3)) * 125;
+
+ return 0;
+ case hwmon_temp_max:
+ if (channel)
+ addr = MCP9982_EXT_HIGH_LIMIT_ADDR(channel);
+ else
+ addr = MCP9982_INTERNAL_HIGH_LIMIT_ADDR;
+
+ return mcp9982_read_limit(priv, addr, val);
+ case hwmon_temp_max_alarm:
+ *val = regmap_test_bits(priv->regmap, MCP9982_HIGH_LIMIT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ case hwmon_temp_max_hyst:
+ if (channel)
+ addr = MCP9982_EXT_HIGH_LIMIT_ADDR(channel);
+ else
+ addr = MCP9982_INTERNAL_HIGH_LIMIT_ADDR;
+ ret = mcp9982_read_limit(priv, addr, val);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(priv->regmap, MCP9982_HYS_ADDR, &hyst);
+ if (ret)
+ return ret;
+
+ *val -= hyst * 1000;
+
+ return 0;
+ case hwmon_temp_min:
+ if (channel)
+ addr = MCP9982_EXT_LOW_LIMIT_ADDR(channel);
+ else
+ addr = MCP9982_INTERNAL_LOW_LIMIT_ADDR;
+
+ return mcp9982_read_limit(priv, addr, val);
+ case hwmon_temp_min_alarm:
+ *val = regmap_test_bits(priv->regmap, MCP9982_LOW_LIMIT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ case hwmon_temp_crit:
+ return mcp9982_read_limit(priv, MCP9982_THERM_LIMIT_ADDR(channel), val);
+ case hwmon_temp_crit_alarm:
+ *val = regmap_test_bits(priv->regmap, MCP9982_THERM_LIMIT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ case hwmon_temp_crit_hyst:
+ ret = mcp9982_read_limit(priv, MCP9982_THERM_LIMIT_ADDR(channel), val);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(priv->regmap, MCP9982_HYS_ADDR, &hyst);
+ if (ret)
+ return ret;
+
+ *val -= hyst * 1000;
+
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ *val = mcp9982_update_interval[priv->interval_idx];
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp9982_read_label(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, const char **str)
+{
+ struct mcp9982_priv *priv = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_label:
+ *str = priv->labels[channel];
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int mcp9982_write_limit(struct mcp9982_priv *priv, u8 address, long val)
+{
+ int ret;
+ unsigned int regh, regl;
+
+ switch (address) {
+ case MCP9982_INTERNAL_HIGH_LIMIT_ADDR:
+ case MCP9982_INTERNAL_LOW_LIMIT_ADDR:
+ case MCP9982_THERM_LIMIT_ADDR(0):
+ case MCP9982_THERM_LIMIT_ADDR(1):
+ case MCP9982_THERM_LIMIT_ADDR(2):
+ case MCP9982_THERM_LIMIT_ADDR(3):
+ case MCP9982_THERM_LIMIT_ADDR(4):
+ regh = DIV_ROUND_CLOSEST(val, 1000);
+ regh = clamp_val(regh, 0, 255);
+
+ return regmap_write(priv->regmap, address, regh);
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(1):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(2):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(3):
+ case MCP9982_EXT_HIGH_LIMIT_ADDR(4):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(1):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(2):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(3):
+ case MCP9982_EXT_LOW_LIMIT_ADDR(4):
+ val = DIV_ROUND_CLOSEST(val, 125);
+ regh = (val >> 3) & 0xff;
+ regl = (val & 0x07) << 5;
+ /* Block writing is not supported by the chip. */
+ ret = regmap_write(priv->regmap, address, regh);
+ if (ret)
+ return ret;
+
+ return regmap_write(priv->regmap, address + 1, regl);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp9982_write_hyst(struct mcp9982_priv *priv, int channel, long val)
+{
+ int hyst, ret;
+ int limit;
+
+ val = DIV_ROUND_CLOSEST(val, 1000);
+ val = clamp_val(val, 0, 255);
+
+ /* Therm register is 8 bits and so it keeps only the integer part of the temperature. */
+ ret = regmap_read(priv->regmap, MCP9982_THERM_LIMIT_ADDR(channel), &limit);
+ if (ret)
+ return ret;
+
+ hyst = clamp_val(limit - val, 0, 255);
+
+ return regmap_write(priv->regmap, MCP9982_HYS_ADDR, hyst);
+}
+
+static int mcp9982_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
+ long val)
+{
+ struct mcp9982_priv *priv = dev_get_drvdata(dev);
+ unsigned int idx;
+ u8 addr;
+
+ switch (type) {
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+
+ /*
+ * For MCP998XD and MCP9933D update interval
+ * can't be longer than 1 second.
+ */
+ if (priv->chip->hw_thermal_shutdown)
+ val = clamp_val(val, 0, 1000);
+
+ idx = find_closest_descending(val, mcp9982_update_interval,
+ ARRAY_SIZE(mcp9982_update_interval));
+ priv->interval_idx = idx;
+
+ return regmap_write(priv->regmap, MCP9982_CONV_ADDR, idx);
+ default:
+ return -EINVAL;
+ }
+ case hwmon_temp:
+ val = clamp_val(val, -64000, 191875);
+ val = val + (MCP9982_OFFSET * 1000);
+ switch (attr) {
+ case hwmon_temp_max:
+ if (channel)
+ addr = MCP9982_EXT_HIGH_LIMIT_ADDR(channel);
+ else
+ addr = MCP9982_INTERNAL_HIGH_LIMIT_ADDR;
+
+ return mcp9982_write_limit(priv, addr, val);
+ case hwmon_temp_min:
+ if (channel)
+ addr = MCP9982_EXT_LOW_LIMIT_ADDR(channel);
+ else
+ addr = MCP9982_INTERNAL_LOW_LIMIT_ADDR;
+
+ return mcp9982_write_limit(priv, addr, val);
+ case hwmon_temp_crit:
+ return mcp9982_write_limit(priv, MCP9982_THERM_LIMIT_ADDR(channel), val);
+ case hwmon_temp_crit_hyst:
+ return mcp9982_write_hyst(priv, channel, val);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static umode_t mcp9982_is_visible(const void *_data, enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ const struct mcp9982_priv *priv = _data;
+
+ if (!test_bit(channel, &priv->enabled_channel_mask))
+ return 0;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_label:
+ if (priv->labels[channel])
+ return 0444;
+ else
+ return 0;
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_crit_alarm:
+ return 0444;
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ case hwmon_temp_crit:
+ case hwmon_temp_crit_hyst:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return 0644;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_ops mcp9982_hwmon_ops = {
+ .is_visible = mcp9982_is_visible,
+ .read = mcp9982_read,
+ .read_string = mcp9982_read_label,
+ .write = mcp9982_write,
+};
+
+static int mcp9982_init(struct device *dev, struct mcp9982_priv *priv)
+{
+ long high_limit, low_limit;
+ unsigned int i;
+ int ret;
+ u8 val;
+
+ /* Chips 82/83 and 82D/83D do not support anti-parallel diode mode. */
+ if (!priv->chip->allow_apdd && priv->apdd_enable == 1)
+ return dev_err_probe(dev, -EINVAL, "Incorrect setting of APDD.\n");
+
+ /* Chips with "D" work only in Run state. */
+ if (priv->chip->hw_thermal_shutdown && !priv->run_state)
+ return dev_err_probe(dev, -EINVAL, "Incorrect setting of Power State.\n");
+
+ /* All chips with "D" in the name must have RECD12 enabled. */
+ if (priv->chip->hw_thermal_shutdown && !priv->recd12_enable)
+ return dev_err_probe(dev, -EINVAL, "Incorrect setting of RECD12.\n");
+ /* Chips 83D/84D/85D must have RECD34 enabled. */
+ if (priv->chip->hw_thermal_shutdown)
+ if ((priv->chip->has_recd34 && !priv->recd34_enable))
+ return dev_err_probe(dev, -EINVAL, "Incorrect setting of RECD34.\n");
+
+ /*
+ * Set default values in registers.
+ * APDD, RECD12 and RECD34 are active on 0.
+ */
+ val = FIELD_PREP(MCP9982_CFG_MSKAL, 1) |
+ FIELD_PREP(MCP9982_CFG_RS, !priv->run_state) |
+ FIELD_PREP(MCP9982_CFG_ATTHM, 1) |
+ FIELD_PREP(MCP9982_CFG_RECD12, !priv->recd12_enable) |
+ FIELD_PREP(MCP9982_CFG_RECD34, !priv->recd34_enable) |
+ FIELD_PREP(MCP9982_CFG_RANGE, 1) | FIELD_PREP(MCP9982_CFG_DA_ENA, 0) |
+ FIELD_PREP(MCP9982_CFG_APDD, !priv->apdd_enable);
+
+ ret = regmap_write(priv->regmap, MCP9982_CFG_ADDR, val);
+ if (ret)
+ return ret;
+
+ /*
+ * Read initial value from register.
+ * The convert register utilises only 4 out of 8 bits.
+ * Numerical values 0->10 set their respective update intervals,
+ * while numerical values 11->15 default to 1 second.
+ */
+ ret = regmap_read(priv->regmap, MCP9982_CONV_ADDR, &priv->interval_idx);
+ if (ret)
+ return ret;
+ if (priv->interval_idx >= 11)
+ priv->interval_idx = 4;
+
+ ret = regmap_write(priv->regmap, MCP9982_HYS_ADDR, MCP9982_DEFAULT_HYS_VAL);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, MCP9982_CONSEC_ALRT_ADDR, MCP9982_DEFAULT_CONSEC_ALRT_VAL);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, MCP9982_ALRT_CFG_ADDR, 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, MCP9982_RUNNING_AVG_ADDR, 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, MCP9982_HOTTEST_CFG_ADDR, 0);
+ if (ret)
+ return ret;
+
+ /*
+ * Only external channels 1 and 2 support beta compensation.
+ * Set beta auto-detection.
+ */
+ for (i = 1; i < 3; i++)
+ if (test_bit(i, &priv->enabled_channel_mask)) {
+ ret = regmap_write(priv->regmap, MCP9982_EXT_BETA_CFG_ADDR(i),
+ MCP9982_BETA_AUTODETECT);
+ if (ret)
+ return ret;
+ }
+
+ high_limit = MCP9982_HIGH_LIMIT_DEFAULT + (MCP9982_OFFSET * 1000);
+ low_limit = MCP9982_LOW_LIMIT_DEFAULT + (MCP9982_OFFSET * 1000);
+
+ /* Set default values for internal channel limits. */
+ if (test_bit(0, &priv->enabled_channel_mask)) {
+ ret = mcp9982_write_limit(priv, MCP9982_INTERNAL_HIGH_LIMIT_ADDR, high_limit);
+ if (ret)
+ return ret;
+
+ ret = mcp9982_write_limit(priv, MCP9982_INTERNAL_LOW_LIMIT_ADDR, low_limit);
+ if (ret)
+ return ret;
+
+ ret = mcp9982_write_limit(priv, MCP9982_THERM_LIMIT_ADDR(0), high_limit);
+ if (ret)
+ return ret;
+ }
+
+ /* Set ideality factor and limits to default for external channels. */
+ for (i = 1; i < MCP9982_MAX_NUM_CHANNELS; i++)
+ if (test_bit(i, &priv->enabled_channel_mask)) {
+ ret = regmap_write(priv->regmap, MCP9982_EXT_IDEAL_ADDR(i),
+ MCP9982_IDEALITY_DEFAULT);
+ if (ret)
+ return ret;
+
+ ret = mcp9982_write_limit(priv, MCP9982_EXT_HIGH_LIMIT_ADDR(i), high_limit);
+ if (ret)
+ return ret;
+
+ ret = mcp9982_write_limit(priv, MCP9982_EXT_LOW_LIMIT_ADDR(i), low_limit);
+ if (ret)
+ return ret;
+
+ ret = mcp9982_write_limit(priv, MCP9982_THERM_LIMIT_ADDR(i), high_limit);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp9982_parse_fw_config(struct device *dev, int device_nr_channels)
+{
+ struct mcp9982_priv *priv = dev_get_drvdata(dev);
+ unsigned int reg_nr;
+ int ret;
+
+ /* Initialise internal channel( which is always present ). */
+ priv->labels[0] = "internal diode";
+ priv->enabled_channel_mask = 1;
+
+ /* Default values to work on systems without devicetree or firmware nodes. */
+ if (!dev_fwnode(dev)) {
+ priv->num_channels = device_nr_channels;
+ priv->enabled_channel_mask = BIT(priv->num_channels) - 1;
+ priv->apdd_enable = false;
+ priv->recd12_enable = true;
+ priv->recd34_enable = true;
+ priv->run_state = true;
+ return 0;
+ }
+
+ priv->apdd_enable =
+ device_property_read_bool(dev, "microchip,enable-anti-parallel");
+
+ priv->recd12_enable =
+ device_property_read_bool(dev, "microchip,parasitic-res-on-channel1-2");
+
+ priv->recd34_enable =
+ device_property_read_bool(dev, "microchip,parasitic-res-on-channel3-4");
+
+ priv->run_state =
+ device_property_read_bool(dev, "microchip,power-state");
+
+ priv->num_channels = device_get_child_node_count(dev) + 1;
+
+ if (priv->num_channels > device_nr_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "More channels than the chip supports.\n");
+
+ /* Read information about the external channels. */
+ device_for_each_named_child_node_scoped(dev, child, "channel") {
+ reg_nr = 0;
+ ret = fwnode_property_read_u32(child, "reg", ®_nr);
+ if (ret || !reg_nr || reg_nr >= device_nr_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "Channel reg is incorrectly set.\n");
+
+ fwnode_property_read_string(child, "label", &priv->labels[reg_nr]);
+ set_bit(reg_nr, &priv->enabled_channel_mask);
+ }
+
+ return 0;
+}
+
+static const struct hwmon_chip_info mcp998x_chip_info = {
+ .ops = &mcp9982_hwmon_ops,
+ .info = mcp9985_info,
+};
+
+static int mcp9982_probe(struct i2c_client *client)
+{
+ const struct mcp9982_features *chip;
+ struct device *dev = &client->dev;
+ struct mcp9982_priv *priv;
+ struct device *hwmon_dev;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(struct mcp9982_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = devm_regmap_init_i2c(client, &mcp9982_regmap_config);
+
+ if (IS_ERR(priv->regmap))
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
+ "Cannot initialize register map.\n");
+
+ dev_set_drvdata(dev, priv);
+
+ chip = i2c_get_match_data(client);
+ if (!chip)
+ return -EINVAL;
+ priv->chip = chip;
+
+ ret = mcp9982_parse_fw_config(dev, chip->phys_channels);
+ if (ret)
+ return ret;
+
+ ret = mcp9982_init(dev, priv);
+ if (ret)
+ return ret;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, chip->name, priv,
+ &mcp998x_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id mcp9982_id[] = {
+ { .name = "mcp9933", .driver_data = (kernel_ulong_t)&mcp9933_chip_config },
+ { .name = "mcp9933d", .driver_data = (kernel_ulong_t)&mcp9933d_chip_config },
+ { .name = "mcp9982", .driver_data = (kernel_ulong_t)&mcp9982_chip_config },
+ { .name = "mcp9982d", .driver_data = (kernel_ulong_t)&mcp9982d_chip_config },
+ { .name = "mcp9983", .driver_data = (kernel_ulong_t)&mcp9983_chip_config },
+ { .name = "mcp9983d", .driver_data = (kernel_ulong_t)&mcp9983d_chip_config },
+ { .name = "mcp9984", .driver_data = (kernel_ulong_t)&mcp9984_chip_config },
+ { .name = "mcp9984d", .driver_data = (kernel_ulong_t)&mcp9984d_chip_config },
+ { .name = "mcp9985", .driver_data = (kernel_ulong_t)&mcp9985_chip_config },
+ { .name = "mcp9985d", .driver_data = (kernel_ulong_t)&mcp9985d_chip_config },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mcp9982_id);
+
+static const struct of_device_id mcp9982_of_match[] = {
+ {
+ .compatible = "microchip,mcp9933",
+ .data = &mcp9933_chip_config,
+ }, {
+ .compatible = "microchip,mcp9933d",
+ .data = &mcp9933d_chip_config,
+ }, {
+ .compatible = "microchip,mcp9982",
+ .data = &mcp9982_chip_config,
+ }, {
+ .compatible = "microchip,mcp9982d",
+ .data = &mcp9982d_chip_config,
+ }, {
+ .compatible = "microchip,mcp9983",
+ .data = &mcp9983_chip_config,
+ }, {
+ .compatible = "microchip,mcp9983d",
+ .data = &mcp9983d_chip_config,
+ }, {
+ .compatible = "microchip,mcp9984",
+ .data = &mcp9984_chip_config,
+ }, {
+ .compatible = "microchip,mcp9984d",
+ .data = &mcp9984d_chip_config,
+ }, {
+ .compatible = "microchip,mcp9985",
+ .data = &mcp9985_chip_config,
+ }, {
+ .compatible = "microchip,mcp9985d",
+ .data = &mcp9985d_chip_config,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp9982_of_match);
+
+static struct i2c_driver mcp9982_driver = {
+ .driver = {
+ .name = "mcp9982",
+ .of_match_table = mcp9982_of_match,
+ },
+ .probe = mcp9982_probe,
+ .id_table = mcp9982_id,
+};
+module_i2c_driver(mcp9982_driver);
+
+MODULE_AUTHOR("Victor Duicu <victor.duicu@microchip.com>");
+MODULE_DESCRIPTION("MCP998X/33 and MCP998XD/33D Multichannel Automotive Temperature Monitor Driver");
+MODULE_LICENSE("GPL");
--
2.51.0
^ permalink raw reply related
* [PATCH v12 0/2] add support in hwmon for MCP998X
From: Victor Duicu @ 2026-04-03 13:32 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet
Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, marius.cristea,
victor.duicu
Add support in hwmon for Microchip MCP998X/33 and MCP998XD/33D
Multichannel Automotive Temperature Monitor Family.
The chips in the family have different numbers of external channels,
ranging from 1(MCP9982) to 4 channels (MCP9985).
Reading diodes in anti-parallel connection is supported by MCP9984/85/33
and MCP9984D/85D/33D.
Dedicated hardware shutdown circuitry is present only in MCP998XD
and MCP9933D.
The driver supports reading the temperature channels, the temperature
limits, the limit hysteresis and their corresponding alarms. The user can
set the limits, the update interval and the hysteresis value through
the critical limit hysteresis.
Differences related to previous patch:
v12:
- in devicetree list items in enum.
- make microchip,parasitic-res-on-channel3-4
required only for the "D" chips that are
affected by it.
- in mcp9982.rst rephrase to "device starts
with a 10 degree hysteresis".
- in driver check recd34 is enabled only for
the "D" chips that are affected by it.
- in mcp9982_read() initiate a conversion cycle
only when reading temperature values and alarms.
Use poll function to check the BUSY bit.
- define hyst as unsigned int.
- add comment to clarify that in Standby mode,
after writing in OneShot register 125ms need
to pass before the conversion cycle begins.
- add comment to clarify the behavior of the chip
regarding block read.
- rework the way temperature limits and hysteresis
are written in order to round the result instead
of truncating.
- return regmap_write() directly where applicable.
- in mcp9982_write() use clamp_val().
- in mcp9982_init(), if update interval value is
outside mcp9982_update_interval[] set default
value of 1 second.
- use device_for_each_named_child_node_scoped().
- rephrase some comments.
- link to v11: https://lore.kernel.org/r/20260305-add-mcp9982-hwmon-v11-0-6e914ba63239@microchip.com
v11:
- in devicetree set minItems to interrupts.
- in interrupt-names define both items and remove maxItems.
- in conditionals list the items that must be present.
- in driver in mcp9982_write_limit() calculate regh and regl
at the start of the function.
- link to v10: https://lore.kernel.org/all/20260217-add-mcp9982-hwmon-v10-0-5e0aaae6f289@microchip.com/
v10:
- in devicetree rework interrupt-names.
- rework conditionals to disable the channels that are not used.
- in patternProperties remove minItems from reg and change maxItems to 1.
- in mcp9982.rst fix indentation errors and clarify sysfs entries
regarding limit hysteresis.
- add power state in the list of devicetree parameters.
- in driver change default high and critical temperature limit
value to 85000.
- rework driver to not force wait until the next conversion is done.
Only in Standby state wait the wake up time.
- fix typo in comment about mcp9982_priv.
- remove bitwise operations with mask FF.
- remove clamp_val() from limit hysteresis calculation.
- edit comments regarding block read and write.
- in mcp9982_write_limit() replace bulk write with two writes.
- in mcp9982_write() remove pointless assignment to ret.
- in mcp9982_init() do not override update interval.
- define mcp998x_chip_info as static const struct.
- link to v9: https://lore.kernel.org/all/20260127151823.9728-1-victor.duicu@microchip.com/
v9:
- update copyright year.
- add tempX_max_hyst and tempX_crit_hyst attributes and document
them in mcp9982.rst.
- in include list add byteorder/generic.h and remove unaligned.h.
- remove definitions for temperature memory block
and status memory block.
- remove individual definitions for register addresses 1Dh->21h.
- add constants MCP9982_WAKE_UP_TIME_MAX_US and
MCP9982_TIMER_BUFFER_US.
- add checks to ensure that values read from registers are on 8 bits.
- in mcp9982_read_limit() simplify calculation, replace bulk read
with individual operations and add comment.
- in mcp9982_read_limit() add explicit case branches for limits
that are on 16 bits.
- in mcp9982_read() replace mdelay() with usleep_range().
- in mcp9982_read() replace block reading for temperature values with
individual operations, add comment and remove unnecessary
mask variable.
- in regmap_read_poll_timeout() add final timeout.
- in mcp9982_read_label() remove label check.
- in mcp9982_write_limit() replace put_unaligned_be16() with cpu_to_be16().
- in mcp9982_write_limit() add explicit case branches for limits
that are on 16 bits.
- in mcp9982_init() write default value for diode alert mask register.
- in mcp9982_parse_fw_config() replace E2BIG with EINVAL.
- link to v8: https://lore.kernel.org/all/20251120071248.3767-1-victor.duicu@microchip.com/
v8:
- in Kconfig add select REGMAP_I2C.
- in yaml add power state attribute. For chips with "D" in the name
check that Run mode is set in yaml and driver.
- in the include list: remove cleanup.h, add math.h, minmax.h and
util_macros.h.
- add min, max and crit limits for all channels. These attributes can
be read and written. In mcp9982_init() set default values for limits.
- add alarms for limits.
- edit regmap ranges to add the limit registers.
- when writing update interval, don't force the user to set exact value.
Search for closest valid value.
- in mcp9982_parse_fw_config() check value from fwnode_property_read_u32().
- edit coding style and comments.
- remove constant MCP9982_SCALE.
- rename variable sampl_idx from mcp9982_priv to interval_idx.
- in mcp9982_write() rename variable use_previous_freq
to use_previous_interval.
- link to v7: https://lore.kernel.org/all/20251031155831.42763-1-victor.duicu@microchip.com/
v7:
- send driver to hwmon subsystem.
- include index.rst and mcp9982.rst.
- in microchip,mcp9982.yaml set microchip,parasitic-res-on-channel1-2
and 3-4 to required.
- in mcp9982.c rework read raw, read label and write raw functions.
- remove avail parameters.
- rework sampling frequency to update interval.
- lock running average filter to off.
- rework definition of channels.
- add cache type Maple to mcp9982_regmap_config().
- define constants for the numerical values used.
- in include list add: bitops.h, cleanup.h, device.h, hwmon.h,
time64.h, unaligned.h. Remove iio.h, math64.h, string.h, units.h.
- add explicit definitions for beta and ideality registers.
- add definitions for status memory block registers.
- add mcp9982_is_visible() and set visible only the channels
that are enabled.
- in mcp9982_parse_fw_config() add branch with default values for
systems that do not have devicetree or firmware nodes.
- remove mutex.
- link to v6: https://lore.kernel.org/all/20250930133131.13797-1-victor.duicu@microchip.com/
Differences related to the IIO patch:
v6:
- in yaml first condition list part numbers instead
of regular expression. Add ^ to regular expression.
- edit coding style and comments.
- use hex values in defines.
- remove MCP9982_TEMP_MEM_BLOCK_LOW and
MCP9982_TEMP_MEM_BLOCK_HIGH.
- in MCP9982_CHAN() place macro parameters in ().
- move all variable definitions at the start of functions.
- in mcp9982_parse_fw_config() initialise iio_idx to 0.
- remove bit flags.
- in MCP9982_CHAN remove outer ().
- remove variable start in mcp9982_write_raw().
- replace constant in .max_register.
- use get_unaligned_be16 in mcp9982_read_raw().
- link to v5: https://lore.kernel.org/all/20250918111937.5150-1-victor.duicu@microchip.com/
v5:
- in yaml edit description of interrupts.
- add min and maxItems to reg.
- remove ideality parameter.
- use pattern recognition in conditionals.
- group conditions based on the chip.
- correct microchip,parasitic-res-on-channel3-4 to true.
- in driver include bitops.h.
- change name of some variables.
- rename mcp9982_parse_of_config() to mcp9982_parse_fw_config().
- implement bulk reading of temp registers.
- lock ideality parameter to default value.
- implement bit flags.
- add compound literal to MCP9982_CHAN.
- remove hysteresis parameter.
- edit comments.
- change values from int to bool in mcp9982_features.
- remove mcp9982_calc_all_3db_values() and hardcode values.
When filter is OFF the 3db value is equal to frequency.
- add .max_register to regmap_config.
- remove devm_kcalloc().
- in mcp9982_read_avail() add an else branch to hw_thermal_shutdown
check.
- in mcp9982_read_raw use USEC_PER_MSEC and set regmap_read_poll_timeout
to never timeout.
Replace switch with bitmap_weight.
- in mcp9982_read_label() remove unnecessary if.
- in mcp9982_write_raw() remove duplicated code.
- in mcp9982_init add error messages when APDD and RECD are incorrectly
set.
- in mcp9982_parse_fw_config() add default for reg_nr.
- link to v4: https://lore.kernel.org/all/20250829143447.18893-1-victor.duicu@microchip.com/
v4:
- lock beta parameters to default value of beta-autodetect.
Remove beta parameters and checks from devicetree.
- lock temperature range to extended.
This change avoids the issue of the average filter using raw values
with different scales when changing the range.
- change driver to wait an amount of time before reading a raw value
to ensure it is valid.
- change driver to stop calculating the physical temp when reading
in_tempx_raw. Reading from in_tempx_raw will return the raw value.
The physical temp will be calculated with in_tempx_raw, scale and
offset parameters.
- add scale parameter to channel definition.
- initialise chips with "D" to work in Run state and those without
in Standby state.
- when activating the low pass filter for chips without "D",
set the power state to RUN to ensure fresh values for the average.
- add minimum and maximum to microchip,beta1 and microchip,beta2 in yaml.
- rename microchip,resistance-comp-ch1-2-enable and
microchip,resistance-comp-ch3-4-enable to
microchip,parasitic-res-on-channel1-2
and microchip,parasitic-res-on-channel3-4
and edit description in yaml.
- add conditional logic to check if the chip supports APDD
and force default values where necessary in yaml.
- edit comments and coding style.
- replace asm/div64.h with linux/math64.h.
- add delay.h to includes.
- redefine mcp9982_sampl_fr with new structure division.
- in mcp9982_priv remove dev_name,extended_temp_range and beta_values.
Add run_state, wait_before_read, time_limit and pointer to chip
structure to remove all instances of matching strings.
Reorder parameters for memory optimization.
- in mcp9982_features add flags to know if the chip has thermal shutdown
circuitry and supports APDD.
- in mcp9982_read_avail() rework verification of chip type in sampling
frequency case.
- in mcp9982_read_raw() rework switch in low pass filter case.
- in mcp9982_parse_of_config() replace generic -EINVAL code
with -E2BIG and -EOVERFLOW.
- link to v3: https://lore.kernel.org/all/20250613130207.8560-1-victor.duicu@microchip.com/
v3:
- move beta parameters to devicetree.
- change the name of the interrupts and add
check to match them to the device in yaml.
- remove label for device and remove "0x" from
channel registers in example in yaml.
- edit comments in yaml and driver.
- add minItems to interrupts in yaml.
- rename microchip,recd12 and microchip,recd34 to
microchip,resistance-comp-ch1-2-enable
and microchip,resistance-comp-ch3-4-enable.
- rename microchip,apdd-state to microchip,enable-anti-parallel.
- add static to mcp9982_3db_values_map_tbl to fix
kernel test robot warning.
- in mcp9982_init() add check to ensure that hardware
shutdown feature can't be overridden.
- replace div_u64_rem with do_div and add
asm/div64.h to includes.
- remove unused includes.
- add iio_chan_spec in the macro definition of MCP9982_CHAN.
- remove MCP9982_EXT_BETA_ENBL.
- in mcp9982_init() replace regmap_assign_bits
with regmap_write when setting beta compensation.
- remove custom attribute enable_extended_temp_range and
map it to IIO_CHAN_INFO_OFFSET.
- add unsigned to int variables that allow it.
- reorder parameters in mcp9982_priv, change some
from int to bool, add const to labels and add dev_name.
- add check for chips with "D" in the name to not
allow sampling frequencies lower than 1 to
prevent overriding of hardware shutdown.
- remove mcp9982_attributes.
- move mcp9982_calc_all_3db_values() to before
mcp9982_init().
- use MICRO instead of number constant.
- in mcp9982_write_raw replace ">=" with "==".
- rename index2 to idx in mcp9982_read_raw().
- remove i2c_set_clientdata() in mcp9982_probe().
- since there are no more custom ABI attributes
the testing file was removed.
- link to v2: https://lore.kernel.org/all/20250529093628.15042-1-victor.duicu@microchip.com/
v2:
- move hysteresis, extended temperature range and beta parameters
from devicetree into user space.
- edit comments in yaml and driver.
- remove "|" in descpriptions, remove "+" from PatternProperties in yaml.
- add default to microchip,ideality-factor, delete blank lines and wrap to
80 chars in yaml.
- remove variables with upper case.
- add check for microchip,apdd-state and microchip,recd34 in yaml.
- improve coding style in driver code.
- add includes for all functions used.
- rename MCP9982_INT_HIGH_BYTE_ADDR to MCP9982_INT_VALUE_ADDR and
MCP9982_INT_LOW_BYTE_ADDR to MCP9982_FRAC_VALUE_ADDR.
- remove custom attribute running_average_window and
running_average_window_available and map them to a low pass filter.
- update sysfs-bus-iio-temperature-mcp9982 to reflect current
driver attributes and point to next kernel version (6.17).
- use compound literal to define driver channels.
- replace device_property_read_string() with i2c_get_match_data() to read
chip name from devicetree.
- remove MCP9982_DEV_ATTR and mcp9982_prep_custom_attributes().
- remove client, chip_name, iio_info from mcp9982_priv.
- replace sprintf() with sysfs_emit().
- remove error messages which are triggered by keyboard input.
- replace devm_kzalloc() with devm_kcalloc(), array mcp9982_chip_config[]
with individual structures, device_property_present() with
device_property_read_bool().
- reordered parameters in mcp9982_features and mcp9982_priv to optimize
memory allocation.
- remove .endianness from channel properties.
- change name of some parameters in mcp9982_priv.
- add check for reg value 0 from devicetree (channel 0 is for internal
temperature and can't be disabled).
- link to v1: https://lore.kernel.org/all/20250415132623.14913-1-victor.duicu@microchip.com/
v1:
- initial version.
Signed-off-by: Victor Duicu <victor.duicu@microchip.com>
---
Victor Duicu (2):
dt-bindings: hwmon: add support for MCP998X
hwmon: add support for MCP998X
.../bindings/hwmon/microchip,mcp9982.yaml | 237 +++++
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/mcp9982.rst | 111 +++
MAINTAINERS | 8 +
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/mcp9982.c | 997 +++++++++++++++++++++
7 files changed, 1366 insertions(+)
---
base-commit: 05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
change-id: 20260305-add-mcp9982-hwmon-9ac964ca3191
Best regards,
--
Victor Duicu <victor.duicu@microchip.com>
^ permalink raw reply
* [PATCH 3/3] arm64: defconfig: enable the Qualcomm Nord TLMM driver
From: Bartosz Golaszewski @ 2026-04-03 13:27 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel,
Bartosz Golaszewski
In-Reply-To: <20260403-nord-tlmm-v1-0-4864f400c700@oss.qualcomm.com>
This is required to boot linux on the Nord platforms from Qualcomm.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 163b7f0314c90fc45eb6c4aa5e8faa549c60fdf7..31f8cd7cde6fcc8c8da8e69950dd4976ae04cfc4 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -675,6 +675,7 @@ CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QDU1000=y
CONFIG_PINCTRL_RP1=m
CONFIG_PINCTRL_SA8775P=y
+CONFIG_PINCTRL_NORD=y
CONFIG_PINCTRL_SC7180=y
CONFIG_PINCTRL_SC7280=y
CONFIG_PINCTRL_SC8180X=y
--
2.47.3
^ permalink raw reply related
* [PATCH 2/3] pinctrl: qcom: add the TLMM driver for the Nord platforms
From: Bartosz Golaszewski @ 2026-04-03 13:27 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel,
Bartosz Golaszewski
In-Reply-To: <20260403-nord-tlmm-v1-0-4864f400c700@oss.qualcomm.com>
Add support for the TLMM controller on the Qualcomm Nord platform.
Co-developed-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/pinctrl/qcom/Kconfig.msm | 7 +
drivers/pinctrl/qcom/Makefile | 1 +
drivers/pinctrl/qcom/pinctrl-nord.c | 3297 +++++++++++++++++++++++++++++++++++
3 files changed, 3305 insertions(+)
diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm
index 6df6159fa5f89f9f0470e700b4698dc8849ed515..6698e2a50b2f67b1aadb4a840339e769c92f95f8 100644
--- a/drivers/pinctrl/qcom/Kconfig.msm
+++ b/drivers/pinctrl/qcom/Kconfig.msm
@@ -261,6 +261,13 @@ config PINCTRL_SA8775P
This is the pinctrl, pinmux and pinconf driver for the Qualcomm
TLMM block found on the Qualcomm SA8775P platforms.
+config PINCTRL_NORD
+ tristate "Qualcomm Technologies Inc NORD (SA8797p) pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux and pinconf driver for the Qualcomm
+ TLMM block found on the Qualcomm NORD platforms.
+
config PINCTRL_SAR2130P
tristate "Qualcomm Technologies Inc SAR2130P pin controller driver"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index a8fd12f90d6e6f8e139097cc0a81d6f178f09000..ba6e9408373ff4327bb0c092f1f30889998503a1 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_PINCTRL_MDM9607) += pinctrl-mdm9607.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
obj-$(CONFIG_PINCTRL_MILOS) += pinctrl-milos.o
obj-$(CONFIG_PINCTRL_MILOS_LPASS_LPI) += pinctrl-milos-lpass-lpi.o
+obj-$(CONFIG_PINCTRL_NORD) += pinctrl-nord.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
diff --git a/drivers/pinctrl/qcom/pinctrl-nord.c b/drivers/pinctrl/qcom/pinctrl-nord.c
new file mode 100644
index 0000000000000000000000000000000000000000..82e519abaf75771817a0f811c6af80c4f98e93ed
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-nord.c
@@ -0,0 +1,3297 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#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)), \
+ .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, \
+ .intr_target_reg = 0x8 + 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_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ .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, \
+ }
+
+#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, offset) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .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, \
+ }
+
+#define QUP_I3C(qup_mode, qup_offset) \
+ { \
+ .mode = qup_mode, \
+ .offset = qup_offset, \
+ }
+
+static const struct pinctrl_pin_desc nord_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, "UFS_RESET"),
+};
+
+#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);
+
+static const unsigned int ufs_reset_pins[] = { 181 };
+
+enum nord_functions {
+ msm_mux_gpio,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_char_start,
+ msm_mux_atest_usb20,
+ msm_mux_atest_usb21,
+ msm_mux_aud_intfc0_clk,
+ msm_mux_aud_intfc0_data0,
+ msm_mux_aud_intfc0_data1,
+ msm_mux_aud_intfc0_data2,
+ msm_mux_aud_intfc0_data3,
+ msm_mux_aud_intfc0_data4,
+ msm_mux_aud_intfc0_data5,
+ msm_mux_aud_intfc0_data6,
+ msm_mux_aud_intfc0_data7,
+ msm_mux_aud_intfc0_ws,
+ msm_mux_aud_intfc10_clk,
+ msm_mux_aud_intfc10_data0,
+ msm_mux_aud_intfc10_data1,
+ msm_mux_aud_intfc10_ws,
+ msm_mux_aud_intfc1_clk,
+ msm_mux_aud_intfc1_data0,
+ msm_mux_aud_intfc1_data1,
+ msm_mux_aud_intfc1_data2,
+ msm_mux_aud_intfc1_data3,
+ msm_mux_aud_intfc1_data4,
+ msm_mux_aud_intfc1_data5,
+ msm_mux_aud_intfc1_data6,
+ msm_mux_aud_intfc1_data7,
+ msm_mux_aud_intfc1_ws,
+ msm_mux_aud_intfc2_clk,
+ msm_mux_aud_intfc2_data0,
+ msm_mux_aud_intfc2_data1,
+ msm_mux_aud_intfc2_data2,
+ msm_mux_aud_intfc2_data3,
+ msm_mux_aud_intfc2_ws,
+ msm_mux_aud_intfc3_clk,
+ msm_mux_aud_intfc3_data0,
+ msm_mux_aud_intfc3_data1,
+ msm_mux_aud_intfc3_ws,
+ msm_mux_aud_intfc4_clk,
+ msm_mux_aud_intfc4_data0,
+ msm_mux_aud_intfc4_data1,
+ msm_mux_aud_intfc4_ws,
+ msm_mux_aud_intfc5_clk,
+ msm_mux_aud_intfc5_data0,
+ msm_mux_aud_intfc5_data1,
+ msm_mux_aud_intfc5_ws,
+ msm_mux_aud_intfc6_clk,
+ msm_mux_aud_intfc6_data0,
+ msm_mux_aud_intfc6_data1,
+ msm_mux_aud_intfc6_ws,
+ msm_mux_aud_intfc7_clk,
+ msm_mux_aud_intfc7_data0,
+ msm_mux_aud_intfc7_data1,
+ msm_mux_aud_intfc7_ws,
+ msm_mux_aud_intfc8_clk,
+ msm_mux_aud_intfc8_data0,
+ msm_mux_aud_intfc8_data1,
+ msm_mux_aud_intfc8_ws,
+ msm_mux_aud_intfc9_clk,
+ msm_mux_aud_intfc9_data0,
+ msm_mux_aud_intfc9_ws,
+ msm_mux_aud_mclk0_mira,
+ msm_mux_aud_mclk0_mirb,
+ msm_mux_aud_mclk1_mira,
+ msm_mux_aud_mclk1_mirb,
+ msm_mux_aud_mclk2_mira,
+ msm_mux_aud_mclk2_mirb,
+ msm_mux_aud_refclk0,
+ msm_mux_aud_refclk1,
+ msm_mux_bist_done,
+ msm_mux_ccu_async_in0,
+ msm_mux_ccu_async_in1,
+ msm_mux_ccu_async_in2,
+ msm_mux_ccu_async_in3,
+ msm_mux_ccu_async_in4,
+ msm_mux_ccu_async_in5,
+ msm_mux_ccu_i2c_scl0,
+ msm_mux_ccu_i2c_scl1,
+ msm_mux_ccu_i2c_scl2,
+ msm_mux_ccu_i2c_scl3,
+ msm_mux_ccu_i2c_scl4,
+ msm_mux_ccu_i2c_scl5,
+ msm_mux_ccu_i2c_scl6,
+ msm_mux_ccu_i2c_scl7,
+ msm_mux_ccu_i2c_scl8,
+ msm_mux_ccu_i2c_scl9,
+ msm_mux_ccu_i2c_sda0,
+ msm_mux_ccu_i2c_sda1,
+ msm_mux_ccu_i2c_sda2,
+ msm_mux_ccu_i2c_sda3,
+ msm_mux_ccu_i2c_sda4,
+ msm_mux_ccu_i2c_sda5,
+ msm_mux_ccu_i2c_sda6,
+ msm_mux_ccu_i2c_sda7,
+ msm_mux_ccu_i2c_sda8,
+ msm_mux_ccu_i2c_sda9,
+ msm_mux_ccu_timer0,
+ msm_mux_ccu_timer1,
+ msm_mux_ccu_timer10,
+ msm_mux_ccu_timer11,
+ msm_mux_ccu_timer12,
+ msm_mux_ccu_timer13,
+ msm_mux_ccu_timer14,
+ msm_mux_ccu_timer15,
+ msm_mux_ccu_timer2,
+ msm_mux_ccu_timer3,
+ msm_mux_ccu_timer4,
+ msm_mux_ccu_timer5,
+ msm_mux_ccu_timer6,
+ msm_mux_ccu_timer7,
+ msm_mux_ccu_timer8,
+ msm_mux_ccu_timer9,
+ msm_mux_clink_debug,
+ msm_mux_dbg_out,
+ msm_mux_dbg_out_clk,
+ msm_mux_ddr_bist_complete,
+ msm_mux_ddr_bist_fail,
+ msm_mux_ddr_bist_start,
+ msm_mux_ddr_bist_stop,
+ msm_mux_ddr_pxi0,
+ msm_mux_ddr_pxi1,
+ msm_mux_ddr_pxi10,
+ msm_mux_ddr_pxi11,
+ msm_mux_ddr_pxi12,
+ msm_mux_ddr_pxi13,
+ msm_mux_ddr_pxi14,
+ msm_mux_ddr_pxi15,
+ msm_mux_ddr_pxi2,
+ msm_mux_ddr_pxi3,
+ msm_mux_ddr_pxi4,
+ msm_mux_ddr_pxi5,
+ msm_mux_ddr_pxi6,
+ msm_mux_ddr_pxi7,
+ msm_mux_ddr_pxi8,
+ msm_mux_ddr_pxi9,
+ msm_mux_dp_rx0,
+ msm_mux_dp_rx00,
+ msm_mux_dp_rx01,
+ msm_mux_dp_rx0_mute,
+ msm_mux_dp_rx1,
+ msm_mux_dp_rx10,
+ msm_mux_dp_rx11,
+ msm_mux_dp_rx1_mute,
+ msm_mux_edp0_hot,
+ msm_mux_edp0_lcd,
+ msm_mux_edp1_hot,
+ msm_mux_edp1_lcd,
+ msm_mux_edp2_hot,
+ msm_mux_edp2_lcd,
+ msm_mux_edp3_hot,
+ msm_mux_edp3_lcd,
+ msm_mux_emac0_mcg0,
+ msm_mux_emac0_mcg1,
+ msm_mux_emac0_mcg2,
+ msm_mux_emac0_mcg3,
+ msm_mux_emac0_mdc,
+ msm_mux_emac0_mdio,
+ msm_mux_emac0_ptp,
+ msm_mux_emac1_mcg0,
+ msm_mux_emac1_mcg1,
+ msm_mux_emac1_mcg2,
+ msm_mux_emac1_mcg3,
+ msm_mux_emac1_mdc,
+ msm_mux_emac1_mdio,
+ msm_mux_emac1_ptp,
+ msm_mux_gcc_gp1_clk,
+ msm_mux_gcc_gp2_clk,
+ msm_mux_gcc_gp3_clk,
+ msm_mux_gcc_gp4_clk,
+ msm_mux_gcc_gp5_clk,
+ msm_mux_gcc_gp6_clk,
+ msm_mux_gcc_gp7_clk,
+ msm_mux_gcc_gp8_clk,
+ msm_mux_jitter_bist,
+ msm_mux_lbist_pass,
+ msm_mux_mbist_pass,
+ msm_mux_mdp0_vsync0_out,
+ msm_mux_mdp0_vsync10_out,
+ msm_mux_mdp0_vsync1_out,
+ msm_mux_mdp0_vsync2_out,
+ msm_mux_mdp0_vsync3_out,
+ msm_mux_mdp0_vsync4_out,
+ msm_mux_mdp0_vsync5_out,
+ msm_mux_mdp0_vsync6_out,
+ msm_mux_mdp0_vsync7_out,
+ msm_mux_mdp0_vsync8_out,
+ msm_mux_mdp0_vsync9_out,
+ msm_mux_mdp1_vsync0_out,
+ msm_mux_mdp1_vsync10_out,
+ msm_mux_mdp1_vsync1_out,
+ msm_mux_mdp1_vsync2_out,
+ msm_mux_mdp1_vsync3_out,
+ msm_mux_mdp1_vsync4_out,
+ msm_mux_mdp1_vsync5_out,
+ msm_mux_mdp1_vsync6_out,
+ msm_mux_mdp1_vsync7_out,
+ msm_mux_mdp1_vsync8_out,
+ msm_mux_mdp1_vsync9_out,
+ msm_mux_mdp_vsync_e,
+ msm_mux_mdp_vsync_p,
+ msm_mux_mdp_vsync_s,
+ msm_mux_pcie0_clk_req_n,
+ msm_mux_pcie1_clk_req_n,
+ msm_mux_pcie2_clk_req_n,
+ msm_mux_pcie3_clk_req_n,
+ msm_mux_phase_flag0,
+ msm_mux_phase_flag1,
+ msm_mux_phase_flag10,
+ msm_mux_phase_flag11,
+ msm_mux_phase_flag12,
+ msm_mux_phase_flag13,
+ msm_mux_phase_flag14,
+ msm_mux_phase_flag15,
+ msm_mux_phase_flag16,
+ msm_mux_phase_flag17,
+ msm_mux_phase_flag18,
+ msm_mux_phase_flag19,
+ msm_mux_phase_flag2,
+ msm_mux_phase_flag20,
+ msm_mux_phase_flag21,
+ msm_mux_phase_flag22,
+ msm_mux_phase_flag23,
+ msm_mux_phase_flag24,
+ msm_mux_phase_flag25,
+ msm_mux_phase_flag26,
+ msm_mux_phase_flag27,
+ msm_mux_phase_flag28,
+ msm_mux_phase_flag29,
+ msm_mux_phase_flag3,
+ msm_mux_phase_flag30,
+ msm_mux_phase_flag31,
+ msm_mux_phase_flag4,
+ msm_mux_phase_flag5,
+ msm_mux_phase_flag6,
+ msm_mux_phase_flag7,
+ msm_mux_phase_flag8,
+ msm_mux_phase_flag9,
+ msm_mux_pll_bist_sync,
+ msm_mux_pll_clk_aux,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_pwrbrk_i_n,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_gpio,
+ msm_mux_qdss_gpio0,
+ msm_mux_qdss_gpio1,
+ msm_mux_qdss_gpio10,
+ msm_mux_qdss_gpio11,
+ msm_mux_qdss_gpio12,
+ msm_mux_qdss_gpio13,
+ msm_mux_qdss_gpio14,
+ msm_mux_qdss_gpio15,
+ msm_mux_qdss_gpio2,
+ msm_mux_qdss_gpio3,
+ msm_mux_qdss_gpio4,
+ msm_mux_qdss_gpio5,
+ msm_mux_qdss_gpio6,
+ msm_mux_qdss_gpio7,
+ msm_mux_qdss_gpio8,
+ msm_mux_qdss_gpio9,
+ msm_mux_qspi0,
+ msm_mux_qspi1,
+ msm_mux_qspi2,
+ msm_mux_qspi3,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs0_n,
+ msm_mux_qspi_cs1_n,
+ msm_mux_qup0_se0_l0,
+ msm_mux_qup0_se0_l1,
+ msm_mux_qup0_se0_l2,
+ msm_mux_qup0_se0_l3,
+ msm_mux_qup0_se1_l0,
+ msm_mux_qup0_se1_l1,
+ msm_mux_qup0_se1_l2,
+ msm_mux_qup0_se1_l3,
+ msm_mux_qup0_se2_l0,
+ msm_mux_qup0_se2_l1,
+ msm_mux_qup0_se2_l2,
+ msm_mux_qup0_se2_l3,
+ msm_mux_qup0_se3_l0,
+ msm_mux_qup0_se3_l1,
+ msm_mux_qup0_se3_l2,
+ msm_mux_qup0_se3_l3,
+ msm_mux_qup0_se4_l0,
+ msm_mux_qup0_se4_l1,
+ msm_mux_qup0_se4_l2,
+ msm_mux_qup0_se4_l3,
+ msm_mux_qup0_se5_l0,
+ msm_mux_qup0_se5_l1,
+ msm_mux_qup0_se5_l2,
+ msm_mux_qup0_se5_l3,
+ msm_mux_qup1_se0_l0,
+ msm_mux_qup1_se0_l1,
+ msm_mux_qup1_se0_l2,
+ msm_mux_qup1_se0_l3,
+ msm_mux_qup1_se1_l0,
+ msm_mux_qup1_se1_l1,
+ msm_mux_qup1_se1_l2,
+ msm_mux_qup1_se1_l3,
+ msm_mux_qup1_se2_l0,
+ msm_mux_qup1_se2_l1,
+ msm_mux_qup1_se2_l2,
+ msm_mux_qup1_se2_l3,
+ msm_mux_qup1_se3_l0,
+ msm_mux_qup1_se3_l1,
+ msm_mux_qup1_se3_l2,
+ msm_mux_qup1_se3_l3,
+ msm_mux_qup1_se4_l0,
+ msm_mux_qup1_se4_l1,
+ msm_mux_qup1_se4_l2,
+ msm_mux_qup1_se4_l3,
+ msm_mux_qup1_se5_l0,
+ msm_mux_qup1_se5_l1,
+ msm_mux_qup1_se5_l2,
+ msm_mux_qup1_se5_l3,
+ msm_mux_qup1_se6_l0,
+ msm_mux_qup1_se6_l1,
+ msm_mux_qup1_se6_l2,
+ msm_mux_qup1_se6_l3,
+ msm_mux_qup2_se0_l0,
+ msm_mux_qup2_se0_l1,
+ msm_mux_qup2_se0_l2,
+ msm_mux_qup2_se0_l3,
+ msm_mux_qup2_se1_l0,
+ msm_mux_qup2_se1_l1,
+ msm_mux_qup2_se1_l2,
+ msm_mux_qup2_se1_l3,
+ msm_mux_qup2_se2_l0,
+ msm_mux_qup2_se2_l1,
+ msm_mux_qup2_se2_l2,
+ msm_mux_qup2_se2_l3,
+ msm_mux_qup2_se2_l4,
+ msm_mux_qup2_se3_l0,
+ msm_mux_qup2_se3_l1,
+ msm_mux_qup2_se3_l2,
+ msm_mux_qup2_se3_l3,
+ msm_mux_qup2_se4_l0,
+ msm_mux_qup2_se4_l1,
+ msm_mux_qup2_se4_l2,
+ msm_mux_qup2_se4_l3,
+ msm_mux_qup2_se4_l4,
+ msm_mux_qup2_se4_l5,
+ msm_mux_qup2_se4_l6,
+ msm_mux_qup2_se5_l0,
+ msm_mux_qup2_se5_l1,
+ msm_mux_qup2_se5_l2,
+ msm_mux_qup2_se5_l3,
+ msm_mux_qup2_se6_l0,
+ msm_mux_qup2_se6_l1,
+ msm_mux_qup2_se6_l2,
+ msm_mux_qup2_se6_l3,
+ msm_mux_qup3_se0_l0_mira,
+ msm_mux_qup3_se0_l0_mirb,
+ msm_mux_qup3_se0_l1_mira,
+ msm_mux_qup3_se0_l1_mirb,
+ msm_mux_qup3_se0_l2,
+ msm_mux_qup3_se0_l3,
+ msm_mux_qup3_se0_l4,
+ msm_mux_qup3_se0_l5,
+ msm_mux_qup3_se0_l6,
+ msm_mux_sailss_ospi,
+ msm_mux_sdc4_clk,
+ msm_mux_sdc4_cmd,
+ msm_mux_sdc4_data,
+ msm_mux_smb_alert,
+ msm_mux_smb_alert_n,
+ msm_mux_smb_clk,
+ msm_mux_smb_dat,
+ msm_mux_tb_trig_sdc4,
+ msm_mux_tmess_prng0,
+ msm_mux_tmess_prng1,
+ msm_mux_tsc_timer0,
+ msm_mux_tsc_timer1,
+ msm_mux_tsc_timer2,
+ msm_mux_tsc_timer3,
+ msm_mux_tsc_timer4,
+ msm_mux_tsc_timer5,
+ msm_mux_tsc_timer6,
+ msm_mux_tsc_timer7,
+ msm_mux_tsc_timer8,
+ msm_mux_tsc_timer9,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_tsense_pwm3,
+ msm_mux_tsense_pwm4,
+ msm_mux_tsense_pwm5,
+ msm_mux_tsense_pwm6,
+ msm_mux_tsense_pwm7,
+ msm_mux_tsense_pwm8,
+ msm_mux_usb0_hs,
+ msm_mux_usb0_phy_ps,
+ msm_mux_usb1_hs,
+ msm_mux_usb1_phy_ps,
+ msm_mux_usb2_hs,
+ msm_mux_usxgmii0_phy,
+ msm_mux_usxgmii1_phy,
+ msm_mux_vsense_trigger_mirnat,
+ msm_mux_wcn_sw,
+ 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",
+};
+
+static const char *const aoss_cti_groups[] = {
+ "gpio83",
+ "gpio84",
+ "gpio85",
+ "gpio86",
+};
+
+static const char *const atest_char0_groups[] = {
+ "gpio177",
+};
+
+static const char *const atest_char1_groups[] = {
+ "gpio178",
+};
+
+static const char *const atest_char2_groups[] = {
+ "gpio179",
+};
+
+static const char *const atest_char3_groups[] = {
+ "gpio180",
+};
+
+static const char *const atest_char_start_groups[] = {
+ "gpio176",
+};
+
+static const char *const atest_usb20_groups[] = {
+ "gpio126",
+ "gpio128",
+ "gpio130",
+};
+
+static const char *const atest_usb21_groups[] = {
+ "gpio127",
+ "gpio129",
+ "gpio131",
+};
+
+static const char *const aud_intfc0_clk_groups[] = {
+ "gpio57",
+};
+
+static const char *const aud_intfc0_data0_groups[] = {
+ "gpio59",
+};
+
+static const char *const aud_intfc0_data1_groups[] = {
+ "gpio60",
+};
+
+static const char *const aud_intfc0_data2_groups[] = {
+ "gpio61",
+};
+
+static const char *const aud_intfc0_data3_groups[] = {
+ "gpio62",
+};
+
+static const char *const aud_intfc0_data4_groups[] = {
+ "gpio63",
+};
+
+static const char *const aud_intfc0_data5_groups[] = {
+ "gpio64",
+};
+
+static const char *const aud_intfc0_data6_groups[] = {
+ "gpio65",
+};
+
+static const char *const aud_intfc0_data7_groups[] = {
+ "gpio66",
+};
+
+static const char *const aud_intfc0_ws_groups[] = {
+ "gpio58",
+};
+
+static const char *const aud_intfc10_clk_groups[] = {
+ "gpio61",
+};
+
+static const char *const aud_intfc10_data0_groups[] = {
+ "gpio81",
+};
+
+static const char *const aud_intfc10_data1_groups[] = {
+ "gpio82",
+};
+
+static const char *const aud_intfc10_ws_groups[] = {
+ "gpio62",
+};
+
+static const char *const aud_intfc1_clk_groups[] = {
+ "gpio67",
+};
+
+static const char *const aud_intfc1_data0_groups[] = {
+ "gpio69",
+};
+
+static const char *const aud_intfc1_data1_groups[] = {
+ "gpio70",
+};
+
+static const char *const aud_intfc1_data2_groups[] = {
+ "gpio71",
+};
+
+static const char *const aud_intfc1_data3_groups[] = {
+ "gpio72",
+};
+
+static const char *const aud_intfc1_data4_groups[] = {
+ "gpio73",
+};
+
+static const char *const aud_intfc1_data5_groups[] = {
+ "gpio74",
+};
+
+static const char *const aud_intfc1_data6_groups[] = {
+ "gpio75",
+};
+
+static const char *const aud_intfc1_data7_groups[] = {
+ "gpio76",
+};
+
+static const char *const aud_intfc1_ws_groups[] = {
+ "gpio68",
+};
+
+static const char *const aud_intfc2_clk_groups[] = {
+ "gpio77",
+};
+
+static const char *const aud_intfc2_data0_groups[] = {
+ "gpio79",
+};
+
+static const char *const aud_intfc2_data1_groups[] = {
+ "gpio80",
+};
+
+static const char *const aud_intfc2_data2_groups[] = {
+ "gpio81",
+};
+
+static const char *const aud_intfc2_data3_groups[] = {
+ "gpio82",
+};
+
+static const char *const aud_intfc2_ws_groups[] = {
+ "gpio78",
+};
+
+static const char *const aud_intfc3_clk_groups[] = {
+ "gpio83",
+};
+
+static const char *const aud_intfc3_data0_groups[] = {
+ "gpio85",
+};
+
+static const char *const aud_intfc3_data1_groups[] = {
+ "gpio86",
+};
+
+static const char *const aud_intfc3_ws_groups[] = {
+ "gpio84",
+};
+
+static const char *const aud_intfc4_clk_groups[] = {
+ "gpio87",
+};
+
+static const char *const aud_intfc4_data0_groups[] = {
+ "gpio89",
+};
+
+static const char *const aud_intfc4_data1_groups[] = {
+ "gpio90",
+};
+
+static const char *const aud_intfc4_ws_groups[] = {
+ "gpio88",
+};
+
+static const char *const aud_intfc5_clk_groups[] = {
+ "gpio91",
+};
+
+static const char *const aud_intfc5_data0_groups[] = {
+ "gpio93",
+};
+
+static const char *const aud_intfc5_data1_groups[] = {
+ "gpio94",
+};
+
+static const char *const aud_intfc5_ws_groups[] = {
+ "gpio92",
+};
+
+static const char *const aud_intfc6_clk_groups[] = {
+ "gpio95",
+};
+
+static const char *const aud_intfc6_data0_groups[] = {
+ "gpio97",
+};
+
+static const char *const aud_intfc6_data1_groups[] = {
+ "gpio98",
+};
+
+static const char *const aud_intfc6_ws_groups[] = {
+ "gpio96",
+};
+
+static const char *const aud_intfc7_clk_groups[] = {
+ "gpio63",
+};
+
+static const char *const aud_intfc7_data0_groups[] = {
+ "gpio65",
+};
+
+static const char *const aud_intfc7_data1_groups[] = {
+ "gpio66",
+};
+
+static const char *const aud_intfc7_ws_groups[] = {
+ "gpio64",
+};
+
+static const char *const aud_intfc8_clk_groups[] = {
+ "gpio73",
+};
+
+static const char *const aud_intfc8_data0_groups[] = {
+ "gpio75",
+};
+
+static const char *const aud_intfc8_data1_groups[] = {
+ "gpio76",
+};
+
+static const char *const aud_intfc8_ws_groups[] = {
+ "gpio74",
+};
+
+static const char *const aud_intfc9_clk_groups[] = {
+ "gpio70",
+};
+
+static const char *const aud_intfc9_data0_groups[] = {
+ "gpio72",
+};
+
+static const char *const aud_intfc9_ws_groups[] = {
+ "gpio71",
+};
+
+static const char *const aud_mclk0_mira_groups[] = {
+ "gpio99",
+};
+
+static const char *const aud_mclk0_mirb_groups[] = {
+ "gpio86",
+};
+
+static const char *const aud_mclk1_mira_groups[] = {
+ "gpio100",
+};
+
+static const char *const aud_mclk1_mirb_groups[] = {
+ "gpio90",
+};
+
+static const char *const aud_mclk2_mira_groups[] = {
+ "gpio101",
+};
+
+static const char *const aud_mclk2_mirb_groups[] = {
+ "gpio94",
+};
+
+static const char *const aud_refclk0_groups[] = {
+ "gpio100",
+};
+
+static const char *const aud_refclk1_groups[] = {
+ "gpio101",
+};
+
+static const char *const bist_done_groups[] = {
+ "gpio168",
+};
+
+static const char *const ccu_async_in0_groups[] = {
+ "gpio176",
+};
+
+static const char *const ccu_async_in1_groups[] = {
+ "gpio177",
+};
+
+static const char *const ccu_async_in2_groups[] = {
+ "gpio178",
+};
+
+static const char *const ccu_async_in3_groups[] = {
+ "gpio179",
+};
+
+static const char *const ccu_async_in4_groups[] = {
+ "gpio180",
+};
+
+static const char *const ccu_async_in5_groups[] = {
+ "gpio45",
+};
+
+static const char *const ccu_i2c_scl0_groups[] = {
+ "gpio16",
+};
+
+static const char *const ccu_i2c_scl1_groups[] = {
+ "gpio18",
+};
+
+static const char *const ccu_i2c_scl2_groups[] = {
+ "gpio20",
+};
+
+static const char *const ccu_i2c_scl3_groups[] = {
+ "gpio22",
+};
+
+static const char *const ccu_i2c_scl4_groups[] = {
+ "gpio24",
+};
+
+static const char *const ccu_i2c_scl5_groups[] = {
+ "gpio114",
+};
+
+static const char *const ccu_i2c_scl6_groups[] = {
+ "gpio116",
+};
+
+static const char *const ccu_i2c_scl7_groups[] = {
+ "gpio126",
+};
+
+static const char *const ccu_i2c_scl8_groups[] = {
+ "gpio130",
+};
+
+static const char *const ccu_i2c_scl9_groups[] = {
+ "gpio132",
+};
+
+static const char *const ccu_i2c_sda0_groups[] = {
+ "gpio15",
+};
+
+static const char *const ccu_i2c_sda1_groups[] = {
+ "gpio17",
+};
+
+static const char *const ccu_i2c_sda2_groups[] = {
+ "gpio19",
+};
+
+static const char *const ccu_i2c_sda3_groups[] = {
+ "gpio21",
+};
+
+static const char *const ccu_i2c_sda4_groups[] = {
+ "gpio23",
+};
+
+static const char *const ccu_i2c_sda5_groups[] = {
+ "gpio113",
+};
+
+static const char *const ccu_i2c_sda6_groups[] = {
+ "gpio115",
+};
+
+static const char *const ccu_i2c_sda7_groups[] = {
+ "gpio125",
+};
+
+static const char *const ccu_i2c_sda8_groups[] = {
+ "gpio129",
+};
+
+static const char *const ccu_i2c_sda9_groups[] = {
+ "gpio131",
+};
+
+static const char *const ccu_timer0_groups[] = {
+ "gpio25",
+};
+
+static const char *const ccu_timer1_groups[] = {
+ "gpio26",
+};
+
+static const char *const ccu_timer10_groups[] = {
+ "gpio143",
+};
+
+static const char *const ccu_timer11_groups[] = {
+ "gpio144",
+};
+
+static const char *const ccu_timer12_groups[] = {
+ "gpio150",
+};
+
+static const char *const ccu_timer13_groups[] = {
+ "gpio151",
+};
+
+static const char *const ccu_timer14_groups[] = {
+ "gpio152",
+};
+
+static const char *const ccu_timer15_groups[] = {
+ "gpio153",
+};
+
+static const char *const ccu_timer2_groups[] = {
+ "gpio27",
+};
+
+static const char *const ccu_timer3_groups[] = {
+ "gpio28",
+};
+
+static const char *const ccu_timer4_groups[] = {
+ "gpio29",
+};
+
+static const char *const ccu_timer5_groups[] = {
+ "gpio30",
+};
+
+static const char *const ccu_timer6_groups[] = {
+ "gpio31",
+};
+
+static const char *const ccu_timer7_groups[] = {
+ "gpio32",
+};
+
+static const char *const ccu_timer8_groups[] = {
+ "gpio33",
+};
+
+static const char *const ccu_timer9_groups[] = {
+ "gpio34",
+};
+
+static const char *const clink_debug_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio51",
+ "gpio52", "gpio53", "gpio54", "gpio55",
+};
+
+static const char *const dbg_out_groups[] = {
+ "gpio113",
+};
+
+static const char *const dbg_out_clk_groups[] = {
+ "gpio165",
+};
+
+static const char *const ddr_bist_complete_groups[] = {
+ "gpio37",
+};
+
+static const char *const ddr_bist_fail_groups[] = {
+ "gpio39",
+};
+
+static const char *const ddr_bist_start_groups[] = {
+ "gpio36",
+};
+
+static const char *const ddr_bist_stop_groups[] = {
+ "gpio38",
+};
+
+static const char *const ddr_pxi0_groups[] = {
+ "gpio99",
+ "gpio100",
+};
+
+static const char *const ddr_pxi1_groups[] = {
+ "gpio109",
+ "gpio110",
+};
+
+static const char *const ddr_pxi10_groups[] = {
+ "gpio130",
+ "gpio131",
+};
+
+static const char *const ddr_pxi11_groups[] = {
+ "gpio132",
+ "gpio133",
+};
+
+static const char *const ddr_pxi12_groups[] = {
+ "gpio134",
+ "gpio135",
+};
+
+static const char *const ddr_pxi13_groups[] = {
+ "gpio136",
+ "gpio137",
+};
+
+static const char *const ddr_pxi14_groups[] = {
+ "gpio138",
+ "gpio139",
+};
+
+static const char *const ddr_pxi15_groups[] = {
+ "gpio162",
+ "gpio163",
+};
+
+static const char *const ddr_pxi2_groups[] = {
+ "gpio113",
+ "gpio114",
+};
+
+static const char *const ddr_pxi3_groups[] = {
+ "gpio115",
+ "gpio116",
+};
+
+static const char *const ddr_pxi4_groups[] = {
+ "gpio117",
+ "gpio118",
+};
+
+static const char *const ddr_pxi5_groups[] = {
+ "gpio164",
+ "gpio165",
+};
+
+static const char *const ddr_pxi6_groups[] = {
+ "gpio119",
+ "gpio120",
+};
+
+static const char *const ddr_pxi7_groups[] = {
+ "gpio121",
+ "gpio122",
+};
+
+static const char *const ddr_pxi8_groups[] = {
+ "gpio126",
+ "gpio127",
+};
+
+static const char *const ddr_pxi9_groups[] = {
+ "gpio128",
+ "gpio129",
+};
+
+static const char *const dp_rx0_groups[] = {
+ "gpio55", "gpio83", "gpio84", "gpio85", "gpio86",
+ "gpio88", "gpio89", "gpio137", "gpio138",
+};
+
+static const char *const dp_rx00_groups[] = {
+ "gpio99",
+};
+
+static const char *const dp_rx01_groups[] = {
+ "gpio100",
+};
+
+static const char *const dp_rx0_mute_groups[] = {
+ "gpio35",
+};
+
+static const char *const dp_rx1_groups[] = {
+ "gpio56", "gpio92", "gpio93", "gpio95", "gpio96",
+ "gpio97", "gpio98", "gpio158", "gpio159",
+};
+
+static const char *const dp_rx10_groups[] = {
+ "gpio121",
+};
+
+static const char *const dp_rx11_groups[] = {
+ "gpio122",
+};
+
+static const char *const dp_rx1_mute_groups[] = {
+ "gpio36",
+};
+
+static const char *const edp0_hot_groups[] = {
+ "gpio51",
+};
+
+static const char *const edp0_lcd_groups[] = {
+ "gpio47",
+};
+
+static const char *const edp1_hot_groups[] = {
+ "gpio52",
+};
+
+static const char *const edp1_lcd_groups[] = {
+ "gpio48",
+};
+
+static const char *const edp2_hot_groups[] = {
+ "gpio53",
+};
+
+static const char *const edp2_lcd_groups[] = {
+ "gpio49",
+};
+
+static const char *const edp3_hot_groups[] = {
+ "gpio54",
+};
+
+static const char *const edp3_lcd_groups[] = {
+ "gpio50",
+};
+
+static const char *const emac0_mcg0_groups[] = {
+ "gpio16",
+};
+
+static const char *const emac0_mcg1_groups[] = {
+ "gpio17",
+};
+
+static const char *const emac0_mcg2_groups[] = {
+ "gpio18",
+};
+
+static const char *const emac0_mcg3_groups[] = {
+ "gpio19",
+};
+
+static const char *const emac0_mdc_groups[] = {
+ "gpio47",
+};
+
+static const char *const emac0_mdio_groups[] = {
+ "gpio48",
+};
+
+static const char *const emac0_ptp_groups[] = {
+ "gpio133", "gpio134", "gpio135", "gpio136",
+ "gpio139", "gpio140", "gpio141", "gpio142",
+};
+
+static const char *const emac1_mcg0_groups[] = {
+ "gpio20",
+};
+
+static const char *const emac1_mcg1_groups[] = {
+ "gpio21",
+};
+
+static const char *const emac1_mcg2_groups[] = {
+ "gpio22",
+};
+
+static const char *const emac1_mcg3_groups[] = {
+ "gpio23",
+};
+
+static const char *const emac1_mdc_groups[] = {
+ "gpio49",
+};
+
+static const char *const emac1_mdio_groups[] = {
+ "gpio50",
+};
+
+static const char *const emac1_ptp_groups[] = {
+ "gpio37", "gpio38", "gpio39", "gpio40",
+ "gpio41", "gpio42", "gpio43", "gpio44",
+};
+
+static const char *const gcc_gp1_clk_groups[] = {
+ "gpio51",
+};
+
+static const char *const gcc_gp2_clk_groups[] = {
+ "gpio52",
+};
+
+static const char *const gcc_gp3_clk_groups[] = {
+ "gpio42",
+};
+
+static const char *const gcc_gp4_clk_groups[] = {
+ "gpio43",
+};
+
+static const char *const gcc_gp5_clk_groups[] = {
+ "gpio105",
+};
+
+static const char *const gcc_gp6_clk_groups[] = {
+ "gpio106",
+};
+
+static const char *const gcc_gp7_clk_groups[] = {
+ "gpio13",
+};
+
+static const char *const gcc_gp8_clk_groups[] = {
+ "gpio14",
+};
+
+static const char *const jitter_bist_groups[] = {
+ "gpio123",
+ "gpio138",
+};
+
+static const char *const lbist_pass_groups[] = {
+ "gpio121",
+};
+
+static const char *const mbist_pass_groups[] = {
+ "gpio122",
+};
+
+static const char *const mdp0_vsync0_out_groups[] = {
+ "gpio113",
+};
+
+static const char *const mdp0_vsync10_out_groups[] = {
+ "gpio143",
+};
+
+static const char *const mdp0_vsync1_out_groups[] = {
+ "gpio114",
+};
+
+static const char *const mdp0_vsync2_out_groups[] = {
+ "gpio115",
+};
+
+static const char *const mdp0_vsync3_out_groups[] = {
+ "gpio116",
+};
+
+static const char *const mdp0_vsync4_out_groups[] = {
+ "gpio121",
+};
+
+static const char *const mdp0_vsync5_out_groups[] = {
+ "gpio122",
+};
+
+static const char *const mdp0_vsync6_out_groups[] = {
+ "gpio139",
+};
+
+static const char *const mdp0_vsync7_out_groups[] = {
+ "gpio140",
+};
+
+static const char *const mdp0_vsync8_out_groups[] = {
+ "gpio141",
+};
+
+static const char *const mdp0_vsync9_out_groups[] = {
+ "gpio142",
+};
+
+static const char *const mdp1_vsync0_out_groups[] = {
+ "gpio123",
+};
+
+static const char *const mdp1_vsync10_out_groups[] = {
+ "gpio135",
+};
+
+static const char *const mdp1_vsync1_out_groups[] = {
+ "gpio124",
+};
+
+static const char *const mdp1_vsync2_out_groups[] = {
+ "gpio125",
+};
+
+static const char *const mdp1_vsync3_out_groups[] = {
+ "gpio126",
+};
+
+static const char *const mdp1_vsync4_out_groups[] = {
+ "gpio129",
+};
+
+static const char *const mdp1_vsync5_out_groups[] = {
+ "gpio130",
+};
+
+static const char *const mdp1_vsync6_out_groups[] = {
+ "gpio131",
+};
+
+static const char *const mdp1_vsync7_out_groups[] = {
+ "gpio132",
+};
+
+static const char *const mdp1_vsync8_out_groups[] = {
+ "gpio133",
+};
+
+static const char *const mdp1_vsync9_out_groups[] = {
+ "gpio134",
+};
+
+static const char *const mdp_vsync_e_groups[] = {
+ "gpio109",
+};
+
+static const char *const mdp_vsync_p_groups[] = {
+ "gpio110",
+};
+
+static const char *const mdp_vsync_s_groups[] = {
+ "gpio144",
+};
+
+static const char *const pcie0_clk_req_n_groups[] = {
+ "gpio1",
+};
+
+static const char *const pcie1_clk_req_n_groups[] = {
+ "gpio4",
+};
+
+static const char *const pcie2_clk_req_n_groups[] = {
+ "gpio7",
+};
+
+static const char *const pcie3_clk_req_n_groups[] = {
+ "gpio10",
+};
+
+static const char *const phase_flag0_groups[] = {
+ "gpio98",
+};
+
+static const char *const phase_flag1_groups[] = {
+ "gpio82",
+};
+
+static const char *const phase_flag10_groups[] = {
+ "gpio90",
+};
+
+static const char *const phase_flag11_groups[] = {
+ "gpio91",
+};
+
+static const char *const phase_flag12_groups[] = {
+ "gpio92",
+};
+
+static const char *const phase_flag13_groups[] = {
+ "gpio93",
+};
+
+static const char *const phase_flag14_groups[] = {
+ "gpio94",
+};
+
+static const char *const phase_flag15_groups[] = {
+ "gpio95",
+};
+
+static const char *const phase_flag16_groups[] = {
+ "gpio96",
+};
+
+static const char *const phase_flag17_groups[] = {
+ "gpio101",
+};
+
+static const char *const phase_flag18_groups[] = {
+ "gpio67",
+};
+
+static const char *const phase_flag19_groups[] = {
+ "gpio68",
+};
+
+static const char *const phase_flag2_groups[] = {
+ "gpio81",
+};
+
+static const char *const phase_flag20_groups[] = {
+ "gpio69",
+};
+
+static const char *const phase_flag21_groups[] = {
+ "gpio70",
+};
+
+static const char *const phase_flag22_groups[] = {
+ "gpio71",
+};
+
+static const char *const phase_flag23_groups[] = {
+ "gpio72",
+};
+
+static const char *const phase_flag24_groups[] = {
+ "gpio73",
+};
+
+static const char *const phase_flag25_groups[] = {
+ "gpio74",
+};
+
+static const char *const phase_flag26_groups[] = {
+ "gpio75",
+};
+
+static const char *const phase_flag27_groups[] = {
+ "gpio76",
+};
+
+static const char *const phase_flag28_groups[] = {
+ "gpio83",
+};
+
+static const char *const phase_flag29_groups[] = {
+ "gpio84",
+};
+
+static const char *const phase_flag3_groups[] = {
+ "gpio80",
+};
+
+static const char *const phase_flag30_groups[] = {
+ "gpio85",
+};
+
+static const char *const phase_flag31_groups[] = {
+ "gpio86",
+};
+
+static const char *const phase_flag4_groups[] = {
+ "gpio79",
+};
+
+static const char *const phase_flag5_groups[] = {
+ "gpio78",
+};
+
+static const char *const phase_flag6_groups[] = {
+ "gpio77",
+};
+
+static const char *const phase_flag7_groups[] = {
+ "gpio87",
+};
+
+static const char *const phase_flag8_groups[] = {
+ "gpio88",
+};
+
+static const char *const phase_flag9_groups[] = {
+ "gpio89",
+};
+
+static const char *const pll_bist_sync_groups[] = {
+ "gpio176",
+};
+
+static const char *const pll_clk_aux_groups[] = {
+ "gpio100",
+};
+
+static const char *const prng_rosc0_groups[] = {
+ "gpio117",
+};
+
+static const char *const prng_rosc1_groups[] = {
+ "gpio118",
+};
+
+static const char *const pwrbrk_i_n_groups[] = {
+ "gpio167",
+};
+
+static const char *const qdss_cti_groups[] = {
+ "gpio41", "gpio42", "gpio110", "gpio138",
+ "gpio142", "gpio144", "gpio162", "gpio163",
+};
+
+static const char *const qdss_gpio_groups[] = {
+ "gpio75",
+ "gpio76",
+ "gpio93",
+ "gpio108",
+};
+
+static const char *const qdss_gpio0_groups[] = {
+ "gpio67",
+ "gpio85",
+};
+
+static const char *const qdss_gpio1_groups[] = {
+ "gpio68",
+ "gpio86",
+};
+
+static const char *const qdss_gpio10_groups[] = {
+ "gpio79",
+ "gpio96",
+};
+
+static const char *const qdss_gpio11_groups[] = {
+ "gpio80",
+ "gpio97",
+};
+
+static const char *const qdss_gpio12_groups[] = {
+ "gpio81",
+ "gpio98",
+};
+
+static const char *const qdss_gpio13_groups[] = {
+ "gpio82",
+ "gpio99",
+};
+
+static const char *const qdss_gpio14_groups[] = {
+ "gpio83",
+ "gpio100",
+};
+
+static const char *const qdss_gpio15_groups[] = {
+ "gpio84",
+ "gpio101",
+};
+
+static const char *const qdss_gpio2_groups[] = {
+ "gpio69",
+ "gpio87",
+};
+
+static const char *const qdss_gpio3_groups[] = {
+ "gpio70",
+ "gpio88",
+};
+
+static const char *const qdss_gpio4_groups[] = {
+ "gpio71",
+ "gpio89",
+};
+
+static const char *const qdss_gpio5_groups[] = {
+ "gpio72",
+ "gpio90",
+};
+
+static const char *const qdss_gpio6_groups[] = {
+ "gpio73",
+ "gpio91",
+};
+
+static const char *const qdss_gpio7_groups[] = {
+ "gpio74",
+ "gpio92",
+};
+
+static const char *const qdss_gpio8_groups[] = {
+ "gpio77",
+ "gpio94",
+};
+
+static const char *const qdss_gpio9_groups[] = {
+ "gpio78",
+ "gpio95",
+};
+
+static const char *const qspi0_groups[] = {
+ "gpio102",
+};
+
+static const char *const qspi1_groups[] = {
+ "gpio103",
+};
+
+static const char *const qspi2_groups[] = {
+ "gpio106",
+};
+
+static const char *const qspi3_groups[] = {
+ "gpio107",
+};
+
+static const char *const qspi_clk_groups[] = {
+ "gpio104",
+};
+
+static const char *const qspi_cs0_n_groups[] = {
+ "gpio105",
+};
+
+static const char *const qspi_cs1_n_groups[] = {
+ "gpio108",
+};
+
+static const char *const qup0_se0_l0_groups[] = {
+ "gpio111",
+};
+
+static const char *const qup0_se0_l1_groups[] = {
+ "gpio112",
+};
+
+static const char *const qup0_se0_l2_groups[] = {
+ "gpio109",
+};
+
+static const char *const qup0_se0_l3_groups[] = {
+ "gpio110",
+};
+
+static const char *const qup0_se1_l0_groups[] = {
+ "gpio111",
+};
+
+static const char *const qup0_se1_l1_groups[] = {
+ "gpio112",
+};
+
+static const char *const qup0_se1_l2_groups[] = {
+ "gpio109",
+};
+
+static const char *const qup0_se1_l3_groups[] = {
+ "gpio110",
+};
+
+static const char *const qup0_se2_l0_groups[] = {
+ "gpio113",
+};
+
+static const char *const qup0_se2_l1_groups[] = {
+ "gpio114",
+};
+
+static const char *const qup0_se2_l2_groups[] = {
+ "gpio115",
+};
+
+static const char *const qup0_se2_l3_groups[] = {
+ "gpio116",
+};
+
+static const char *const qup0_se3_l0_groups[] = {
+ "gpio115",
+};
+
+static const char *const qup0_se3_l1_groups[] = {
+ "gpio116",
+};
+
+static const char *const qup0_se3_l2_groups[] = {
+ "gpio113",
+};
+
+static const char *const qup0_se3_l3_groups[] = {
+ "gpio114",
+};
+
+static const char *const qup0_se4_l0_groups[] = {
+ "gpio117",
+};
+
+static const char *const qup0_se4_l1_groups[] = {
+ "gpio118",
+};
+
+static const char *const qup0_se4_l2_groups[] = {
+ "gpio119",
+};
+
+static const char *const qup0_se4_l3_groups[] = {
+ "gpio120",
+};
+
+static const char *const qup0_se5_l0_groups[] = {
+ "gpio121",
+};
+
+static const char *const qup0_se5_l1_groups[] = {
+ "gpio122",
+};
+
+static const char *const qup0_se5_l2_groups[] = {
+ "gpio109",
+};
+
+static const char *const qup0_se5_l3_groups[] = {
+ "gpio110",
+};
+
+static const char *const qup1_se0_l0_groups[] = {
+ "gpio123",
+};
+
+static const char *const qup1_se0_l1_groups[] = {
+ "gpio124",
+};
+
+static const char *const qup1_se0_l2_groups[] = {
+ "gpio125",
+};
+
+static const char *const qup1_se0_l3_groups[] = {
+ "gpio126",
+};
+
+static const char *const qup1_se1_l0_groups[] = {
+ "gpio125",
+};
+
+static const char *const qup1_se1_l1_groups[] = {
+ "gpio126",
+};
+
+static const char *const qup1_se1_l2_groups[] = {
+ "gpio123",
+};
+
+static const char *const qup1_se1_l3_groups[] = {
+ "gpio124",
+};
+
+static const char *const qup1_se2_l0_groups[] = {
+ "gpio127",
+};
+
+static const char *const qup1_se2_l1_groups[] = {
+ "gpio128",
+};
+
+static const char *const qup1_se2_l2_groups[] = {
+ "gpio127",
+};
+
+static const char *const qup1_se2_l3_groups[] = {
+ "gpio128",
+};
+
+static const char *const qup1_se3_l0_groups[] = {
+ "gpio129",
+};
+
+static const char *const qup1_se3_l1_groups[] = {
+ "gpio130",
+};
+
+static const char *const qup1_se3_l2_groups[] = {
+ "gpio129",
+};
+
+static const char *const qup1_se3_l3_groups[] = {
+ "gpio130",
+};
+
+static const char *const qup1_se4_l0_groups[] = {
+ "gpio131",
+};
+
+static const char *const qup1_se4_l1_groups[] = {
+ "gpio132",
+};
+
+static const char *const qup1_se4_l2_groups[] = {
+ "gpio137",
+};
+
+static const char *const qup1_se4_l3_groups[] = {
+ "gpio138",
+};
+
+static const char *const qup1_se5_l0_groups[] = {
+ "gpio133",
+};
+
+static const char *const qup1_se5_l1_groups[] = {
+ "gpio134",
+};
+
+static const char *const qup1_se5_l2_groups[] = {
+ "gpio135",
+};
+
+static const char *const qup1_se5_l3_groups[] = {
+ "gpio136",
+};
+
+static const char *const qup1_se6_l0_groups[] = {
+ "gpio137",
+};
+
+static const char *const qup1_se6_l1_groups[] = {
+ "gpio138",
+};
+
+static const char *const qup1_se6_l2_groups[] = {
+ "gpio131",
+};
+
+static const char *const qup1_se6_l3_groups[] = {
+ "gpio132",
+};
+
+static const char *const qup2_se0_l0_groups[] = {
+ "gpio139",
+};
+
+static const char *const qup2_se0_l1_groups[] = {
+ "gpio140",
+};
+
+static const char *const qup2_se0_l2_groups[] = {
+ "gpio141",
+};
+
+static const char *const qup2_se0_l3_groups[] = {
+ "gpio142",
+};
+
+static const char *const qup2_se1_l0_groups[] = {
+ "gpio154",
+};
+
+static const char *const qup2_se1_l1_groups[] = {
+ "gpio155",
+};
+
+static const char *const qup2_se1_l2_groups[] = {
+ "gpio143",
+};
+
+static const char *const qup2_se1_l3_groups[] = {
+ "gpio144",
+};
+
+static const char *const qup2_se2_l0_groups[] = {
+ "gpio145",
+};
+
+static const char *const qup2_se2_l1_groups[] = {
+ "gpio146",
+};
+
+static const char *const qup2_se2_l2_groups[] = {
+ "gpio147",
+};
+
+static const char *const qup2_se2_l3_groups[] = {
+ "gpio148",
+};
+
+static const char *const qup2_se2_l4_groups[] = {
+ "gpio149",
+};
+
+static const char *const qup2_se3_l0_groups[] = {
+ "gpio150",
+};
+
+static const char *const qup2_se3_l1_groups[] = {
+ "gpio151",
+};
+
+static const char *const qup2_se3_l2_groups[] = {
+ "gpio152",
+};
+
+static const char *const qup2_se3_l3_groups[] = {
+ "gpio153",
+};
+
+static const char *const qup2_se4_l0_groups[] = {
+ "gpio154",
+};
+
+static const char *const qup2_se4_l1_groups[] = {
+ "gpio155",
+};
+
+static const char *const qup2_se4_l2_groups[] = {
+ "gpio143",
+};
+
+static const char *const qup2_se4_l3_groups[] = {
+ "gpio144",
+};
+
+static const char *const qup2_se4_l4_groups[] = {
+ "gpio150",
+};
+
+static const char *const qup2_se4_l5_groups[] = {
+ "gpio151",
+};
+
+static const char *const qup2_se4_l6_groups[] = {
+ "gpio152",
+};
+
+static const char *const qup2_se5_l0_groups[] = {
+ "gpio156",
+};
+
+static const char *const qup2_se5_l1_groups[] = {
+ "gpio157",
+};
+
+static const char *const qup2_se5_l2_groups[] = {
+ "gpio158",
+};
+
+static const char *const qup2_se5_l3_groups[] = {
+ "gpio159",
+};
+
+static const char *const qup2_se6_l0_groups[] = {
+ "gpio158",
+};
+
+static const char *const qup2_se6_l1_groups[] = {
+ "gpio159",
+};
+
+static const char *const qup2_se6_l2_groups[] = {
+ "gpio156",
+};
+
+static const char *const qup2_se6_l3_groups[] = {
+ "gpio157",
+};
+
+static const char *const qup3_se0_l0_mira_groups[] = {
+ "gpio102",
+};
+
+static const char *const qup3_se0_l0_mirb_groups[] = {
+ "gpio103",
+};
+
+static const char *const qup3_se0_l1_mira_groups[] = {
+ "gpio103",
+};
+
+static const char *const qup3_se0_l1_mirb_groups[] = {
+ "gpio102",
+};
+
+static const char *const qup3_se0_l2_groups[] = {
+ "gpio104",
+};
+
+static const char *const qup3_se0_l3_groups[] = {
+ "gpio105",
+};
+
+static const char *const qup3_se0_l4_groups[] = {
+ "gpio106",
+};
+
+static const char *const qup3_se0_l5_groups[] = {
+ "gpio107",
+};
+
+static const char *const qup3_se0_l6_groups[] = {
+ "gpio108",
+};
+
+static const char *const sailss_ospi_groups[] = {
+ "gpio164",
+ "gpio165",
+};
+
+static const char *const sdc4_clk_groups[] = {
+ "gpio175",
+};
+
+static const char *const sdc4_cmd_groups[] = {
+ "gpio174",
+};
+
+static const char *const sdc4_data_groups[] = {
+ "gpio170",
+ "gpio171",
+ "gpio172",
+ "gpio173",
+};
+
+static const char *const smb_alert_groups[] = {
+ "gpio110",
+};
+
+static const char *const smb_alert_n_groups[] = {
+ "gpio109",
+};
+
+static const char *const smb_clk_groups[] = {
+ "gpio112",
+};
+
+static const char *const smb_dat_groups[] = {
+ "gpio111",
+};
+
+static const char *const tb_trig_sdc4_groups[] = {
+ "gpio169",
+};
+
+static const char *const tmess_prng0_groups[] = {
+ "gpio94",
+};
+
+static const char *const tmess_prng1_groups[] = {
+ "gpio95",
+};
+
+static const char *const tsc_timer0_groups[] = {
+ "gpio25",
+};
+
+static const char *const tsc_timer1_groups[] = {
+ "gpio26",
+};
+
+static const char *const tsc_timer2_groups[] = {
+ "gpio27",
+};
+
+static const char *const tsc_timer3_groups[] = {
+ "gpio28",
+};
+
+static const char *const tsc_timer4_groups[] = {
+ "gpio29",
+};
+
+static const char *const tsc_timer5_groups[] = {
+ "gpio30",
+};
+
+static const char *const tsc_timer6_groups[] = {
+ "gpio31",
+};
+
+static const char *const tsc_timer7_groups[] = {
+ "gpio32",
+};
+
+static const char *const tsc_timer8_groups[] = {
+ "gpio33",
+};
+
+static const char *const tsc_timer9_groups[] = {
+ "gpio34",
+};
+
+static const char *const tsense_pwm1_groups[] = {
+ "gpio43",
+};
+
+static const char *const tsense_pwm2_groups[] = {
+ "gpio44",
+};
+
+static const char *const tsense_pwm3_groups[] = {
+ "gpio45",
+};
+
+static const char *const tsense_pwm4_groups[] = {
+ "gpio46",
+};
+
+static const char *const tsense_pwm5_groups[] = {
+ "gpio47",
+};
+
+static const char *const tsense_pwm6_groups[] = {
+ "gpio48",
+};
+
+static const char *const tsense_pwm7_groups[] = {
+ "gpio49",
+};
+
+static const char *const tsense_pwm8_groups[] = {
+ "gpio50",
+};
+
+static const char *const usb0_hs_groups[] = {
+ "gpio12",
+};
+
+static const char *const usb0_phy_ps_groups[] = {
+ "gpio164",
+};
+
+static const char *const usb1_hs_groups[] = {
+ "gpio13",
+};
+
+static const char *const usb1_phy_ps_groups[] = {
+ "gpio165",
+};
+
+static const char *const usb2_hs_groups[] = {
+ "gpio14",
+};
+
+static const char *const usxgmii0_phy_groups[] = {
+ "gpio45",
+};
+
+static const char *const usxgmii1_phy_groups[] = {
+ "gpio46",
+};
+
+static const char *const vsense_trigger_mirnat_groups[] = {
+ "gpio132",
+};
+
+static const char *const wcn_sw_groups[] = {
+ "gpio161",
+};
+
+static const char *const wcn_sw_ctrl_groups[] = {
+ "gpio160",
+};
+
+static const struct pinfunction nord_functions[] = {
+ MSM_GPIO_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_char_start),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(aud_intfc0_clk),
+ MSM_PIN_FUNCTION(aud_intfc0_data0),
+ MSM_PIN_FUNCTION(aud_intfc0_data1),
+ MSM_PIN_FUNCTION(aud_intfc0_data2),
+ MSM_PIN_FUNCTION(aud_intfc0_data3),
+ MSM_PIN_FUNCTION(aud_intfc0_data4),
+ MSM_PIN_FUNCTION(aud_intfc0_data5),
+ MSM_PIN_FUNCTION(aud_intfc0_data6),
+ MSM_PIN_FUNCTION(aud_intfc0_data7),
+ MSM_PIN_FUNCTION(aud_intfc0_ws),
+ MSM_PIN_FUNCTION(aud_intfc10_clk),
+ MSM_PIN_FUNCTION(aud_intfc10_data0),
+ MSM_PIN_FUNCTION(aud_intfc10_data1),
+ MSM_PIN_FUNCTION(aud_intfc10_ws),
+ MSM_PIN_FUNCTION(aud_intfc1_clk),
+ MSM_PIN_FUNCTION(aud_intfc1_data0),
+ MSM_PIN_FUNCTION(aud_intfc1_data1),
+ MSM_PIN_FUNCTION(aud_intfc1_data2),
+ MSM_PIN_FUNCTION(aud_intfc1_data3),
+ MSM_PIN_FUNCTION(aud_intfc1_data4),
+ MSM_PIN_FUNCTION(aud_intfc1_data5),
+ MSM_PIN_FUNCTION(aud_intfc1_data6),
+ MSM_PIN_FUNCTION(aud_intfc1_data7),
+ MSM_PIN_FUNCTION(aud_intfc1_ws),
+ MSM_PIN_FUNCTION(aud_intfc2_clk),
+ MSM_PIN_FUNCTION(aud_intfc2_data0),
+ MSM_PIN_FUNCTION(aud_intfc2_data1),
+ MSM_PIN_FUNCTION(aud_intfc2_data2),
+ MSM_PIN_FUNCTION(aud_intfc2_data3),
+ MSM_PIN_FUNCTION(aud_intfc2_ws),
+ MSM_PIN_FUNCTION(aud_intfc3_clk),
+ MSM_PIN_FUNCTION(aud_intfc3_data0),
+ MSM_PIN_FUNCTION(aud_intfc3_data1),
+ MSM_PIN_FUNCTION(aud_intfc3_ws),
+ MSM_PIN_FUNCTION(aud_intfc4_clk),
+ MSM_PIN_FUNCTION(aud_intfc4_data0),
+ MSM_PIN_FUNCTION(aud_intfc4_data1),
+ MSM_PIN_FUNCTION(aud_intfc4_ws),
+ MSM_PIN_FUNCTION(aud_intfc5_clk),
+ MSM_PIN_FUNCTION(aud_intfc5_data0),
+ MSM_PIN_FUNCTION(aud_intfc5_data1),
+ MSM_PIN_FUNCTION(aud_intfc5_ws),
+ MSM_PIN_FUNCTION(aud_intfc6_clk),
+ MSM_PIN_FUNCTION(aud_intfc6_data0),
+ MSM_PIN_FUNCTION(aud_intfc6_data1),
+ MSM_PIN_FUNCTION(aud_intfc6_ws),
+ MSM_PIN_FUNCTION(aud_intfc7_clk),
+ MSM_PIN_FUNCTION(aud_intfc7_data0),
+ MSM_PIN_FUNCTION(aud_intfc7_data1),
+ MSM_PIN_FUNCTION(aud_intfc7_ws),
+ MSM_PIN_FUNCTION(aud_intfc8_clk),
+ MSM_PIN_FUNCTION(aud_intfc8_data0),
+ MSM_PIN_FUNCTION(aud_intfc8_data1),
+ MSM_PIN_FUNCTION(aud_intfc8_ws),
+ MSM_PIN_FUNCTION(aud_intfc9_clk),
+ MSM_PIN_FUNCTION(aud_intfc9_data0),
+ MSM_PIN_FUNCTION(aud_intfc9_ws),
+ MSM_PIN_FUNCTION(aud_mclk0_mira),
+ MSM_PIN_FUNCTION(aud_mclk0_mirb),
+ MSM_PIN_FUNCTION(aud_mclk1_mira),
+ MSM_PIN_FUNCTION(aud_mclk1_mirb),
+ MSM_PIN_FUNCTION(aud_mclk2_mira),
+ MSM_PIN_FUNCTION(aud_mclk2_mirb),
+ MSM_PIN_FUNCTION(aud_refclk0),
+ MSM_PIN_FUNCTION(aud_refclk1),
+ MSM_PIN_FUNCTION(bist_done),
+ MSM_PIN_FUNCTION(ccu_async_in0),
+ MSM_PIN_FUNCTION(ccu_async_in1),
+ MSM_PIN_FUNCTION(ccu_async_in2),
+ MSM_PIN_FUNCTION(ccu_async_in3),
+ MSM_PIN_FUNCTION(ccu_async_in4),
+ MSM_PIN_FUNCTION(ccu_async_in5),
+ MSM_PIN_FUNCTION(ccu_i2c_scl0),
+ MSM_PIN_FUNCTION(ccu_i2c_scl1),
+ MSM_PIN_FUNCTION(ccu_i2c_scl2),
+ MSM_PIN_FUNCTION(ccu_i2c_scl3),
+ MSM_PIN_FUNCTION(ccu_i2c_scl4),
+ MSM_PIN_FUNCTION(ccu_i2c_scl5),
+ MSM_PIN_FUNCTION(ccu_i2c_scl6),
+ MSM_PIN_FUNCTION(ccu_i2c_scl7),
+ MSM_PIN_FUNCTION(ccu_i2c_scl8),
+ MSM_PIN_FUNCTION(ccu_i2c_scl9),
+ MSM_PIN_FUNCTION(ccu_i2c_sda0),
+ MSM_PIN_FUNCTION(ccu_i2c_sda1),
+ MSM_PIN_FUNCTION(ccu_i2c_sda2),
+ MSM_PIN_FUNCTION(ccu_i2c_sda3),
+ MSM_PIN_FUNCTION(ccu_i2c_sda4),
+ MSM_PIN_FUNCTION(ccu_i2c_sda5),
+ MSM_PIN_FUNCTION(ccu_i2c_sda6),
+ MSM_PIN_FUNCTION(ccu_i2c_sda7),
+ MSM_PIN_FUNCTION(ccu_i2c_sda8),
+ MSM_PIN_FUNCTION(ccu_i2c_sda9),
+ MSM_PIN_FUNCTION(ccu_timer0),
+ MSM_PIN_FUNCTION(ccu_timer1),
+ MSM_PIN_FUNCTION(ccu_timer10),
+ MSM_PIN_FUNCTION(ccu_timer11),
+ MSM_PIN_FUNCTION(ccu_timer12),
+ MSM_PIN_FUNCTION(ccu_timer13),
+ MSM_PIN_FUNCTION(ccu_timer14),
+ MSM_PIN_FUNCTION(ccu_timer15),
+ MSM_PIN_FUNCTION(ccu_timer2),
+ MSM_PIN_FUNCTION(ccu_timer3),
+ MSM_PIN_FUNCTION(ccu_timer4),
+ MSM_PIN_FUNCTION(ccu_timer5),
+ MSM_PIN_FUNCTION(ccu_timer6),
+ MSM_PIN_FUNCTION(ccu_timer7),
+ MSM_PIN_FUNCTION(ccu_timer8),
+ MSM_PIN_FUNCTION(ccu_timer9),
+ MSM_PIN_FUNCTION(clink_debug),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist_complete),
+ MSM_PIN_FUNCTION(ddr_bist_fail),
+ MSM_PIN_FUNCTION(ddr_bist_start),
+ MSM_PIN_FUNCTION(ddr_bist_stop),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi10),
+ MSM_PIN_FUNCTION(ddr_pxi11),
+ MSM_PIN_FUNCTION(ddr_pxi12),
+ MSM_PIN_FUNCTION(ddr_pxi13),
+ MSM_PIN_FUNCTION(ddr_pxi14),
+ MSM_PIN_FUNCTION(ddr_pxi15),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(ddr_pxi4),
+ MSM_PIN_FUNCTION(ddr_pxi5),
+ MSM_PIN_FUNCTION(ddr_pxi6),
+ MSM_PIN_FUNCTION(ddr_pxi7),
+ MSM_PIN_FUNCTION(ddr_pxi8),
+ MSM_PIN_FUNCTION(ddr_pxi9),
+ MSM_PIN_FUNCTION(dp_rx0),
+ MSM_PIN_FUNCTION(dp_rx00),
+ MSM_PIN_FUNCTION(dp_rx01),
+ MSM_PIN_FUNCTION(dp_rx0_mute),
+ MSM_PIN_FUNCTION(dp_rx1),
+ MSM_PIN_FUNCTION(dp_rx10),
+ MSM_PIN_FUNCTION(dp_rx11),
+ MSM_PIN_FUNCTION(dp_rx1_mute),
+ MSM_PIN_FUNCTION(edp0_hot),
+ MSM_PIN_FUNCTION(edp0_lcd),
+ MSM_PIN_FUNCTION(edp1_hot),
+ MSM_PIN_FUNCTION(edp1_lcd),
+ MSM_PIN_FUNCTION(edp2_hot),
+ MSM_PIN_FUNCTION(edp2_lcd),
+ MSM_PIN_FUNCTION(edp3_hot),
+ MSM_PIN_FUNCTION(edp3_lcd),
+ MSM_PIN_FUNCTION(emac0_mcg0),
+ MSM_PIN_FUNCTION(emac0_mcg1),
+ MSM_PIN_FUNCTION(emac0_mcg2),
+ MSM_PIN_FUNCTION(emac0_mcg3),
+ MSM_PIN_FUNCTION(emac0_mdc),
+ MSM_PIN_FUNCTION(emac0_mdio),
+ MSM_PIN_FUNCTION(emac0_ptp),
+ MSM_PIN_FUNCTION(emac1_mcg0),
+ MSM_PIN_FUNCTION(emac1_mcg1),
+ MSM_PIN_FUNCTION(emac1_mcg2),
+ MSM_PIN_FUNCTION(emac1_mcg3),
+ MSM_PIN_FUNCTION(emac1_mdc),
+ MSM_PIN_FUNCTION(emac1_mdio),
+ MSM_PIN_FUNCTION(emac1_ptp),
+ MSM_PIN_FUNCTION(gcc_gp1_clk),
+ MSM_PIN_FUNCTION(gcc_gp2_clk),
+ MSM_PIN_FUNCTION(gcc_gp3_clk),
+ MSM_PIN_FUNCTION(gcc_gp4_clk),
+ MSM_PIN_FUNCTION(gcc_gp5_clk),
+ MSM_PIN_FUNCTION(gcc_gp6_clk),
+ MSM_PIN_FUNCTION(gcc_gp7_clk),
+ MSM_PIN_FUNCTION(gcc_gp8_clk),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lbist_pass),
+ MSM_PIN_FUNCTION(mbist_pass),
+ MSM_PIN_FUNCTION(mdp0_vsync0_out),
+ MSM_PIN_FUNCTION(mdp0_vsync10_out),
+ MSM_PIN_FUNCTION(mdp0_vsync1_out),
+ MSM_PIN_FUNCTION(mdp0_vsync2_out),
+ MSM_PIN_FUNCTION(mdp0_vsync3_out),
+ MSM_PIN_FUNCTION(mdp0_vsync4_out),
+ MSM_PIN_FUNCTION(mdp0_vsync5_out),
+ MSM_PIN_FUNCTION(mdp0_vsync6_out),
+ MSM_PIN_FUNCTION(mdp0_vsync7_out),
+ MSM_PIN_FUNCTION(mdp0_vsync8_out),
+ MSM_PIN_FUNCTION(mdp0_vsync9_out),
+ MSM_PIN_FUNCTION(mdp1_vsync0_out),
+ MSM_PIN_FUNCTION(mdp1_vsync10_out),
+ MSM_PIN_FUNCTION(mdp1_vsync1_out),
+ MSM_PIN_FUNCTION(mdp1_vsync2_out),
+ MSM_PIN_FUNCTION(mdp1_vsync3_out),
+ MSM_PIN_FUNCTION(mdp1_vsync4_out),
+ MSM_PIN_FUNCTION(mdp1_vsync5_out),
+ MSM_PIN_FUNCTION(mdp1_vsync6_out),
+ MSM_PIN_FUNCTION(mdp1_vsync7_out),
+ MSM_PIN_FUNCTION(mdp1_vsync8_out),
+ MSM_PIN_FUNCTION(mdp1_vsync9_out),
+ MSM_PIN_FUNCTION(mdp_vsync_e),
+ MSM_PIN_FUNCTION(mdp_vsync_p),
+ MSM_PIN_FUNCTION(mdp_vsync_s),
+ MSM_PIN_FUNCTION(pcie0_clk_req_n),
+ MSM_PIN_FUNCTION(pcie1_clk_req_n),
+ MSM_PIN_FUNCTION(pcie2_clk_req_n),
+ MSM_PIN_FUNCTION(pcie3_clk_req_n),
+ MSM_PIN_FUNCTION(phase_flag0),
+ MSM_PIN_FUNCTION(phase_flag1),
+ MSM_PIN_FUNCTION(phase_flag10),
+ MSM_PIN_FUNCTION(phase_flag11),
+ MSM_PIN_FUNCTION(phase_flag12),
+ MSM_PIN_FUNCTION(phase_flag13),
+ MSM_PIN_FUNCTION(phase_flag14),
+ MSM_PIN_FUNCTION(phase_flag15),
+ MSM_PIN_FUNCTION(phase_flag16),
+ MSM_PIN_FUNCTION(phase_flag17),
+ MSM_PIN_FUNCTION(phase_flag18),
+ MSM_PIN_FUNCTION(phase_flag19),
+ MSM_PIN_FUNCTION(phase_flag2),
+ MSM_PIN_FUNCTION(phase_flag20),
+ MSM_PIN_FUNCTION(phase_flag21),
+ MSM_PIN_FUNCTION(phase_flag22),
+ MSM_PIN_FUNCTION(phase_flag23),
+ MSM_PIN_FUNCTION(phase_flag24),
+ MSM_PIN_FUNCTION(phase_flag25),
+ MSM_PIN_FUNCTION(phase_flag26),
+ MSM_PIN_FUNCTION(phase_flag27),
+ MSM_PIN_FUNCTION(phase_flag28),
+ MSM_PIN_FUNCTION(phase_flag29),
+ MSM_PIN_FUNCTION(phase_flag3),
+ MSM_PIN_FUNCTION(phase_flag30),
+ MSM_PIN_FUNCTION(phase_flag31),
+ MSM_PIN_FUNCTION(phase_flag4),
+ MSM_PIN_FUNCTION(phase_flag5),
+ MSM_PIN_FUNCTION(phase_flag6),
+ MSM_PIN_FUNCTION(phase_flag7),
+ MSM_PIN_FUNCTION(phase_flag8),
+ MSM_PIN_FUNCTION(phase_flag9),
+ MSM_PIN_FUNCTION(pll_bist_sync),
+ MSM_PIN_FUNCTION(pll_clk_aux),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(pwrbrk_i_n),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qdss_gpio0),
+ MSM_PIN_FUNCTION(qdss_gpio1),
+ MSM_PIN_FUNCTION(qdss_gpio10),
+ MSM_PIN_FUNCTION(qdss_gpio11),
+ MSM_PIN_FUNCTION(qdss_gpio12),
+ MSM_PIN_FUNCTION(qdss_gpio13),
+ MSM_PIN_FUNCTION(qdss_gpio14),
+ MSM_PIN_FUNCTION(qdss_gpio15),
+ MSM_PIN_FUNCTION(qdss_gpio2),
+ MSM_PIN_FUNCTION(qdss_gpio3),
+ MSM_PIN_FUNCTION(qdss_gpio4),
+ MSM_PIN_FUNCTION(qdss_gpio5),
+ MSM_PIN_FUNCTION(qdss_gpio6),
+ MSM_PIN_FUNCTION(qdss_gpio7),
+ MSM_PIN_FUNCTION(qdss_gpio8),
+ MSM_PIN_FUNCTION(qdss_gpio9),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs0_n),
+ MSM_PIN_FUNCTION(qspi_cs1_n),
+ MSM_PIN_FUNCTION(qup0_se0_l0),
+ MSM_PIN_FUNCTION(qup0_se0_l1),
+ MSM_PIN_FUNCTION(qup0_se0_l2),
+ MSM_PIN_FUNCTION(qup0_se0_l3),
+ MSM_PIN_FUNCTION(qup0_se1_l0),
+ MSM_PIN_FUNCTION(qup0_se1_l1),
+ MSM_PIN_FUNCTION(qup0_se1_l2),
+ MSM_PIN_FUNCTION(qup0_se1_l3),
+ MSM_PIN_FUNCTION(qup0_se2_l0),
+ MSM_PIN_FUNCTION(qup0_se2_l1),
+ MSM_PIN_FUNCTION(qup0_se2_l2),
+ MSM_PIN_FUNCTION(qup0_se2_l3),
+ MSM_PIN_FUNCTION(qup0_se3_l0),
+ MSM_PIN_FUNCTION(qup0_se3_l1),
+ MSM_PIN_FUNCTION(qup0_se3_l2),
+ MSM_PIN_FUNCTION(qup0_se3_l3),
+ MSM_PIN_FUNCTION(qup0_se4_l0),
+ MSM_PIN_FUNCTION(qup0_se4_l1),
+ MSM_PIN_FUNCTION(qup0_se4_l2),
+ MSM_PIN_FUNCTION(qup0_se4_l3),
+ MSM_PIN_FUNCTION(qup0_se5_l0),
+ MSM_PIN_FUNCTION(qup0_se5_l1),
+ MSM_PIN_FUNCTION(qup0_se5_l2),
+ MSM_PIN_FUNCTION(qup0_se5_l3),
+ MSM_PIN_FUNCTION(qup1_se0_l0),
+ MSM_PIN_FUNCTION(qup1_se0_l1),
+ MSM_PIN_FUNCTION(qup1_se0_l2),
+ MSM_PIN_FUNCTION(qup1_se0_l3),
+ MSM_PIN_FUNCTION(qup1_se1_l0),
+ MSM_PIN_FUNCTION(qup1_se1_l1),
+ MSM_PIN_FUNCTION(qup1_se1_l2),
+ MSM_PIN_FUNCTION(qup1_se1_l3),
+ MSM_PIN_FUNCTION(qup1_se2_l0),
+ MSM_PIN_FUNCTION(qup1_se2_l1),
+ MSM_PIN_FUNCTION(qup1_se2_l2),
+ MSM_PIN_FUNCTION(qup1_se2_l3),
+ MSM_PIN_FUNCTION(qup1_se3_l0),
+ MSM_PIN_FUNCTION(qup1_se3_l1),
+ MSM_PIN_FUNCTION(qup1_se3_l2),
+ MSM_PIN_FUNCTION(qup1_se3_l3),
+ MSM_PIN_FUNCTION(qup1_se4_l0),
+ MSM_PIN_FUNCTION(qup1_se4_l1),
+ MSM_PIN_FUNCTION(qup1_se4_l2),
+ MSM_PIN_FUNCTION(qup1_se4_l3),
+ MSM_PIN_FUNCTION(qup1_se5_l0),
+ MSM_PIN_FUNCTION(qup1_se5_l1),
+ MSM_PIN_FUNCTION(qup1_se5_l2),
+ MSM_PIN_FUNCTION(qup1_se5_l3),
+ MSM_PIN_FUNCTION(qup1_se6_l0),
+ MSM_PIN_FUNCTION(qup1_se6_l1),
+ MSM_PIN_FUNCTION(qup1_se6_l2),
+ MSM_PIN_FUNCTION(qup1_se6_l3),
+ MSM_PIN_FUNCTION(qup2_se0_l0),
+ MSM_PIN_FUNCTION(qup2_se0_l1),
+ MSM_PIN_FUNCTION(qup2_se0_l2),
+ MSM_PIN_FUNCTION(qup2_se0_l3),
+ MSM_PIN_FUNCTION(qup2_se1_l0),
+ MSM_PIN_FUNCTION(qup2_se1_l1),
+ MSM_PIN_FUNCTION(qup2_se1_l2),
+ MSM_PIN_FUNCTION(qup2_se1_l3),
+ MSM_PIN_FUNCTION(qup2_se2_l0),
+ MSM_PIN_FUNCTION(qup2_se2_l1),
+ MSM_PIN_FUNCTION(qup2_se2_l2),
+ MSM_PIN_FUNCTION(qup2_se2_l3),
+ MSM_PIN_FUNCTION(qup2_se2_l4),
+ MSM_PIN_FUNCTION(qup2_se3_l0),
+ MSM_PIN_FUNCTION(qup2_se3_l1),
+ MSM_PIN_FUNCTION(qup2_se3_l2),
+ MSM_PIN_FUNCTION(qup2_se3_l3),
+ MSM_PIN_FUNCTION(qup2_se4_l0),
+ MSM_PIN_FUNCTION(qup2_se4_l1),
+ MSM_PIN_FUNCTION(qup2_se4_l2),
+ MSM_PIN_FUNCTION(qup2_se4_l3),
+ MSM_PIN_FUNCTION(qup2_se4_l4),
+ MSM_PIN_FUNCTION(qup2_se4_l5),
+ MSM_PIN_FUNCTION(qup2_se4_l6),
+ MSM_PIN_FUNCTION(qup2_se5_l0),
+ MSM_PIN_FUNCTION(qup2_se5_l1),
+ MSM_PIN_FUNCTION(qup2_se5_l2),
+ MSM_PIN_FUNCTION(qup2_se5_l3),
+ MSM_PIN_FUNCTION(qup2_se6_l0),
+ MSM_PIN_FUNCTION(qup2_se6_l1),
+ MSM_PIN_FUNCTION(qup2_se6_l2),
+ MSM_PIN_FUNCTION(qup2_se6_l3),
+ MSM_PIN_FUNCTION(qup3_se0_l0_mira),
+ MSM_PIN_FUNCTION(qup3_se0_l0_mirb),
+ MSM_PIN_FUNCTION(qup3_se0_l1_mira),
+ MSM_PIN_FUNCTION(qup3_se0_l1_mirb),
+ MSM_PIN_FUNCTION(qup3_se0_l2),
+ MSM_PIN_FUNCTION(qup3_se0_l3),
+ MSM_PIN_FUNCTION(qup3_se0_l4),
+ MSM_PIN_FUNCTION(qup3_se0_l5),
+ MSM_PIN_FUNCTION(qup3_se0_l6),
+ MSM_PIN_FUNCTION(sailss_ospi),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sdc4_data),
+ MSM_PIN_FUNCTION(smb_alert),
+ MSM_PIN_FUNCTION(smb_alert_n),
+ MSM_PIN_FUNCTION(smb_clk),
+ MSM_PIN_FUNCTION(smb_dat),
+ MSM_PIN_FUNCTION(tb_trig_sdc4),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tsc_timer0),
+ MSM_PIN_FUNCTION(tsc_timer1),
+ MSM_PIN_FUNCTION(tsc_timer2),
+ MSM_PIN_FUNCTION(tsc_timer3),
+ MSM_PIN_FUNCTION(tsc_timer4),
+ MSM_PIN_FUNCTION(tsc_timer5),
+ MSM_PIN_FUNCTION(tsc_timer6),
+ MSM_PIN_FUNCTION(tsc_timer7),
+ MSM_PIN_FUNCTION(tsc_timer8),
+ MSM_PIN_FUNCTION(tsc_timer9),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsense_pwm3),
+ MSM_PIN_FUNCTION(tsense_pwm4),
+ MSM_PIN_FUNCTION(tsense_pwm5),
+ MSM_PIN_FUNCTION(tsense_pwm6),
+ MSM_PIN_FUNCTION(tsense_pwm7),
+ MSM_PIN_FUNCTION(tsense_pwm8),
+ MSM_PIN_FUNCTION(usb0_hs),
+ MSM_PIN_FUNCTION(usb0_phy_ps),
+ MSM_PIN_FUNCTION(usb1_hs),
+ MSM_PIN_FUNCTION(usb1_phy_ps),
+ MSM_PIN_FUNCTION(usb2_hs),
+ MSM_PIN_FUNCTION(usxgmii0_phy),
+ MSM_PIN_FUNCTION(usxgmii1_phy),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
+ MSM_PIN_FUNCTION(wcn_sw),
+ 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 nord_groups[] = {
+ [0] = PINGROUP(0, _, _, _, _, _, _, _, _, _, _, _),
+ [1] = PINGROUP(1, pcie0_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [2] = PINGROUP(2, _, _, _, _, _, _, _, _, _, _, _),
+ [3] = PINGROUP(3, _, _, _, _, _, _, _, _, _, _, _),
+ [4] = PINGROUP(4, pcie1_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [5] = PINGROUP(5, _, _, _, _, _, _, _, _, _, _, _),
+ [6] = PINGROUP(6, _, _, _, _, _, _, _, _, _, _, _),
+ [7] = PINGROUP(7, pcie2_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [8] = PINGROUP(8, _, _, _, _, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, _, _, _, _, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, pcie3_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, _, _, _, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, usb0_hs, clink_debug, _, _, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, usb1_hs, clink_debug, gcc_gp7_clk, _, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, usb2_hs, clink_debug, gcc_gp8_clk, _, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, ccu_i2c_sda0, _, _, _, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, ccu_i2c_scl0, emac0_mcg0, _, _, _, _, _, _, _, _, _),
+ [17] = PINGROUP(17, ccu_i2c_sda1, emac0_mcg1, _, _, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, ccu_i2c_scl1, emac0_mcg2, _, _, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, ccu_i2c_sda2, emac0_mcg3, _, _, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, ccu_i2c_scl2, emac1_mcg0, _, _, _, _, _, _, _, _, _),
+ [21] = PINGROUP(21, ccu_i2c_sda3, emac1_mcg1, _, _, _, _, _, _, _, _, _),
+ [22] = PINGROUP(22, ccu_i2c_scl3, emac1_mcg2, _, _, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, ccu_i2c_sda4, emac1_mcg3, _, _, _, _, _, _, _, _, _),
+ [24] = PINGROUP(24, ccu_i2c_scl4, _, _, _, _, _, _, _, _, _, _),
+ [25] = PINGROUP(25, ccu_timer0, tsc_timer0, _, _, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, ccu_timer1, tsc_timer1, _, _, _, _, _, _, _, _, _),
+ [27] = PINGROUP(27, ccu_timer2, tsc_timer2, _, _, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, ccu_timer3, tsc_timer3, _, _, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, ccu_timer4, tsc_timer4, _, _, _, _, _, _, _, _, _),
+ [30] = PINGROUP(30, ccu_timer5, tsc_timer5, _, _, _, _, _, _, _, _, _),
+ [31] = PINGROUP(31, ccu_timer6, tsc_timer6, _, _, _, _, _, _, _, _, _),
+ [32] = PINGROUP(32, ccu_timer7, tsc_timer7, _, _, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, ccu_timer8, tsc_timer8, _, _, _, _, _, _, _, _, _),
+ [34] = PINGROUP(34, ccu_timer9, tsc_timer9, _, _, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, dp_rx0_mute, _, _, _, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, dp_rx1_mute, ddr_bist_start, _, _, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, emac1_ptp, ddr_bist_complete, _, _, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, emac1_ptp, ddr_bist_stop, _, _, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, emac1_ptp, ddr_bist_fail, _, _, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, emac1_ptp, _, _, _, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, emac1_ptp, qdss_cti, _, _, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, emac1_ptp, qdss_cti, gcc_gp3_clk, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, emac1_ptp, gcc_gp4_clk, tsense_pwm1, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, emac1_ptp, tsense_pwm2, _, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, usxgmii0_phy, ccu_async_in5, tsense_pwm3, _, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, usxgmii1_phy, tsense_pwm4, _, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, emac0_mdc, edp0_lcd, tsense_pwm5, _, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, emac0_mdio, edp1_lcd, tsense_pwm6, _, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, emac1_mdc, edp2_lcd, tsense_pwm7, _, _, _, _, _, _, _, _),
+ [50] = PINGROUP(50, emac1_mdio, edp3_lcd, tsense_pwm8, _, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, edp0_hot, clink_debug, gcc_gp1_clk, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, edp1_hot, clink_debug, gcc_gp2_clk, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, edp2_hot, clink_debug, _, _, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, edp3_hot, clink_debug, _, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, dp_rx0, clink_debug, _, _, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, dp_rx1, _, _, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, aud_intfc0_clk, _, _, _, _, _, _, _, _, _, _),
+ [58] = PINGROUP(58, aud_intfc0_ws, _, _, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, aud_intfc0_data0, _, _, _, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, aud_intfc0_data1, _, _, _, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, aud_intfc0_data2, aud_intfc10_clk, _, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, aud_intfc0_data3, aud_intfc10_ws, _, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, aud_intfc0_data4, aud_intfc7_clk, _, _, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, aud_intfc0_data5, aud_intfc7_ws, _, _, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, aud_intfc0_data6, aud_intfc7_data0, _, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, aud_intfc0_data7, aud_intfc7_data1, _, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, aud_intfc1_clk, phase_flag18, _, qdss_gpio0, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, aud_intfc1_ws, phase_flag19, _, qdss_gpio1, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, aud_intfc1_data0, phase_flag20, _, qdss_gpio2, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, aud_intfc1_data1, aud_intfc9_clk, phase_flag21, _, qdss_gpio3,
+ _, _, _, _, _, _),
+ [71] = PINGROUP(71, aud_intfc1_data2, aud_intfc9_ws, phase_flag22, _, qdss_gpio4, _, _,
+ _, _, _, _),
+ [72] = PINGROUP(72, aud_intfc1_data3, aud_intfc9_data0, phase_flag23, _, qdss_gpio5, _,
+ _, _, _, _, _),
+ [73] = PINGROUP(73, aud_intfc1_data4, aud_intfc8_clk, phase_flag24, _, qdss_gpio6, _,
+ _, _, _, _, _),
+ [74] = PINGROUP(74, aud_intfc1_data5, aud_intfc8_ws, phase_flag25, _, qdss_gpio7, _,
+ _, _, _, _, _),
+ [75] = PINGROUP(75, aud_intfc1_data6, aud_intfc8_data0, phase_flag26, _, qdss_gpio,
+ _, _, _, _, _, _),
+ [76] = PINGROUP(76, aud_intfc1_data7, aud_intfc8_data1, phase_flag27, _, qdss_gpio,
+ _, _, _, _, _, _),
+ [77] = PINGROUP(77, aud_intfc2_clk, phase_flag6, _, qdss_gpio8, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, aud_intfc2_ws, phase_flag5, _, qdss_gpio9, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, aud_intfc2_data0, phase_flag4, _, qdss_gpio10, _, _, _, _, _, _, _),
+ [80] = PINGROUP(80, aud_intfc2_data1, phase_flag3, _, _, qdss_gpio11, _, _, _, _, _, _),
+ [81] = PINGROUP(81, aud_intfc2_data2, aud_intfc10_data0, phase_flag2, _, _, qdss_gpio12,
+ _, _, _, _, _),
+ [82] = PINGROUP(82, aud_intfc2_data3, aud_intfc10_data1, phase_flag1, _, qdss_gpio13,
+ _, _, _, _, _, _),
+ [83] = PINGROUP(83, aud_intfc3_clk, dp_rx0, aoss_cti, phase_flag28, _, qdss_gpio14,
+ _, _, _, _, _),
+ [84] = PINGROUP(84, aud_intfc3_ws, dp_rx0, aoss_cti, phase_flag29, _, qdss_gpio15,
+ _, _, _, _, _),
+ [85] = PINGROUP(85, aud_intfc3_data0, dp_rx0, aoss_cti, phase_flag30, _, qdss_gpio0,
+ _, _, _, _, _),
+ [86] = PINGROUP(86, aud_intfc3_data1, aud_mclk0_mirb, dp_rx0, aoss_cti, phase_flag31,
+ _, qdss_gpio1, _, _, _, _),
+ [87] = PINGROUP(87, aud_intfc4_clk, phase_flag7, _, qdss_gpio2, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, aud_intfc4_ws, dp_rx0, phase_flag8, _, qdss_gpio3, _, _, _, _, _, _),
+ [89] = PINGROUP(89, aud_intfc4_data0, dp_rx0, phase_flag9, _, qdss_gpio4,
+ _, _, _, _, _, _),
+ [90] = PINGROUP(90, aud_intfc4_data1, aud_mclk1_mirb, phase_flag10, _, qdss_gpio5,
+ _, _, _, _, _, _),
+ [91] = PINGROUP(91, aud_intfc5_clk, phase_flag11, _, qdss_gpio6, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, aud_intfc5_ws, dp_rx1, phase_flag12, _, qdss_gpio7, _, _, _, _, _, _),
+ [93] = PINGROUP(93, aud_intfc5_data0, dp_rx1, phase_flag13, _, qdss_gpio,
+ _, _, _, _, _, _),
+ [94] = PINGROUP(94, aud_intfc5_data1, aud_mclk2_mirb, phase_flag14, tmess_prng0, _,
+ qdss_gpio8, _, _, _, _, _),
+ [95] = PINGROUP(95, aud_intfc6_clk, dp_rx1, phase_flag15, tmess_prng1, _, qdss_gpio9,
+ _, _, _, _, _),
+ [96] = PINGROUP(96, aud_intfc6_ws, dp_rx1, phase_flag16, _, qdss_gpio10, _, _, _, _, _, _),
+ [97] = PINGROUP(97, aud_intfc6_data0, dp_rx1, qdss_gpio11, _, _, _, _, _, _, _, _),
+ [98] = PINGROUP(98, aud_intfc6_data1, dp_rx1, phase_flag0, _, qdss_gpio12,
+ _, _, _, _, _, _),
+ [99] = PINGROUP(99, aud_mclk0_mira, qdss_gpio13, dp_rx00, ddr_pxi0, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, aud_mclk1_mira, aud_refclk0, pll_clk_aux, qdss_gpio14, dp_rx01,
+ ddr_pxi0, _, _, _, _, _),
+ [101] = PINGROUP(101, aud_mclk2_mira, aud_refclk1, phase_flag17, _, qdss_gpio15,
+ _, _, _, _, _, _),
+ [102] = PINGROUP(102, qspi0, qup3_se0_l0_mira, qup3_se0_l1_mirb, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, qspi1, qup3_se0_l1_mira, qup3_se0_l0_mirb, _, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, qspi_clk, qup3_se0_l2, _, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, qspi_cs0_n, qup3_se0_l3, gcc_gp5_clk, _, _, _, _, _, _, _, _),
+ [106] = PINGROUP(106, qspi2, qup3_se0_l4, gcc_gp6_clk, _, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, qspi3, qup3_se0_l5, _, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, qspi_cs1_n, qup3_se0_l6, qdss_gpio, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, qup0_se0_l2, qup0_se1_l2, qup0_se5_l2, mdp_vsync_e, smb_alert_n,
+ _, ddr_pxi1, _, _, _, _),
+ [110] = PINGROUP(110, qup0_se0_l3, qup0_se1_l3, qup0_se5_l3, qdss_cti, mdp_vsync_p,
+ smb_alert, _, ddr_pxi1, _, _, _),
+ [111] = PINGROUP(111, qup0_se1_l0, qup0_se0_l0, smb_dat, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, qup0_se1_l1, qup0_se0_l1, smb_clk, _, _, _, _, _, _, _, _),
+ [113] = PINGROUP(113, qup0_se2_l0, qup0_se3_l2, ccu_i2c_sda5, mdp0_vsync0_out,
+ dbg_out, ddr_pxi2, _, _, _, _, _),
+ [114] = PINGROUP(114, qup0_se2_l1, qup0_se3_l3, ccu_i2c_scl5, mdp0_vsync1_out,
+ _, ddr_pxi2, _, _, _, _, _),
+ [115] = PINGROUP(115, qup0_se3_l0, qup0_se2_l2, ccu_i2c_sda6, mdp0_vsync2_out,
+ _, ddr_pxi3, _, _, _, _, _),
+ [116] = PINGROUP(116, qup0_se3_l1, qup0_se2_l3, ccu_i2c_scl6, mdp0_vsync3_out, _,
+ ddr_pxi3, _, _, _, _, _),
+ [117] = PINGROUP(117, qup0_se4_l0, prng_rosc0, _, ddr_pxi4, _, _, _, _, _, _, _),
+ [118] = PINGROUP(118, qup0_se4_l1, prng_rosc1, _, ddr_pxi4, _, _, _, _, _, _, _),
+ [119] = PINGROUP(119, qup0_se4_l2, _, ddr_pxi6, _, _, _, _, _, _, _, _),
+ [120] = PINGROUP(120, qup0_se4_l3, _, ddr_pxi6, _, _, _, _, _, _, _, _),
+ [121] = PINGROUP(121, qup0_se5_l0, lbist_pass, mdp0_vsync4_out, _, dp_rx10, ddr_pxi7,
+ _, _, _, _, _),
+ [122] = PINGROUP(122, qup0_se5_l1, mbist_pass, mdp0_vsync5_out, _, dp_rx11, ddr_pxi7,
+ _, _, _, _, _),
+ [123] = PINGROUP(123, qup1_se0_l0, qup1_se1_l2, mdp1_vsync0_out, jitter_bist,
+ _, _, _, _, _, _, _),
+ [124] = PINGROUP(124, qup1_se0_l1, qup1_se1_l3, mdp1_vsync1_out, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, qup1_se1_l0, qup1_se0_l2, ccu_i2c_sda7, mdp1_vsync2_out,
+ _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, qup1_se1_l1, qup1_se0_l3, ccu_i2c_scl7, mdp1_vsync3_out, _,
+ atest_usb20, ddr_pxi8, _, _, _, _),
+ [127] = PINGROUP(127, qup1_se2_l2, qup1_se2_l0, _, atest_usb21, ddr_pxi8,
+ _, _, _, _, _, _),
+ [128] = PINGROUP(128, qup1_se2_l3, qup1_se2_l1, _, atest_usb20, ddr_pxi9,
+ _, _, _, _, _, _),
+ [129] = PINGROUP(129, qup1_se3_l2, qup1_se3_l0, ccu_i2c_sda8, mdp1_vsync4_out, _,
+ atest_usb21, ddr_pxi9, _, _, _, _),
+ [130] = PINGROUP(130, qup1_se3_l3, qup1_se3_l1, ccu_i2c_scl8, mdp1_vsync5_out, _,
+ atest_usb20, ddr_pxi10, _, _, _, _),
+ [131] = PINGROUP(131, qup1_se4_l0, qup1_se6_l2, ccu_i2c_sda9, mdp1_vsync6_out, _,
+ atest_usb21, ddr_pxi10, _, _, _, _),
+ [132] = PINGROUP(132, qup1_se4_l1, qup1_se6_l3, ccu_i2c_scl9, mdp1_vsync7_out, _,
+ vsense_trigger_mirnat, ddr_pxi11, _, _, _, _),
+ [133] = PINGROUP(133, qup1_se5_l0, emac0_ptp, mdp1_vsync8_out, _, ddr_pxi11,
+ _, _, _, _, _, _),
+ [134] = PINGROUP(134, qup1_se5_l1, emac0_ptp, mdp1_vsync9_out, _, ddr_pxi12,
+ _, _, _, _, _, _),
+ [135] = PINGROUP(135, qup1_se5_l2, emac0_ptp, mdp1_vsync10_out, _, ddr_pxi12,
+ _, _, _, _, _, _),
+ [136] = PINGROUP(136, qup1_se5_l3, emac0_ptp, _, ddr_pxi13, _, _, _, _, _, _, _),
+ [137] = PINGROUP(137, qup1_se6_l0, qup1_se4_l2, dp_rx0, _, ddr_pxi13, _, _, _, _, _, _),
+ [138] = PINGROUP(138, qup1_se6_l1, qup1_se4_l3, dp_rx0, qdss_cti, jitter_bist,
+ ddr_pxi14, _, _, _, _, _),
+ [139] = PINGROUP(139, qup2_se0_l0, emac0_ptp, mdp0_vsync6_out, ddr_pxi14,
+ _, _, _, _, _, _, _),
+ [140] = PINGROUP(140, qup2_se0_l1, emac0_ptp, mdp0_vsync7_out, _, _, _, _, _, _, _, _),
+ [141] = PINGROUP(141, qup2_se0_l2, emac0_ptp, mdp0_vsync8_out, _, _, _, _, _, _, _, _),
+ [142] = PINGROUP(142, qup2_se0_l3, emac0_ptp, qdss_cti, mdp0_vsync9_out,
+ _, _, _, _, _, _, _),
+ [143] = PINGROUP(143, qup2_se1_l2, qup2_se4_l2, ccu_timer10, mdp0_vsync10_out,
+ _, _, _, _, _, _, _),
+ [144] = PINGROUP(144, qup2_se1_l3, qup2_se4_l3, ccu_timer11, qdss_cti, mdp_vsync_s,
+ _, _, _, _, _, _),
+ [145] = PINGROUP(145, qup2_se2_l0, _, _, _, _, _, _, _, _, _, _),
+ [146] = PINGROUP(146, qup2_se2_l1, _, _, _, _, _, _, _, _, _, _),
+ [147] = PINGROUP(147, qup2_se2_l2, _, _, _, _, _, _, _, _, _, _),
+ [148] = PINGROUP(148, qup2_se2_l3, _, _, _, _, _, _, _, _, _, _),
+ [149] = PINGROUP(149, qup2_se2_l4, _, _, _, _, _, _, _, _, _, _),
+ [150] = PINGROUP(150, qup2_se3_l0, qup2_se4_l4, ccu_timer12, _, _, _, _, _, _, _, _),
+ [151] = PINGROUP(151, qup2_se3_l1, qup2_se4_l5, ccu_timer13, _, _, _, _, _, _, _, _),
+ [152] = PINGROUP(152, qup2_se3_l2, qup2_se4_l6, ccu_timer14, _, _, _, _, _, _, _, _),
+ [153] = PINGROUP(153, qup2_se3_l3, ccu_timer15, _, _, _, _, _, _, _, _, _),
+ [154] = PINGROUP(154, qup2_se4_l0, qup2_se1_l0, _, _, _, _, _, _, _, _, _),
+ [155] = PINGROUP(155, qup2_se4_l1, qup2_se1_l1, _, _, _, _, _, _, _, _, _),
+ [156] = PINGROUP(156, qup2_se5_l0, qup2_se6_l2, _, _, _, _, _, _, _, _, _),
+ [157] = PINGROUP(157, qup2_se5_l1, qup2_se6_l3, _, _, _, _, _, _, _, _, _),
+ [158] = PINGROUP(158, qup2_se6_l0, qup2_se5_l2, dp_rx1, _, _, _, _, _, _, _, _),
+ [159] = PINGROUP(159, qup2_se6_l1, qup2_se5_l3, dp_rx1, _, _, _, _, _, _, _, _),
+ [160] = PINGROUP(160, wcn_sw_ctrl, _, _, _, _, _, _, _, _, _, _),
+ [161] = PINGROUP(161, wcn_sw, _, _, _, _, _, _, _, _, _, _),
+ [162] = PINGROUP(162, qdss_cti, _, ddr_pxi15, _, _, _, _, _, _, _, _),
+ [163] = PINGROUP(163, qdss_cti, _, ddr_pxi15, _, _, _, _, _, _, _, _),
+ [164] = PINGROUP(164, usb0_phy_ps, _, sailss_ospi, ddr_pxi5, _, _, _, _, _, _, _),
+ [165] = PINGROUP(165, usb1_phy_ps, dbg_out_clk, sailss_ospi, ddr_pxi5,
+ _, _, _, _, _, _, _),
+ [166] = PINGROUP(166, _, _, _, _, _, _, _, _, _, _, _),
+ [167] = PINGROUP(167, pwrbrk_i_n, _, _, _, _, _, _, _, _, _, _),
+ [168] = PINGROUP(168, bist_done, _, _, _, _, _, _, _, _, _, _),
+ [169] = PINGROUP(169, tb_trig_sdc4, _, _, _, _, _, _, _, _, _, _),
+ [170] = PINGROUP(170, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [171] = PINGROUP(171, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [172] = PINGROUP(172, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [173] = PINGROUP(173, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [174] = PINGROUP(174, sdc4_cmd, _, _, _, _, _, _, _, _, _, _),
+ [175] = PINGROUP(175, sdc4_clk, _, _, _, _, _, _, _, _, _, _),
+ [176] = PINGROUP(176, ccu_async_in0, pll_bist_sync, atest_char_start,
+ _, _, _, _, _, _, _, _),
+ [177] = PINGROUP(177, ccu_async_in1, atest_char0, _, _, _, _, _, _, _, _, _),
+ [178] = PINGROUP(178, ccu_async_in2, atest_char1, _, _, _, _, _, _, _, _, _),
+ [179] = PINGROUP(179, ccu_async_in3, atest_char2, _, _, _, _, _, _, _, _, _),
+ [180] = PINGROUP(180, ccu_async_in4, atest_char3, _, _, _, _, _, _, _, _, _),
+ [181] = UFS_RESET(ufs_reset, 0xBD004),
+};
+
+static const struct msm_gpio_wakeirq_map nord_pdc_map[] = {
+ { 0, 67 }, { 1, 68 }, { 2, 82 }, { 3, 69 }, { 4, 70 },
+ { 5, 83 }, { 6, 71 }, { 7, 72 }, { 8, 84 }, { 9, 73 },
+ { 10, 119 }, { 11, 85 }, { 45, 107 }, { 46, 98 }, { 102, 77 },
+ { 108, 78 }, { 110, 120 }, { 114, 80 }, { 116, 81 }, { 120, 117 },
+ { 124, 108 }, { 126, 99 }, { 128, 100 }, { 132, 101 }, { 138, 87 },
+ { 142, 88 }, { 144, 89 }, { 153, 90 }, { 157, 91 }, { 159, 118 },
+ { 160, 110 }, { 161, 79 }, { 166, 109 }, { 168, 111 },
+};
+
+static const struct msm_pinctrl_soc_data nord_tlmm = {
+ .pins = nord_pins,
+ .npins = ARRAY_SIZE(nord_pins),
+ .functions = nord_functions,
+ .nfunctions = ARRAY_SIZE(nord_functions),
+ .groups = nord_groups,
+ .ngroups = ARRAY_SIZE(nord_groups),
+ .ngpios = 182,
+ .wakeirq_map = nord_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(nord_pdc_map),
+ .egpio_func = 11,
+};
+
+static const struct of_device_id nord_tlmm_of_match[] = {
+ { .compatible = "qcom,nord-tlmm", .data = &nord_tlmm },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nord_tlmm_of_match);
+
+static int nord_tlmm_probe(struct platform_device *pdev)
+{
+ const struct msm_pinctrl_soc_data *pinctrl_data;
+ struct device *dev = &pdev->dev;
+
+ pinctrl_data = device_get_match_data(dev);
+ if (!pinctrl_data)
+ return -EINVAL;
+
+ return msm_pinctrl_probe(pdev, &nord_tlmm);
+}
+
+static struct platform_driver nord_tlmm_driver = {
+ .driver = {
+ .name = "nord-tlmm",
+ .of_match_table = nord_tlmm_of_match,
+ },
+ .probe = nord_tlmm_probe,
+};
+
+static int __init nord_tlmm_init(void)
+{
+ return platform_driver_register(&nord_tlmm_driver);
+}
+arch_initcall(nord_tlmm_init);
+
+static void __exit nord_tlmm_exit(void)
+{
+ platform_driver_unregister(&nord_tlmm_driver);
+}
+module_exit(nord_tlmm_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies Inc. Nord TLMM driver");
+MODULE_LICENSE("GPL");
--
2.47.3
^ permalink raw reply related
* [PATCH 1/3] dt-bindings: pinctrl: describe the TLMM controller on Qualcomm Nord platforms
From: Bartosz Golaszewski @ 2026-04-03 13:27 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel,
Bartosz Golaszewski
In-Reply-To: <20260403-nord-tlmm-v1-0-4864f400c700@oss.qualcomm.com>
Add a DT binding document describing the TLMM pin controller available
on the Nord platforms from Qualcomm.
Co-developed-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
.../bindings/pinctrl/qcom,nord-tlmm.yaml | 206 +++++++++++++++++++++
1 file changed, 206 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,nord-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,nord-tlmm.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b1fdaa24a045469e3dec512ce0200f240daa1959
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,nord-tlmm.yaml
@@ -0,0 +1,206 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,nord-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. Nord TLMM block
+
+maintainers:
+ - Bartosz Golaszewski <brgl@kernel.org>
+
+description: |
+ Top Level Mode Multiplexer pin controller in Qualcomm Nord SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,nord-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 74
+
+ gpio-line-names:
+ maxItems: 180
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-nord-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-nord-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-nord-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+ unevaluatedProperties: false
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9]|180])$"
+ - enum: [ ufs_reset ]
+ minItems: 1
+ maxItems: 16
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ aoss_cti, atest_char0, atest_char1, atest_char2, atest_char3,
+ atest_char_start, atest_usb20, atest_usb21, aud_intfc0_clk,
+ aud_intfc0_data0, aud_intfc0_data1, aud_intfc0_data2,
+ aud_intfc0_data3, aud_intfc0_data4, aud_intfc0_data5,
+ aud_intfc0_data6, aud_intfc0_data7, aud_intfc0_ws,
+ aud_intfc10_clk, aud_intfc10_data0, aud_intfc10_data1,
+ aud_intfc10_ws, aud_intfc1_clk, aud_intfc1_data0,
+ aud_intfc1_data1, aud_intfc1_data2, aud_intfc1_data3,
+ aud_intfc1_data4, aud_intfc1_data5, aud_intfc1_data6,
+ aud_intfc1_data7, aud_intfc1_ws, aud_intfc2_clk,
+ aud_intfc2_data0, aud_intfc2_data1, aud_intfc2_data2,
+ aud_intfc2_data3, aud_intfc2_ws, aud_intfc3_clk,
+ aud_intfc3_data0, aud_intfc3_data1, aud_intfc3_ws,
+ aud_intfc4_clk, aud_intfc4_data0, aud_intfc4_data1,
+ aud_intfc4_ws, aud_intfc5_clk, aud_intfc5_data0,
+ aud_intfc5_data1, aud_intfc5_ws, aud_intfc6_clk,
+ aud_intfc6_data0, aud_intfc6_data1, aud_intfc6_ws,
+ aud_intfc7_clk, aud_intfc7_data0, aud_intfc7_data1,
+ aud_intfc7_ws, aud_intfc8_clk, aud_intfc8_data0,
+ aud_intfc8_data1, aud_intfc8_ws, aud_intfc9_clk,
+ aud_intfc9_data0, aud_intfc9_ws, aud_mclk0_mira,
+ aud_mclk0_mirb, aud_mclk1_mira, aud_mclk1_mirb,
+ aud_mclk2_mira, aud_mclk2_mirb, aud_refclk0, aud_refclk1,
+ bist_done, ccu_async_in0, ccu_async_in1, ccu_async_in2,
+ ccu_async_in3, ccu_async_in4, ccu_async_in5, ccu_i2c_scl0,
+ ccu_i2c_scl1, ccu_i2c_scl2, ccu_i2c_scl3, ccu_i2c_scl4,
+ ccu_i2c_scl5, ccu_i2c_scl6, ccu_i2c_scl7, ccu_i2c_scl8,
+ ccu_i2c_scl9, ccu_i2c_sda0, ccu_i2c_sda1, ccu_i2c_sda2,
+ ccu_i2c_sda3, ccu_i2c_sda4, ccu_i2c_sda5, ccu_i2c_sda6,
+ ccu_i2c_sda7, ccu_i2c_sda8, ccu_i2c_sda9, ccu_timer0,
+ ccu_timer1, ccu_timer10, ccu_timer11, ccu_timer12, ccu_timer13,
+ ccu_timer14, ccu_timer15, ccu_timer2, ccu_timer3, ccu_timer4,
+ ccu_timer5, ccu_timer6, ccu_timer7, ccu_timer8, ccu_timer9,
+ clink_debug, dbg_out, dbg_out_clk, ddr_bist_complete,
+ ddr_bist_fail, ddr_bist_start, ddr_bist_stop, ddr_pxi0,
+ ddr_pxi1, ddr_pxi10, ddr_pxi11, ddr_pxi12, ddr_pxi13, ddr_pxi14,
+ ddr_pxi15, ddr_pxi2, ddr_pxi3, ddr_pxi4, ddr_pxi5, ddr_pxi6,
+ ddr_pxi7, ddr_pxi8, ddr_pxi9, dp_rx0, dp_rx00, dp_rx01,
+ dp_rx0_mute, dp_rx1, dp_rx10, dp_rx11, dp_rx1_mute, edp0_hot,
+ edp0_lcd, edp1_hot, edp1_lcd, edp2_hot, edp2_lcd, edp3_hot,
+ edp3_lcd, emac0_mcg0, emac0_mcg1, emac0_mcg2, emac0_mcg3,
+ emac0_mdc, emac0_mdio, emac0_ptp, emac1_mcg0, emac1_mcg1,
+ emac1_mcg2, emac1_mcg3, emac1_mdc, emac1_mdio, emac1_ptp,
+ gcc_gp1_clk, gcc_gp2_clk, gcc_gp3_clk, gcc_gp4_clk, gcc_gp5_clk,
+ gcc_gp6_clk, gcc_gp7_clk, gcc_gp8_clk, jitter_bist, lbist_pass,
+ mbist_pass, mdp0_vsync0_out, mdp0_vsync10_out, mdp0_vsync1_out,
+ mdp0_vsync2_out, mdp0_vsync3_out, mdp0_vsync4_out,
+ mdp0_vsync5_out, mdp0_vsync6_out, mdp0_vsync7_out,
+ mdp0_vsync8_out, mdp0_vsync9_out, mdp1_vsync0_out,
+ mdp1_vsync10_out, mdp1_vsync1_out, mdp1_vsync2_out,
+ mdp1_vsync3_out, mdp1_vsync4_out, mdp1_vsync5_out,
+ mdp1_vsync6_out, mdp1_vsync7_out, mdp1_vsync8_out,
+ mdp1_vsync9_out, mdp_vsync_e, mdp_vsync_p, mdp_vsync_s,
+ pcie0_clk_req_n, pcie1_clk_req_n, pcie2_clk_req_n,
+ pcie3_clk_req_n, phase_flag0, phase_flag1, phase_flag10,
+ phase_flag11, phase_flag12, phase_flag13, phase_flag14,
+ phase_flag15, phase_flag16, phase_flag17, phase_flag18,
+ phase_flag19, phase_flag2, phase_flag20, phase_flag21,
+ phase_flag22, phase_flag23, phase_flag24, phase_flag25,
+ phase_flag26, phase_flag27, phase_flag28, phase_flag29,
+ phase_flag3, phase_flag30, phase_flag31, phase_flag4,
+ phase_flag5, phase_flag6, phase_flag7, phase_flag8,
+ phase_flag9, pll_bist_sync, pll_clk_aux, prng_rosc0, prng_rosc1,
+ pwrbrk_i_n, qdss_cti, qdss_gpio, qdss_gpio0, qdss_gpio1,
+ qdss_gpio10, qdss_gpio11, qdss_gpio12, qdss_gpio13, qdss_gpio14,
+ qdss_gpio15, qdss_gpio2, qdss_gpio3, qdss_gpio4, qdss_gpio5,
+ qdss_gpio6, qdss_gpio7, qdss_gpio8, qdss_gpio9, qspi0, qspi1,
+ qspi2, qspi3, qspi_clk, qspi_cs0_n, qspi_cs1_n, qup0_se0_l0,
+ qup0_se0_l1, qup0_se0_l2, qup0_se0_l3, qup0_se1_l0, qup0_se1_l1,
+ qup0_se1_l2, qup0_se1_l3, qup0_se2_l0, qup0_se2_l1, qup0_se2_l2,
+ qup0_se2_l3, qup0_se3_l0, qup0_se3_l1, qup0_se3_l2, qup0_se3_l3,
+ qup0_se4_l0, qup0_se4_l1, qup0_se4_l2, qup0_se4_l3, qup0_se5_l0,
+ qup0_se5_l1, qup0_se5_l2, qup0_se5_l3, qup1_se0_l0, qup1_se0_l1,
+ qup1_se0_l2, qup1_se0_l3, qup1_se1_l0, qup1_se1_l1, qup1_se1_l2,
+ qup1_se1_l3, qup1_se2_l0, qup1_se2_l1, qup1_se2_l2, qup1_se2_l3,
+ qup1_se3_l0, qup1_se3_l1, qup1_se3_l2, qup1_se3_l3, qup1_se4_l0,
+ qup1_se4_l1, qup1_se4_l2, qup1_se4_l3, qup1_se5_l0, qup1_se5_l1,
+ qup1_se5_l2, qup1_se5_l3, qup1_se6_l0, qup1_se6_l1, qup1_se6_l2,
+ qup1_se6_l3, qup2_se0_l0, qup2_se0_l1, qup2_se0_l2, qup2_se0_l3,
+ qup2_se1_l0, qup2_se1_l1, qup2_se1_l2, qup2_se1_l3, qup2_se2_l0,
+ qup2_se2_l1, qup2_se2_l2, qup2_se2_l3, qup2_se2_l4, qup2_se3_l0,
+ qup2_se3_l1, qup2_se3_l2, qup2_se3_l3, qup2_se4_l0, qup2_se4_l1,
+ qup2_se4_l2, qup2_se4_l3, qup2_se4_l4, qup2_se4_l5, qup2_se4_l6,
+ qup2_se5_l0, qup2_se5_l1, qup2_se5_l2, qup2_se5_l3, qup2_se6_l0,
+ qup2_se6_l1, qup2_se6_l2, qup2_se6_l3, qup3_se0_l0_mira,
+ qup3_se0_l0_mirb, qup3_se0_l1_mira, qup3_se0_l1_mirb,
+ qup3_se0_l2, qup3_se0_l3, qup3_se0_l4, qup3_se0_l5, qup3_se0_l6,
+ sailss_ospi, sdc4_clk, sdc4_cmd, sdc4_data, smb_alert,
+ smb_alert_n, smb_clk, smb_dat, tb_trig_sdc4, tmess_prng0,
+ tmess_prng1, tsc_timer0, tsc_timer1, tsc_timer2, tsc_timer3,
+ tsc_timer4, tsc_timer5, tsc_timer6, tsc_timer7, tsc_timer8,
+ tsc_timer9, tsense_pwm1, tsense_pwm2, tsense_pwm3, tsense_pwm4,
+ tsense_pwm5, tsense_pwm6, tsense_pwm7, tsense_pwm8, usb0_hs,
+ usb0_phy_ps, usb1_hs, usb1_phy_ps, usb2_hs, usxgmii0_phy,
+ usxgmii1_phy, vsense_trigger_mirnat, wcn_sw, wcn_sw_ctrl]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@f100000 {
+ compatible = "qcom,nord-tlmm";
+ reg = <0x0f100000 0xc0000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 181>;
+ wakeup-parent = <&pdc>;
+
+ qup_uart15_default: qup-uart15-default-state {
+ tx-pins {
+ pins = "gpio147";
+ function = "qup2_se2_l2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio148";
+ function = "qup2_se2_l3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+...
--
2.47.3
^ permalink raw reply related
* [PATCH 0/3] pinctrl: qcom: add support for the TLMM controller on Nord platforms
From: Bartosz Golaszewski @ 2026-04-03 13:27 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel,
Bartosz Golaszewski
This adds DT bindings describing the TLMM controller on Qualcomm Nord
platforms, the pinctrl driver and enables it in arm64 defconfig.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Bartosz Golaszewski (3):
dt-bindings: pinctrl: describe the TLMM controller on Qualcomm Nord platforms
pinctrl: qcom: add the TLMM driver for the Nord platforms
arm64: defconfig: enable the Qualcomm Nord TLMM driver
.../bindings/pinctrl/qcom,nord-tlmm.yaml | 206 ++
arch/arm64/configs/defconfig | 1 +
drivers/pinctrl/qcom/Kconfig.msm | 7 +
drivers/pinctrl/qcom/Makefile | 1 +
drivers/pinctrl/qcom/pinctrl-nord.c | 3297 ++++++++++++++++++++
5 files changed, 3512 insertions(+)
---
base-commit: 3b058d1aeeeff27a7289529c4944291613b364e9
change-id: 20260403-nord-tlmm-b5878960cec6
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v3 0/3] thermal: spacemit: Add support for SpacemiT K1 SoC thermal sensor
From: Vincent Legoll @ 2026-04-03 12:57 UTC (permalink / raw)
To: alex, aou, conor+dt, daniel.lezcano, devicetree, dlan, krzk+dt,
krzysztof.kozlowski, linux-kernel, linux-pm, linux-riscv,
lukasz.luba, p.zabel, palmer, pjw, rafael, robh, rui.zhang,
spacemit, gsh517025
In-Reply-To: <20260119-patchv2-k1-thermal-v3-0-3d82c9ebe8a4@163.com>
Hello,
I applied this series on top of:
- next-20260402
-
https://patchwork.kernel.org/project/linux-riscv/patch/20260330-orangepi-sd-card-uhs-v5-9-bd853604322d@gmail.com/
I need the the SD card series to boot from SD card.
I'm also seeing the same "it works" state as Gong Shuai.
So you can add another:
Tested-by: Vincent Legoll <legoll@online.fr> # OrangePi-RV2
Regards
Thanks
^ permalink raw reply
* Re: [PATCH 2/3] clk: eswin: Add eic7700 HSP clock driver
From: Benoît Monin @ 2026-04-03 13:00 UTC (permalink / raw)
To: dongxuyang
Cc: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
linux-kernel, p.zabel, huangyifeng, ningyu, linmin,
pinkesh.vaghela
In-Reply-To: <20260403093612.725-1-dongxuyang@eswincomputing.com>
On Fri, 03 Apr 2026 17:36:12 +0800, dongxuyang@eswincomputing.com <dongxuyang@eswincomputing.com> wrote:
> diff --git a/drivers/clk/eswin/clk-eic7700-hsp.c b/drivers/clk/eswin/clk-eic7700-hsp.c
> new file mode 100644
> index 000000000000..65ad9e762ee9
> --- /dev/null
> +++ b/drivers/clk/eswin/clk-eic7700-hsp.c
> @@ -0,0 +1,339 @@
> [ ... skip 64 lines ... ]
> +{
> + struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
> + unsigned long flags;
> + u32 reg;
> +
> + spin_lock_irqsave(gate->lock, flags);
You can use guard(spinlock_irqsave)(gate->lock) instead, and drop the unlock.
--
Benoît Monin, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* [PATCH v8 3/3] riscv: dts: spacemit: Enable USB3.0/PCIe on OrangePi RV2
From: Han Gao @ 2026-04-03 12:51 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775220547.git.gaohan@iscas.ac.cn>
Enable the DWC3 USB 3.0 controller and its associated usbphy2 on the
OrangePi RV2 board.
The board utilizes a Genesys Logic GL3523 USB3.0 hub.
Define a 3.3v fixed voltage regulator for PCIe and enable PCIe and
PHY-related Device Tree nodes for the OrangePi RV2.
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 81 +++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index f7a1dadaa95f..5b331bf987db 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -23,6 +23,15 @@ chosen {
stdout-path = "serial0";
};
+ pcie_vcc3v3: regulator-pcie-vcc3v3 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio K1_GPIO(116) GPIO_ACTIVE_HIGH>;
+ regulator-name = "pcie_vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
vcc_5v0: regulator-vcc-5v0 {
compatible = "regulator-fixed";
regulator-name = "vcc_5v0";
@@ -42,6 +51,16 @@ vcc4v0: regulator-vcc4v0 {
vin-supply = <&vcc_5v0>;
};
+ vcc5v0_usb30: regulator-vcc5v0-usb30 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb30";
+ enable-active-high;
+ gpios = <&gpio K1_GPIO(123) GPIO_ACTIVE_HIGH>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -54,6 +73,10 @@ led1 {
};
};
+&combo_phy {
+ status = "okay";
+};
+
ð0 {
phy-handle = <&rgmii0>;
phy-mode = "rgmii-id";
@@ -224,8 +247,66 @@ dldo7 {
};
};
+&pcie1_phy {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_3_cfg>;
+ status = "okay";
+};
+
+&pcie1_port {
+ phys = <&pcie1_phy>;
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+};
+
+&pcie1 {
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+ status = "okay";
+};
+
+&pcie2_phy {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_4_cfg>;
+ status = "okay";
+};
+
+&pcie2_port {
+ phys = <&pcie2_phy>;
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+};
+
+&pcie2 {
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
status = "okay";
};
+
+&usbphy2 {
+ status = "okay";
+};
+
+&usb_dwc3 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ vbus-supply = <&vcc5v0_usb30>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb5e3,610";
+ reg = <0x1>;
+ peer-hub = <&hub_3_0>;
+ vdd-supply = <&vcc_5v0>;
+ };
+
+ hub_3_0: hub@2 {
+ compatible = "usb5e3,620";
+ reg = <0x2>;
+ peer-hub = <&hub_2_0>;
+ vdd-supply = <&vcc_5v0>;
+ };
+};
--
2.47.3
^ permalink raw reply related
* [PATCH v8 2/3] riscv: dts: spacemit: Define the P1 PMIC regulators for OrangePi RV2
From: Han Gao @ 2026-04-03 12:51 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775220547.git.gaohan@iscas.ac.cn>
Define the DC power input and the 4v power as fixed regulator supplies.
Define the SpacemiT P1 PMIC voltage regulators and their constraints.
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 131 ++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 57ec1cc32b03..f7a1dadaa95f 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -23,6 +23,25 @@ chosen {
stdout-path = "serial0";
};
+ vcc_5v0: regulator-vcc-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_5v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc4v0: regulator-vcc4v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc4v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ vin-supply = <&vcc_5v0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -91,6 +110,118 @@ &i2c8 {
pinctrl-names = "default";
pinctrl-0 = <&i2c8_cfg>;
status = "okay";
+
+ pmic@41 {
+ compatible = "spacemit,p1";
+ reg = <0x41>;
+ interrupts = <64>;
+ vin1-supply = <&vcc4v0>;
+ vin2-supply = <&vcc4v0>;
+ vin3-supply = <&vcc4v0>;
+ vin4-supply = <&vcc4v0>;
+ vin5-supply = <&vcc4v0>;
+ vin6-supply = <&vcc4v0>;
+ aldoin-supply = <&vcc4v0>;
+ dldoin1-supply = <&buck5>;
+ dldoin2-supply = <&buck5>;
+
+ regulators {
+ buck1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck3_1v8: buck3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck4_3v3: buck4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck5: buck5 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck6 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ aldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ aldo2 {
+ /* not connected */
+ };
+
+ aldo3 {
+ /* not connected */
+ };
+
+ aldo4 {
+ /* not connected */
+ };
+
+ dldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ dldo2 {
+ /* not connected */
+ };
+
+ dldo3 {
+ /* not connected */
+ };
+
+ dldo4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-always-on;
+ };
+
+ dldo5 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ dldo6 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-always-on;
+ };
+
+ dldo7 {
+ /* not connected */
+ };
+ };
+ };
};
&uart0 {
--
2.47.3
^ permalink raw reply related
* [PATCH v8 1/3] riscv: dts: spacemit: Enable i2c8 adapter for OrangePi RV2
From: Han Gao @ 2026-04-03 12:51 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775220547.git.gaohan@iscas.ac.cn>
The adapter is used to access the SpacemiT P1 PMIC present in this board.
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 7b7331cb3c72..57ec1cc32b03 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -87,6 +87,12 @@ &pdma {
status = "okay";
};
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8_cfg>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
--
2.47.3
^ permalink raw reply related
* [PATCH v8 0/3] riscv: dts: spacemit: Add PMIC regulators usb pcie
From: Han Gao @ 2026-04-03 12:51 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
Changes in v7:
- patch 3:
rename usb_dwc3 from vdd-supply to vbus-supply
- Link to v7: https://lore.kernel.org/linux-riscv/cover.1775219669.git.gaohan@iscas.ac.cn
Changes in v6:
- patch 1:
reorder i2c8
- patch 3:
restore vcc5v0_usb30
remove vin-supply from pcie_vcc3v3
restore vpcie3v3-supply from pcie2
update hub vdd-supply
- Link to v6: https://lore.kernel.org/linux-riscv/cover.1775214644.git.gaohan@iscas.ac.cn/
Changes in v5:
- patch 2:
restore floating nodes and mark as 'not connected'
- patch 3:
remove vcc5v0_usb30
reorder pcie_vcc3v3 and add vin-supply
remove redundant vpcie3v3-supply from pcie2
update hub vdd-supply based on Chukun's patch
- Link to v5: https://lore.kernel.org/linux-riscv/cover.1775148159.git.gaohan@iscas.ac.cn/
Han Gao (3):
riscv: dts: spacemit: Enable i2c8 adapter for OrangePi RV2
riscv: dts: spacemit: Define the P1 PMIC regulators for OrangePi RV2
riscv: dts: spacemit: Enable USB3.0/PCIe on OrangePi RV2
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 218 ++++++++++++++++++
1 file changed, 218 insertions(+)
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
prerequisite-patch-id: ef6e9c7b5854d0c08066b72f9a7868db8c2140eb
prerequisite-patch-id: cfe3800f8c791ec4c63e070af9628e88e0fc31b9
prerequisite-patch-id: b76493e625ae257c8adcd67874178458420e4d47
prerequisite-patch-id: 88e01dc92c83bd88ddeb78891d3088209fed8d6b
prerequisite-patch-id: 60336d10ab8322c70596d0f046b6b5c54bb24b54
prerequisite-patch-id: 68c4d869548687dc115dd91e2ffb8f4c11482d86
prerequisite-patch-id: fdadcf964c2cb3406160edb579d99a8d5695f8e6
prerequisite-patch-id: 73b9e745338b0499b849fa4f7f9508987ab39a59
prerequisite-patch-id: cd26770c2160c3c31a406bd8a6b01ab666180ae0
prerequisite-patch-id: e5dfddc32cefae195692da8b80e19adf086e4ad7
prerequisite-patch-id: 7fd53cbe4977598f26148a4bb1cf692bbdb79a09
prerequisite-patch-id: 96ebac57bb29619b97fe95422206a685825618e9
prerequisite-patch-id: 00fac16b52f60383db3140e2885f3f7f8d14dd1a
prerequisite-patch-id: 3b7a60047b922c48e93599f621cb738856f42354
prerequisite-patch-id: 275c030b963be05dd1041451f539a130ce614277
prerequisite-patch-id: 93963424b0871e64276af0e0b2199b52e29b4603
prerequisite-patch-id: 8383188b1c01ed6280629faaa29c37d699ade241
prerequisite-patch-id: 5f8126b912b924d63d4a1e0c5eb42d212eb0d369
prerequisite-patch-id: e80af628a2e0b5f2eeb3cb1b5e7133d08bdd2c4e
prerequisite-patch-id: 0234a6dca15eb91f98a45a46604ce5b4935048a5
--
2.47.3
^ permalink raw reply
* [PATCH v9 0/2] Add support for Microchip EMC1812
From: Marius Cristea @ 2026-04-03 12:39 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet
Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, Marius Cristea,
Conor Dooley
This is the hwmon driver for EMC1812/13/14/15/33 multichannel Low-Voltage
Remote Diode Sensor Family. The chips in the family have one internal
and different numbers of external channels, ranging from 1 (EMC1812) to
4 channels (EMC1815).
Reading diodes in anti-parallel connection is supported by EMC1814, EMC1815
and EMC1833.
Signed-off-by: Marius Cristea <marius.cristea@microchip.com>
---
Changes in v9:
- improve the wording in the Documentation/hwmon/emc1812.rst file
- add const to variables in the driver
- initialize the EXT2_BETA_CONFIG only for the pats that support it
- update the writeble regmap table to exclude read-only registers
- Link to v8: https://lore.kernel.org/r/20260310-hw_mon-emc1812-v8-0-bc155727e0d2@microchip.com
Changes in v8:
- remove "address scan" from emc1812.rst documentation
- change the second dimension of emc1812_limit_regs_low[][] to 2
- clamp input value before doing math on it to avoid overflow
- use rounding instead of truncation for 8 bits limit registers
- fix misleading comment when HW ID is not recognized
- Link to v7: https://lore.kernel.org/r/20260223-hw_mon-emc1812-v7-0-51e2676f4e20@microchip.com
Changes in v7:
- driver
- fix an overflow emc1812_set_hyst
- remove unused parameter in emc1812_set_temp
- devicetree binding:
- remove unneeded restrictions not to bloating the binding
- Link to v6: https://lore.kernel.org/r/20260212-hw_mon-emc1812-v6-0-e37e9b38d898@microchip.com
Changes in v6:
- driver
- fix an overflow when writing more then 191875 to limits stored on 8
bits register
- remove "i2c_set_clientdata" from probe
- fix discrepancy where writing 16ms and reading it back returns 15ms
at update interval
- skip setting the ideality factor for channels that are not available
on the device
- devicetree binding:
- change the way interrupts are described/used
- add "microchip,enable-anti-parallel"
- rewrite "allOf" section to be more clear
- Link to v5: https://lore.kernel.org/r/20260205-hw_mon-emc1812-v5-0-232835aefe8f@microchip.com
Changes in v5:
- fix calculation in emc1812_get_limit_temp
- use i2c_get_match_data cover the case when the driver is instantiated
via I2C ID table.
- replace dev_info with dev_warn
- remove some unnecessary truncation on 8 bits
- remove clamping when reading the temerature with hyst
- not change the conversion rate at probe time
- use a generic define to remove duplicate channel_info entries
- Link to v4: https://lore.kernel.org/r/20260127-hw_mon-emc1812-v4-0-6bf636b54847@microchip.com
Changes in v4:
- fix file permissions for read only properties
- fix calculation when the limits are written
- remove the temp_min_hyst because the part doesn't support it
- Link to v3: https://lore.kernel.org/r/20251218-hw_mon-emc1812-v3-0-a123ada7b859@microchip.com
Changes in v3:
- remove mesages that are not helpfull
- fix an issue related to NULL labels
- fix sign/unsign calculation
- replace E2BIG with EINVAL
- use BIT() to create mask
- Link to v2: https://lore.kernel.org/r/20251121-hw_mon-emc1812-v2-0-5b2070f8b778@microchip.com
Changes in v2:
- update the interrupt section from yaml file
- update index.rst
- remove fault condition from internal sensor
- remove unused members from structures
- update the driver to work on systems without device tree or
firmware nodes
- add missing include files
- make NULL labels to be not visible
- corect sign/unsign calculations
- corect possible underflow for limits
- Link to v1: https://lore.kernel.org/r/20251029-hw_mon-emc1812-v1-0-be4fd8af016a@microchip.com
---
Marius Cristea (2):
dt-bindings: hwmon: temperature: add support for EMC1812
hwmon: temperature: add support for EMC1812
.../bindings/hwmon/microchip,emc1812.yaml | 184 ++++
Documentation/hwmon/emc1812.rst | 67 ++
Documentation/hwmon/index.rst | 1 +
MAINTAINERS | 8 +
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/emc1812.c | 965 +++++++++++++++++++++
7 files changed, 1237 insertions(+)
---
base-commit: d2b2fea3503e5e12b2e28784152937e48bcca6ff
change-id: 20251002-hw_mon-emc1812-f1b806487d10
Best regards,
--
Marius Cristea <marius.cristea@microchip.com>
^ permalink raw reply
* [PATCH v9 2/2] hwmon: temperature: add support for EMC1812
From: Marius Cristea @ 2026-04-03 12:39 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet
Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, Marius Cristea
In-Reply-To: <20260403-hw_mon-emc1812-v9-0-1a798f31cf2e@microchip.com>
This is the hwmon driver for Microchip EMC1812/13/14/15/33
Multichannel Low-Voltage Remote Diode Sensor Family.
EMC1812 has one external remote temperature monitoring channel.
EMC1813 has two external remote temperature monitoring channels.
EMC1814 has three external remote temperature monitoring channels and
channels 2 and 3 support anti parallel diode.
EMC1815 has four external remote temperature monitoring channels and
channels 1/2 and 3/4 support anti parallel diode.
EMC1833 has two external remote temperature monitoring channels and
channels 1 and 2 support anti parallel diode.
Signed-off-by: Marius Cristea <marius.cristea@microchip.com>
---
Documentation/hwmon/emc1812.rst | 67 +++
Documentation/hwmon/index.rst | 1 +
MAINTAINERS | 2 +
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/emc1812.c | 965 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 1047 insertions(+)
diff --git a/Documentation/hwmon/emc1812.rst b/Documentation/hwmon/emc1812.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0b4fbcaaea71a42ef4db1be25182ab363a136a5d
--- /dev/null
+++ b/Documentation/hwmon/emc1812.rst
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver emc1812
+=====================
+
+Supported chips:
+
+ * Microchip EMC1812, EMC1813, EMC1814, EMC1815, EMC1833
+
+ Prefix: 'emc1812'
+
+ Datasheets:
+
+ - https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC1812-3-4-5-33-Data-Sheet-DS20005751.pdf
+
+Author:
+ Marius Cristea <marius.cristea@microchip.com>
+
+
+Description
+-----------
+
+The Microchip EMC181x/33 chips contain up to 4 remote temperature sensors
+and one internal.
+- The EMC1812 is a single channel remote temperature sensor.
+- The EMC1813 and EMC1833 are dual channel remote temperature sensor. The
+remote channels for this selection of devices can support substrate diodes,
+discrete diode-connected transistors or CPU/GPU thermal diodes.
+- The EMC1814 is a three channel remote temperature sensor that supports
+Anti-Parallel Diode (APD) only on one channel. For the channel that does not
+support APD functionality, substrate diodes, discrete diode-connected
+transistors or CPU/GPU thermal diodes are supported. For the channel that
+supports APD, only discrete diode-connected transistors may be implemented.
+However, if APD is disabled on the EMC1814, then the channel that supports
+APD will be functional with substrate diodes, discrete diode-connected
+transistors and CPU/GPU thermal diodes.
+- The EMC1815 is a four channel remote temperature sensor.
+
+The EMC1815 and EMC1833 support APD on all channels. When APD is enabled,
+the channels support only diode-connected transistors. If APD is disabled,
+then the channels will support substrate transistors, discrete diode-connected
+transistors and CPU/GPU thermal diodes.
+
+Note: Disabling APD functionality to implement substrate diodes on devices
+that support APD eliminates the benefit of APD (two diodes on one channel).
+
+The chips implement three limits for each sensor: low (tempX_min), high
+(tempX_max) and critical (tempX_crit). The chips also implement an
+hysteresis mechanism which applies to all limits. The relative difference
+is stored in a single register on the chip, which means that the relative
+difference between the limit and its hysteresis is always the same for
+all three limits.
+
+This implementation detail implies the following:
+
+* When setting a limit, its hysteresis will automatically follow, the
+ difference staying unchanged. For example, if the old critical limit was
+ 80 degrees C, and the hysteresis was 75 degrees C, and you change the
+ critical limit to 90 degrees C, then the hysteresis will automatically
+ change to 85 degrees C.
+* The hysteresis values can't be set independently. We decided to make
+ only tempX_crit_hyst writable, while all other hysteresis attributes
+ are read-only. Setting tempX_crit_hyst writes the difference between
+ tempX_crit_hyst and tempX_crit into the chip, and the same relative
+ hysteresis applies automatically to all other limits.
+* The limits should be set before the hysteresis. At power up the device
+ starts with 10 degree hysteresis.
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 51a5bdf75b08656ee6499c6b5c50a51fc4d7c210..a03e97f9a97f4d3edf7bcd1e8d1b73a21d5f0ab5 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -69,6 +69,7 @@ Hardware Monitoring Kernel Drivers
ds1621
ds620
emc1403
+ emc1812
emc2103
emc2305
emc6w201
diff --git a/MAINTAINERS b/MAINTAINERS
index 85c236df781e47c78deeb7ef4d80bc94bba604c4..fcb712549ea679d49fde8c97840af9528b52d52b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16651,6 +16651,8 @@ M: Marius Cristea <marius.cristea@microchip.com>
L: linux-hwmon@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/hwmon/microchip,emc1812.yaml
+F: Documentation/hwmon/emc1812.rst
+F: drivers/hwmon/emc1812.c
MICROCHIP I2C DRIVER
M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2760feb9f83b5d3b990b27acff572e587b373e9d..3b53572fd8bfbd752c2235ca429c4f74b1db3095 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -2042,6 +2042,17 @@ config SENSORS_EMC1403
Threshold values can be configured using sysfs.
Data from the different diodes are accessible via sysfs.
+config SENSORS_EMC1812
+ tristate "Microchip Technology EMC1812 driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here to build support for Microchip Technology's
+ EMC181X/33 Multichannel Low-Voltage Remote Diode Sensor Family.
+
+ This driver can also be built as a module. If so, the module
+ will be called emc1812.
+
config SENSORS_EMC2103
tristate "SMSC EMC2103"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 73b2abdcc6dd9cfae4c84b350febc5d8c191e385..e93e4051e99db698dbaae97ac4841e6d810ee8c4 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o
obj-$(CONFIG_SENSORS_DS620) += ds620.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
+obj-$(CONFIG_SENSORS_EMC1812) += emc1812.o
obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o
obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o
obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o
diff --git a/drivers/hwmon/emc1812.c b/drivers/hwmon/emc1812.c
new file mode 100644
index 0000000000000000000000000000000000000000..1ba8feac93b5f078d4e544c72711e69f0be06238
--- /dev/null
+++ b/drivers/hwmon/emc1812.c
@@ -0,0 +1,965 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * HWMON driver for Microchip EMC1812/13/14/15/33 Multichannel high-accuracy
+ * 2-wire low-voltage remote diode temperature monitor family.
+ *
+ * Copyright (C) 2026 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Marius Cristea <marius.cristea@microchip.com>
+ *
+ * Datasheet can be found here:
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC1812-3-4-5-33-Data-Sheet-DS20005751.pdf
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/string.h>
+#include <linux/units.h>
+#include <linux/util_macros.h>
+
+/* EMC1812 Registers Addresses */
+#define EMC1812_STATUS_ADDR 0x02
+#define EMC1812_CONFIG_LO_ADDR 0x03
+
+#define EMC1812_CFG_ADDR 0x09
+#define EMC1812_CONV_ADDR 0x0A
+#define EMC1812_INT_DIODE_HIGH_LIMIT_ADDR 0x0B
+#define EMC1812_INT_DIODE_LOW_LIMIT_ADDR 0x0C
+#define EMC1812_EXT1_HIGH_LIMIT_HIGH_BYTE_ADDR 0x0D
+#define EMC1812_EXT1_LOW_LIMIT_HIGH_BYTE_ADDR 0x0E
+#define EMC1812_ONE_SHOT_ADDR 0x0F
+
+#define EMC1812_EXT1_HIGH_LIMIT_LOW_BYTE_ADDR 0x13
+#define EMC1812_EXT1_LOW_LIMIT_LOW_BYTE_ADDR 0x14
+#define EMC1812_EXT2_HIGH_LIMIT_HIGH_BYTE_ADDR 0x15
+#define EMC1812_EXT2_LOW_LIMIT_HIGH_BYTE_ADDR 0x16
+#define EMC1812_EXT2_HIGH_LIMIT_LOW_BYTE_ADDR 0x17
+#define EMC1812_EXT2_LOW_LIMIT_LOW_BYTE_ADDR 0x18
+#define EMC1812_EXT1_THERM_LIMIT_ADDR 0x19
+#define EMC1812_EXT2_THERM_LIMIT_ADDR 0x1A
+#define EMC1812_EXT_DIODE_FAULT_STATUS_ADDR 0x1B
+
+#define EMC1812_DIODE_FAULT_MASK_ADDR 0x1F
+#define EMC1812_INT_DIODE_THERM_LIMIT_ADDR 0x20
+#define EMC1812_THRM_HYS_ADDR 0x21
+#define EMC1812_CONSEC_ALERT_ADDR 0x22
+
+#define EMC1812_EXT1_BETA_CONFIG_ADDR 0x25
+#define EMC1812_EXT2_BETA_CONFIG_ADDR 0x26
+#define EMC1812_EXT1_IDEALITY_FACTOR_ADDR 0x27
+#define EMC1812_EXT2_IDEALITY_FACTOR_ADDR 0x28
+
+#define EMC1812_EXT3_HIGH_LIMIT_HIGH_BYTE_ADDR 0x2C
+#define EMC1812_EXT3_LOW_LIMIT_HIGH_BYTE_ADDR 0x2D
+#define EMC1812_EXT3_HIGH_LIMIT_LOW_BYTE_ADDR 0x2E
+#define EMC1812_EXT3_LOW_LIMIT_LOW_BYTE_ADDR 0x2F
+#define EMC1812_EXT3_THERM_LIMIT_ADDR 0x30
+#define EMC1812_EXT3_IDEALITY_FACTOR_ADDR 0x31
+
+#define EMC1812_EXT4_HIGH_LIMIT_HIGH_BYTE_ADDR 0x34
+#define EMC1812_EXT4_LOW_LIMIT_HIGH_BYTE_ADDR 0x35
+#define EMC1812_EXT4_HIGH_LIMIT_LOW_BYTE_ADDR 0x36
+#define EMC1812_EXT4_LOW_LIMIT_LOW_BYTE_ADDR 0x37
+#define EMC1812_EXT4_THERM_LIMIT_ADDR 0x38
+#define EMC1812_EXT4_IDEALITY_FACTOR_ADDR 0x39
+#define EMC1812_HIGH_LIMIT_STATUS_ADDR 0x3A
+#define EMC1812_LOW_LIMIT_STATUS_ADDR 0x3B
+#define EMC1812_THERM_LIMIT_STATUS_ADDR 0x3C
+#define EMC1812_ROC_GAIN_ADDR 0x3D
+#define EMC1812_ROC_CONFIG_ADDR 0x3E
+#define EMC1812_ROC_STATUS_ADDR 0x3F
+#define EMC1812_R1_RESH_ADDR 0x40
+#define EMC1812_R1_LIMH_ADDR 0x41
+#define EMC1812_R1_LIML_ADDR 0x42
+#define EMC1812_R1_SMPL_ADDR 0x43
+#define EMC1812_R2_RESH_ADDR 0x44
+#define EMC1812_R2_3_RESL_ADDR 0x45
+#define EMC1812_R2_LIMH_ADDR 0x46
+#define EMC1812_R2_LIML_ADDR 0x47
+#define EMC1812_R2_SMPL_ADDR 0x48
+#define EMC1812_PER_MAXTH_1_ADDR 0x49
+#define EMC1812_PER_MAXT1L_ADDR 0x4A
+#define EMC1812_PER_MAXTH_2_ADDR 0x4B
+#define EMC1812_PER_MAXT2_3L_ADDR 0x4C
+#define EMC1812_GBL_MAXT1H_ADDR 0x4D
+#define EMC1812_GBL_MAXT1L_ADDR 0x4E
+#define EMC1812_GBL_MAXT2H_ADDR 0x4F
+#define EMC1812_GBL_MAXT2L_ADDR 0x50
+#define EMC1812_FILTER_SEL_ADDR 0x51
+
+#define EMC1812_INT_HIGH_BYTE_ADDR 0x60
+#define EMC1812_INT_LOW_BYTE_ADDR 0x61
+#define EMC1812_EXT1_HIGH_BYTE_ADDR 0x62
+#define EMC1812_EXT1_LOW_BYTE_ADDR 0x63
+#define EMC1812_EXT2_HIGH_BYTE_ADDR 0x64
+#define EMC1812_EXT2_LOW_BYTE_ADDR 0x65
+#define EMC1812_EXT3_HIGH_BYTE_ADDR 0x66
+#define EMC1812_EXT3_LOW_BYTE_ADDR 0x67
+#define EMC1812_EXT4_HIGH_BYTE_ADDR 0x68
+#define EMC1812_EXT4_LOW_BYTE_ADDR 0x69
+#define EMC1812_HOTTEST_DIODE_HIGH_BYTE_ADDR 0x6A
+#define EMC1812_HOTTEST_DIODE_LOW_BYTE_ADDR 0x6B
+#define EMC1812_HOTTEST_STATUS_ADDR 0x6C
+#define EMC1812_HOTTEST_CFG_ADDR 0x6D
+
+#define EMC1812_PRODUCT_ID_ADDR 0xFD
+#define EMC1812_MANUFACTURER_ID_ADDR 0xFE
+#define EMC1812_REVISION_ADDR 0xFF
+
+/* EMC1812 Config Bits */
+#define EMC1812_CFG_MSKAL BIT(7)
+#define EMC1812_CFG_RS BIT(6)
+#define EMC1812_CFG_ATTHM BIT(5)
+#define EMC1812_CFG_RECD12 BIT(4)
+#define EMC1812_CFG_RECD34 BIT(3)
+#define EMC1812_CFG_RANGE BIT(2)
+#define EMC1812_CFG_DA_ENA BIT(1)
+#define EMC1812_CFG_APDD BIT(0)
+
+/* EMC1812 Status Bits */
+#define EMC1812_STATUS_ROCF BIT(7)
+#define EMC1812_STATUS_HOTCHG BIT(6)
+#define EMC1812_STATUS_BUSY BIT(5)
+#define EMC1812_STATUS_HIGH BIT(4)
+#define EMC1812_STATUS_LOW BIT(3)
+#define EMC1812_STATUS_FAULT BIT(2)
+#define EMC1812_STATUS_ETHRM BIT(1)
+#define EMC1812_STATUS_ITHRM BIT(0)
+
+#define EMC1812_BETA_LOCK_VAL 0x0F
+
+#define EMC1812_TEMP_CH_ADDR(index) (EMC1812_INT_HIGH_BYTE_ADDR + 2 * (index))
+
+#define EMC1812_FILTER_MASK_LEN 2
+
+#define EMC1812_PID 0x81
+#define EMC1813_PID 0x87
+#define EMC1814_PID 0x84
+#define EMC1815_PID 0x85
+#define EMC1833_PID 0x83
+
+/* The maximum number of channels a member of the family can have */
+#define EMC1812_MAX_NUM_CHANNELS 5
+#define EMC1812_TEMP_OFFSET 64
+
+#define EMC1812_DEFAULT_IDEALITY_FACTOR 0x12
+
+#define EMC1812_TEMP_MASK (HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | \
+ HWMON_T_CRIT | HWMON_T_MAX_HYST | HWMON_T_CRIT_HYST | \
+ HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM | \
+ HWMON_T_CRIT_ALARM | HWMON_T_LABEL)
+
+static const struct hwmon_channel_info * const emc1812_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
+ HWMON_CHANNEL_INFO(temp,
+ EMC1812_TEMP_MASK,
+ EMC1812_TEMP_MASK | HWMON_T_FAULT,
+ EMC1812_TEMP_MASK | HWMON_T_FAULT,
+ EMC1812_TEMP_MASK | HWMON_T_FAULT,
+ EMC1812_TEMP_MASK | HWMON_T_FAULT
+ ),
+ NULL
+};
+
+/**
+ * struct emc1812_features - features of a emc1812 instance
+ * @name: chip's name
+ * @phys_channels: number of physical channels supported by the chip
+ * @has_ext2_beta_reg: the EXT2_BETA register is available on the chip
+ */
+struct emc1812_features {
+ const char *name;
+ u8 phys_channels;
+ bool has_ext2_beta_reg;
+};
+
+static const struct emc1812_features emc1833_chip_config = {
+ .name = "emc1833",
+ .phys_channels = 3,
+ .has_ext2_beta_reg = true,
+};
+
+static const struct emc1812_features emc1812_chip_config = {
+ .name = "emc1812",
+ .phys_channels = 2,
+ .has_ext2_beta_reg = false,
+};
+
+static const struct emc1812_features emc1813_chip_config = {
+ .name = "emc1813",
+ .phys_channels = 3,
+ .has_ext2_beta_reg = true,
+};
+
+static const struct emc1812_features emc1814_chip_config = {
+ .name = "emc1814",
+ .phys_channels = 4,
+ .has_ext2_beta_reg = false,
+};
+
+static const struct emc1812_features emc1815_chip_config = {
+ .name = "emc1815",
+ .phys_channels = 5,
+ .has_ext2_beta_reg = false,
+};
+
+enum emc1812_limit_type {temp_min, temp_max};
+
+static const u8 emc1812_temp_map[] = {
+ [hwmon_temp_min] = temp_min,
+ [hwmon_temp_max] = temp_max,
+};
+
+static const u8 emc1812_temp_crit_regs[] = {
+ [0] = EMC1812_INT_DIODE_THERM_LIMIT_ADDR,
+ [1] = EMC1812_EXT1_THERM_LIMIT_ADDR,
+ [2] = EMC1812_EXT2_THERM_LIMIT_ADDR,
+ [3] = EMC1812_EXT3_THERM_LIMIT_ADDR,
+ [4] = EMC1812_EXT4_THERM_LIMIT_ADDR,
+};
+
+static const u8 emc1812_limit_regs[][2] = {
+ [0] = {
+ [temp_min] = EMC1812_INT_DIODE_LOW_LIMIT_ADDR,
+ [temp_max] = EMC1812_INT_DIODE_HIGH_LIMIT_ADDR,
+ },
+ [1] = {
+ [temp_min] = EMC1812_EXT1_LOW_LIMIT_HIGH_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT1_HIGH_LIMIT_HIGH_BYTE_ADDR,
+ },
+ [2] = {
+ [temp_min] = EMC1812_EXT2_LOW_LIMIT_HIGH_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT2_HIGH_LIMIT_HIGH_BYTE_ADDR,
+ },
+ [3] = {
+ [temp_min] = EMC1812_EXT3_LOW_LIMIT_HIGH_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT3_HIGH_LIMIT_HIGH_BYTE_ADDR,
+ },
+ [4] = {
+ [temp_min] = EMC1812_EXT4_LOW_LIMIT_HIGH_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT4_HIGH_LIMIT_HIGH_BYTE_ADDR,
+ },
+};
+
+static const u8 emc1812_limit_regs_low[][2] = {
+ [0] = {
+ [temp_min] = 0xff,
+ [temp_max] = 0xff,
+ },
+ [1] = {
+ [temp_min] = EMC1812_EXT1_LOW_LIMIT_LOW_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT1_HIGH_LIMIT_LOW_BYTE_ADDR,
+ },
+ [2] = {
+ [temp_min] = EMC1812_EXT2_LOW_LIMIT_LOW_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT2_HIGH_LIMIT_LOW_BYTE_ADDR,
+ },
+ [3] = {
+ [temp_min] = EMC1812_EXT3_LOW_LIMIT_LOW_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT3_HIGH_LIMIT_LOW_BYTE_ADDR,
+ },
+ [4] = {
+ [temp_min] = EMC1812_EXT4_LOW_LIMIT_LOW_BYTE_ADDR,
+ [temp_max] = EMC1812_EXT4_HIGH_LIMIT_LOW_BYTE_ADDR,
+ },
+};
+
+/* Lookup table for temperature conversion times in msec */
+static const u16 emc1812_conv_time[] = {
+ 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 62, 31, 16
+};
+
+/**
+ * struct emc1812_data - information about chip parameters
+ * @labels: labels of the channels
+ * @active_ch_mask: active channels
+ * @chip: pointer to structure holding chip features
+ * @regmap: device register map
+ * @recd34_en: state of Resistance Error Correction (REC) on channels 3 and 4
+ * @recd12_en: state of Resistance Error Correction (REC) on channels 1 and 2
+ * @apdd_en: state of anti-parallel diode mode
+ */
+struct emc1812_data {
+ const char *labels[EMC1812_MAX_NUM_CHANNELS];
+ unsigned long active_ch_mask;
+ const struct emc1812_features *chip;
+ struct regmap *regmap;
+ bool recd34_en;
+ bool recd12_en;
+ bool apdd_en;
+};
+
+/* emc1812 regmap configuration */
+static const struct regmap_range emc1812_regmap_writable_ranges[] = {
+ regmap_reg_range(EMC1812_CFG_ADDR, EMC1812_ONE_SHOT_ADDR),
+ regmap_reg_range(EMC1812_EXT1_HIGH_LIMIT_LOW_BYTE_ADDR, EMC1812_EXT2_THERM_LIMIT_ADDR),
+ regmap_reg_range(EMC1812_DIODE_FAULT_MASK_ADDR, EMC1812_CONSEC_ALERT_ADDR),
+ regmap_reg_range(EMC1812_EXT1_BETA_CONFIG_ADDR, EMC1812_EXT4_IDEALITY_FACTOR_ADDR),
+ regmap_reg_range(EMC1812_ROC_GAIN_ADDR, EMC1812_ROC_CONFIG_ADDR),
+ regmap_reg_range(EMC1812_R1_LIMH_ADDR, EMC1812_R1_SMPL_ADDR),
+ regmap_reg_range(EMC1812_R2_LIMH_ADDR, EMC1812_R2_SMPL_ADDR),
+ regmap_reg_range(EMC1812_FILTER_SEL_ADDR, EMC1812_FILTER_SEL_ADDR),
+ regmap_reg_range(EMC1812_HOTTEST_CFG_ADDR, EMC1812_HOTTEST_CFG_ADDR),
+};
+
+static const struct regmap_access_table emc1812_regmap_wr_table = {
+ .yes_ranges = emc1812_regmap_writable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(emc1812_regmap_writable_ranges),
+};
+
+static const struct regmap_range emc1812_regmap_rd_ranges[] = {
+ regmap_reg_range(EMC1812_STATUS_ADDR, EMC1812_CONFIG_LO_ADDR),
+ regmap_reg_range(EMC1812_CFG_ADDR, EMC1812_ONE_SHOT_ADDR),
+ regmap_reg_range(EMC1812_EXT1_HIGH_LIMIT_LOW_BYTE_ADDR,
+ EMC1812_EXT_DIODE_FAULT_STATUS_ADDR),
+ regmap_reg_range(EMC1812_DIODE_FAULT_MASK_ADDR, EMC1812_CONSEC_ALERT_ADDR),
+ regmap_reg_range(EMC1812_EXT1_BETA_CONFIG_ADDR, EMC1812_FILTER_SEL_ADDR),
+ regmap_reg_range(EMC1812_INT_HIGH_BYTE_ADDR, EMC1812_HOTTEST_CFG_ADDR),
+ regmap_reg_range(EMC1812_PRODUCT_ID_ADDR, EMC1812_REVISION_ADDR),
+};
+
+static const struct regmap_access_table emc1812_regmap_rd_table = {
+ .yes_ranges = emc1812_regmap_rd_ranges,
+ .n_yes_ranges = ARRAY_SIZE(emc1812_regmap_rd_ranges),
+};
+
+static bool emc1812_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case EMC1812_STATUS_ADDR:
+ case EMC1812_EXT_DIODE_FAULT_STATUS_ADDR:
+ case EMC1812_DIODE_FAULT_MASK_ADDR:
+ case EMC1812_EXT1_BETA_CONFIG_ADDR:
+ case EMC1812_EXT2_BETA_CONFIG_ADDR:
+ case EMC1812_HIGH_LIMIT_STATUS_ADDR:
+ case EMC1812_LOW_LIMIT_STATUS_ADDR:
+ case EMC1812_THERM_LIMIT_STATUS_ADDR:
+ case EMC1812_ROC_STATUS_ADDR:
+ case EMC1812_PER_MAXTH_1_ADDR:
+ case EMC1812_PER_MAXT1L_ADDR:
+ case EMC1812_PER_MAXTH_2_ADDR:
+ case EMC1812_PER_MAXT2_3L_ADDR:
+ case EMC1812_GBL_MAXT1H_ADDR:
+ case EMC1812_GBL_MAXT1L_ADDR:
+ case EMC1812_GBL_MAXT2H_ADDR:
+ case EMC1812_GBL_MAXT2L_ADDR:
+ case EMC1812_INT_HIGH_BYTE_ADDR:
+ case EMC1812_INT_LOW_BYTE_ADDR:
+ case EMC1812_EXT1_HIGH_BYTE_ADDR:
+ case EMC1812_EXT1_LOW_BYTE_ADDR:
+ case EMC1812_EXT2_HIGH_BYTE_ADDR:
+ case EMC1812_EXT2_LOW_BYTE_ADDR:
+ case EMC1812_EXT3_HIGH_BYTE_ADDR:
+ case EMC1812_EXT3_LOW_BYTE_ADDR:
+ case EMC1812_EXT4_HIGH_BYTE_ADDR:
+ case EMC1812_EXT4_LOW_BYTE_ADDR:
+ case EMC1812_HOTTEST_DIODE_HIGH_BYTE_ADDR:
+ case EMC1812_HOTTEST_DIODE_LOW_BYTE_ADDR:
+ case EMC1812_HOTTEST_STATUS_ADDR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config emc1812_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .rd_table = &emc1812_regmap_rd_table,
+ .wr_table = &emc1812_regmap_wr_table,
+ .volatile_reg = emc1812_is_volatile_reg,
+ .max_register = EMC1812_REVISION_ADDR,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static umode_t emc1812_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct emc1812_data *data = _data;
+
+ switch (type) {
+ case hwmon_temp:
+ /* Don't show channels which are not described into the device tree */
+ if (!(data->active_ch_mask & BIT(channel)))
+ return 0;
+
+ /* Don't show channels which are not physically connected */
+ if (channel >= data->chip->phys_channels)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ case hwmon_temp_crit:
+ case hwmon_temp_crit_hyst:
+ return 0644;
+ case hwmon_temp_crit_alarm:
+ case hwmon_temp_input:
+ case hwmon_temp_fault:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_min_alarm:
+ return 0444;
+ case hwmon_temp_label:
+ if (data->labels[channel])
+ return 0444;
+ return 0;
+ default:
+ return 0;
+ }
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return 0644;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+};
+
+static int emc1812_get_temp(struct emc1812_data *data, int channel, long *val)
+{
+ __be16 tmp_be16;
+ int ret;
+
+ ret = regmap_bulk_read(data->regmap, EMC1812_TEMP_CH_ADDR(channel),
+ &tmp_be16, sizeof(tmp_be16));
+ if (ret)
+ return ret;
+
+ /* Range is always -64 to 191.875°C */
+ *val = ((be16_to_cpu(tmp_be16) >> 5) - (EMC1812_TEMP_OFFSET << 3)) * 125;
+
+ return 0;
+}
+
+static int emc1812_get_crit_limit_temp(struct emc1812_data *data, int channel, long *val)
+{
+ unsigned int tmp;
+ int ret;
+
+ /* Critical register is 8bits long and keeps only integer part of temperature */
+ ret = regmap_read(data->regmap, emc1812_temp_crit_regs[channel], &tmp);
+ if (ret)
+ return ret;
+
+ *val = tmp;
+ /* Range is always -64 to 191°C */
+ *val = (*val - EMC1812_TEMP_OFFSET) * 1000;
+
+ return 0;
+}
+
+static int emc1812_get_limit_temp(struct emc1812_data *data, int ch,
+ enum emc1812_limit_type type, long *val)
+{
+ unsigned int regvalh;
+ unsigned int regvall = 0;
+ int ret;
+
+ ret = regmap_read(data->regmap, emc1812_limit_regs[ch][type], ®valh);
+ if (ret < 0)
+ return ret;
+
+ if (ch) {
+ ret = regmap_read(data->regmap, emc1812_limit_regs_low[ch][type], ®vall);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Range is always -64 to 191.875°C */
+ *val = ((regvalh << 3) | (regvall >> 5));
+ *val = (*val - (EMC1812_TEMP_OFFSET << 3)) * 125;
+
+ return 0;
+}
+
+static int emc1812_read_reg(struct device *dev, struct emc1812_data *data, u32 attr,
+ int channel, long *val)
+{
+ int hyst, ret;
+
+ switch (attr) {
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ return emc1812_get_limit_temp(data, channel, emc1812_temp_map[attr], val);
+ case hwmon_temp_crit:
+ return emc1812_get_crit_limit_temp(data, channel, val);
+ case hwmon_temp_input:
+ return emc1812_get_temp(data, channel, val);
+ case hwmon_temp_max_hyst:
+ ret = emc1812_get_limit_temp(data, channel, temp_max, val);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(data->regmap, EMC1812_THRM_HYS_ADDR, &hyst);
+ if (ret < 0)
+ return ret;
+
+ *val -= hyst * 1000;
+
+ return 0;
+ case hwmon_temp_crit_hyst:
+ ret = emc1812_get_crit_limit_temp(data, channel, val);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(data->regmap, EMC1812_THRM_HYS_ADDR, &hyst);
+ if (ret < 0)
+ return ret;
+
+ *val -= hyst * 1000;
+
+ return 0;
+ case hwmon_temp_min_alarm:
+ *val = regmap_test_bits(data->regmap, EMC1812_LOW_LIMIT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ case hwmon_temp_max_alarm:
+ *val = regmap_test_bits(data->regmap, EMC1812_HIGH_LIMIT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ case hwmon_temp_crit_alarm:
+ *val = regmap_test_bits(data->regmap, EMC1812_THERM_LIMIT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ case hwmon_temp_fault:
+ *val = regmap_test_bits(data->regmap, EMC1812_EXT_DIODE_FAULT_STATUS_ADDR,
+ BIT(channel));
+ if (*val < 0)
+ return *val;
+
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int emc1812_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long *val)
+{
+ struct emc1812_data *data = dev_get_drvdata(dev);
+ unsigned int convrate;
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ return emc1812_read_reg(dev, data, attr, channel, val);
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ ret = regmap_read(data->regmap, EMC1812_CONV_ADDR, &convrate);
+ if (ret < 0)
+ return ret;
+
+ if (convrate > 10)
+ convrate = 4;
+
+ *val = DIV_ROUND_CLOSEST(16000, 1 << convrate);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int emc1812_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ struct emc1812_data *data = dev_get_drvdata(dev);
+
+ if (channel >= data->chip->phys_channels)
+ return 0;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_label:
+ *str = data->labels[channel];
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int emc1812_set_hyst(struct emc1812_data *data, int channel, int val)
+{
+ int hyst, ret;
+ int limit;
+
+ /* Critical register is 8bits long and keeps only integer part of temperature */
+ ret = regmap_read(data->regmap, emc1812_temp_crit_regs[channel], &limit);
+ if (ret)
+ return ret;
+
+ hyst = clamp_val(limit - val, 0, 255);
+
+ ret = regmap_write(data->regmap, EMC1812_THRM_HYS_ADDR, hyst);
+
+ return ret;
+}
+
+static int emc1812_set_temp(struct emc1812_data *data, int channel,
+ enum emc1812_limit_type map, int val)
+{
+ long valh, vall;
+ u8 regh, regl;
+ int ret;
+
+ regh = emc1812_limit_regs[channel][map];
+ regl = emc1812_limit_regs_low[channel][map];
+
+ if (channel) {
+ val = DIV_ROUND_CLOSEST(val, 125);
+ valh = (val >> 3) & 0xff;
+ vall = (val & 0x07) << 5;
+ } else {
+ /* Temperature limit for internal channel is stored on 8bits */
+ valh = DIV_ROUND_CLOSEST(val, 1000);
+ valh = clamp_val(valh, 0, 255);
+ }
+
+ ret = regmap_write(data->regmap, regh, valh);
+ if (ret < 0)
+ return ret;
+
+ if (channel)
+ ret = regmap_write(data->regmap, regl, vall);
+
+ return ret;
+}
+
+static int emc1812_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long val)
+{
+ struct emc1812_data *data = dev_get_drvdata(dev);
+ unsigned int interval;
+ int convrate;
+
+ switch (type) {
+ case hwmon_temp:
+ /* Range should be -64000 to 191875°C + (EMC1812_TEMP_OFFSET * 1000) */
+ val = clamp_val(val, -64000, 191875);
+ val = val + (EMC1812_TEMP_OFFSET * 1000);
+
+ switch (attr) {
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ return emc1812_set_temp(data, channel, emc1812_temp_map[attr], val);
+ case hwmon_temp_crit:
+ /* Critical temperature limit is stored on 8bits */
+ val = DIV_ROUND_CLOSEST(val, 1000);
+ val = clamp_val(val, 0, 255);
+ return regmap_write(data->regmap, emc1812_temp_crit_regs[channel], val);
+ case hwmon_temp_crit_hyst:
+ /* Critical temperature hysteresis is stored on 8bits */
+ val = DIV_ROUND_CLOSEST(val, 1000);
+ val = clamp_val(val, 0, 255);
+ return emc1812_set_hyst(data, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ interval = clamp_val(val, 0, 16000);
+ convrate = find_closest_descending(interval, emc1812_conv_time,
+ ARRAY_SIZE(emc1812_conv_time));
+ return regmap_write(data->regmap, EMC1812_CONV_ADDR, convrate);
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int emc1812_init(struct emc1812_data *priv)
+{
+ int ret;
+ u8 val;
+
+ /*
+ * Set default values in registers. APDD, RECD12 and RECD34 are active
+ * on 0. Set ALERT pin to be in comparator mode.
+ * Set the device to be in Run (Active) state and converting on all
+ * channels.
+ * Don't change conversion rate. After reset, default is 4 conversions/seconds.
+ * The temperature measurement range is -64°C to +191.875°C.
+ */
+ val = FIELD_PREP(EMC1812_CFG_MSKAL, 0) |
+ FIELD_PREP(EMC1812_CFG_RS, 0) |
+ FIELD_PREP(EMC1812_CFG_ATTHM, 1) |
+ FIELD_PREP(EMC1812_CFG_RECD12, !priv->recd12_en) |
+ FIELD_PREP(EMC1812_CFG_RECD34, !priv->recd34_en) |
+ FIELD_PREP(EMC1812_CFG_RANGE, 1) |
+ FIELD_PREP(EMC1812_CFG_DA_ENA, 0) |
+ FIELD_PREP(EMC1812_CFG_APDD, !priv->apdd_en);
+
+ ret = regmap_write(priv->regmap, EMC1812_CFG_ADDR, val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, EMC1812_THRM_HYS_ADDR, 0x0A);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, EMC1812_CONSEC_ALERT_ADDR, 0x70);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, EMC1812_FILTER_SEL_ADDR, 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(priv->regmap, EMC1812_HOTTEST_CFG_ADDR, 0);
+ if (ret)
+ return ret;
+
+ /* Enables the beta compensation factor auto-detection function for beta1 and beta2 */
+ ret = regmap_write(priv->regmap, EMC1812_EXT1_BETA_CONFIG_ADDR,
+ EMC1812_BETA_LOCK_VAL);
+ if (ret)
+ return ret;
+
+ if (priv->chip->has_ext2_beta_reg) {
+ ret = regmap_write(priv->regmap, EMC1812_EXT2_BETA_CONFIG_ADDR,
+ EMC1812_BETA_LOCK_VAL);
+ if (ret)
+ return ret;
+ }
+
+ /* Set ideality factor for all external channels */
+ ret = regmap_write(priv->regmap, EMC1812_EXT1_IDEALITY_FACTOR_ADDR,
+ EMC1812_DEFAULT_IDEALITY_FACTOR);
+ if (ret)
+ return ret;
+
+ /* Set the ideality factor only for the channels supported by the chip */
+ if (priv->chip->phys_channels < 3)
+ return 0;
+
+ ret = regmap_write(priv->regmap, EMC1812_EXT2_IDEALITY_FACTOR_ADDR,
+ EMC1812_DEFAULT_IDEALITY_FACTOR);
+ if (ret)
+ return ret;
+
+ if (priv->chip->phys_channels < 4)
+ return 0;
+
+ ret = regmap_write(priv->regmap, EMC1812_EXT3_IDEALITY_FACTOR_ADDR,
+ EMC1812_DEFAULT_IDEALITY_FACTOR);
+ if (ret)
+ return ret;
+
+ if (priv->chip->phys_channels < 5)
+ return 0;
+
+ return regmap_write(priv->regmap, EMC1812_EXT4_IDEALITY_FACTOR_ADDR,
+ EMC1812_DEFAULT_IDEALITY_FACTOR);
+}
+
+static int emc1812_parse_fw_config(struct emc1812_data *data, struct device *dev)
+{
+ unsigned int reg_nr = 0;
+ int num_channels, ret;
+
+ /* To be able to load the driver in case we don't have device tree */
+ if (!dev_fwnode(dev)) {
+ data->active_ch_mask = BIT(data->chip->phys_channels) - 1;
+ return 0;
+ }
+
+ data->apdd_en = device_property_read_bool(dev, "microchip,enable-anti-parallel");
+ data->recd12_en = device_property_read_bool(dev, "microchip,parasitic-res-on-channel1-2");
+ data->recd34_en = device_property_read_bool(dev, "microchip,parasitic-res-on-channel3-4");
+
+ num_channels = device_get_child_node_count(dev) + 1;
+
+ if (num_channels > data->chip->phys_channels)
+ return dev_err_probe(dev, -EINVAL, "More channels than the chip supports\n");
+
+ /* Internal temperature channel is always active */
+ data->labels[reg_nr] = "internal_diode";
+ set_bit(reg_nr, &data->active_ch_mask);
+
+ device_for_each_child_node_scoped(dev, child) {
+ ret = fwnode_property_read_u32(child, "reg", ®_nr);
+ if (ret || reg_nr >= data->chip->phys_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "The index of the channels does not match the chip\n");
+ /* Mark external channel as active */
+ set_bit(reg_nr, &data->active_ch_mask);
+
+ fwnode_property_read_string(child, "label", &data->labels[reg_nr]);
+ }
+
+ return 0;
+}
+
+static int emc1812_chip_identify(struct emc1812_data *data, struct i2c_client *client)
+{
+ const struct emc1812_features *chip;
+ struct device *dev = &client->dev;
+ int ret, tmp;
+
+ ret = regmap_read(data->regmap, EMC1812_PRODUCT_ID_ADDR, &tmp);
+ if (ret)
+ return ret;
+
+ switch (tmp) {
+ case EMC1812_PID:
+ data->chip = &emc1812_chip_config;
+ break;
+ case EMC1813_PID:
+ data->chip = &emc1813_chip_config;
+ break;
+ case EMC1814_PID:
+ data->chip = &emc1814_chip_config;
+ break;
+ case EMC1815_PID:
+ data->chip = &emc1815_chip_config;
+ break;
+ case EMC1833_PID:
+ data->chip = &emc1833_chip_config;
+ break;
+ default:
+ /*
+ * If failed to identify the hardware based on internal registers,
+ * try using fallback compatible in device tree to deal with some
+ * newer part number.
+ */
+ chip = i2c_get_match_data(client);
+ if (!chip)
+ return -ENODEV;
+
+ dev_warn(dev, "Unrecognized hardware ID 0x%x, using %s from devicetree data\n",
+ tmp, chip->name);
+
+ data->chip = chip;
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct hwmon_ops emc1812_ops = {
+ .is_visible = emc1812_is_visible,
+ .read = emc1812_read,
+ .read_string = emc1812_read_string,
+ .write = emc1812_write,
+};
+
+static const struct hwmon_chip_info emc1812_chip_info = {
+ .ops = &emc1812_ops,
+ .info = emc1812_info,
+};
+
+static int emc1812_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct emc1812_data *data;
+ struct device *hwmon_dev;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->regmap = devm_regmap_init_i2c(client, &emc1812_regmap_config);
+ if (IS_ERR(data->regmap))
+ return dev_err_probe(dev, PTR_ERR(data->regmap),
+ "Cannot initialize register map\n");
+
+ ret = emc1812_chip_identify(data, client);
+ if (ret)
+ return dev_err_probe(dev, ret, "Chip identification fails\n");
+
+ ret = emc1812_parse_fw_config(data, dev);
+ if (ret)
+ return ret;
+
+ ret = emc1812_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Cannot initialize device\n");
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
+ &emc1812_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id emc1812_id[] = {
+ { .name = "emc1812", .driver_data = (kernel_ulong_t)&emc1812_chip_config },
+ { .name = "emc1813", .driver_data = (kernel_ulong_t)&emc1813_chip_config },
+ { .name = "emc1814", .driver_data = (kernel_ulong_t)&emc1814_chip_config },
+ { .name = "emc1815", .driver_data = (kernel_ulong_t)&emc1815_chip_config },
+ { .name = "emc1833", .driver_data = (kernel_ulong_t)&emc1833_chip_config },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, emc1812_id);
+
+static const struct of_device_id emc1812_of_match[] = {
+ {
+ .compatible = "microchip,emc1812",
+ .data = &emc1812_chip_config
+ },
+ {
+ .compatible = "microchip,emc1813",
+ .data = &emc1813_chip_config
+ },
+ {
+ .compatible = "microchip,emc1814",
+ .data = &emc1814_chip_config
+ },
+ {
+ .compatible = "microchip,emc1815",
+ .data = &emc1815_chip_config
+ },
+ {
+ .compatible = "microchip,emc1833",
+ .data = &emc1833_chip_config
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, emc1812_of_match);
+
+static struct i2c_driver emc1812_driver = {
+ .driver = {
+ .name = "emc1812",
+ .of_match_table = emc1812_of_match,
+ },
+ .probe = emc1812_probe,
+ .id_table = emc1812_id,
+};
+module_i2c_driver(emc1812_driver);
+
+MODULE_AUTHOR("Marius Cristea <marius.cristea@microchip.com>");
+MODULE_DESCRIPTION("EMC1812/13/14/15/33 high-accuracy remote diode temperature monitor Driver");
+MODULE_LICENSE("GPL");
--
2.51.0
^ permalink raw reply related
* [PATCH v9 1/2] dt-bindings: hwmon: temperature: add support for EMC1812
From: Marius Cristea @ 2026-04-03 12:39 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet
Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, Marius Cristea,
Conor Dooley
In-Reply-To: <20260403-hw_mon-emc1812-v9-0-1a798f31cf2e@microchip.com>
This is the devicetree schema for Microchip EMC1812/13/14/15/33
Multichannel Low-Voltage Remote Diode Sensor Family.
EMC1812 has one external remote temperature monitoring channel.
EMC1813 has two external remote temperature monitoring channels.
EMC1814 has three external remote temperature monitoring channels and
channels 2 and 3 support anti parallel diode.
EMC1815 has four external remote temperature monitoring channels and
channels 1/2 and 3/4 support anti parallel diode.
EMC1833 has two external remote temperature monitoring channels and
channels 1 and 2 support anti parallel diode.
Signed-off-by: Marius Cristea <marius.cristea@microchip.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/hwmon/microchip,emc1812.yaml | 184 +++++++++++++++++++++
MAINTAINERS | 6 +
2 files changed, 190 insertions(+)
diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc1812.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc1812.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5f766a3b6a297cdc9bdfff2215fce6fa41434f0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/microchip,emc1812.yaml
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/microchip,emc1812.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip EMC1812/13/14/15/33 multichannel temperature sensor
+
+maintainers:
+ - Marius Cristea <marius.cristea@microchip.com>
+
+description: |
+ The Microchip EMC1812/13/14/15/33 is a high-accuracy 2-wire multichannel
+ low-voltage remote diode temperature monitor.
+
+ The datasheet can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC1812-3-4-5-33-Data-Sheet-DS20005751.pdf
+
+ EMC1812 has one external remote temperature monitoring channel
+ EMC1813 has two external remote temperature monitoring channels
+ EMC1814 has three external remote temperature monitoring channels and
+ channels 2 and 3 support anti parallel diode
+ EMC1815 has four external remote temperature monitoring channels and
+ channels 1/2 and 3/4 support anti parallel diode
+ EMC1833 has two external remote temperature monitoring channels and
+ channels 1 and 2 support anti parallel diode
+
+properties:
+ compatible:
+ enum:
+ - microchip,emc1812
+ - microchip,emc1813
+ - microchip,emc1814
+ - microchip,emc1815
+ - microchip,emc1833
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: alert-therm2 asserts when the ALERT limit is exceeded.
+ - description: therm-addr asserts when the THERM limit is exceeded.
+ minItems: 1
+
+ interrupt-names:
+ items:
+ enum: [alert-therm2, therm-addr]
+ minItems: 1
+ maxItems: 2
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ microchip,enable-anti-parallel:
+ description:
+ Enable anti-parallel diode mode operation. EMC1814, EMC1815 and EMC1833
+ support reading two external diodes in anti-parallel connection on the
+ same set of pins. Disabling APD functionality to implement substrate
+ diodes on devices that support APD eliminates the benefit of APD
+ (two diodes on one channel).
+ type: boolean
+
+ microchip,parasitic-res-on-channel1-2:
+ description:
+ Indicates that the chip and the diodes/transistors are sufficiently
+ far apart that a parasitic resistance is added to the wires, which can
+ affect the measurements. Due to the anti-parallel diode connections,
+ channels 1 and 2 are affected together.
+ type: boolean
+
+ microchip,parasitic-res-on-channel3-4:
+ description:
+ Indicates that the chip and the diodes/transistors are sufficiently far
+ apart that a parasitic resistance is added to the wires, which can affect
+ the measurements. Due to the anti-parallel diode connections, channels
+ 3 and 4 are affected together.
+ type: boolean
+
+ vdd-supply: true
+
+patternProperties:
+ "^channel@[1-4]$":
+ description:
+ Represents the external temperature channels to which
+ a remote diode is connected.
+ type: object
+
+ properties:
+ reg:
+ maxItems: 1
+
+ label:
+ description: Unique name to identify which channel this is.
+
+ required:
+ - reg
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+
+allOf:
+ # EMC1812: 1 Channel, No APD, REC on channel 1
+ - if:
+ properties:
+ compatible:
+ const: microchip,emc1812
+ then:
+ properties:
+ microchip,enable-anti-parallel: false
+ microchip,parasitic-res-on-channel3-4: false
+ patternProperties:
+ "^channel@[2-4]$": false
+
+ # EMC1813: 2 Channels, No APD, REC on both channel 1 & 2
+ - if:
+ properties:
+ compatible:
+ const: microchip,emc1813
+ then:
+ properties:
+ microchip,enable-anti-parallel: false
+ microchip,parasitic-res-on-channel3-4: false
+ patternProperties:
+ "^channel@[3-4]$": false
+
+ # EMC1833: 2 Channels, Supports APD, REC on both channel 1 & 2
+ - if:
+ properties:
+ compatible:
+ const: microchip,emc1833
+ then:
+ properties:
+ microchip,parasitic-res-on-channel3-4: false
+ patternProperties:
+ "^channel@[3-4]$": false
+
+ # EMC1814: 3 Channels, Supports APD,
+ # REC on both channel 1 & 2 and channel 3
+ - if:
+ properties:
+ compatible:
+ const: microchip,emc1814
+ then:
+ properties:
+ channel@4: false
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ temperature-sensor@4c {
+ compatible = "microchip,emc1813";
+ reg = <0x4c>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ microchip,parasitic-res-on-channel1-2;
+
+ vdd-supply = <&vdd>;
+
+ channel@1 {
+ reg = <1>;
+ label = "External CH1 Temperature";
+ };
+
+ channel@2 {
+ reg = <2>;
+ label = "External CH2 Temperature";
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 6d7b697bfdba16e4f0ee5f4f0195b9d7da06dae5..85c236df781e47c78deeb7ef4d80bc94bba604c4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16646,6 +16646,12 @@ S: Supported
F: Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml
F: drivers/irqchip/irq-mchp-eic.c
+MICROCHIP EMC1812 DRIVER
+M: Marius Cristea <marius.cristea@microchip.com>
+L: linux-hwmon@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/hwmon/microchip,emc1812.yaml
+
MICROCHIP I2C DRIVER
M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
L: linux-i2c@vger.kernel.org
--
2.51.0
^ permalink raw reply related
* [PATCH v7 2/3] riscv: dts: spacemit: Define the P1 PMIC regulators for OrangePi RV2
From: Han Gao @ 2026-04-03 12:37 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775219669.git.gaohan@iscas.ac.cn>
Define the DC power input and the 4v power as fixed regulator supplies.
Define the SpacemiT P1 PMIC voltage regulators and their constraints.
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 131 ++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 57ec1cc32b03..f7a1dadaa95f 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -23,6 +23,25 @@ chosen {
stdout-path = "serial0";
};
+ vcc_5v0: regulator-vcc-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_5v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc4v0: regulator-vcc4v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc4v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ vin-supply = <&vcc_5v0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -91,6 +110,118 @@ &i2c8 {
pinctrl-names = "default";
pinctrl-0 = <&i2c8_cfg>;
status = "okay";
+
+ pmic@41 {
+ compatible = "spacemit,p1";
+ reg = <0x41>;
+ interrupts = <64>;
+ vin1-supply = <&vcc4v0>;
+ vin2-supply = <&vcc4v0>;
+ vin3-supply = <&vcc4v0>;
+ vin4-supply = <&vcc4v0>;
+ vin5-supply = <&vcc4v0>;
+ vin6-supply = <&vcc4v0>;
+ aldoin-supply = <&vcc4v0>;
+ dldoin1-supply = <&buck5>;
+ dldoin2-supply = <&buck5>;
+
+ regulators {
+ buck1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck3_1v8: buck3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck4_3v3: buck4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck5: buck5 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck6 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ aldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ aldo2 {
+ /* not connected */
+ };
+
+ aldo3 {
+ /* not connected */
+ };
+
+ aldo4 {
+ /* not connected */
+ };
+
+ dldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ dldo2 {
+ /* not connected */
+ };
+
+ dldo3 {
+ /* not connected */
+ };
+
+ dldo4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-always-on;
+ };
+
+ dldo5 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ dldo6 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-always-on;
+ };
+
+ dldo7 {
+ /* not connected */
+ };
+ };
+ };
};
&uart0 {
--
2.47.3
^ permalink raw reply related
* [PATCH v7 3/3] riscv: dts: spacemit: Enable USB3.0/PCIe on OrangePi RV2
From: Han Gao @ 2026-04-03 12:37 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775219669.git.gaohan@iscas.ac.cn>
Enable the DWC3 USB 3.0 controller and its associated usbphy2 on the
OrangePi RV2 board.
The board utilizes a Genesys Logic GL3523 USB3.0 hub.
Define a 3.3v fixed voltage regulator for PCIe and enable PCIe and
PHY-related Device Tree nodes for the OrangePi RV2.
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 81 +++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index f7a1dadaa95f..3679a6cb110e 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -23,6 +23,15 @@ chosen {
stdout-path = "serial0";
};
+ pcie_vcc3v3: regulator-pcie-vcc3v3 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio K1_GPIO(116) GPIO_ACTIVE_HIGH>;
+ regulator-name = "pcie_vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
vcc_5v0: regulator-vcc-5v0 {
compatible = "regulator-fixed";
regulator-name = "vcc_5v0";
@@ -42,6 +51,16 @@ vcc4v0: regulator-vcc4v0 {
vin-supply = <&vcc_5v0>;
};
+ vcc5v0_usb30: regulator-vcc5v0-usb30 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb30";
+ enable-active-high;
+ gpios = <&gpio K1_GPIO(123) GPIO_ACTIVE_HIGH>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -54,6 +73,10 @@ led1 {
};
};
+&combo_phy {
+ status = "okay";
+};
+
ð0 {
phy-handle = <&rgmii0>;
phy-mode = "rgmii-id";
@@ -224,8 +247,66 @@ dldo7 {
};
};
+&pcie1_phy {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_3_cfg>;
+ status = "okay";
+};
+
+&pcie1_port {
+ phys = <&pcie1_phy>;
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+};
+
+&pcie1 {
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+ status = "okay";
+};
+
+&pcie2_phy {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_4_cfg>;
+ status = "okay";
+};
+
+&pcie2_port {
+ phys = <&pcie2_phy>;
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+};
+
+&pcie2 {
+ vpcie3v3-supply = <&pcie_vcc3v3>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
status = "okay";
};
+
+&usbphy2 {
+ status = "okay";
+};
+
+&usb_dwc3 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ vdd-supply = <&vcc5v0_usb30>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb5e3,610";
+ reg = <0x1>;
+ peer-hub = <&hub_3_0>;
+ vdd-supply = <&vcc_5v0>;
+ };
+
+ hub_3_0: hub@2 {
+ compatible = "usb5e3,620";
+ reg = <0x2>;
+ peer-hub = <&hub_2_0>;
+ vdd-supply = <&vcc_5v0>;
+ };
+};
--
2.47.3
^ permalink raw reply related
* [PATCH v7 0/3] riscv: dts: spacemit: Add PMIC regulators usb pcie
From: Han Gao @ 2026-04-03 12:37 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
Changes in v6:
- patch 1:
reorder i2c8
- patch 3:
restore vcc5v0_usb30
remove vin-supply from pcie_vcc3v3
restore vpcie3v3-supply from pcie2
update hub vdd-supply
- Link to v6: https://lore.kernel.org/linux-riscv/cover.1775214644.git.gaohan@iscas.ac.cn/
Han Gao (3):
riscv: dts: spacemit: Enable i2c8 adapter for OrangePi RV2
riscv: dts: spacemit: Define the P1 PMIC regulators for OrangePi RV2
riscv: dts: spacemit: Enable USB3.0/PCIe on OrangePi RV2
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 218 ++++++++++++++++++
1 file changed, 218 insertions(+)
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
prerequisite-patch-id: ef6e9c7b5854d0c08066b72f9a7868db8c2140eb
prerequisite-patch-id: cfe3800f8c791ec4c63e070af9628e88e0fc31b9
prerequisite-patch-id: b76493e625ae257c8adcd67874178458420e4d47
prerequisite-patch-id: 88e01dc92c83bd88ddeb78891d3088209fed8d6b
prerequisite-patch-id: 60336d10ab8322c70596d0f046b6b5c54bb24b54
prerequisite-patch-id: 68c4d869548687dc115dd91e2ffb8f4c11482d86
prerequisite-patch-id: fdadcf964c2cb3406160edb579d99a8d5695f8e6
prerequisite-patch-id: 73b9e745338b0499b849fa4f7f9508987ab39a59
prerequisite-patch-id: cd26770c2160c3c31a406bd8a6b01ab666180ae0
prerequisite-patch-id: e5dfddc32cefae195692da8b80e19adf086e4ad7
prerequisite-patch-id: 7fd53cbe4977598f26148a4bb1cf692bbdb79a09
prerequisite-patch-id: 96ebac57bb29619b97fe95422206a685825618e9
prerequisite-patch-id: 00fac16b52f60383db3140e2885f3f7f8d14dd1a
prerequisite-patch-id: 3b7a60047b922c48e93599f621cb738856f42354
prerequisite-patch-id: 275c030b963be05dd1041451f539a130ce614277
prerequisite-patch-id: 93963424b0871e64276af0e0b2199b52e29b4603
prerequisite-patch-id: 8383188b1c01ed6280629faaa29c37d699ade241
prerequisite-patch-id: 5f8126b912b924d63d4a1e0c5eb42d212eb0d369
prerequisite-patch-id: e80af628a2e0b5f2eeb3cb1b5e7133d08bdd2c4e
prerequisite-patch-id: 0234a6dca15eb91f98a45a46604ce5b4935048a5
--
2.47.3
^ permalink raw reply
* [PATCH v7 1/3] riscv: dts: spacemit: Enable i2c8 adapter for OrangePi RV2
From: Han Gao @ 2026-04-03 12:37 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775219669.git.gaohan@iscas.ac.cn>
The adapter is used to access the SpacemiT P1 PMIC present in this board.
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 7b7331cb3c72..57ec1cc32b03 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -87,6 +87,12 @@ &pdma {
status = "okay";
};
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8_cfg>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
--
2.47.3
^ permalink raw reply related
* [GIT PULL] RISC-V SpacemiT Devicetrees for v7.1
From: Yixun Lan @ 2026-04-03 12:32 UTC (permalink / raw)
To: soc
Cc: Yixun Lan, Arnd Bergmann, spacemit, linux-riscv, devicetree,
linux-kernel
From: Yixun Lan <dlan@gentoo.org>
Hi Arnd,
Please pull SpacemiT's DeviceTree changes for v7.1
Yixun Lan
The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:
Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)
are available in the Git repository at:
https://github.com/spacemit-com/linux tags/spacemit-dt-for-7.1-1
for you to fetch changes up to af62a095eb0c3359d477b55ef72d2afd94c83c8f:
dts: riscv: spacemit: k3: add P1 PMIC regulator tree (2026-03-30 04:42:10 +0000)
----------------------------------------------------------------
RISC-V SpacemiT DT changes for 7.1
For K3 SoC
- Add I2C support
- Add PMIC regulator tree
- Add ethernet support
- Add pinctrl/GPIO/Clock
- Enable full UART support
For K1 SoC
On Milk-V Jupiter
- Enable PCIe/USB on
- Enable QSPI/SPI NOR
- Enable EEPROM, LEDs
Others
- Fix PMIC supply properties
- Fix PCIe missing power regulator
----------------------------------------------------------------
Aurelien Jarno (7):
riscv: dts: spacemit: drop incorrect pinctrl for combo PHY
riscv: dts: spacemit: add LEDs for Milk-V Jupiter board
riscv: dts: spacemit: add 24c04 eeprom on Milk-V Jupiter
riscv: dts: spacemit: add i2c aliases on Milk-V Jupiter
riscv: dts: spacemit: enable QSPI and add SPI NOR on Milk-V Jupiter
riscv: dts: spacemit: enable USB 3 ports on Milk-V Jupiter
riscv: dts: spacemit: enable PCIe ports on Milk-V Jupiter
Chukun Pan (2):
riscv: dts: spacemit: Add 'linux,pci-domain' to PCIe nodes for K1
riscv: dts: spacemit: reorder phy nodes for K1
Guodong Xu (1):
riscv: dts: spacemit: Update PMIC supply properties for BPI-F3 and Jupiter
Inochi Amaoto (1):
riscv: dts: spacemit: Add ethernet device for K3
Yixun Lan (9):
riscv: dts: spacemit: pcie: fix missing power regulator
riscv: dts: spacemit: adapt regulator node name to preferred form
dt-bindings: serial: 8250: spacemit: fix clock property for K3 SoC
riscv: dts: spacemit: k3: add clock tree
riscv: dts: spacemit: k3: add pinctrl support
riscv: dts: spacemit: k3: add GPIO support
riscv: dts: spacemit: k3: add full resource to UART
dts: riscv: spacemit: k3: Add i2c nodes
dts: riscv: spacemit: k3: add P1 PMIC regulator tree
Documentation/devicetree/bindings/serial/8250.yaml | 5 +-
arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 26 +-
arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts | 204 +++++++++++-
arch/riscv/boot/dts/spacemit/k1.dtsi | 112 ++++---
arch/riscv/boot/dts/spacemit/k3-pico-itx.dts | 170 ++++++++++
arch/riscv/boot/dts/spacemit/k3-pinctrl.dtsi | 69 ++++
arch/riscv/boot/dts/spacemit/k3.dtsi | 369 ++++++++++++++++++++-
7 files changed, 876 insertions(+), 79 deletions(-)
create mode 100644 arch/riscv/boot/dts/spacemit/k3-pinctrl.dtsi
^ permalink raw reply
* Re: [PATCH 19/19] gpio: add GPIO controller found on Waveshare DSI TOUCH panels
From: Bartosz Golaszewski @ 2026-04-03 12:30 UTC (permalink / raw)
To: Dmitry Baryshkov
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, Bartosz Golaszewski
In-Reply-To: <20260401-waveshare-dsi-touch-v1-19-5e9119b5a014@oss.qualcomm.com>
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?
> +};
> +
> +struct waveshare_gpio {
> + struct mutex dir_lock;
> + struct mutex pwr_lock;
> + struct regmap *regmap;
> + u16 poweron_state;
> +
> + struct gpio_chip gc;
> +};
> +
> +static const struct regmap_config waveshare_gpio_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = REG_PWM,
> +};
> +
> +static int waveshare_gpio_get(struct waveshare_gpio *state, unsigned int offset)
> +{
> + u16 pwr_state;
> +
> + mutex_lock(&state->pwr_lock);
> + pwr_state = state->poweron_state & BIT(offset);
> + mutex_unlock(&state->pwr_lock);
> +
> + return !!pwr_state;
> +}
> +
> +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?
> +
> + 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.
> +
> + mutex_unlock(&state->pwr_lock);
> +
> + return 0;
> +}
> +
> +static int waveshare_gpio_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
> +{
> + return GPIO_LINE_DIRECTION_OUT;
> +}
> +
> +static int waveshare_gpio_gpio_get(struct gpio_chip *gc, unsigned int offset)
> +{
> + struct waveshare_gpio *state = gpiochip_get_data(gc);
> +
> + return waveshare_gpio_get(state, offset);
> +}
> +
> +static int waveshare_gpio_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
> +{
> + struct waveshare_gpio *state = gpiochip_get_data(gc);
> +
> + return waveshare_gpio_set(state, offset, value);
> +}
> +
> +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 const struct backlight_ops waveshare_gpio_bl = {
> + .update_status = waveshare_gpio_update_status,
> +};
> +
> +static int waveshare_gpio_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf)
> +{
> + int val;
> +
> + val = i2c_smbus_read_byte_data(client, reg);
> + if (val < 0)
> + return val;
> +
> + *buf = val;
> +
> + return 0;
> +}
> +
> +static int waveshare_gpio_probe(struct i2c_client *i2c)
> +{
> + struct backlight_properties props = {};
> + struct waveshare_gpio *state;
> + struct device *dev = &i2c->dev;
> + struct backlight_device *bl;
> + struct regmap *regmap;
> + unsigned int data;
> + int ret;
> +
> + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
> + if (!state)
> + return -ENOMEM;
> +
> + ret = devm_mutex_init(dev, &state->dir_lock);
> + if (ret)
> + return ret;
> +
> + ret = devm_mutex_init(dev, &state->pwr_lock);
> + if (ret)
> + return ret;
> +
> + i2c_set_clientdata(i2c, state);
> +
> + regmap = devm_regmap_init_i2c(i2c, &waveshare_gpio_regmap_config);
> + if (IS_ERR(regmap))
> + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to allocate register map\n");
> +
> + ret = waveshare_gpio_i2c_read(i2c, REG_ID, &data);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to read register\n");
> +
> + dev_dbg(dev, "waveshare panel hw id = 0x%x\n", data);
> +
> + ret = waveshare_gpio_i2c_read(i2c, REG_SIZE, &data);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to read register\n");
> +
> + dev_dbg(dev, "waveshare panel size = %d\n", data);
> +
> + ret = waveshare_gpio_i2c_read(i2c, REG_VERSION, &data);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to read register\n");
> +
> + 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);
> + 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?
> + 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);
> +}
> +
> +static const struct of_device_id waveshare_gpio_dt_ids[] = {
> + { .compatible = "waveshare,dsi-touch-gpio" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, waveshare_gpio_dt_ids);
> +
> +static struct i2c_driver waveshare_gpio_regulator_driver = {
> + .driver = {
> + .name = "waveshare-regulator",
> + .of_match_table = of_match_ptr(waveshare_gpio_dt_ids),
> + },
> + .probe = waveshare_gpio_probe,
> +};
> +
> +module_i2c_driver(waveshare_gpio_regulator_driver);
> +
> +MODULE_DESCRIPTION("GPIO controller driver for Waveshare DSI touch panels");
> +MODULE_LICENSE("GPL");
>
> --
> 2.47.3
>
>
Bart
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: iio: dac: add support for Microchip MCP48FEB02 to MCP47FEB02
From: Rob Herring (Arm) @ 2026-04-03 12:25 UTC (permalink / raw)
To: Ariana Lazar
Cc: David Lechner, Jonathan Cameron, linux-iio, devicetree,
linux-kernel, Conor Dooley, Jonathan Cameron, Andy Shevchenko,
Conor Dooley, Nuno Sá, Krzysztof Kozlowski
In-Reply-To: <20260403-mcp47feb02-fix2-v1-1-da60c773550e@microchip.com>
On Fri, 03 Apr 2026 13:50:13 +0300, Ariana Lazar wrote:
> This is the device tree schema for iio driver for Microchip
> MCP48FxBy1/2/4/8 series of buffered voltage output Digital-to-Analog
> Converters with nonvolatile or volatile memory on top of MCP47FEB02.
> The families support up to 8 output channels and have 8-bit, 10-bit or
> 12-bit resolution.
>
> The I2C (MCP47F(E/V)BXX) and SPI (MCP48F(E/V)BXX) DAC families were merged
> into the same dt-binding file.
>
> Fixes: 4ba12d304175 ("dt-bindings: iio: dac: adding support for Microchip MCP47FEB02")
> Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
> Link: https://lore.kernel.org/all/20260216-shiny-itunes-00a31d1f4db7@spud/
> ---
> .../bindings/iio/dac/microchip,mcp47feb02.yaml | 291 +++++++++++++++------
> MAINTAINERS | 1 -
> 2 files changed, 217 insertions(+), 75 deletions(-)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
./Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml:245:22: [error] string value is redundantly quoted with any quotes (quoted-strings)
dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.example.dts:22.20-39.13: Warning (i2c_bus_reg): /example-0/i2c/dac@60: I2C bus unit address format error, expected "0"
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/20260403-mcp47feb02-fix2-v1-1-da60c773550e@microchip.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply
* [PATCH] arm64: dts: qcom: sc8280xp: Add ADSP FastRPC node
From: Pengyu Luo @ 2026-04-03 12:07 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: Pengyu Luo, linux-arm-msm, devicetree, linux-kernel
Add the FastRPC node to enable offloading compute tasks to the ADSP
via the FastRPC framework.
Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
---
arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 27 ++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
index 761f229e8f47..ee02acd18856 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
@@ -2966,6 +2966,33 @@ IPCC_MPROC_SIGNAL_GLINK_QMP
label = "lpass";
qcom,remote-pid = <2>;
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,glink-channels = "fastrpcglink-apps-dsp";
+ label = "adsp";
+ qcom,non-secure-domain;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compute-cb@3 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <3>;
+ iommus = <&apps_smmu 0x0c03 0x0>;
+ };
+
+ compute-cb@4 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <4>;
+ iommus = <&apps_smmu 0x0c04 0x0>;
+ };
+
+ compute-cb@5 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <5>;
+ iommus = <&apps_smmu 0x0c05 0x0>;
+ };
+ };
+
gpr {
compatible = "qcom,gpr";
qcom,glink-channels = "adsp_apps";
--
2.53.0
^ permalink raw reply related
* [PATCH v2 3/3] arm64: dts: qcom: milos: Add GX clock controller
From: Luca Weiss @ 2026-04-03 12:03 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Alexander Koskovich
Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm, linux-clk,
devicetree, linux-kernel, Luca Weiss, Konrad Dybcio,
Jagadeesh Kona
In-Reply-To: <20260403-milos-gxclkctl-v2-0-95eb94a7d0a4@fairphone.com>
Add a node for the GX clock controller, which provides a power domain to
consumers.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
arch/arm64/boot/dts/qcom/milos.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/milos.dtsi b/arch/arm64/boot/dts/qcom/milos.dtsi
index 4a64a98a434b..4bd9181ca03e 100644
--- a/arch/arm64/boot/dts/qcom/milos.dtsi
+++ b/arch/arm64/boot/dts/qcom/milos.dtsi
@@ -1542,6 +1542,16 @@ lpass_ag_noc: interconnect@3c40000 {
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ gxclkctl: clock-controller@3d64000 {
+ compatible = "qcom,milos-gxclkctl";
+ reg = <0x0 0x03d64000 0x0 0x6000>;
+
+ power-domains = <&rpmhpd RPMHPD_GFX>,
+ <&gpucc GPU_CC_CX_GDSC>;
+
+ #power-domain-cells = <1>;
+ };
+
gpucc: clock-controller@3d90000 {
compatible = "qcom,milos-gpucc";
reg = <0x0 0x03d90000 0x0 0x9800>;
--
2.53.0
^ permalink raw reply related
* [PATCH v2 2/3] clk: qcom: Add support for GXCLK for Milos
From: Luca Weiss @ 2026-04-03 12:03 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Alexander Koskovich
Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm, linux-clk,
devicetree, linux-kernel, Luca Weiss, Jagadeesh Kona, Taniya Das
In-Reply-To: <20260403-milos-gxclkctl-v2-0-95eb94a7d0a4@fairphone.com>
GXCLKCTL (Graphics GX Clock Controller) is a block dedicated to managing
clocks for the GPU subsystem on GX power domain. The GX clock controller
driver manages only the GX GDSC and the rest of the resources of the
controller are managed by the firmware.
We can use the existing kaanapali driver for Milos as well since the
GX_CLKCTL_GX_GDSC supported by the Linux driver requires the same
configuration.
Reviewed-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
Reviewed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
drivers/clk/qcom/Makefile | 2 +-
drivers/clk/qcom/gxclkctl-kaanapali.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index b818fd5af8bf..13e7892ba39a 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -187,7 +187,7 @@ obj-$(CONFIG_SM_GPUCC_8450) += gpucc-sm8450.o
obj-$(CONFIG_SM_GPUCC_8550) += gpucc-sm8550.o
obj-$(CONFIG_SM_GPUCC_8650) += gpucc-sm8650.o
obj-$(CONFIG_SM_GPUCC_8750) += gpucc-sm8750.o gxclkctl-kaanapali.o
-obj-$(CONFIG_SM_GPUCC_MILOS) += gpucc-milos.o
+obj-$(CONFIG_SM_GPUCC_MILOS) += gpucc-milos.o gxclkctl-kaanapali.o
obj-$(CONFIG_SM_LPASSCC_6115) += lpasscc-sm6115.o
obj-$(CONFIG_SM_TCSRCC_8550) += tcsrcc-sm8550.o
obj-$(CONFIG_SM_TCSRCC_8650) += tcsrcc-sm8650.o
diff --git a/drivers/clk/qcom/gxclkctl-kaanapali.c b/drivers/clk/qcom/gxclkctl-kaanapali.c
index 40d856378a74..7b0af0ba1e68 100644
--- a/drivers/clk/qcom/gxclkctl-kaanapali.c
+++ b/drivers/clk/qcom/gxclkctl-kaanapali.c
@@ -53,6 +53,7 @@ static const struct qcom_cc_desc gx_clkctl_kaanapali_desc = {
static const struct of_device_id gx_clkctl_kaanapali_match_table[] = {
{ .compatible = "qcom,glymur-gxclkctl" },
{ .compatible = "qcom,kaanapali-gxclkctl" },
+ { .compatible = "qcom,milos-gxclkctl" },
{ .compatible = "qcom,sm8750-gxclkctl" },
{ }
};
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox