aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig22
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/ab8500-core.c43
-rw-r--r--drivers/mfd/acer-ec-a500.c202
-rw-r--r--drivers/mfd/altera-sysmgr.c3
-rw-r--r--drivers/mfd/arizona-core.c11
-rw-r--r--drivers/mfd/arizona-i2c.c11
-rw-r--r--drivers/mfd/arizona-spi.c138
-rw-r--r--drivers/mfd/arizona.h9
-rw-r--r--drivers/mfd/axp20x-i2c.c4
-rw-r--r--drivers/mfd/axp20x-rsb.c4
-rw-r--r--drivers/mfd/axp20x.c4
-rw-r--r--drivers/mfd/bd9571mwv.c178
-rw-r--r--drivers/mfd/db8500-prcmu.c6
-rw-r--r--drivers/mfd/gateworks-gsc.c2
-rw-r--r--drivers/mfd/intel-lpss-pci.c28
-rw-r--r--drivers/mfd/intel-m10-bmc.c43
-rw-r--r--drivers/mfd/intel_msic.c425
-rw-r--r--drivers/mfd/iqs62x.c144
-rw-r--r--drivers/mfd/max8997.c4
-rw-r--r--drivers/mfd/mcp-sa11x0.c3
-rw-r--r--drivers/mfd/mt6360-core.c12
-rw-r--r--drivers/mfd/wm831x-auxadc.c3
23 files changed, 668 insertions, 633 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bdfce7b15621..b74efa469e90 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -659,15 +659,6 @@ config MFD_INTEL_LPSS_PCI
I2C, SPI and HS-UART starting from Intel Sunrisepoint (Intel Skylake
PCH) in PCI mode.
-config MFD_INTEL_MSIC
- bool "Intel MSIC"
- depends on INTEL_SCU
- select MFD_CORE
- help
- Select this option to enable access to Intel MSIC (Avatele
- Passage) chip. This chip embeds audio, battery, GPIO, etc.
- devices used in Intel Medfield platforms.
-
config MFD_INTEL_PMC_BXT
tristate "Intel PMC Driver for Broxton"
depends on X86
@@ -2085,6 +2076,17 @@ config MFD_KHADAS_MCU
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_ACER_A500_EC
+ tristate "Support for Acer Iconia Tab A500 Embedded Controller"
+ depends on I2C
+ depends on (ARCH_TEGRA_2x_SOC && OF) || COMPILE_TEST
+ select MFD_CORE
+ select REGMAP
+ help
+ Support for Embedded Controller found on Acer Iconia Tab A500.
+ The controller itself is ENE KB930, it is running firmware
+ customized for the specific needs of the Acer A500 hardware.
+
menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100
@@ -2129,7 +2131,7 @@ config RAVE_SP_CORE
device found on several devices in RAVE line of hardware.
config SGI_MFD_IOC3
- tristate "SGI IOC3 core driver"
+ bool "SGI IOC3 core driver"
depends on PCI && MIPS && 64BIT
select MFD_CORE
help
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 14fdb188af02..834f5463af28 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -214,7 +214,6 @@ obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o
obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o
obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o
-obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o
obj-$(CONFIG_MFD_INTEL_PMT) += intel_pmt.o
obj-$(CONFIG_MFD_PALMAS) += palmas.o
@@ -264,6 +263,7 @@ obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
obj-$(CONFIG_MFD_STMFX) += stmfx.o
obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o
+obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o
obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index a3bac9da8cbb..a9037911162b 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -21,7 +21,6 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/dbx500-prcmu.h>
-#include <linux/regulator/ab8500.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -610,52 +609,52 @@ int ab8500_suspend(struct ab8500 *ab8500)
}
static const struct mfd_cell ab8500_bm_devs[] = {
- OF_MFD_CELL("ab8500-charger", NULL, &ab8500_bm_data,
+ MFD_CELL_OF("ab8500-charger", NULL, &ab8500_bm_data,
sizeof(ab8500_bm_data), 0, "stericsson,ab8500-charger"),
- OF_MFD_CELL("ab8500-btemp", NULL, &ab8500_bm_data,
+ MFD_CELL_OF("ab8500-btemp", NULL, &ab8500_bm_data,
sizeof(ab8500_bm_data), 0, "stericsson,ab8500-btemp"),
- OF_MFD_CELL("ab8500-fg", NULL, &ab8500_bm_data,
+ MFD_CELL_OF("ab8500-fg", NULL, &ab8500_bm_data,
sizeof(ab8500_bm_data), 0, "stericsson,ab8500-fg"),
- OF_MFD_CELL("ab8500-chargalg", NULL, &ab8500_bm_data,
+ MFD_CELL_OF("ab8500-chargalg", NULL, &ab8500_bm_data,
sizeof(ab8500_bm_data), 0, "stericsson,ab8500-chargalg"),
};
static const struct mfd_cell ab8500_devs[] = {
#ifdef CONFIG_DEBUG_FS
- OF_MFD_CELL("ab8500-debug",
+ MFD_CELL_OF("ab8500-debug",
NULL, NULL, 0, 0, "stericsson,ab8500-debug"),
#endif
- OF_MFD_CELL("ab8500-sysctrl",
+ MFD_CELL_OF("ab8500-sysctrl",
NULL, NULL, 0, 0, "stericsson,ab8500-sysctrl"),
- OF_MFD_CELL("ab8500-ext-regulator",
+ MFD_CELL_OF("ab8500-ext-regulator",
NULL, NULL, 0, 0, "stericsson,ab8500-ext-regulator"),
- OF_MFD_CELL("ab8500-regulator",
+ MFD_CELL_OF("ab8500-regulator",
NULL, NULL, 0, 0, "stericsson,ab8500-regulator"),
- OF_MFD_CELL("ab8500-clk",
+ MFD_CELL_OF("ab8500-clk",
NULL, NULL, 0, 0, "stericsson,ab8500-clk"),
- OF_MFD_CELL("ab8500-gpadc",
+ MFD_CELL_OF("ab8500-gpadc",
NULL, NULL, 0, 0, "stericsson,ab8500-gpadc"),
- OF_MFD_CELL("ab8500-rtc",
+ MFD_CELL_OF("ab8500-rtc",
NULL, NULL, 0, 0, "stericsson,ab8500-rtc"),
- OF_MFD_CELL("ab8500-acc-det",
+ MFD_CELL_OF("ab8500-acc-det",
NULL, NULL, 0, 0, "stericsson,ab8500-acc-det"),
- OF_MFD_CELL("ab8500-poweron-key",
+ MFD_CELL_OF("ab8500-poweron-key",
NULL, NULL, 0, 0, "stericsson,ab8500-poweron-key"),
- OF_MFD_CELL("ab8500-pwm",
+ MFD_CELL_OF("ab8500-pwm",
NULL, NULL, 0, 1, "stericsson,ab8500-pwm"),
- OF_MFD_CELL("ab8500-pwm",
+ MFD_CELL_OF("ab8500-pwm",
NULL, NULL, 0, 2, "stericsson,ab8500-pwm"),
- OF_MFD_CELL("ab8500-pwm",
+ MFD_CELL_OF("ab8500-pwm",
NULL, NULL, 0, 3, "stericsson,ab8500-pwm"),
- OF_MFD_CELL("ab8500-denc",
+ MFD_CELL_OF("ab8500-denc",
NULL, NULL, 0, 0, "stericsson,ab8500-denc"),
- OF_MFD_CELL("pinctrl-ab8500",
+ MFD_CELL_OF("pinctrl-ab8500",
NULL, NULL, 0, 0, "stericsson,ab8500-gpio"),
- OF_MFD_CELL("abx500-temp",
+ MFD_CELL_OF("abx500-temp",
NULL, NULL, 0, 0, "stericsson,abx500-temp"),
- OF_MFD_CELL("ab8500-usb",
+ MFD_CELL_OF("ab8500-usb",
NULL, NULL, 0, 0, "stericsson,ab8500-usb"),
- OF_MFD_CELL("ab8500-codec",
+ MFD_CELL_OF("ab8500-codec",
NULL, NULL, 0, 0, "stericsson,ab8500-codec"),
};
diff --git a/drivers/mfd/acer-ec-a500.c b/drivers/mfd/acer-ec-a500.c
new file mode 100644
index 000000000000..80c2fdd14fc4
--- /dev/null
+++ b/drivers/mfd/acer-ec-a500.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Acer Iconia Tab A500 Embedded Controller Driver
+ *
+ * Copyright 2020 GRATE-driver project
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
+
+#define A500_EC_I2C_ERR_TIMEOUT 500
+#define A500_EC_POWER_CMD_TIMEOUT 1000
+
+/*
+ * Controller's firmware expects specific command opcodes to be used for the
+ * corresponding registers. Unsupported commands are skipped by the firmware.
+ */
+#define CMD_SHUTDOWN 0x0
+#define CMD_WARM_REBOOT 0x0
+#define CMD_COLD_REBOOT 0x1
+
+enum {
+ REG_CURRENT_NOW = 0x03,
+ REG_SHUTDOWN = 0x52,
+ REG_WARM_REBOOT = 0x54,
+ REG_COLD_REBOOT = 0x55,
+};
+
+static struct i2c_client *a500_ec_client_pm_off;
+
+static int a500_ec_read(void *context, const void *reg_buf, size_t reg_size,
+ void *val_buf, size_t val_sizel)
+{
+ struct i2c_client *client = context;
+ unsigned int reg, retries = 5;
+ u16 *ret_val = val_buf;
+ s32 ret = 0;
+
+ reg = *(u8 *)reg_buf;
+
+ while (retries-- > 0) {
+ ret = i2c_smbus_read_word_data(client, reg);
+ if (ret >= 0)
+ break;
+
+ msleep(A500_EC_I2C_ERR_TIMEOUT);
+ }
+
+ if (ret < 0) {
+ dev_err(&client->dev, "read 0x%x failed: %d\n", reg, ret);
+ return ret;
+ }
+
+ *ret_val = ret;
+
+ if (reg == REG_CURRENT_NOW)
+ fsleep(10000);
+
+ return 0;
+}
+
+static int a500_ec_write(void *context, const void *data, size_t count)
+{
+ struct i2c_client *client = context;
+ unsigned int reg, val, retries = 5;
+ s32 ret = 0;
+
+ reg = *(u8 *)(data + 0);
+ val = *(u16 *)(data + 1);
+
+ while (retries-- > 0) {
+ ret = i2c_smbus_write_word_data(client, reg, val);
+ if (ret >= 0)
+ break;
+
+ msleep(A500_EC_I2C_ERR_TIMEOUT);
+ }
+
+ if (ret < 0) {
+ dev_err(&client->dev, "write 0x%x failed: %d\n", reg, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct regmap_config a500_ec_regmap_config = {
+ .name = "KB930",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0xff,
+};
+
+static const struct regmap_bus a500_ec_regmap_bus = {
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
+ .write = a500_ec_write,
+ .read = a500_ec_read,
+ .max_raw_read = 2,
+};
+
+static void a500_ec_poweroff(void)
+{
+ i2c_smbus_write_word_data(a500_ec_client_pm_off,
+ REG_SHUTDOWN, CMD_SHUTDOWN);
+
+ mdelay(A500_EC_POWER_CMD_TIMEOUT);
+}
+
+static int a500_ec_restart_notify(struct notifier_block *this,
+ unsigned long reboot_mode, void *data)
+{
+ if (reboot_mode == REBOOT_WARM)
+ i2c_smbus_write_word_data(a500_ec_client_pm_off,
+ REG_WARM_REBOOT, CMD_WARM_REBOOT);
+ else
+ i2c_smbus_write_word_data(a500_ec_client_pm_off,
+ REG_COLD_REBOOT, CMD_COLD_REBOOT);
+
+ mdelay(A500_EC_POWER_CMD_TIMEOUT);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block a500_ec_restart_handler = {
+ .notifier_call = a500_ec_restart_notify,
+ .priority = 200,
+};
+
+static const struct mfd_cell a500_ec_cells[] = {
+ { .name = "acer-a500-iconia-battery", },
+ { .name = "acer-a500-iconia-leds", },
+};
+
+static int a500_ec_probe(struct i2c_client *client)
+{
+ struct regmap *regmap;
+ int err;
+
+ regmap = devm_regmap_init(&client->dev, &a500_ec_regmap_bus,
+ client, &a500_ec_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ err = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
+ a500_ec_cells, ARRAY_SIZE(a500_ec_cells),
+ NULL, 0, NULL);
+ if (err) {
+ dev_err(&client->dev, "failed to add sub-devices: %d\n", err);
+ return err;
+ }
+
+ if (of_device_is_system_power_controller(client->dev.of_node)) {
+ a500_ec_client_pm_off = client;
+
+ err = register_restart_handler(&a500_ec_restart_handler);
+ if (err)
+ return err;
+
+ if (!pm_power_off)
+ pm_power_off = a500_ec_poweroff;
+ }
+
+ return 0;
+}
+
+static int a500_ec_remove(struct i2c_client *client)
+{
+ if (of_device_is_system_power_controller(client->dev.of_node)) {
+ if (pm_power_off == a500_ec_poweroff)
+ pm_power_off = NULL;
+
+ unregister_restart_handler(&a500_ec_restart_handler);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id a500_ec_match[] = {
+ { .compatible = "acer,a500-iconia-ec" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, a500_ec_match);
+
+static struct i2c_driver a500_ec_driver = {
+ .driver = {
+ .name = "acer-a500-embedded-controller",
+ .of_match_table = a500_ec_match,
+ },
+ .probe_new = a500_ec_probe,
+ .remove = a500_ec_remove,
+};
+module_i2c_driver(a500_ec_driver);
+
+MODULE_DESCRIPTION("Acer Iconia Tab A500 Embedded Controller driver");
+MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c
index 193a96c8b1ea..20cb294c7512 100644
--- a/drivers/mfd/altera-sysmgr.c
+++ b/drivers/mfd/altera-sysmgr.c
@@ -145,7 +145,8 @@ static int sysmgr_probe(struct platform_device *pdev)
sysmgr_config.reg_write = s10_protected_reg_write;
/* Need physical address for SMCC call */
- regmap = devm_regmap_init(dev, NULL, (void *)res->start,
+ regmap = devm_regmap_init(dev, NULL,
+ (void *)(uintptr_t)res->start,
&sysmgr_config);
} else {
base = devm_ioremap(dev, res->start, resource_size(res));
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 000cb82023e3..75f1bc671d59 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -797,17 +797,6 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF
-unsigned long arizona_of_get_type(struct device *dev)
-{
- const struct of_device_id *id = of_match_device(arizona_of_match, dev);
-
- if (id)
- return (unsigned long)id->data;
- else
- return 0;
-}
-EXPORT_SYMBOL_GPL(arizona_of_get_type);
-
static int arizona_of_get_core_pdata(struct arizona *arizona)
{
struct arizona_pdata *pdata = &arizona->pdata;
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 4b58e3ad6eb6..5e83b730c4ce 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -23,14 +23,16 @@
static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
- unsigned long type;
+ unsigned long type = 0;
int ret;
- if (i2c->dev.of_node)
- type = arizona_of_get_type(&i2c->dev);
- else
+ match_data = device_get_match_data(&i2c->dev);
+ if (match_data)
+ type = (unsigned long)match_data;
+ else if (id)
type = id->driver_data;
switch (type) {
@@ -115,6 +117,7 @@ static struct i2c_driver arizona_i2c_driver = {
module_i2c_driver(arizona_i2c_driver);
+MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona I2C bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index 2633e147b76c..24a2c75d691a 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -7,7 +7,10 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/acpi.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -15,22 +18,141 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
+#include <uapi/linux/input-event-codes.h>
#include <linux/mfd/arizona/core.h>
#include "arizona.h"
+#ifdef CONFIG_ACPI
+const struct acpi_gpio_params reset_gpios = { 1, 0, false };
+const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
+
+static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
+ { "reset-gpios", &reset_gpios, 1, },
+ { "wlf,ldoena-gpios", &ldoena_gpios, 1 },
+ { }
+};
+
+/*
+ * The ACPI resources for the device only describe external GPIO-s. They do
+ * not provide mappings for the GPIO-s coming from the Arizona codec itself.
+ */
+static const struct gpiod_lookup arizona_soc_gpios[] = {
+ { "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
+ { "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
+};
+
+/*
+ * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
+ * Function A Play/Pause: 0 ohm
+ * Function D Voice assistant: 135 ohm
+ * Function B Volume Up 240 ohm
+ * Function C Volume Down 470 ohm
+ * Minimum Mic DC resistance 1000 ohm
+ * Minimum Ear speaker impedance 16 ohm
+ * Note the first max value below must be less then the min. speaker impedance,
+ * to allow CTIA/OMTP detection to work. The other max values are the closest
+ * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
+ */
+static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
+ { .max = 11, .key = KEY_PLAYPAUSE },
+ { .max = 186, .key = KEY_VOICECOMMAND },
+ { .max = 348, .key = KEY_VOLUMEUP },
+ { .max = 752, .key = KEY_VOLUMEDOWN },
+};
+
+static void arizona_spi_acpi_remove_lookup(void *lookup)
+{
+ gpiod_remove_lookup_table(lookup);
+}
+
+static int arizona_spi_acpi_probe(struct arizona *arizona)
+{
+ struct gpiod_lookup_table *lookup;
+ acpi_status status;
+ int ret;
+
+ /* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
+ devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
+
+ /* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
+ lookup = devm_kzalloc(arizona->dev,
+ struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
+ GFP_KERNEL);
+ if (!lookup)
+ return -ENOMEM;
+
+ lookup->dev_id = dev_name(arizona->dev);
+ memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
+
+ gpiod_add_lookup_table(lookup);
+ ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
+ if (ret)
+ return ret;
+
+ /* Enable 32KHz clock from SoC to codec for jack-detect */
+ status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
+
+ /*
+ * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
+ * The IRQ line will stay low when a new IRQ event happens between reading
+ * the IRQ status flags and acknowledging them. When the IRQ line stays
+ * low like this the IRQ will never trigger again when its type is set
+ * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
+ *
+ * Note theoretically it is possible that some boards are not capable
+ * of handling active low level interrupts. In that case setting the
+ * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
+ * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
+ * are a bug in the board's DSDT.
+ */
+ arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
+
+ /* Wait 200 ms after jack insertion */
+ arizona->pdata.micd_detect_debounce = 200;
+
+ /* Use standard AOSP values for headset-button mappings */
+ arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
+ arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
+
+ return 0;
+}
+
+static const struct acpi_device_id arizona_acpi_match[] = {
+ {
+ .id = "WM510204",
+ .driver_data = WM5102,
+ },
+ {
+ .id = "WM510205",
+ .driver_data = WM5102,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
+#else
+static int arizona_spi_acpi_probe(struct arizona *arizona)
+{
+ return -ENODEV;
+}
+#endif
+
static int arizona_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
+ const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
- unsigned long type;
+ unsigned long type = 0;
int ret;
- if (spi->dev.of_node)
- type = arizona_of_get_type(&spi->dev);
- else
+ match_data = device_get_match_data(&spi->dev);
+ if (match_data)
+ type = (unsigned long)match_data;
+ else if (id)
type = id->driver_data;
switch (type) {
@@ -75,6 +197,12 @@ static int arizona_spi_probe(struct spi_device *spi)
arizona->dev = &spi->dev;
arizona->irq = spi->irq;
+ if (has_acpi_companion(&spi->dev)) {
+ ret = arizona_spi_acpi_probe(arizona);
+ if (ret)
+ return ret;
+ }
+
return arizona_dev_init(arizona);
}
@@ -102,6 +230,7 @@ static struct spi_driver arizona_spi_driver = {
.name = "arizona",
.pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match),
+ .acpi_match_table = ACPI_PTR(arizona_acpi_match),
},
.probe = arizona_spi_probe,
.remove = arizona_spi_remove,
@@ -110,6 +239,7 @@ static struct spi_driver arizona_spi_driver = {
module_spi_driver(arizona_spi_driver);
+MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona SPI bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h
index 995efc6d7f32..801cbbcd71cb 100644
--- a/drivers/mfd/arizona.h
+++ b/drivers/mfd/arizona.h
@@ -50,13 +50,4 @@ int arizona_dev_exit(struct arizona *arizona);
int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona);
-#ifdef CONFIG_OF
-unsigned long arizona_of_get_type(struct device *dev);
-#else
-static inline unsigned long arizona_of_get_type(struct device *dev)
-{
- return 0;
-}
-#endif
-
#endif
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index 2cfde81f5fbf..00ab48018d8d 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -54,7 +54,9 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
{
struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
- return axp20x_device_remove(axp20x);
+ axp20x_device_remove(axp20x);
+
+ return 0;
}
#ifdef CONFIG_OF
diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c
index 4cdc79f5cc48..214bc0d84d44 100644
--- a/drivers/mfd/axp20x-rsb.c
+++ b/drivers/mfd/axp20x-rsb.c
@@ -49,11 +49,11 @@ static int axp20x_rsb_probe(struct sunxi_rsb_device *rdev)
return axp20x_device_probe(axp20x);
}
-static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
+static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
{
struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev);
- return axp20x_device_remove(axp20x);
+ axp20x_device_remove(axp20x);
}
static const struct of_device_id axp20x_rsb_of_match[] = {
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index aa59496e4376..3eae04e24ac8 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -987,7 +987,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
}
EXPORT_SYMBOL(axp20x_device_probe);
-int axp20x_device_remove(struct axp20x_dev *axp20x)
+void axp20x_device_remove(struct axp20x_dev *axp20x)
{
if (axp20x == axp20x_pm_power_off) {
axp20x_pm_power_off = NULL;
@@ -996,8 +996,6 @@ int axp20x_device_remove(struct axp20x_dev *axp20x)
mfd_remove_devices(axp20x->dev);
regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
-
- return 0;
}
EXPORT_SYMBOL(axp20x_device_remove);
diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c
index fab3cdc27ed6..e15b1acfb063 100644
--- a/drivers/mfd/bd9571mwv.c
+++ b/drivers/mfd/bd9571mwv.c
@@ -1,16 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
- * ROHM BD9571MWV-M MFD driver
+ * ROHM BD9571MWV-M and BD9574MVF-M core driver
*
* Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether expressed or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License version 2 for more details.
+ * Copyright (C) 2020 Renesas Electronics Corporation
*
* Based on the TPS65086 driver
*/
@@ -18,6 +11,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
+#include <linux/mfd/rohm-generic.h>
#include <linux/module.h>
#include <linux/mfd/bd9571mwv.h>
@@ -110,13 +104,78 @@ static struct regmap_irq_chip bd9571mwv_irq_chip = {
.num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
};
-static int bd9571mwv_identify(struct bd9571mwv *bd)
+static const struct mfd_cell bd9574mwf_cells[] = {
+ { .name = "bd9574mwf-regulator", },
+ { .name = "bd9574mwf-gpio", },
+};
+
+static const struct regmap_range bd9574mwf_readable_yes_ranges[] = {
+ regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
+ regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
+ regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_SETVMAX),
+ regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_MONIVDAC),
+ regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
+ regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
+ regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
+};
+
+static const struct regmap_access_table bd9574mwf_readable_table = {
+ .yes_ranges = bd9574mwf_readable_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(bd9574mwf_readable_yes_ranges),
+};
+
+static const struct regmap_range bd9574mwf_writable_yes_ranges[] = {
+ regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
+ regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
+ regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
+ regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
+ regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
+};
+
+static const struct regmap_access_table bd9574mwf_writable_table = {
+ .yes_ranges = bd9574mwf_writable_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(bd9574mwf_writable_yes_ranges),
+};
+
+static const struct regmap_range bd9574mwf_volatile_yes_ranges[] = {
+ regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
+ regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
+ regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
+ regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
+};
+
+static const struct regmap_access_table bd9574mwf_volatile_table = {
+ .yes_ranges = bd9574mwf_volatile_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(bd9574mwf_volatile_yes_ranges),
+};
+
+static const struct regmap_config bd9574mwf_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+ .rd_table = &bd9574mwf_readable_table,
+ .wr_table = &bd9574mwf_writable_table,
+ .volatile_table = &bd9574mwf_volatile_table,
+ .max_register = 0xff,
+};
+
+static struct regmap_irq_chip bd9574mwf_irq_chip = {
+ .name = "bd9574mwf",
+ .status_base = BD9571MWV_INT_INTREQ,
+ .mask_base = BD9571MWV_INT_INTMASK,
+ .ack_base = BD9571MWV_INT_INTREQ,
+ .init_ack_masked = true,
+ .num_regs = 1,
+ .irqs = bd9571mwv_irqs,
+ .num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
+};
+
+static int bd957x_identify(struct device *dev, struct regmap *regmap)
{
- struct device *dev = bd->dev;
unsigned int value;
int ret;
- ret = regmap_read(bd->regmap, BD9571MWV_VENDOR_CODE, &value);
+ ret = regmap_read(regmap, BD9571MWV_VENDOR_CODE, &value);
if (ret) {
dev_err(dev, "Failed to read vendor code register (ret=%i)\n",
ret);
@@ -129,84 +188,82 @@ static int bd9571mwv_identify(struct bd9571mwv *bd)
return -EINVAL;
}
- ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_CODE, &value);
+ ret = regmap_read(regmap, BD9571MWV_PRODUCT_CODE, &value);
if (ret) {
dev_err(dev, "Failed to read product code register (ret=%i)\n",
ret);
return ret;
}
-
- if (value != BD9571MWV_PRODUCT_CODE_VAL) {
- dev_err(dev, "Invalid product code ID %02x (expected %02x)\n",
- value, BD9571MWV_PRODUCT_CODE_VAL);
- return -EINVAL;
- }
-
- ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_REVISION, &value);
+ ret = regmap_read(regmap, BD9571MWV_PRODUCT_REVISION, &value);
if (ret) {
dev_err(dev, "Failed to read revision register (ret=%i)\n",
ret);
return ret;
}
- dev_info(dev, "Device: BD9571MWV rev. %d\n", value & 0xff);
-
return 0;
}
static int bd9571mwv_probe(struct i2c_client *client,
- const struct i2c_device_id *ids)
+ const struct i2c_device_id *ids)
{
- struct bd9571mwv *bd;
- int ret;
-
- bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL);
- if (!bd)
- return -ENOMEM;
+ const struct regmap_config *regmap_config;
+ const struct regmap_irq_chip *irq_chip;
+ const struct mfd_cell *cells;
+ struct device *dev = &client->dev;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_data;
+ int ret, num_cells, irq = client->irq;
+
+ /* Read the PMIC product code */
+ ret = i2c_smbus_read_byte_data(client, BD9571MWV_PRODUCT_CODE);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read product code\n");
+ return ret;
+ }
- i2c_set_clientdata(client, bd);
- bd->dev = &client->dev;
- bd->irq = client->irq;
+ switch (ret) {
+ case BD9571MWV_PRODUCT_CODE_BD9571MWV:
+ regmap_config = &bd9571mwv_regmap_config;
+ irq_chip = &bd9571mwv_irq_chip;
+ cells = bd9571mwv_cells;
+ num_cells = ARRAY_SIZE(bd9571mwv_cells);
+ break;
+ case BD9571MWV_PRODUCT_CODE_BD9574MWF:
+ regmap_config = &bd9574mwf_regmap_config;
+ irq_chip = &bd9574mwf_irq_chip;
+ cells = bd9574mwf_cells;
+ num_cells = ARRAY_SIZE(bd9574mwf_cells);
+ break;
+ default:
+ dev_err(dev, "Unsupported device 0x%x\n", ret);
+ return -ENODEV;
+ }
- bd->regmap = devm_regmap_init_i2c(client, &bd9571mwv_regmap_config);
- if (IS_ERR(bd->regmap)) {
- dev_err(bd->dev, "Failed to initialize register map\n");
- return PTR_ERR(bd->regmap);
+ regmap = devm_regmap_init_i2c(client, regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to initialize register map\n");
+ return PTR_ERR(regmap);
}
- ret = bd9571mwv_identify(bd);
+ ret = bd957x_identify(dev, regmap);
if (ret)
return ret;
- ret = regmap_add_irq_chip(bd->regmap, bd->irq, IRQF_ONESHOT, 0,
- &bd9571mwv_irq_chip, &bd->irq_data);
- if (ret) {
- dev_err(bd->dev, "Failed to register IRQ chip\n");
- return ret;
- }
-
- ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, bd9571mwv_cells,
- ARRAY_SIZE(bd9571mwv_cells), NULL, 0,
- regmap_irq_get_domain(bd->irq_data));
+ ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT, 0,
+ irq_chip, &irq_data);
if (ret) {
- regmap_del_irq_chip(bd->irq, bd->irq_data);
+ dev_err(dev, "Failed to register IRQ chip\n");
return ret;
}
- return 0;
-}
-
-static int bd9571mwv_remove(struct i2c_client *client)
-{
- struct bd9571mwv *bd = i2c_get_clientdata(client);
-
- regmap_del_irq_chip(bd->irq, bd->irq_data);
-
- return 0;
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, num_cells,
+ NULL, 0, regmap_irq_get_domain(irq_data));
}
static const struct of_device_id bd9571mwv_of_match_table[] = {
{ .compatible = "rohm,bd9571mwv", },
+ { .compatible = "rohm,bd9574mwf", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table);
@@ -223,7 +280,6 @@ static struct i2c_driver bd9571mwv_driver = {
.of_match_table = bd9571mwv_of_match_table,
},
.probe = bd9571mwv_probe,
- .remove = bd9571mwv_remove,
.id_table = bd9571mwv_id_table,
};
module_i2c_driver(bd9571mwv_driver);
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index a5983d515db0..167faac9b75b 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2954,12 +2954,12 @@ static const struct mfd_cell common_prcmu_devs[] = {
};
static const struct mfd_cell db8500_prcmu_devs[] = {
- OF_MFD_CELL("db8500-prcmu-regulators", NULL,
+ MFD_CELL_OF("db8500-prcmu-regulators", NULL,
&db8500_regulators, sizeof(db8500_regulators), 0,
"stericsson,db8500-prcmu-regulator"),
- OF_MFD_CELL("cpuidle-dbx500",
+ MFD_CELL_OF("cpuidle-dbx500",
NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"),
- OF_MFD_CELL("db8500-thermal",
+ MFD_CELL_OF("db8500-thermal",
NULL, NULL, 0, 0, "stericsson,db8500-thermal"),
};
diff --git a/drivers/mfd/gateworks-gsc.c b/drivers/mfd/gateworks-gsc.c
index 576da62fbb0c..d87876747b91 100644
--- a/drivers/mfd/gateworks-gsc.c
+++ b/drivers/mfd/gateworks-gsc.c
@@ -234,7 +234,7 @@ static int gsc_probe(struct i2c_client *client)
ret = devm_regmap_add_irq_chip(dev, gsc->regmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED |
- IRQF_TRIGGER_FALLING, 0,
+ IRQF_TRIGGER_LOW, 0,
&gsc_irq_chip, &irq_data);
if (ret)
return ret;
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 2d7c588ef1ed..1522c8afc540 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -277,6 +277,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x4dea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x4deb), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x4dfb), (kernel_ulong_t)&spt_info },
+ /* ADL-P */
+ { PCI_VDEVICE(INTEL, 0x51a8), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x51a9), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x51aa), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x51ab), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x51c5), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x51c6), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x51c7), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x51e8), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x51e9), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x51ea), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x51eb), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x51fb), (kernel_ulong_t)&bxt_info },
/* APL */
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
@@ -293,6 +306,21 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info },
+ /* ADL-S */
+ { PCI_VDEVICE(INTEL, 0x7aa8), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7aa9), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7aaa), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7aab), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7acc), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7acd), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7ace), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7acf), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7adc), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7af9), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7afb), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7afc), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7afd), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7afe), (kernel_ulong_t)&bxt_uart_info },
/* LKF */
{ PCI_VDEVICE(INTEL, 0x98a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x98a9), (kernel_ulong_t)&bxt_uart_info },
diff --git a/drivers/mfd/intel-m10-bmc.c b/drivers/mfd/intel-m10-bmc.c
index b84579b7b4f0..06c977519479 100644
--- a/drivers/mfd/intel-m10-bmc.c
+++ b/drivers/mfd/intel-m10-bmc.c
@@ -60,9 +60,52 @@ static ssize_t bmcfw_version_show(struct device *dev,
}
static DEVICE_ATTR_RO(bmcfw_version);
+static ssize_t mac_address_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct intel_m10bmc *max10 = dev_get_drvdata(dev);
+ unsigned int macaddr_low, macaddr_high;
+ int ret;
+
+ ret = m10bmc_sys_read(max10, M10BMC_MAC_LOW, &macaddr_low);
+ if (ret)
+ return ret;
+
+ ret = m10bmc_sys_read(max10, M10BMC_MAC_HIGH, &macaddr_high);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (u8)FIELD_GET(M10BMC_MAC_BYTE1, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE2, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE3, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE4, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE5, macaddr_high),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE6, macaddr_high));
+}
+static DEVICE_ATTR_RO(mac_address);
+
+static ssize_t mac_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct intel_m10bmc *max10 = dev_get_drvdata(dev);
+ unsigned int macaddr_high;
+ int ret;
+
+ ret = m10bmc_sys_read(max10, M10BMC_MAC_HIGH, &macaddr_high);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%u\n",
+ (u8)FIELD_GET(M10BMC_MAC_COUNT, macaddr_high));
+}
+static DEVICE_ATTR_RO(mac_count);
+
static struct attribute *m10bmc_attrs[] = {
&dev_attr_bmc_version.attr,
&dev_attr_bmcfw_version.attr,
+ &dev_attr_mac_address.attr,
+ &dev_attr_mac_count.attr,
NULL,
};
ATTRIBUTE_GROUPS(m10bmc);
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
deleted file mode 100644
index daa772f8146b..000000000000
--- a/drivers/mfd/intel_msic.c
+++ /dev/null
@@ -1,425 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Driver for Intel MSIC
- *
- * Copyright (C) 2011, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/init.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/intel_msic.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <asm/intel_scu_ipc.h>
-
-#define MSIC_VENDOR(id) ((id >> 6) & 3)
-#define MSIC_VERSION(id) (id & 0x3f)
-#define MSIC_MAJOR(id) ('A' + ((id >> 3) & 7))
-#define MSIC_MINOR(id) (id & 7)
-
-/*
- * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
- * Since IRQ block starts from address 0x002 we need to subtract that from
- * the actual IRQ status register address.
- */
-#define MSIC_IRQ_STATUS(x) (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
-#define MSIC_IRQ_STATUS_ACCDET MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET)
-
-/*
- * The SCU hardware has limitation of 16 bytes per read/write buffer on
- * Medfield.
- */
-#define SCU_IPC_RWBUF_LIMIT 16
-
-/**
- * struct intel_msic - an MSIC MFD instance
- * @pdev: pointer to the platform device
- * @vendor: vendor ID
- * @version: chip version
- * @irq_base: base address of the mapped MSIC SRAM interrupt tree
- */
-struct intel_msic {
- struct platform_device *pdev;
- unsigned vendor;
- unsigned version;
- void __iomem *irq_base;
-};
-
-static const struct resource msic_touch_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_adc_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_battery_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_gpio_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_audio_resources[] = {
- DEFINE_RES_IRQ_NAMED(0, "IRQ"),
- /*
- * We will pass IRQ_BASE to the driver now but this can be removed
- * when/if the driver starts to use intel_msic_irq_read().
- */
- DEFINE_RES_MEM_NAMED(MSIC_IRQ_STATUS_ACCDET, 1, "IRQ_BASE"),
-};
-
-static const struct resource msic_hdmi_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_thermal_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_power_btn_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-static const struct resource msic_ocd_resources[] = {
- DEFINE_RES_IRQ(0),
-};
-
-/*
- * Devices that are part of the MSIC and are available via firmware
- * populated SFI DEVS table.
- */
-static struct mfd_cell msic_devs[] = {
- [INTEL_MSIC_BLOCK_TOUCH] = {
- .name = "msic_touch",
- .num_resources = ARRAY_SIZE(msic_touch_resources),
- .resources = msic_touch_resources,
- },
- [INTEL_MSIC_BLOCK_ADC] = {
- .name = "msic_adc",
- .num_resources = ARRAY_SIZE(msic_adc_resources),
- .resources = msic_adc_resources,
- },
- [INTEL_MSIC_BLOCK_BATTERY] = {
- .name = "msic_battery",
- .num_resources = ARRAY_SIZE(msic_battery_resources),
- .resources = msic_battery_resources,
- },
- [INTEL_MSIC_BLOCK_GPIO] = {
- .name = "msic_gpio",
- .num_resources = ARRAY_SIZE(msic_gpio_resources),
- .resources = msic_gpio_resources,
- },
- [INTEL_MSIC_BLOCK_AUDIO] = {
- .name = "msic_audio",
- .num_resources = ARRAY_SIZE(msic_audio_resources),
- .resources = msic_audio_resources,
- },
- [INTEL_MSIC_BLOCK_HDMI] = {
- .name = "msic_hdmi",
- .num_resources = ARRAY_SIZE(msic_hdmi_resources),
- .resources = msic_hdmi_resources,
- },
- [INTEL_MSIC_BLOCK_THERMAL] = {
- .name = "msic_thermal",
- .num_resources = ARRAY_SIZE(msic_thermal_resources),
- .resources = msic_thermal_resources,
- },
- [INTEL_MSIC_BLOCK_POWER_BTN] = {
- .name = "msic_power_btn",
- .num_resources = ARRAY_SIZE(msic_power_btn_resources),
- .resources = msic_power_btn_resources,
- },
- [INTEL_MSIC_BLOCK_OCD] = {
- .name = "msic_ocd",
- .num_resources = ARRAY_SIZE(msic_ocd_resources),
- .resources = msic_ocd_resources,
- },
-};
-
-/*
- * Other MSIC related devices which are not directly available via SFI DEVS
- * table. These can be pseudo devices, regulators etc. which are needed for
- * different purposes.
- *
- * These devices appear only after the MSIC driver itself is initialized so
- * we can guarantee that the SCU IPC interface is ready.
- */
-static const struct mfd_cell msic_other_devs[] = {
- /* Audio codec in the MSIC */
- {
- .id = -1,
- .name = "sn95031",
- },
-};
-
-/**
- * intel_msic_reg_read - read a single MSIC register
- * @reg: register to read
- * @val: register value is placed here
- *
- * Read a single register from MSIC. Returns %0 on success and negative
- * errno in case of failure.
- *
- * Function may sleep.
- */
-int intel_msic_reg_read(unsigned short reg, u8 *val)
-{
- return intel_scu_ipc_ioread8(reg, val);
-}
-EXPORT_SYMBOL_GPL(intel_msic_reg_read);
-
-/**
- * intel_msic_reg_write - write a single MSIC register
- * @reg: register to write
- * @val: value to write to that register
- *
- * Write a single MSIC register. Returns 0 on success and negative
- * errno in case of failure.
- *
- * Function may sleep.
- */
-int intel_msic_reg_write(unsigned short reg, u8 val)
-{
- return intel_scu_ipc_iowrite8(reg, val);
-}
-EXPORT_SYMBOL_GPL(intel_msic_reg_write);
-
-/**
- * intel_msic_reg_update - update a single MSIC register
- * @reg: register to update
- * @val: value to write to the register
- * @mask: specifies which of the bits are updated (%0 = don't update,
- * %1 = update)
- *
- * Perform an update to a register @reg. @mask is used to specify which
- * bits are updated. Returns %0 in case of success and negative errno in
- * case of failure.
- *
- * Function may sleep.
- */
-int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask)
-{
- return intel_scu_ipc_update_register(reg, val, mask);
-}
-EXPORT_SYMBOL_GPL(intel_msic_reg_update);
-
-/**
- * intel_msic_bulk_read - read an array of registers
- * @reg: array of register addresses to read
- * @buf: array where the read values are placed
- * @count: number of registers to read
- *
- * Function reads @count registers from the MSIC using addresses passed in
- * @reg. Read values are placed in @buf. Reads are performed atomically
- * wrt. MSIC.
- *
- * Returns %0 in case of success and negative errno in case of failure.
- *
- * Function may sleep.
- */
-int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count)
-{
- if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
- return -EINVAL;
-
- return intel_scu_ipc_readv(reg, buf, count);
-}
-EXPORT_SYMBOL_GPL(intel_msic_bulk_read);
-
-/**
- * intel_msic_bulk_write - write an array of values to the MSIC registers
- * @reg: array of registers to write
- * @buf: values to write to each register
- * @count: number of registers to write
- *
- * Function writes @count registers in @buf to MSIC. Writes are performed
- * atomically wrt MSIC. Returns %0 in case of success and negative errno in
- * case of failure.
- *
- * Function may sleep.
- */
-int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count)
-{
- if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
- return -EINVAL;
-
- return intel_scu_ipc_writev(reg, buf, count);
-}
-EXPORT_SYMBOL_GPL(intel_msic_bulk_write);
-
-/**
- * intel_msic_irq_read - read a register from an MSIC interrupt tree
- * @msic: MSIC instance
- * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and
- * %INTEL_MSIC_RESETIRQ2)
- * @val: value of the register is placed here
- *
- * This function can be used by an MSIC subdevice interrupt handler to read
- * a register value from the MSIC interrupt tree. In this way subdevice
- * drivers don't have to map in the interrupt tree themselves but can just
- * call this function instead.
- *
- * Function doesn't sleep and is callable from interrupt context.
- *
- * Returns %-EINVAL if @reg is outside of the allowed register region.
- */
-int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
-{
- if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2))
- return -EINVAL;
-
- *val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1));
- return 0;
-}
-EXPORT_SYMBOL_GPL(intel_msic_irq_read);
-
-static int intel_msic_init_devices(struct intel_msic *msic)
-{
- struct platform_device *pdev = msic->pdev;
- struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
- int ret, i;
-
- if (pdata->gpio) {
- struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO];
-
- cell->platform_data = pdata->gpio;
- cell->pdata_size = sizeof(*pdata->gpio);
- }
-
- if (pdata->ocd) {
- unsigned gpio = pdata->ocd->gpio;
-
- ret = devm_gpio_request_one(&pdev->dev, gpio,
- GPIOF_IN, "ocd_gpio");
- if (ret) {
- dev_err(&pdev->dev, "failed to register OCD GPIO\n");
- return ret;
- }
-
- ret = gpio_to_irq(gpio);
- if (ret < 0) {
- dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n");
- return ret;
- }
-
- /* Update the IRQ number for the OCD */
- pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret;
- }
-
- for (i = 0; i < ARRAY_SIZE(msic_devs); i++) {
- if (!pdata->irq[i])
- continue;
-
- ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
- pdata->irq[i], NULL);
- if (ret)
- goto fail;
- }
-
- ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
- ARRAY_SIZE(msic_other_devs), NULL, 0, NULL);
- if (ret)
- goto fail;
-
- return 0;
-
-fail:
- mfd_remove_devices(&pdev->dev);
-
- return ret;
-}
-
-static void intel_msic_remove_devices(struct intel_msic *msic)
-{
- struct platform_device *pdev = msic->pdev;
-
- mfd_remove_devices(&pdev->dev);
-}
-
-static int intel_msic_probe(struct platform_device *pdev)
-{
- struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct intel_msic *msic;
- struct resource *res;
- u8 id0, id1;
- int ret;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data passed\n");
- return -EINVAL;
- }
-
- /* First validate that we have an MSIC in place */
- ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0);
- if (ret) {
- dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n");
- return -ENXIO;
- }
-
- ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1);
- if (ret) {
- dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n");
- return -ENXIO;
- }
-
- if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) {
- dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1);
- return -ENXIO;
- }
-
- msic = devm_kzalloc(&pdev->dev, sizeof(*msic), GFP_KERNEL);
- if (!msic)
- return -ENOMEM;
-
- msic->vendor = MSIC_VENDOR(id0);
- msic->version = MSIC_VERSION(id0);
- msic->pdev = pdev;
-
- /*
- * Map in the MSIC interrupt tree area in SRAM. This is exposed to
- * the clients via intel_msic_irq_read().
- */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- msic->irq_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(msic->irq_base))
- return PTR_ERR(msic->irq_base);
-
- platform_set_drvdata(pdev, msic);
-
- ret = intel_msic_init_devices(msic);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
- return ret;
- }
-
- dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
- MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version),
- msic->vendor);
-
- return 0;
-}
-
-static int intel_msic_remove(struct platform_device *pdev)
-{
- struct intel_msic *msic = platform_get_drvdata(pdev);
-
- intel_msic_remove_devices(msic);
-
- return 0;
-}
-
-static struct platform_driver intel_msic_driver = {
- .probe = intel_msic_probe,
- .remove = intel_msic_remove,
- .driver = {
- .name = "intel_msic",
- },
-};
-builtin_platform_driver(intel_msic_driver);
diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c
index 761b4ef3a381..d1fc38a78acb 100644
--- a/drivers/mfd/iqs62x.c
+++ b/drivers/mfd/iqs62x.c
@@ -36,7 +36,6 @@
#define IQS62X_PROD_NUM 0x00
#define IQS62X_SYS_FLAGS 0x10
-#define IQS62X_SYS_FLAGS_IN_ATI BIT(2)
#define IQS620_HALL_FLAGS 0x16
#define IQS621_HALL_FLAGS 0x19
@@ -57,10 +56,10 @@
#define IQS620_TEMP_CAL_OFFS 0xC4
#define IQS62X_SYS_SETTINGS 0xD0
-#define IQS62X_SYS_SETTINGS_SOFT_RESET BIT(7)
#define IQS62X_SYS_SETTINGS_ACK_RESET BIT(6)
#define IQS62X_SYS_SETTINGS_EVENT_MODE BIT(5)
#define IQS62X_SYS_SETTINGS_CLK_DIV BIT(4)
+#define IQS62X_SYS_SETTINGS_COMM_ATI BIT(3)
#define IQS62X_SYS_SETTINGS_REDO_ATI BIT(1)
#define IQS62X_PWR_SETTINGS 0xD2
@@ -82,9 +81,8 @@
#define IQS62X_FW_REC_TYPE_MASK 3
#define IQS62X_FW_REC_TYPE_DATA 4
-#define IQS62X_ATI_POLL_SLEEP_US 10000
-#define IQS62X_ATI_POLL_TIMEOUT_US 500000
-#define IQS62X_ATI_STABLE_DELAY_MS 150
+#define IQS62X_ATI_STARTUP_MS 350
+#define IQS62X_FILT_SETTLE_MS 250
struct iqs62x_fw_rec {
u8 type;
@@ -112,9 +110,16 @@ static int iqs62x_dev_init(struct iqs62x_core *iqs62x)
struct iqs62x_fw_blk *fw_blk;
unsigned int val;
int ret;
- u8 clk_div = 1;
list_for_each_entry(fw_blk, &iqs62x->fw_blk_head, list) {
+ /*
+ * In case ATI is in progress, wait for it to complete before
+ * lowering the core clock frequency.
+ */
+ if (fw_blk->addr == IQS62X_SYS_SETTINGS &&
+ *fw_blk->data & IQS62X_SYS_SETTINGS_CLK_DIV)
+ msleep(IQS62X_ATI_STARTUP_MS);
+
if (fw_blk->mask)
ret = regmap_update_bits(iqs62x->regmap, fw_blk->addr,
fw_blk->mask, *fw_blk->data);
@@ -135,7 +140,6 @@ static int iqs62x_dev_init(struct iqs62x_core *iqs62x)
if (val & IQS620_PROX_SETTINGS_4_SAR_EN)
iqs62x->ui_sel = IQS62X_UI_SAR1;
-
fallthrough;
case IQS621_PROD_NUM:
@@ -183,28 +187,32 @@ static int iqs62x_dev_init(struct iqs62x_core *iqs62x)
return ret;
}
- ret = regmap_read(iqs62x->regmap, IQS62X_SYS_SETTINGS, &val);
- if (ret)
- return ret;
-
- if (val & IQS62X_SYS_SETTINGS_CLK_DIV)
- clk_div = iqs62x->dev_desc->clk_div;
-
- ret = regmap_write(iqs62x->regmap, IQS62X_SYS_SETTINGS, val |
- IQS62X_SYS_SETTINGS_ACK_RESET |
- IQS62X_SYS_SETTINGS_EVENT_MODE |
- IQS62X_SYS_SETTINGS_REDO_ATI);
- if (ret)
- return ret;
-
- ret = regmap_read_poll_timeout(iqs62x->regmap, IQS62X_SYS_FLAGS, val,
- !(val & IQS62X_SYS_FLAGS_IN_ATI),
- IQS62X_ATI_POLL_SLEEP_US,
- IQS62X_ATI_POLL_TIMEOUT_US * clk_div);
+ /*
+ * Place the device in streaming mode at first so as not to miss the
+ * limited number of interrupts that would otherwise occur after ATI
+ * completes. The device is subsequently placed in event mode by the
+ * interrupt handler.
+ *
+ * In the meantime, mask interrupts during ATI to prevent the device
+ * from soliciting I2C traffic until the noise-sensitive ATI process
+ * is complete.
+ */
+ ret = regmap_update_bits(iqs62x->regmap, IQS62X_SYS_SETTINGS,
+ IQS62X_SYS_SETTINGS_ACK_RESET |
+ IQS62X_SYS_SETTINGS_EVENT_MODE |
+ IQS62X_SYS_SETTINGS_COMM_ATI |
+ IQS62X_SYS_SETTINGS_REDO_ATI,
+ IQS62X_SYS_SETTINGS_ACK_RESET |
+ IQS62X_SYS_SETTINGS_REDO_ATI);
if (ret)
return ret;
- msleep(IQS62X_ATI_STABLE_DELAY_MS * clk_div);
+ /*
+ * The following delay gives the device time to deassert its RDY output
+ * in case a communication window was open while the REDO_ATI field was
+ * written. This prevents an interrupt from being serviced prematurely.
+ */
+ usleep_range(5000, 5100);
return 0;
}
@@ -435,6 +443,11 @@ const struct iqs62x_event_desc iqs62x_events[IQS62X_NUM_EVENTS] = {
.mask = BIT(7),
.val = BIT(7),
},
+ [IQS62X_EVENT_SYS_ATI] = {
+ .reg = IQS62X_EVENT_SYS,
+ .mask = BIT(2),
+ .val = BIT(2),
+ },
};
EXPORT_SYMBOL_GPL(iqs62x_events);
@@ -469,7 +482,6 @@ static irqreturn_t iqs62x_irq(int irq, void *context)
switch (event_reg) {
case IQS62X_EVENT_UI_LO:
event_data.ui_data = get_unaligned_le16(&event_map[i]);
-
fallthrough;
case IQS62X_EVENT_UI_HI:
@@ -490,7 +502,6 @@ static irqreturn_t iqs62x_irq(int irq, void *context)
case IQS62X_EVENT_HYST:
event_map[i] <<= iqs62x->dev_desc->hyst_shift;
-
fallthrough;
case IQS62X_EVENT_WHEEL:
@@ -525,19 +536,46 @@ static irqreturn_t iqs62x_irq(int irq, void *context)
"Failed to re-initialize device: %d\n", ret);
return IRQ_NONE;
}
+
+ iqs62x->event_cache |= BIT(IQS62X_EVENT_SYS_RESET);
+ reinit_completion(&iqs62x->ati_done);
+ } else if (event_flags & BIT(IQS62X_EVENT_SYS_ATI)) {
+ iqs62x->event_cache |= BIT(IQS62X_EVENT_SYS_ATI);
+ reinit_completion(&iqs62x->ati_done);
+ } else if (!completion_done(&iqs62x->ati_done)) {
+ ret = regmap_update_bits(iqs62x->regmap, IQS62X_SYS_SETTINGS,
+ IQS62X_SYS_SETTINGS_EVENT_MODE, 0xFF);
+ if (ret) {
+ dev_err(&client->dev,
+ "Failed to enable event mode: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ msleep(IQS62X_FILT_SETTLE_MS);
+ complete_all(&iqs62x->ati_done);
}
- ret = blocking_notifier_call_chain(&iqs62x->nh, event_flags,
- &event_data);
- if (ret & NOTIFY_STOP_MASK)
- return IRQ_NONE;
+ /*
+ * Reset and ATI events are not broadcast to the sub-device drivers
+ * until ATI has completed. Any other events that may have occurred
+ * during ATI are ignored.
+ */
+ if (completion_done(&iqs62x->ati_done)) {
+ event_flags |= iqs62x->event_cache;
+ ret = blocking_notifier_call_chain(&iqs62x->nh, event_flags,
+ &event_data);
+ if (ret & NOTIFY_STOP_MASK)
+ return IRQ_NONE;
+
+ iqs62x->event_cache = 0;
+ }
/*
* Once the communication window is closed, a small delay is added to
* ensure the device's RDY output has been deasserted by the time the
* interrupt handler returns.
*/
- usleep_range(50, 100);
+ usleep_range(150, 200);
return IRQ_HANDLED;
}
@@ -571,6 +609,12 @@ static void iqs62x_firmware_load(const struct firmware *fw, void *context)
goto err_out;
}
+ if (!wait_for_completion_timeout(&iqs62x->ati_done,
+ msecs_to_jiffies(2000))) {
+ dev_err(&client->dev, "Failed to complete ATI\n");
+ goto err_out;
+ }
+
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
iqs62x->dev_desc->sub_devs,
iqs62x->dev_desc->num_sub_devs,
@@ -752,22 +796,17 @@ static const struct iqs62x_dev_desc iqs62x_devs[] = {
.dev_name = "iqs620at",
.sub_devs = iqs620at_sub_devs,
.num_sub_devs = ARRAY_SIZE(iqs620at_sub_devs),
-
.prod_num = IQS620_PROD_NUM,
.sw_num = 0x08,
.cal_regs = iqs620at_cal_regs,
.num_cal_regs = ARRAY_SIZE(iqs620at_cal_regs),
-
.prox_mask = BIT(0),
.sar_mask = BIT(1) | BIT(7),
.hall_mask = BIT(2),
.hyst_mask = BIT(3),
.temp_mask = BIT(4),
-
.prox_settings = IQS620_PROX_SETTINGS_4,
.hall_flags = IQS620_HALL_FLAGS,
-
- .clk_div = 4,
.fw_name = "iqs620a.bin",
.event_regs = &iqs620a_event_regs[IQS62X_UI_PROX],
},
@@ -775,20 +814,15 @@ static const struct iqs62x_dev_desc iqs62x_devs[] = {
.dev_name = "iqs620a",
.sub_devs = iqs620a_sub_devs,
.num_sub_devs = ARRAY_SIZE(iqs620a_sub_devs),
-
.prod_num = IQS620_PROD_NUM,
.sw_num = 0x08,
-
.prox_mask = BIT(0),
.sar_mask = BIT(1) | BIT(7),
.hall_mask = BIT(2),
.hyst_mask = BIT(3),
.temp_mask = BIT(4),
-
.prox_settings = IQS620_PROX_SETTINGS_4,
.hall_flags = IQS620_HALL_FLAGS,
-
- .clk_div = 4,
.fw_name = "iqs620a.bin",
.event_regs = &iqs620a_event_regs[IQS62X_UI_PROX],
},
@@ -796,23 +830,18 @@ static const struct iqs62x_dev_desc iqs62x_devs[] = {
.dev_name = "iqs621",
.sub_devs = iqs621_sub_devs,
.num_sub_devs = ARRAY_SIZE(iqs621_sub_devs),
-
.prod_num = IQS621_PROD_NUM,
.sw_num = 0x09,
.cal_regs = iqs621_cal_regs,
.num_cal_regs = ARRAY_SIZE(iqs621_cal_regs),
-
.prox_mask = BIT(0),
.hall_mask = BIT(1),
.als_mask = BIT(2),
.hyst_mask = BIT(3),
.temp_mask = BIT(4),
-
.als_flags = IQS621_ALS_FLAGS,
.hall_flags = IQS621_HALL_FLAGS,
.hyst_shift = 5,
-
- .clk_div = 2,
.fw_name = "iqs621.bin",
.event_regs = &iqs621_event_regs[IQS62X_UI_PROX],
},
@@ -820,21 +849,16 @@ static const struct iqs62x_dev_desc iqs62x_devs[] = {
.dev_name = "iqs622",
.sub_devs = iqs622_sub_devs,
.num_sub_devs = ARRAY_SIZE(iqs622_sub_devs),
-
.prod_num = IQS622_PROD_NUM,
.sw_num = 0x06,
-
.prox_mask = BIT(0),
.sar_mask = BIT(1),
.hall_mask = BIT(2),
.als_mask = BIT(3),
.ir_mask = BIT(4),
-
.prox_settings = IQS622_PROX_SETTINGS_4,
.als_flags = IQS622_ALS_FLAGS,
.hall_flags = IQS622_HALL_FLAGS,
-
- .clk_div = 2,
.fw_name = "iqs622.bin",
.event_regs = &iqs622_event_regs[IQS62X_UI_PROX],
},
@@ -842,14 +866,10 @@ static const struct iqs62x_dev_desc iqs62x_devs[] = {
.dev_name = "iqs624",
.sub_devs = iqs624_sub_devs,
.num_sub_devs = ARRAY_SIZE(iqs624_sub_devs),
-
.prod_num = IQS624_PROD_NUM,
.sw_num = 0x0B,
-
.interval = IQS624_INTERVAL_NUM,
.interval_div = 3,
-
- .clk_div = 2,
.fw_name = "iqs624.bin",
.event_regs = &iqs624_event_regs[IQS62X_UI_PROX],
},
@@ -857,20 +877,16 @@ static const struct iqs62x_dev_desc iqs62x_devs[] = {
.dev_name = "iqs625",
.sub_devs = iqs625_sub_devs,
.num_sub_devs = ARRAY_SIZE(iqs625_sub_devs),
-
.prod_num = IQS625_PROD_NUM,
.sw_num = 0x0B,
-
.interval = IQS625_INTERVAL_NUM,
.interval_div = 10,
-
- .clk_div = 2,
.fw_name = "iqs625.bin",
.event_regs = &iqs625_event_regs[IQS62X_UI_PROX],
},
};
-static const struct regmap_config iqs62x_map_config = {
+static const struct regmap_config iqs62x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = IQS62X_MAX_REG,
@@ -894,9 +910,11 @@ static int iqs62x_probe(struct i2c_client *client)
BLOCKING_INIT_NOTIFIER_HEAD(&iqs62x->nh);
INIT_LIST_HEAD(&iqs62x->fw_blk_head);
+
+ init_completion(&iqs62x->ati_done);
init_completion(&iqs62x->fw_done);
- iqs62x->regmap = devm_regmap_init_i2c(client, &iqs62x_map_config);
+ iqs62x->regmap = devm_regmap_init_i2c(client, &iqs62x_regmap_config);
if (IS_ERR(iqs62x->regmap)) {
ret = PTR_ERR(iqs62x->regmap);
dev_err(&client->dev, "Failed to initialize register map: %d\n",
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 68d8f2b95287..55d3a6f97783 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -29,9 +29,9 @@
static const struct mfd_cell max8997_devs[] = {
{ .name = "max8997-pmic", },
{ .name = "max8997-rtc", },
- { .name = "max8997-battery", },
+ { .name = "max8997-battery", .of_compatible = "maxim,max8997-battery", },
{ .name = "max8997-haptic", },
- { .name = "max8997-muic", },
+ { .name = "max8997-muic", .of_compatible = "maxim,max8997-muic", },
{ .name = "max8997-led", .id = 1 },
{ .name = "max8997-led", .id = 2 },
};
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 98fa0af0e56e..4629dff187cd 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -214,8 +214,7 @@ static int mcp_sa11x0_probe(struct platform_device *dev)
* rate. This is the period for 3 64-bit frames. Always
* round this time up.
*/
- mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
- mcp->sclk_rate;
+ mcp->rw_timeout = DIV_ROUND_UP(64 * 3 * 1000000, mcp->sclk_rate);
ret = mcp_host_add(mcp, data->codec_pdata);
if (ret == 0)
diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c
index 4661c1b29a72..480722acf706 100644
--- a/drivers/mfd/mt6360-core.c
+++ b/drivers/mfd/mt6360-core.c
@@ -292,17 +292,17 @@ static const struct resource mt6360_ldo_resources[] = {
};
static const struct mfd_cell mt6360_devs[] = {
- OF_MFD_CELL("mt6360_adc", mt6360_adc_resources,
+ MFD_CELL_OF("mt6360_adc", mt6360_adc_resources,
NULL, 0, 0, "mediatek,mt6360_adc"),
- OF_MFD_CELL("mt6360_chg", mt6360_chg_resources,
+ MFD_CELL_OF("mt6360_chg", mt6360_chg_resources,
NULL, 0, 0, "mediatek,mt6360_chg"),
- OF_MFD_CELL("mt6360_led", mt6360_led_resources,
+ MFD_CELL_OF("mt6360_led", mt6360_led_resources,
NULL, 0, 0, "mediatek,mt6360_led"),
- OF_MFD_CELL("mt6360_pmic", mt6360_pmic_resources,
+ MFD_CELL_OF("mt6360_pmic", mt6360_pmic_resources,
NULL, 0, 0, "mediatek,mt6360_pmic"),
- OF_MFD_CELL("mt6360_ldo", mt6360_ldo_resources,
+ MFD_CELL_OF("mt6360_ldo", mt6360_ldo_resources,
NULL, 0, 0, "mediatek,mt6360_ldo"),
- OF_MFD_CELL("mt6360_tcpc", NULL,
+ MFD_CELL_OF("mt6360_tcpc", NULL,
NULL, 0, 0, "mediatek,mt6360_tcpc"),
};
diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c
index 8a7cc0f86958..65b98f3fbd92 100644
--- a/drivers/mfd/wm831x-auxadc.c
+++ b/drivers/mfd/wm831x-auxadc.c
@@ -93,11 +93,10 @@ static int wm831x_auxadc_read_irq(struct wm831x *wm831x,
wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
mutex_lock(&wm831x->auxadc_lock);
-
- list_del(&req->list);
ret = req->val;
out:
+ list_del(&req->list);
mutex_unlock(&wm831x->auxadc_lock);
kfree(req);