summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/rt4831.c
diff options
context:
space:
mode:
authorJoel Fernandes <joelagnelf@nvidia.com>2026-07-18 13:15:36 -0400
committerPaul E. McKenney <paulmck@kernel.org>2026-07-23 10:39:57 -0700
commit34ff636f322c6d5e4f0a52338fa63a7dff09a495 (patch)
tree7629759c1ec7148b95bc8ab3080df20a5ecd2273 /drivers/mfd/rt4831.c
downloadlinux-stable-34ff636f322c6d5e4f0a52338fa63a7dff09a495.tar.gz
linux-stable-34ff636f322c6d5e4f0a52338fa63a7dff09a495.zip
scftorture: Count single_rpc offline failures in statistics outputgrafted
scf_torture_stats_print() aggregates each invoker thread's counters into a local scf_statistics structure before printing, but the n_single_rpc_ofl field is missing from the aggregation loop. As a result, the "single_rpc_ofl" value printed in the statistics line is always zero, even when smp_call_function_single() invocations for the RPC test have failed due to offline CPUs and been counted by the invoker threads. Add the missing accumulation so that the printed value reflects the actual counts. Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Diffstat (limited to 'drivers/mfd/rt4831.c')
-rw-r--r--drivers/mfd/rt4831.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/drivers/mfd/rt4831.c b/drivers/mfd/rt4831.c
new file mode 100644
index 000000000..1ab8870e4
--- /dev/null
+++ b/drivers/mfd/rt4831.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Richtek Technology Corp.
+ *
+ * Author: ChiYuan Huang <cy_huang@richtek.com>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define RT4831_REG_REVISION 0x01
+#define RT4831_REG_ENABLE 0x08
+#define RT4831_REG_I2CPROT 0x15
+
+#define RICHTEK_VENDOR_ID 0x03
+#define RT4831_VID_MASK GENMASK(1, 0)
+#define RT4831_RESET_MASK BIT(7)
+#define RT4831_I2CSAFETMR_MASK BIT(0)
+
+static const struct mfd_cell rt4831_subdevs[] = {
+ MFD_CELL_OF("rt4831-backlight", NULL, NULL, 0, 0, "richtek,rt4831-backlight"),
+ MFD_CELL_NAME("rt4831-regulator")
+};
+
+static bool rt4831_is_accessible_reg(struct device *dev, unsigned int reg)
+{
+ if (reg >= RT4831_REG_REVISION && reg <= RT4831_REG_I2CPROT)
+ return true;
+ return false;
+}
+
+static const struct regmap_config rt4831_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RT4831_REG_I2CPROT,
+
+ .readable_reg = rt4831_is_accessible_reg,
+ .writeable_reg = rt4831_is_accessible_reg,
+};
+
+static int rt4831_probe(struct i2c_client *client)
+{
+ struct gpio_desc *enable_gpio;
+ struct regmap *regmap;
+ unsigned int chip_id;
+ int ret;
+
+ enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(enable_gpio)) {
+ dev_err(&client->dev, "Failed to get 'enable' GPIO\n");
+ return PTR_ERR(enable_gpio);
+ }
+
+ regmap = devm_regmap_init_i2c(client, &rt4831_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Failed to initialize regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ ret = regmap_read(regmap, RT4831_REG_REVISION, &chip_id);
+ if (ret) {
+ dev_err(&client->dev, "Failed to get H/W revision\n");
+ return ret;
+ }
+
+ if ((chip_id & RT4831_VID_MASK) != RICHTEK_VENDOR_ID) {
+ dev_err(&client->dev, "Chip vendor ID 0x%02x not matched\n", chip_id);
+ return -ENODEV;
+ }
+
+ /*
+ * Used to prevent the abnormal shutdown.
+ * If SCL/SDA both keep low for one second to reset HW.
+ */
+ ret = regmap_update_bits(regmap, RT4831_REG_I2CPROT, RT4831_I2CSAFETMR_MASK,
+ RT4831_I2CSAFETMR_MASK);
+ if (ret) {
+ dev_err(&client->dev, "Failed to enable I2C safety timer\n");
+ return ret;
+ }
+
+ return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, rt4831_subdevs,
+ ARRAY_SIZE(rt4831_subdevs), NULL, 0, NULL);
+}
+
+static void rt4831_remove(struct i2c_client *client)
+{
+ struct regmap *regmap = dev_get_regmap(&client->dev, NULL);
+ int ret;
+
+ /* Disable WLED and DSV outputs */
+ ret = regmap_update_bits(regmap, RT4831_REG_ENABLE, RT4831_RESET_MASK, RT4831_RESET_MASK);
+ if (ret)
+ dev_warn(&client->dev, "Failed to disable outputs (%pe)\n", ERR_PTR(ret));
+}
+
+static const struct of_device_id __maybe_unused rt4831_of_match[] = {
+ { .compatible = "richtek,rt4831", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rt4831_of_match);
+
+static struct i2c_driver rt4831_driver = {
+ .driver = {
+ .name = "rt4831",
+ .of_match_table = rt4831_of_match,
+ },
+ .probe = rt4831_probe,
+ .remove = rt4831_remove,
+};
+module_i2c_driver(rt4831_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RT4831 core driver");
+MODULE_LICENSE("GPL v2");