summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 17:17:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 17:17:39 -0700
commit54c72d5987ff9f3cf59529d5d4f5cf19eae3f695 (patch)
tree3fee972d54926627895aa07684ddb2e2388e4614 /drivers
parent66bb0aa077978dbb76e6283531eb3cc7a878de38 (diff)
parent7caa79917ad4c1f91366b11f18e48623554aaa52 (diff)
downloadtalos-obmc-linux-54c72d5987ff9f3cf59529d5d4f5cf19eae3f695.tar.gz
talos-obmc-linux-54c72d5987ff9f3cf59529d5d4f5cf19eae3f695.zip
Merge tag 'mfd-for-linus-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD update from Lee Jones: "Changes to existing drivers: - checkpatch fixes throughout the subsystem - use Regmap to handle IRQs in max77686, extcon-max77693 and mc13xxx-core - use DMA in rtsx_pcr - restrict building on unsupported architectures on timberdale, cs5535 - SPI hardening in cros_ec_spi - more robust error handing in asic3, cros_ec, ab8500-debugfs, max77686 and pcf50633-core - reorder PM runtime and regulator handing during shutdown in arizona - enable wakeup in cros_ec_spi - unused variable/code clean-up in pm8921-core, cros_ec, htc-i2cpld, tps65912-spi, wm5110-tables and ab8500-debugfs - add regulator handing into suspend() in sec-core - remove pointless wrapper functions in extcon-max77693 and i2c-cros-ec-tunnel - use cross-architecture friendly data sizes in stmpe-i2c, arizona, max77686 and tps65910 - devicetree documentation updates throughout - provide power management support in max77686 - few OF clean-ups in max77686 - use manged resources in tps6105x New drivers/supported devices: - add support for s2mpu02 to sec-core - add support for Allwinner A32 to sun6i-prcm - add support for Maxim 77802 in max77686 - add support for DA9063 AD in da9063 - new driver for Intel PMICs (generic) and specifically Crystal Cove (Re-)moved drivers == - move out keyboard functionality cros_ec ==> input/keyboard/cros_ec_keyb" * tag 'mfd-for-linus-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (101 commits) MAINTAINERS: Update MFD repo location mfd: omap-usb-host: Fix improper mask use. mfd: arizona: Only free the CTRLIF_ERR IRQ if we requested it mfd: arizona: Add missing handling for ISRC3 under/overclocked mfd: wm5110: Add new interrupt register definitions mfd: arizona: Rename thermal shutdown interrupt mfd: wm5110: Add in the output done interrupts mfd: wm5110: Remove non-existant interrupts mfd: tps65912-spi: Remove unused variable mfd: htc-i2cpld: Remove unused code mfd: da9063: Add support for AD silicon variant mfd: arizona: Map MICVDD from extcon device to the Arizona core mfd: arizona: Add MICVDD to mapped regulators for wm8997 mfd: max77686: Ensure device type IDs are architecture agnostic mfd: max77686: Add Maxim 77802 PMIC support mfd: tps6105x: Use managed resources when allocating memory mfd: wm8997-tables: Suppress 'line over 80 chars' warnings mfd: kempld-core: Correct a variety of checkpatch warnings mfd: ipaq-micro: Fix coding style errors/warnings reported by checkpatch mfd: si476x-cmd: Remedy checkpatch style complains ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig13
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-crystalcove.c380
-rw-r--r--drivers/i2c/busses/i2c-cros-ec-tunnel.c17
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c70
-rw-r--r--drivers/mfd/88pm805.c2
-rw-r--r--drivers/mfd/88pm860x-core.c37
-rw-r--r--drivers/mfd/88pm860x-i2c.c3
-rw-r--r--drivers/mfd/Kconfig25
-rw-r--r--drivers/mfd/Makefile5
-rw-r--r--drivers/mfd/aat2870-core.c5
-rw-r--r--drivers/mfd/ab3100-core.c54
-rw-r--r--drivers/mfd/ab8500-core.c49
-rw-r--r--drivers/mfd/ab8500-debugfs.c308
-rw-r--r--drivers/mfd/arizona-core.c53
-rw-r--r--drivers/mfd/arizona-i2c.c5
-rw-r--r--drivers/mfd/arizona-irq.c29
-rw-r--r--drivers/mfd/arizona-spi.c3
-rw-r--r--drivers/mfd/arizona.h5
-rw-r--r--drivers/mfd/asic3.c12
-rw-r--r--drivers/mfd/cros_ec.c97
-rw-r--r--drivers/mfd/cros_ec_i2c.c44
-rw-r--r--drivers/mfd/cros_ec_spi.c56
-rw-r--r--drivers/mfd/da9063-core.c6
-rw-r--r--drivers/mfd/da9063-i2c.c134
-rw-r--r--drivers/mfd/dm355evm_msp.c2
-rw-r--r--drivers/mfd/ezx-pcap.c3
-rw-r--r--drivers/mfd/htc-i2cpld.c5
-rw-r--r--drivers/mfd/intel_soc_pmic_core.c170
-rw-r--r--drivers/mfd/intel_soc_pmic_core.h32
-rw-r--r--drivers/mfd/intel_soc_pmic_crc.c158
-rw-r--r--drivers/mfd/ipaq-micro.c8
-rw-r--r--drivers/mfd/kempld-core.c10
-rw-r--r--drivers/mfd/lp8788-irq.c2
-rw-r--r--drivers/mfd/max77686-irq.c319
-rw-r--r--drivers/mfd/max77686.c329
-rw-r--r--drivers/mfd/max8925-core.c2
-rw-r--r--drivers/mfd/max8925-i2c.c2
-rw-r--r--drivers/mfd/mc13xxx-core.c310
-rw-r--r--drivers/mfd/mc13xxx.h11
-rw-r--r--drivers/mfd/mcp-core.c1
-rw-r--r--drivers/mfd/omap-usb-host.c2
-rw-r--r--drivers/mfd/pcf50633-core.c18
-rw-r--r--drivers/mfd/pm8921-core.c4
-rw-r--r--drivers/mfd/rtsx_pcr.c76
-rw-r--r--drivers/mfd/sec-core.c82
-rw-r--r--drivers/mfd/sec-irq.c110
-rw-r--r--drivers/mfd/si476x-cmd.c12
-rw-r--r--drivers/mfd/stmpe-i2c.c4
-rw-r--r--drivers/mfd/stmpe.c2
-rw-r--r--drivers/mfd/stmpe.h2
-rw-r--r--drivers/mfd/sun6i-prcm.c30
-rw-r--r--drivers/mfd/tc3589x.c2
-rw-r--r--drivers/mfd/tc6387xb.c7
-rw-r--r--drivers/mfd/tps6105x.c17
-rw-r--r--drivers/mfd/tps65910.c10
-rw-r--r--drivers/mfd/tps65912-spi.c3
-rw-r--r--drivers/mfd/twl4030-irq.c6
-rw-r--r--drivers/mfd/twl6030-irq.c4
-rw-r--r--drivers/mfd/twl6040.c2
-rw-r--r--drivers/mfd/wm5102-tables.c8
-rw-r--r--drivers/mfd/wm5110-tables.c245
-rw-r--r--drivers/mfd/wm8350-i2c.c8
-rw-r--r--drivers/mfd/wm8350-irq.c3
-rw-r--r--drivers/mfd/wm8994-regmap.c64
-rw-r--r--drivers/mfd/wm8997-tables.c16
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c133
-rw-r--r--drivers/regulator/s2mps11.c321
-rw-r--r--drivers/rtc/rtc-da9063.c54
-rw-r--r--drivers/rtc/rtc-max77686.c27
70 files changed, 2790 insertions, 1259 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 4a1b5113e527..4a065b45330f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -450,6 +450,19 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
+config GPIO_CRYSTAL_COVE
+ tristate "GPIO support for Crystal Cove PMIC"
+ depends on INTEL_SOC_PMIC
+ select GPIOLIB_IRQCHIP
+ help
+ Support for GPIO pins on Crystal Cove PMIC.
+
+ Say Yes if you have a Intel SoC based tablet with Crystal Cove PMIC
+ inside.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-crystalcove.
+
config GPIO_LP3943
tristate "TI/National Semiconductor LP3943 GPIO expander"
depends on MFD_LP3943
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d10f6a9d875a..e18e9564b073 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
+obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
new file mode 100644
index 000000000000..934462f5bd22
--- /dev/null
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -0,0 +1,380 @@
+/*
+ * gpio-crystalcove.c - Intel Crystal Cove GPIO Driver
+ *
+ * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved.
+ *
+ * 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 in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/seq_file.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+
+#define CRYSTALCOVE_GPIO_NUM 16
+
+#define UPDATE_IRQ_TYPE BIT(0)
+#define UPDATE_IRQ_MASK BIT(1)
+
+#define GPIO0IRQ 0x0b
+#define GPIO1IRQ 0x0c
+#define MGPIO0IRQS0 0x19
+#define MGPIO1IRQS0 0x1a
+#define MGPIO0IRQSX 0x1b
+#define MGPIO1IRQSX 0x1c
+#define GPIO0P0CTLO 0x2b
+#define GPIO0P0CTLI 0x33
+#define GPIO1P0CTLO 0x3b
+#define GPIO1P0CTLI 0x43
+
+#define CTLI_INTCNT_DIS (0)
+#define CTLI_INTCNT_NE (1 << 1)
+#define CTLI_INTCNT_PE (2 << 1)
+#define CTLI_INTCNT_BE (3 << 1)
+
+#define CTLO_DIR_IN (0)
+#define CTLO_DIR_OUT (1 << 5)
+
+#define CTLO_DRV_CMOS (0)
+#define CTLO_DRV_OD (1 << 4)
+
+#define CTLO_DRV_REN (1 << 3)
+
+#define CTLO_RVAL_2KDW (0)
+#define CTLO_RVAL_2KUP (1 << 1)
+#define CTLO_RVAL_50KDW (2 << 1)
+#define CTLO_RVAL_50KUP (3 << 1)
+
+#define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP)
+#define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET)
+
+enum ctrl_register {
+ CTRL_IN,
+ CTRL_OUT,
+};
+
+/**
+ * struct crystalcove_gpio - Crystal Cove GPIO controller
+ * @buslock: for bus lock/sync and unlock.
+ * @chip: the abstract gpio_chip structure.
+ * @regmap: the regmap from the parent device.
+ * @update: pending IRQ setting update, to be written to the chip upon unlock.
+ * @intcnt_value: the Interrupt Detect value to be written.
+ * @set_irq_mask: true if the IRQ mask needs to be set, false to clear.
+ */
+struct crystalcove_gpio {
+ struct mutex buslock; /* irq_bus_lock */
+ struct gpio_chip chip;
+ struct regmap *regmap;
+ int update;
+ int intcnt_value;
+ bool set_irq_mask;
+};
+
+static inline struct crystalcove_gpio *to_cg(struct gpio_chip *gc)
+{
+ return container_of(gc, struct crystalcove_gpio, chip);
+}
+
+static inline int to_reg(int gpio, enum ctrl_register reg_type)
+{
+ int reg;
+
+ if (reg_type == CTRL_IN) {
+ if (gpio < 8)
+ reg = GPIO0P0CTLI;
+ else
+ reg = GPIO1P0CTLI;
+ } else {
+ if (gpio < 8)
+ reg = GPIO0P0CTLO;
+ else
+ reg = GPIO1P0CTLO;
+ }
+
+ return reg + gpio % 8;
+}
+
+static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg,
+ int gpio)
+{
+ u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0;
+ int mask = BIT(gpio % 8);
+
+ if (cg->set_irq_mask)
+ regmap_update_bits(cg->regmap, mirqs0, mask, mask);
+ else
+ regmap_update_bits(cg->regmap, mirqs0, mask, 0);
+}
+
+static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
+{
+ int reg = to_reg(gpio, CTRL_IN);
+
+ regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value);
+}
+
+static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+
+ return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
+ CTLO_INPUT_SET);
+}
+
+static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
+ int value)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+
+ return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
+ CTLO_OUTPUT_SET | value);
+}
+
+static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
+ if (ret)
+ return ret;
+
+ return val & 0x1;
+}
+
+static void crystalcove_gpio_set(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+
+ if (value)
+ regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
+ else
+ regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
+}
+
+static int crystalcove_irq_type(struct irq_data *data, unsigned type)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ cg->intcnt_value = CTLI_INTCNT_DIS;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ cg->intcnt_value = CTLI_INTCNT_BE;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ cg->intcnt_value = CTLI_INTCNT_PE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ cg->intcnt_value = CTLI_INTCNT_NE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cg->update |= UPDATE_IRQ_TYPE;
+
+ return 0;
+}
+
+static void crystalcove_bus_lock(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ mutex_lock(&cg->buslock);
+}
+
+static void crystalcove_bus_sync_unlock(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+ int gpio = data->hwirq;
+
+ if (cg->update & UPDATE_IRQ_TYPE)
+ crystalcove_update_irq_ctrl(cg, gpio);
+ if (cg->update & UPDATE_IRQ_MASK)
+ crystalcove_update_irq_mask(cg, gpio);
+ cg->update = 0;
+
+ mutex_unlock(&cg->buslock);
+}
+
+static void crystalcove_irq_unmask(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ cg->set_irq_mask = false;
+ cg->update |= UPDATE_IRQ_MASK;
+}
+
+static void crystalcove_irq_mask(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ cg->set_irq_mask = true;
+ cg->update |= UPDATE_IRQ_MASK;
+}
+
+static struct irq_chip crystalcove_irqchip = {
+ .name = "Crystal Cove",
+ .irq_mask = crystalcove_irq_mask,
+ .irq_unmask = crystalcove_irq_unmask,
+ .irq_set_type = crystalcove_irq_type,
+ .irq_bus_lock = crystalcove_bus_lock,
+ .irq_bus_sync_unlock = crystalcove_bus_sync_unlock,
+};
+
+static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data)
+{
+ struct crystalcove_gpio *cg = data;
+ unsigned int p0, p1;
+ int pending;
+ int gpio;
+ unsigned int virq;
+
+ if (regmap_read(cg->regmap, GPIO0IRQ, &p0) ||
+ regmap_read(cg->regmap, GPIO1IRQ, &p1))
+ return IRQ_NONE;
+
+ regmap_write(cg->regmap, GPIO0IRQ, p0);
+ regmap_write(cg->regmap, GPIO1IRQ, p1);
+
+ pending = p0 | p1 << 8;
+
+ for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+ if (pending & BIT(gpio)) {
+ virq = irq_find_mapping(cg->chip.irqdomain, gpio);
+ generic_handle_irq(virq);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void crystalcove_gpio_dbg_show(struct seq_file *s,
+ struct gpio_chip *chip)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+ int gpio, offset;
+ unsigned int ctlo, ctli, mirqs0, mirqsx, irq;
+
+ for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+ regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
+ regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli);
+ regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0,
+ &mirqs0);
+ regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQSX : MGPIO1IRQSX,
+ &mirqsx);
+ regmap_read(cg->regmap, gpio < 8 ? GPIO0IRQ : GPIO1IRQ,
+ &irq);
+
+ offset = gpio % 8;
+ seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s %s\n",
+ gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ",
+ ctli & 0x1 ? "hi" : "lo",
+ ctli & CTLI_INTCNT_NE ? "fall" : " ",
+ ctli & CTLI_INTCNT_PE ? "rise" : " ",
+ ctlo,
+ mirqs0 & BIT(offset) ? "s0 mask " : "s0 unmask",
+ mirqsx & BIT(offset) ? "sx mask " : "sx unmask",
+ irq & BIT(offset) ? "pending" : " ");
+ }
+}
+
+static int crystalcove_gpio_probe(struct platform_device *pdev)
+{
+ int irq = platform_get_irq(pdev, 0);
+ struct crystalcove_gpio *cg;
+ int retval;
+ struct device *dev = pdev->dev.parent;
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ if (irq < 0)
+ return irq;
+
+ cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL);
+ if (!cg)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cg);
+
+ mutex_init(&cg->buslock);
+ cg->chip.label = KBUILD_MODNAME;
+ cg->chip.direction_input = crystalcove_gpio_dir_in;
+ cg->chip.direction_output = crystalcove_gpio_dir_out;
+ cg->chip.get = crystalcove_gpio_get;
+ cg->chip.set = crystalcove_gpio_set;
+ cg->chip.base = -1;
+ cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM;
+ cg->chip.can_sleep = true;
+ cg->chip.dev = dev;
+ cg->chip.dbg_show = crystalcove_gpio_dbg_show;
+ cg->regmap = pmic->regmap;
+
+ retval = gpiochip_add(&cg->chip);
+ if (retval) {
+ dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval);
+ return retval;
+ }
+
+ gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
+
+ retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
+ IRQF_ONESHOT, KBUILD_MODNAME, cg);
+
+ if (retval) {
+ dev_warn(&pdev->dev, "request irq failed: %d\n", retval);
+ goto out_remove_gpio;
+ }
+
+ return 0;
+
+out_remove_gpio:
+ WARN_ON(gpiochip_remove(&cg->chip));
+ return retval;
+}
+
+static int crystalcove_gpio_remove(struct platform_device *pdev)
+{
+ struct crystalcove_gpio *cg = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+ int err;
+
+ err = gpiochip_remove(&cg->chip);
+
+ if (irq >= 0)
+ free_irq(irq, cg);
+
+ return err;
+}
+
+static struct platform_driver crystalcove_gpio_driver = {
+ .probe = crystalcove_gpio_probe,
+ .remove = crystalcove_gpio_remove,
+ .driver = {
+ .name = "crystal_cove_gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(crystalcove_gpio_driver);
+
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_DESCRIPTION("Intel Crystal Cove GPIO Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index 8e7a71487bb1..05e033c98115 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -183,6 +183,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
u8 *request = NULL;
u8 *response = NULL;
int result;
+ struct cros_ec_command msg;
request_len = ec_i2c_count_message(i2c_msgs, num);
if (request_len < 0) {
@@ -218,10 +219,16 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
}
ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
- result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
- request, request_len,
- response, response_len);
- if (result)
+
+ msg.version = 0;
+ msg.command = EC_CMD_I2C_PASSTHRU;
+ msg.outdata = request;
+ msg.outsize = request_len;
+ msg.indata = response;
+ msg.insize = response_len;
+
+ result = bus->ec->cmd_xfer(bus->ec, &msg);
+ if (result < 0)
goto exit;
result = ec_i2c_parse_response(response, i2c_msgs, &num);
@@ -258,7 +265,7 @@ static int ec_i2c_probe(struct platform_device *pdev)
u32 remote_bus;
int err;
- if (!ec->command_sendrecv) {
+ if (!ec->cmd_xfer) {
dev_err(dev, "Missing sendrecv\n");
return -EINVAL;
}
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 408379669d3c..791781ade4e7 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -24,8 +24,8 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
-#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/input/matrix_keypad.h>
@@ -42,7 +42,6 @@
* @dev: Device pointer
* @idev: Input device
* @ec: Top level ChromeOS device to use to talk to EC
- * @event_notifier: interrupt event notifier for transport devices
*/
struct cros_ec_keyb {
unsigned int rows;
@@ -55,7 +54,6 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
- struct notifier_block notifier;
};
@@ -173,41 +171,55 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
input_sync(ckdev->idev);
}
-static int cros_ec_keyb_open(struct input_dev *dev)
-{
- struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-
- return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
- &ckdev->notifier);
-}
-
-static void cros_ec_keyb_close(struct input_dev *dev)
-{
- struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-
- blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
- &ckdev->notifier);
-}
-
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
{
- return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
- kb_state, ckdev->cols);
+ struct cros_ec_command msg = {
+ .version = 0,
+ .command = EC_CMD_MKBP_STATE,
+ .outdata = NULL,
+ .outsize = 0,
+ .indata = kb_state,
+ .insize = ckdev->cols,
+ };
+
+ return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
}
-static int cros_ec_keyb_work(struct notifier_block *nb,
- unsigned long state, void *_notify)
+static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
{
+ struct cros_ec_keyb *ckdev = data;
+ struct cros_ec_device *ec = ckdev->ec;
int ret;
- struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
- notifier);
uint8_t kb_state[ckdev->cols];
+ if (device_may_wakeup(ec->dev))
+ pm_wakeup_event(ec->dev, 0);
+
ret = cros_ec_keyb_get_state(ckdev, kb_state);
if (ret >= 0)
cros_ec_keyb_process(ckdev, kb_state, ret);
+ else
+ dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
- return NOTIFY_DONE;
+ return IRQ_HANDLED;
+}
+
+static int cros_ec_keyb_open(struct input_dev *dev)
+{
+ struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+ struct cros_ec_device *ec = ckdev->ec;
+
+ return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "cros_ec_keyb", ckdev);
+}
+
+static void cros_ec_keyb_close(struct input_dev *dev)
+{
+ struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+ struct cros_ec_device *ec = ckdev->ec;
+
+ free_irq(ec->irq, ckdev);
}
static int cros_ec_keyb_probe(struct platform_device *pdev)
@@ -238,8 +250,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
if (!idev)
return -ENOMEM;
+ if (!ec->irq) {
+ dev_err(dev, "no EC IRQ specified\n");
+ return -EINVAL;
+ }
+
ckdev->ec = ec;
- ckdev->notifier.notifier_call = cros_ec_keyb_work;
ckdev->dev = dev;
dev_set_drvdata(&pdev->dev, ckdev);
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 64751c2a1ace..e9d50644660c 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -158,7 +158,7 @@ static int device_irq_init_805(struct pm80x_chip *chip)
* PM805_INT_STATUS is under 32K clock domain, so need to
* add proper delay before the next I2C register access.
*/
- msleep(1);
+ usleep_range(1000, 3000);
if (ret < 0)
goto out;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index bcfc9e85b4a0..3a2604580164 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -2,7 +2,8 @@
* Base driver for Marvell 88PM8607
*
* Copyright (C) 2009 Marvell International Ltd.
- * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.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
@@ -140,7 +141,8 @@ static struct resource codec_resources[] = {
/* Headset insertion or removal */
{PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
/* Audio short */
- {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
+ {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short",
+ IORESOURCE_IRQ,},
};
static struct resource battery_resources[] = {
@@ -150,10 +152,14 @@ static struct resource battery_resources[] = {
static struct resource charger_resources[] = {
{PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,},
- {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,},
- {PM8607_IRQ_CHG_FAIL, PM8607_IRQ_CHG_FAIL, "charging timeout", IORESOURCE_IRQ,},
- {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault", IORESOURCE_IRQ,},
- {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,},
+ {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done",
+ IORESOURCE_IRQ,},
+ {PM8607_IRQ_CHG_FAIL, PM8607_IRQ_CHG_FAIL, "charging timeout",
+ IORESOURCE_IRQ,},
+ {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault",
+ IORESOURCE_IRQ,},
+ {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature",
+ IORESOURCE_IRQ,},
{PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
};
@@ -568,8 +574,8 @@ static struct irq_domain_ops pm860x_irq_domain_ops = {
static int device_irq_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
- struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
- : chip->companion;
+ struct i2c_client *i2c = (chip->id == CHIP_PM8607) ?
+ chip->client : chip->companion;
unsigned char status_buf[INT_STATUS_NUM];
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
int data, mask, ret = -EINVAL;
@@ -631,8 +637,8 @@ static int device_irq_init(struct pm860x_chip *chip,
if (!chip->core_irq)
goto out;
- ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
- "88pm860x", chip);
+ ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq,
+ flags | IRQF_ONESHOT, "88pm860x", chip);
if (ret) {
dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
chip->core_irq = 0;
@@ -871,7 +877,7 @@ static void device_rtc_init(struct pm860x_chip *chip,
{
int ret;
- if ((pdata == NULL))
+ if (!pdata)
return;
rtc_devs[0].platform_data = pdata->rtc;
@@ -997,8 +1003,9 @@ static void device_8607_init(struct pm860x_chip *chip,
ret);
break;
default:
- dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
- "Chip ID: %02x\n", ret);
+ dev_err(chip->dev,
+ "Failed to detect Marvell 88PM8607. Chip ID: %02x\n",
+ ret);
goto out;
}
@@ -1120,8 +1127,8 @@ static int pm860x_dt_init(struct device_node *np,
ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
&pdata->companion_addr);
if (ret) {
- dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
- "property\n");
+ dev_err(dev,
+ "Not found \"marvell,88pm860x-slave-addr\" property\n");
pdata->companion_addr = 0;
}
return 0;
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index ff8f803ce833..a93b4d0134a2 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -2,7 +2,8 @@
* I2C driver for Marvell 88PM860x
*
* Copyright (C) 2009 Marvell International Ltd.
- * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.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
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fb824f501197..de5abf244746 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -13,7 +13,7 @@ config MFD_CORE
config MFD_CS5535
tristate "AMD CS5535 and CS5536 southbridge core functions"
select MFD_CORE
- depends on PCI && X86
+ depends on PCI && (X86_32 || (X86 && COMPILE_TEST))
---help---
This is the core driver for CS5535/CS5536 MFD functions. This is
necessary for using the board's GPIO and MFGPT functionality.
@@ -187,6 +187,7 @@ config MFD_MC13XXX
tristate
depends on (SPI_MASTER || I2C)
select MFD_CORE
+ select REGMAP_IRQ
help
Enable support for the Freescale MC13783 and MC13892 PMICs.
This driver provides common support for accessing the device,
@@ -253,6 +254,18 @@ config LPC_SCH
LPC bridge function of the Intel SCH provides support for
System Management Bus and General Purpose I/O.
+config INTEL_SOC_PMIC
+ bool "Support for Intel Atom SoC PMIC"
+ depends on I2C=y
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Select this option to enable support for the PMIC device
+ on some Intel SoC systems. The PMIC provides ADC, GPIO,
+ thermal, charger and related power management functions
+ on these systems.
+
config MFD_INTEL_MSIC
bool "Intel MSIC"
depends on INTEL_SCU_IPC
@@ -367,14 +380,15 @@ config MFD_MAX14577
of the device.
config MFD_MAX77686
- bool "Maxim Semiconductor MAX77686 PMIC Support"
+ bool "Maxim Semiconductor MAX77686/802 PMIC Support"
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
+ select REGMAP_IRQ
select IRQ_DOMAIN
help
- Say yes here to add support for Maxim Semiconductor MAX77686.
- This is a Power Management IC with RTC on chip.
+ Say yes here to add support for Maxim Semiconductor MAX77686 and
+ MAX77802 which are Power Management IC with an RTC on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
@@ -574,6 +588,7 @@ config MFD_SEC_CORE
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
+ select REGULATOR
help
Support for the Samsung Electronics MFD series.
This driver provides common support for accessing the device,
@@ -1057,7 +1072,7 @@ config MFD_LM3533
config MFD_TIMBERDALE
tristate "Timberdale FPGA"
select MFD_CORE
- depends on PCI && GPIOLIB
+ depends on PCI && GPIOLIB && (X86_32 || COMPILE_TEST)
---help---
This is the core driver for the timberdale FPGA. This device is a
multifunction device which exposes numerous platform devices.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8c6e7bba4660..f00148782d9b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -115,7 +115,7 @@ da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o
obj-$(CONFIG_MFD_DA9063) += da9063.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
-obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
+obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
max8925-objs := max8925-core.o max8925-i2c.o
@@ -169,3 +169,6 @@ obj-$(CONFIG_MFD_AS3711) += as3711.o
obj-$(CONFIG_MFD_AS3722) += as3722.o
obj-$(CONFIG_MFD_STW481X) += stw481x.o
obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
+
+intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 14d9542a4eed..4e6e03d63e12 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -303,7 +303,10 @@ static ssize_t aat2870_reg_write_file(struct file *file,
while (*start == ' ')
start++;
- addr = simple_strtoul(start, &start, 16);
+ ret = kstrtoul(start, 16, &addr);
+ if (ret)
+ return ret;
+
if (addr >= AAT2870_REG_NUM) {
dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
return -EINVAL;
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index b348ae520629..4659ac1db039 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -91,8 +91,8 @@ static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
err);
} else if (err != 2) {
dev_err(ab3100->dev,
- "write error (write register) "
- "%d bytes transferred (expected 2)\n",
+ "write error (write register)\n"
+ " %d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
@@ -135,8 +135,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
err);
} else if (err != 2) {
dev_err(ab3100->dev,
- "write error (write test register) "
- "%d bytes transferred (expected 2)\n",
+ "write error (write test register)\n"
+ " %d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
@@ -171,8 +171,8 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (send register address) "
- "%d bytes transferred (expected 1)\n",
+ "write error (send register address)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
@@ -189,8 +189,8 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (read register) "
- "%d bytes transferred (expected 1)\n",
+ "write error (read register)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
@@ -237,8 +237,8 @@ static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
goto get_reg_page_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (send first register address) "
- "%d bytes transferred (expected 1)\n",
+ "write error (send first register address)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_page_out_unlock;
@@ -252,8 +252,8 @@ static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
goto get_reg_page_out_unlock;
} else if (err != numregs) {
dev_err(ab3100->dev,
- "write error (read register page) "
- "%d bytes transferred (expected %d)\n",
+ "write error (read register page)\n"
+ " %d bytes transferred (expected %d)\n",
err, numregs);
err = -EIO;
goto get_reg_page_out_unlock;
@@ -295,8 +295,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (maskset send address) "
- "%d bytes transferred (expected 1)\n",
+ "write error (maskset send address)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_maskset_unlock;
@@ -310,8 +310,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (maskset read register) "
- "%d bytes transferred (expected 1)\n",
+ "write error (maskset read register)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_maskset_unlock;
@@ -330,8 +330,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 2) {
dev_err(ab3100->dev,
- "write error (write register) "
- "%d bytes transferred (expected 2)\n",
+ "write error (write register)\n"
+ " %d bytes transferred (expected 2)\n",
err);
err = -EIO;
goto get_maskset_unlock;
@@ -371,7 +371,7 @@ EXPORT_SYMBOL(ab3100_event_register);
int ab3100_event_unregister(struct ab3100 *ab3100,
struct notifier_block *nb)
{
- return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
+ return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
nb);
}
EXPORT_SYMBOL(ab3100_event_unregister);
@@ -455,7 +455,7 @@ static int ab3100_registers_print(struct seq_file *s, void *p)
u8 value;
u8 reg;
- seq_printf(s, "AB3100 registers:\n");
+ seq_puts(s, "AB3100 registers:\n");
for (reg = 0; reg < 0xff; reg++) {
ab3100_get_register_interruptible(ab3100, reg, &value);
@@ -560,8 +560,8 @@ static ssize_t ab3100_get_set_reg(struct file *file,
ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
dev_info(ab3100->dev,
- "debug write reg[0x%02x] with 0x%02x, "
- "after readback: 0x%02x\n",
+ "debug write reg[0x%02x]\n"
+ " with 0x%02x, after readback: 0x%02x\n",
user_reg, user_value, regvalue);
}
return buf_size;
@@ -719,8 +719,7 @@ static int ab3100_setup(struct ab3100 *ab3100)
*/
if (ab3100->chip_id == 0xc4) {
dev_warn(ab3100->dev,
- "AB3100 P1E variant detected, "
- "forcing chip to 32KHz\n");
+ "AB3100 P1E variant detected forcing chip to 32KHz\n");
err = ab3100_set_test_register_interruptible(ab3100,
0x02, 0x08);
}
@@ -878,8 +877,7 @@ static int ab3100_probe(struct i2c_client *client,
&ab3100->chip_id);
if (err) {
dev_err(&client->dev,
- "could not communicate with the AB3100 analog "
- "baseband chip\n");
+ "failed to communicate with AB3100 chip\n");
goto exit_no_detect;
}
@@ -902,8 +900,8 @@ static int ab3100_probe(struct i2c_client *client,
if (ids[i].id == 0x0) {
dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
ab3100->chip_id);
- dev_err(&client->dev, "accepting it anyway. Please update "
- "the driver.\n");
+ dev_err(&client->dev,
+ "accepting it anyway. Please update the driver.\n");
goto exit_no_detect;
}
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index cf2e6a198c6b..ce48aa72bb42 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -148,8 +148,8 @@ static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
/* AB8540 support */
static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
- 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
- 25, 26, 27, 28, 29, 30, 31,
+ 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22,
+ 23, 25, 26, 27, 28, 29, 30, 31,
};
static const char ab8500_version_str[][7] = {
@@ -322,7 +322,7 @@ static int ab8500_mask_and_set_register(struct device *dev,
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
atomic_inc(&ab8500->transfer_ongoing);
- ret= mask_and_set_register_interruptible(ab8500, bank, reg,
+ ret = mask_and_set_register_interruptible(ab8500, bank, reg,
bitmask, bitvalues);
atomic_dec(&ab8500->transfer_ongoing);
return ret;
@@ -415,9 +415,11 @@ static void ab8500_irq_unmask(struct irq_data *data)
if (type & IRQ_TYPE_EDGE_FALLING) {
if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
ab8500->mask[index + 2] &= ~mask;
- else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
+ else if (offset >= AB9540_INT_GPIO50R &&
+ offset <= AB9540_INT_GPIO54R)
ab8500->mask[index + 1] &= ~mask;
- else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
+ else if (offset == AB8540_INT_GPIO43R ||
+ offset == AB8540_INT_GPIO44R)
/* Here the falling IRQ is one bit lower */
ab8500->mask[index] &= ~(mask << 1);
else
@@ -451,7 +453,7 @@ static void update_latch_offset(u8 *offset, int i)
/* Fix inconsistent ab8540 bit mapping... */
if (unlikely(*offset == 16))
*offset = 25;
- if ((i==3) && (*offset >= 24))
+ if ((i == 3) && (*offset >= 24))
*offset += 2;
}
@@ -573,8 +575,8 @@ static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
}
static struct irq_domain_ops ab8500_irq_ops = {
- .map = ab8500_irq_map,
- .xlate = irq_domain_xlate_twocell,
+ .map = ab8500_irq_map,
+ .xlate = irq_domain_xlate_twocell,
};
static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
@@ -607,8 +609,8 @@ int ab8500_suspend(struct ab8500 *ab8500)
{
if (atomic_read(&ab8500->transfer_ongoing))
return -EINVAL;
- else
- return 0;
+
+ return 0;
}
static struct resource ab8500_gpadc_resources[] = {
@@ -1551,7 +1553,7 @@ static struct attribute_group ab9540_attr_group = {
static int ab8500_probe(struct platform_device *pdev)
{
- static char *switch_off_status[] = {
+ static const char *switch_off_status[] = {
"Swoff bit programming",
"Thermal protection activation",
"Vbat lower then BattOk falling threshold",
@@ -1560,7 +1562,7 @@ static int ab8500_probe(struct platform_device *pdev)
"Battery level lower than power on reset threshold",
"Power on key 1 pressed longer than 10 seconds",
"DB8500 thermal shutdown"};
- static char *turn_on_status[] = {
+ static const char *turn_on_status[] = {
"Battery rising (Vbat)",
"Power On Key 1 dbF",
"Power On Key 2 dbF",
@@ -1579,7 +1581,7 @@ static int ab8500_probe(struct platform_device *pdev)
int i;
u8 value;
- ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
+ ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
if (!ab8500)
return -ENOMEM;
@@ -1636,7 +1638,7 @@ static int ab8500_probe(struct platform_device *pdev)
ab8500->mask_size = AB8540_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab8540_irq_regoffset;
ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
- }/* Configure AB8500 or AB9540 IRQ */
+ } /* Configure AB8500 or AB9540 IRQ */
else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
ab8500->mask_size = AB9540_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab9540_irq_regoffset;
@@ -1646,10 +1648,12 @@ static int ab8500_probe(struct platform_device *pdev)
ab8500->irq_reg_offset = ab8500_irq_regoffset;
ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
}
- ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+ ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
+ GFP_KERNEL);
if (!ab8500->mask)
return -ENOMEM;
- ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+ ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
+ GFP_KERNEL);
if (!ab8500->oldmask)
return -ENOMEM;
@@ -1674,14 +1678,13 @@ static int ab8500_probe(struct platform_device *pdev)
if (value) {
for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
if (value & 1)
- printk(KERN_CONT " \"%s\"",
- switch_off_status[i]);
+ pr_cont(" \"%s\"", switch_off_status[i]);
value = value >> 1;
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
} else {
- printk(KERN_CONT " None\n");
+ pr_cont(" None\n");
}
ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
AB8500_TURN_ON_STATUS, &value);
@@ -1692,12 +1695,12 @@ static int ab8500_probe(struct platform_device *pdev)
if (value) {
for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
if (value & 1)
- printk("\"%s\" ", turn_on_status[i]);
+ pr_cont("\"%s\" ", turn_on_status[i]);
value = value >> 1;
}
- printk("\n");
+ pr_cont("\n");
} else {
- printk("None\n");
+ pr_cont("None\n");
}
if (plat && plat->init)
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index d1a22aae2df5..b2c7e3b1edfa 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -135,10 +135,10 @@ struct ab8500_prcmu_ranges {
/* hwreg- "mask" and "shift" entries ressources */
struct hwreg_cfg {
u32 bank; /* target bank */
- u32 addr; /* target address */
+ unsigned long addr; /* target address */
uint fmt; /* format */
- uint mask; /* read/write mask, applied before any bit shift */
- int shift; /* bit shift (read:right shift, write:left shift */
+ unsigned long mask; /* read/write mask, applied before any bit shift */
+ long shift; /* bit shift (read:right shift, write:left shift */
};
/* fmt bit #0: 0=hexa, 1=dec */
#define REG_FMT_DEC(c) ((c)->fmt & 0x1)
@@ -1304,16 +1304,17 @@ static int ab8500_registers_print(struct device *dev, u32 bank,
}
if (s) {
- err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n",
- bank, reg, value);
+ err = seq_printf(s,
+ " [0x%02X/0x%02X]: 0x%02X\n",
+ bank, reg, value);
if (err < 0) {
/* Error is not returned here since
* the output is wanted in any case */
return 0;
}
} else {
- printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n",
- bank, reg, value);
+ dev_info(dev, " [0x%02X/0x%02X]: 0x%02X\n",
+ bank, reg, value);
}
}
}
@@ -1325,7 +1326,7 @@ static int ab8500_print_bank_registers(struct seq_file *s, void *p)
struct device *dev = s->private;
u32 bank = debug_bank;
- seq_printf(s, AB8500_NAME_STRING " register values:\n");
+ seq_puts(s, AB8500_NAME_STRING " register values:\n");
seq_printf(s, " bank 0x%02X:\n", bank);
@@ -1350,12 +1351,11 @@ static int ab8500_print_all_banks(struct seq_file *s, void *p)
{
struct device *dev = s->private;
unsigned int i;
- int err;
- seq_printf(s, AB8500_NAME_STRING " register values:\n");
+ seq_puts(s, AB8500_NAME_STRING " register values:\n");
for (i = 0; i < AB8500_NUM_BANKS; i++) {
- err = seq_printf(s, " bank 0x%02X:\n", i);
+ seq_printf(s, " bank 0x%02X:\n", i);
ab8500_registers_print(dev, i, s);
}
@@ -1367,10 +1367,10 @@ void ab8500_dump_all_banks(struct device *dev)
{
unsigned int i;
- printk(KERN_INFO"ab8500 register values:\n");
+ dev_info(dev, "ab8500 register values:\n");
for (i = 1; i < AB8500_NUM_BANKS; i++) {
- printk(KERN_INFO" bank 0x%02X:\n", i);
+ dev_info(dev, " bank 0x%02X:\n", i);
ab8500_registers_print(dev, i, NULL);
}
}
@@ -1384,8 +1384,6 @@ static struct ab8500_register_dump
u8 value;
} ab8500_complete_register_dump[DUMP_MAX_REGS];
-extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-
/* This shall only be called upon kernel panic! */
void ab8500_dump_all_banks_to_mem(void)
{
@@ -1393,8 +1391,7 @@ void ab8500_dump_all_banks_to_mem(void)
u8 bank;
int err = 0;
- pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" "
- "for crash analyze.\n");
+ pr_info("Saving all ABB registers for crash analysis.\n");
for (bank = 0; bank < AB8500_NUM_BANKS; bank++) {
for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
@@ -1564,7 +1561,7 @@ static ssize_t ab8500_val_write(struct file *file,
err = abx500_set_register_interruptible(dev,
(u8)debug_bank, debug_address, (u8)user_val);
if (err < 0) {
- printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
+ pr_err("abx500_set_reg failed %d, %d", err, __LINE__);
return -EINVAL;
}
@@ -1596,7 +1593,7 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
{
int line;
- seq_printf(s, "name: number: number of: wake:\n");
+ seq_puts(s, "name: number: number of: wake:\n");
for (line = 0; line < num_interrupt_lines; line++) {
struct irq_desc *desc = irq_to_desc(line + irq_first);
@@ -1722,7 +1719,8 @@ static int ab8500_print_modem_registers(struct seq_file *s, void *p)
static int ab8500_modem_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_print_modem_registers, inode->i_private);
+ return single_open(file, ab8500_print_modem_registers,
+ inode->i_private);
}
static const struct file_operations ab8500_modem_fops = {
@@ -1751,7 +1749,8 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_bat_ctrl_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
@@ -1781,7 +1780,8 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
struct file *file)
{
- return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_btemp_ball_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
@@ -1962,7 +1962,8 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
struct file *file)
{
- return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_main_bat_v_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
@@ -2082,7 +2083,8 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_bk_bat_v_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
@@ -2111,7 +2113,8 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_die_temp_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_die_temp_fops = {
@@ -2190,8 +2193,9 @@ static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS,
avg_sample, trig_edge, trig_timer, conv_type);
- vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
- vbat_true_meas_raw);
+ vbat_true_meas_convert =
+ ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
+ vbat_true_meas_raw);
return seq_printf(s, "%d,0x%X\n",
vbat_true_meas_convert, vbat_true_meas_raw);
@@ -2285,7 +2289,8 @@ static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = {
.owner = THIS_MODULE,
};
-static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s,
+ void *p)
{
int vbat_true_meas_raw;
int vbat_true_meas_convert;
@@ -2314,7 +2319,8 @@ static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode,
inode->i_private);
}
-static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
+static const struct file_operations
+ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
.open = ab8540_gpadc_vbat_true_meas_and_ibat_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -2368,14 +2374,15 @@ static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
&vbat_l, &vbat_h, &ibat_l, &ibat_h);
return seq_printf(s, "VMAIN_L:0x%X\n"
- "VMAIN_H:0x%X\n"
- "BTEMP_L:0x%X\n"
- "BTEMP_H:0x%X\n"
- "VBAT_L:0x%X\n"
- "VBAT_H:0x%X\n"
- "IBAT_L:0x%X\n"
- "IBAT_H:0x%X\n",
- vmain_l, vmain_h, btemp_l, btemp_h, vbat_l, vbat_h, ibat_l, ibat_h);
+ "VMAIN_H:0x%X\n"
+ "BTEMP_L:0x%X\n"
+ "BTEMP_H:0x%X\n"
+ "VBAT_L:0x%X\n"
+ "VBAT_H:0x%X\n"
+ "IBAT_L:0x%X\n"
+ "IBAT_H:0x%X\n",
+ vmain_l, vmain_h, btemp_l, btemp_h,
+ vbat_l, vbat_h, ibat_l, ibat_h);
}
static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
@@ -2419,8 +2426,8 @@ static ssize_t ab8500_gpadc_avg_sample_write(struct file *file,
|| (user_avg_sample == SAMPLE_16)) {
avg_sample = (u8) user_avg_sample;
} else {
- dev_err(dev, "debugfs error input: "
- "should be egal to 1, 4, 8 or 16\n");
+ dev_err(dev,
+ "debugfs err input: should be egal to 1, 4, 8 or 16\n");
return -EINVAL;
}
@@ -2504,14 +2511,14 @@ static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
if (err)
return err;
- if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) {
- trig_timer = (u8) user_trig_timer;
- } else {
- dev_err(dev, "debugfs error input: "
- "should be beetween 0 to 255\n");
+ if (user_trig_timer & ~0xFF) {
+ dev_err(dev,
+ "debugfs error input: should be beetween 0 to 255\n");
return -EINVAL;
}
+ trig_timer = (u8) user_trig_timer;
+
return count;
}
@@ -2579,6 +2586,7 @@ static const struct file_operations ab8500_gpadc_conv_type_fops = {
static int strval_len(char *b)
{
char *s = b;
+
if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
s += 2;
for (; *s && (*s != ' ') && (*s != '\n'); s++) {
@@ -2643,13 +2651,17 @@ static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
b += (*(b+2) == ' ') ? 3 : 6;
if (strval_len(b) == 0)
return -EINVAL;
- loc.mask = simple_strtoul(b, &b, 0);
+ ret = kstrtoul(b, 0, &loc.mask);
+ if (ret)
+ return ret;
} else if ((!strncmp(b, "-s ", 3)) ||
(!strncmp(b, "-shift ", 7))) {
b += (*(b+2) == ' ') ? 3 : 7;
if (strval_len(b) == 0)
return -EINVAL;
- loc.shift = simple_strtol(b, &b, 0);
+ ret = kstrtol(b, 0, &loc.shift);
+ if (ret)
+ return ret;
} else {
return -EINVAL;
}
@@ -2657,29 +2669,36 @@ static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
/* get arg BANK and ADDRESS */
if (strval_len(b) == 0)
return -EINVAL;
- loc.bank = simple_strtoul(b, &b, 0);
+ ret = kstrtouint(b, 0, &loc.bank);
+ if (ret)
+ return ret;
while (*b == ' ')
b++;
if (strval_len(b) == 0)
return -EINVAL;
- loc.addr = simple_strtoul(b, &b, 0);
+ ret = kstrtoul(b, 0, &loc.addr);
+ if (ret)
+ return ret;
if (write) {
while (*b == ' ')
b++;
if (strval_len(b) == 0)
return -EINVAL;
- val = simple_strtoul(b, &b, 0);
+ ret = kstrtouint(b, 0, &val);
+ if (ret)
+ return ret;
}
/* args are ok, update target cfg (mainly for read) */
*cfg = loc;
#ifdef ABB_HWREG_DEBUG
- pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
- "value=0x%X\n", (write) ? "write" : "read",
- REG_FMT_DEC(cfg) ? "decimal" : "hexa",
- cfg->addr, cfg->mask, cfg->shift, val);
+ pr_warn("HWREG request: %s, %s,\n"
+ " addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n",
+ (write) ? "write" : "read",
+ REG_FMT_DEC(cfg) ? "decimal" : "hexa",
+ cfg->addr, cfg->mask, cfg->shift, val);
#endif
if (!write)
@@ -2765,8 +2784,8 @@ static ssize_t show_irq(struct device *dev,
irq_index = name - irq_first;
if (irq_index >= num_irqs)
return -EINVAL;
- else
- return sprintf(buf, "%u\n", irq_count[irq_index]);
+
+ return sprintf(buf, "%u\n", irq_count[irq_index]);
}
static ssize_t ab8500_subscribe_write(struct file *file,
@@ -2815,7 +2834,7 @@ static ssize_t ab8500_subscribe_write(struct file *file,
dev_attr[irq_index]->attr.mode = S_IRUGO;
err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
if (err < 0) {
- printk(KERN_ERR "sysfs_create_file failed %d\n", err);
+ pr_info("sysfs_create_file failed %d\n", err);
return err;
}
@@ -2823,8 +2842,8 @@ static ssize_t ab8500_subscribe_write(struct file *file,
IRQF_SHARED | IRQF_NO_SUSPEND,
"ab8500-debug", &dev->kobj);
if (err < 0) {
- printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
- err, user_val);
+ pr_info("request_threaded_irq failed %d, %lu\n",
+ err, user_val);
sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
return err;
}
@@ -2946,6 +2965,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
struct dentry *file;
struct ab8500 *ab8500;
struct resource *res;
+
debug_bank = AB8500_MISC;
debug_address = AB8500_REV_REG & 0x00FF;
@@ -2958,7 +2978,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
return -ENOMEM;
dev_attr = devm_kzalloc(&plf->dev,
- sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
+ sizeof(*dev_attr)*num_irqs, GFP_KERNEL);
if (!dev_attr)
return -ENOMEM;
@@ -2969,23 +2989,20 @@ static int ab8500_debug_probe(struct platform_device *plf)
res = platform_get_resource_byname(plf, 0, "IRQ_AB8500");
if (!res) {
- dev_err(&plf->dev, "AB8500 irq not found, err %d\n",
- irq_first);
- return ENXIO;
+ dev_err(&plf->dev, "AB8500 irq not found, err %d\n", irq_first);
+ return -ENXIO;
}
irq_ab8500 = res->start;
irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
if (irq_first < 0) {
- dev_err(&plf->dev, "First irq not found, err %d\n",
- irq_first);
+ dev_err(&plf->dev, "First irq not found, err %d\n", irq_first);
return irq_first;
}
irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
if (irq_last < 0) {
- dev_err(&plf->dev, "Last irq not found, err %d\n",
- irq_last);
+ dev_err(&plf->dev, "Last irq not found, err %d\n", irq_last);
return irq_last;
}
@@ -2994,37 +3011,41 @@ static int ab8500_debug_probe(struct platform_device *plf)
goto err;
ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
- ab8500_dir);
+ ab8500_dir);
if (!ab8500_gpadc_dir)
goto err;
- file = debugfs_create_file("all-bank-registers", S_IRUGO,
- ab8500_dir, &plf->dev, &ab8500_registers_fops);
+ file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir,
+ &plf->dev, &ab8500_registers_fops);
if (!file)
goto err;
- file = debugfs_create_file("all-banks", S_IRUGO,
- ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
+ file = debugfs_create_file("all-banks", S_IRUGO, ab8500_dir,
+ &plf->dev, &ab8500_all_banks_fops);
if (!file)
goto err;
- file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_bank_fops);
+ file = debugfs_create_file("register-bank",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_bank_fops);
if (!file)
goto err;
- file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_address_fops);
+ file = debugfs_create_file("register-address",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_address_fops);
if (!file)
goto err;
- file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_val_fops);
+ file = debugfs_create_file("register-value",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_val_fops);
if (!file)
goto err;
- file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
+ file = debugfs_create_file("irq-subscribe",
+ (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir,
+ &plf->dev, &ab8500_subscribe_fops);
if (!file)
goto err;
@@ -3042,158 +3063,191 @@ static int ab8500_debug_probe(struct platform_device *plf)
num_interrupt_lines = AB8540_NR_IRQS;
}
- file = debugfs_create_file("interrupts", (S_IRUGO),
- ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
+ file = debugfs_create_file("interrupts", (S_IRUGO), ab8500_dir,
+ &plf->dev, &ab8500_interrupts_fops);
if (!file)
goto err;
- file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
+ file = debugfs_create_file("irq-unsubscribe",
+ (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir,
+ &plf->dev, &ab8500_unsubscribe_fops);
if (!file)
goto err;
file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
+ ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
if (!file)
goto err;
- file = debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_modem_fops);
+ file = debugfs_create_file("all-modem-registers",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_modem_fops);
if (!file)
goto err;
file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_bat_ctrl_fops);
if (!file)
goto err;
file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
+ ab8500_gpadc_dir,
+ &plf->dev, &ab8500_gpadc_btemp_ball_fops);
if (!file)
goto err;
- file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
+ file = debugfs_create_file("main_charger_v",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_main_charger_v_fops);
if (!file)
goto err;
- file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
+ file = debugfs_create_file("acc_detect1",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_acc_detect1_fops);
if (!file)
goto err;
- file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
+ file = debugfs_create_file("acc_detect2",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_acc_detect2_fops);
if (!file)
goto err;
file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_aux1_fops);
if (!file)
goto err;
file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_aux2_fops);
if (!file)
goto err;
file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_main_bat_v_fops);
if (!file)
goto err;
file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_vbus_v_fops);
if (!file)
goto err;
- file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
+ file = debugfs_create_file("main_charger_c",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_main_charger_c_fops);
if (!file)
goto err;
- file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
+ file = debugfs_create_file("usb_charger_c",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir,
+ &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
if (!file)
goto err;
file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_bk_bat_v_fops);
if (!file)
goto err;
file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_die_temp_fops);
if (!file)
goto err;
file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_id_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_usb_id_fops);
if (!file)
goto err;
if (is_ab8540(ab8500)) {
- file = debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_xtal_temp_fops);
+ file = debugfs_create_file("xtal_temp",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8540_gpadc_xtal_temp_fops);
if (!file)
goto err;
- file = debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_vbat_true_meas_fops);
+ file = debugfs_create_file("vbattruemeas",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8540_gpadc_vbat_true_meas_fops);
if (!file)
goto err;
file = debugfs_create_file("batctrl_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
- &plf->dev, &ab8540_gpadc_bat_ctrl_and_ibat_fops);
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir,
+ &plf->dev,
+ &ab8540_gpadc_bat_ctrl_and_ibat_fops);
if (!file)
goto err;
file = debugfs_create_file("vbatmeas_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
- &plf->dev,
- &ab8540_gpadc_vbat_meas_and_ibat_fops);
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8540_gpadc_vbat_meas_and_ibat_fops);
if (!file)
goto err;
file = debugfs_create_file("vbattruemeas_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
- &plf->dev,
- &ab8540_gpadc_vbat_true_meas_and_ibat_fops);
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir,
+ &plf->dev,
+ &ab8540_gpadc_vbat_true_meas_and_ibat_fops);
if (!file)
goto err;
file = debugfs_create_file("battemp_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir,
&plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops);
if (!file)
goto err;
- file = debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_otp_calib_fops);
+ file = debugfs_create_file("otp_calib",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir,
+ &plf->dev, &ab8540_gpadc_otp_calib_fops);
if (!file)
goto err;
}
file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_avg_sample_fops);
if (!file)
goto err;
file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_trig_edge_fops);
if (!file)
goto err;
file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_trig_timer_fops);
if (!file)
goto err;
file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_conv_type_fops);
if (!file)
goto err;
return 0;
err:
- if (ab8500_dir)
- debugfs_remove_recursive(ab8500_dir);
+ debugfs_remove_recursive(ab8500_dir);
dev_err(&plf->dev, "failed to create debugfs entries.\n");
return -ENOMEM;
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index cfc191abae4a..10a0cb90619a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -123,6 +123,8 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
dev_err(arizona->dev, "AIF2 underclocked\n");
if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
dev_err(arizona->dev, "AIF1 underclocked\n");
+ if (val & ARIZONA_ISRC3_UNDERCLOCKED_STS)
+ dev_err(arizona->dev, "ISRC3 underclocked\n");
if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 underclocked\n");
if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS)
@@ -192,6 +194,8 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
dev_err(arizona->dev, "ASRC sync WARP overclocked\n");
if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS)
dev_err(arizona->dev, "DSP1 overclocked\n");
+ if (val[1] & ARIZONA_ISRC3_OVERCLOCKED_STS)
+ dev_err(arizona->dev, "ISRC3 overclocked\n");
if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 overclocked\n");
if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
@@ -497,12 +501,12 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF
-int arizona_of_get_type(struct device *dev)
+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 (int)id->data;
+ return (unsigned long)id->data;
else
return 0;
}
@@ -578,17 +582,21 @@ static const struct mfd_cell early_devs[] = {
};
static const char *wm5102_supplies[] = {
+ "MICVDD",
"DBVDD2",
"DBVDD3",
"CPVDD",
"SPKVDDL",
"SPKVDDR",
- "MICVDD",
};
static const struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
- { .name = "arizona-extcon" },
+ {
+ .name = "arizona-extcon",
+ .parent_supplies = wm5102_supplies,
+ .num_parent_supplies = 1, /* We only need MICVDD */
+ },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
@@ -601,7 +609,11 @@ static const struct mfd_cell wm5102_devs[] = {
static const struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-micsupp" },
- { .name = "arizona-extcon" },
+ {
+ .name = "arizona-extcon",
+ .parent_supplies = wm5102_supplies,
+ .num_parent_supplies = 1, /* We only need MICVDD */
+ },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
@@ -613,6 +625,7 @@ static const struct mfd_cell wm5110_devs[] = {
};
static const char *wm8997_supplies[] = {
+ "MICVDD",
"DBVDD2",
"CPVDD",
"SPKVDD",
@@ -620,7 +633,11 @@ static const char *wm8997_supplies[] = {
static const struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
- { .name = "arizona-extcon" },
+ {
+ .name = "arizona-extcon",
+ .parent_supplies = wm8997_supplies,
+ .num_parent_supplies = 1, /* We only need MICVDD */
+ },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
@@ -683,7 +700,13 @@ int arizona_dev_init(struct arizona *arizona)
goto err_early;
}
- arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD");
+ /**
+ * Don't use devres here because the only device we have to get
+ * against is the MFD device and DCVDD will likely be supplied by
+ * one of its children. Meaning that the regulator will be
+ * destroyed by the time devres calls regulator put.
+ */
+ arizona->dcvdd = regulator_get(arizona->dev, "DCVDD");
if (IS_ERR(arizona->dcvdd)) {
ret = PTR_ERR(arizona->dcvdd);
dev_err(dev, "Failed to request DCVDD: %d\n", ret);
@@ -697,7 +720,7 @@ int arizona_dev_init(struct arizona *arizona)
"arizona /RESET");
if (ret != 0) {
dev_err(dev, "Failed to request /RESET: %d\n", ret);
- goto err_early;
+ goto err_dcvdd;
}
}
@@ -706,7 +729,7 @@ int arizona_dev_init(struct arizona *arizona)
if (ret != 0) {
dev_err(dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_early;
+ goto err_dcvdd;
}
ret = regulator_enable(arizona->dcvdd);
@@ -1015,6 +1038,8 @@ err_reset:
err_enable:
regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
+err_dcvdd:
+ regulator_put(arizona->dcvdd);
err_early:
mfd_remove_devices(dev);
return ret;
@@ -1023,16 +1048,20 @@ EXPORT_SYMBOL_GPL(arizona_dev_init);
int arizona_dev_exit(struct arizona *arizona)
{
+ pm_runtime_disable(arizona->dev);
+
+ regulator_disable(arizona->dcvdd);
+ regulator_put(arizona->dcvdd);
+
mfd_remove_devices(arizona->dev);
arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
- pm_runtime_disable(arizona->dev);
arizona_irq_exit(arizona);
if (arizona->pdata.reset)
gpio_set_value_cansleep(arizona->pdata.reset, 0);
- regulator_disable(arizona->dcvdd);
- regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies),
+
+ regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
return 0;
}
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index beccb790c9ba..9d4156fb082a 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -24,11 +24,12 @@
#include "arizona.h"
static int arizona_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct arizona *arizona;
const struct regmap_config *regmap_config;
- int ret, type;
+ unsigned long type;
+ int ret;
if (i2c->dev.of_node)
type = arizona_of_get_type(&i2c->dev);
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 17102f589100..d420dbc0e2b0 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -188,24 +188,33 @@ int arizona_irq_init(struct arizona *arizona)
int flags = IRQF_ONESHOT;
int ret, i;
const struct regmap_irq_chip *aod, *irq;
- bool ctrlif_error = true;
struct irq_data *irq_data;
+ arizona->ctrlif_error = true;
+
switch (arizona->type) {
#ifdef CONFIG_MFD_WM5102
case WM5102:
aod = &wm5102_aod;
irq = &wm5102_irq;
- ctrlif_error = false;
+ arizona->ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110:
aod = &wm5110_aod;
- irq = &wm5110_irq;
- ctrlif_error = false;
+ switch (arizona->rev) {
+ case 0 ... 2:
+ irq = &wm5110_irq;
+ break;
+ default:
+ irq = &wm5110_revd_irq;
+ break;
+ }
+
+ arizona->ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM8997
@@ -213,7 +222,7 @@ int arizona_irq_init(struct arizona *arizona)
aod = &wm8997_aod;
irq = &wm8997_irq;
- ctrlif_error = false;
+ arizona->ctrlif_error = false;
break;
#endif
default:
@@ -300,7 +309,7 @@ int arizona_irq_init(struct arizona *arizona)
}
/* Handle control interface errors in the core */
- if (ctrlif_error) {
+ if (arizona->ctrlif_error) {
i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
IRQF_ONESHOT,
@@ -345,7 +354,9 @@ int arizona_irq_init(struct arizona *arizona)
return 0;
err_main_irq:
- free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
+ if (arizona->ctrlif_error)
+ free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
+ arizona);
err_ctrlif:
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
err_boot_done:
@@ -361,7 +372,9 @@ err:
int arizona_irq_exit(struct arizona *arizona)
{
- free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
+ if (arizona->ctrlif_error)
+ free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
+ arizona);
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
arizona->irq_chip);
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index 1ca554b18bef..5145d78bf07e 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -28,7 +28,8 @@ static int arizona_spi_probe(struct spi_device *spi)
const struct spi_device_id *id = spi_get_device_id(spi);
struct arizona *arizona;
const struct regmap_config *regmap_config;
- int ret, type;
+ unsigned long type;
+ int ret;
if (spi->dev.of_node)
type = arizona_of_get_type(&spi->dev);
diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h
index b4cef777df73..fbe2843271c5 100644
--- a/drivers/mfd/arizona.h
+++ b/drivers/mfd/arizona.h
@@ -36,6 +36,7 @@ extern const struct regmap_irq_chip wm5102_irq;
extern const struct regmap_irq_chip wm5110_aod;
extern const struct regmap_irq_chip wm5110_irq;
+extern const struct regmap_irq_chip wm5110_revd_irq;
extern const struct regmap_irq_chip wm8997_aod;
extern const struct regmap_irq_chip wm8997_irq;
@@ -46,9 +47,9 @@ int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona);
#ifdef CONFIG_OF
-int arizona_of_get_type(struct device *dev);
+unsigned long arizona_of_get_type(struct device *dev);
#else
-static inline int arizona_of_get_type(struct device *dev)
+static inline unsigned long arizona_of_get_type(struct device *dev)
{
return 0;
}
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 9f6294f2a070..9fc4186d4132 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -899,13 +899,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
ds1wm_resources[0].end >>= asic->bus_shift;
/* MMC */
- asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
+ if (mem_sdio) {
+ asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start,
ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
- if (!asic->tmio_cnf) {
- ret = -ENOMEM;
- dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
- goto out;
+ if (!asic->tmio_cnf) {
+ ret = -ENOMEM;
+ dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
+ goto out;
+ }
}
asic3_mmc_resources[0].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= asic->bus_shift;
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 38fe9bf0d169..4873f9c50452 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -25,64 +25,42 @@
#include <linux/mfd/cros_ec_commands.h>
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg)
+ struct cros_ec_command *msg)
{
uint8_t *out;
int csum, i;
- BUG_ON(msg->out_len > EC_PROTO2_MAX_PARAM_SIZE);
+ BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE);
out = ec_dev->dout;
out[0] = EC_CMD_VERSION0 + msg->version;
- out[1] = msg->cmd;
- out[2] = msg->out_len;
+ out[1] = msg->command;
+ out[2] = msg->outsize;
csum = out[0] + out[1] + out[2];
- for (i = 0; i < msg->out_len; i++)
- csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->out_buf[i];
- out[EC_MSG_TX_HEADER_BYTES + msg->out_len] = (uint8_t)(csum & 0xff);
+ for (i = 0; i < msg->outsize; i++)
+ csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->outdata[i];
+ out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff);
- return EC_MSG_TX_PROTO_BYTES + msg->out_len;
+ return EC_MSG_TX_PROTO_BYTES + msg->outsize;
}
EXPORT_SYMBOL(cros_ec_prepare_tx);
-static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *out_buf, int out_len,
- void *in_buf, int in_len)
+int cros_ec_check_result(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg)
{
- struct cros_ec_msg msg;
-
- msg.version = cmd >> 8;
- msg.cmd = cmd & 0xff;
- msg.out_buf = out_buf;
- msg.out_len = out_len;
- msg.in_buf = in_buf;
- msg.in_len = in_len;
-
- return ec_dev->command_xfer(ec_dev, &msg);
-}
-
-static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *buf, int buf_len)
-{
- return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
-}
-
-static int cros_ec_command_send(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *buf, int buf_len)
-{
- return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
-}
-
-static irqreturn_t ec_irq_thread(int irq, void *data)
-{
- struct cros_ec_device *ec_dev = data;
-
- if (device_may_wakeup(ec_dev->dev))
- pm_wakeup_event(ec_dev->dev, 0);
-
- blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
-
- return IRQ_HANDLED;
+ switch (msg->result) {
+ case EC_RES_SUCCESS:
+ return 0;
+ case EC_RES_IN_PROGRESS:
+ dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
+ msg->command);
+ return -EAGAIN;
+ default:
+ dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
+ msg->command, msg->result);
+ return 0;
+ }
}
+EXPORT_SYMBOL(cros_ec_check_result);
static const struct mfd_cell cros_devs[] = {
{
@@ -102,12 +80,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
struct device *dev = ec_dev->dev;
int err = 0;
- BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
-
- ec_dev->command_send = cros_ec_command_send;
- ec_dev->command_recv = cros_ec_command_recv;
- ec_dev->command_sendrecv = cros_ec_command_sendrecv;
-
if (ec_dev->din_size) {
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din)
@@ -119,42 +91,23 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return -ENOMEM;
}
- if (!ec_dev->irq) {
- dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
- return err;
- }
-
- err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "chromeos-ec", ec_dev);
- if (err) {
- dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
- return err;
- }
-
err = mfd_add_devices(dev, 0, cros_devs,
ARRAY_SIZE(cros_devs),
NULL, ec_dev->irq, NULL);
if (err) {
dev_err(dev, "failed to add mfd devices\n");
- goto fail_mfd;
+ return err;
}
- dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
+ dev_info(dev, "Chrome EC device registered\n");
return 0;
-
-fail_mfd:
- free_irq(ec_dev->irq, ec_dev);
-
- return err;
}
EXPORT_SYMBOL(cros_ec_register);
int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
- free_irq(ec_dev->irq, ec_dev);
return 0;
}
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 4f71be99a183..c0c30f4f946f 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -29,12 +29,13 @@ static inline struct cros_ec_device *to_ec_dev(struct device *dev)
return i2c_get_clientdata(client);
}
-static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg)
+static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg)
{
struct i2c_client *client = ec_dev->priv;
int ret = -ENOMEM;
int i;
+ int len;
int packet_len;
u8 *out_buf = NULL;
u8 *in_buf = NULL;
@@ -50,7 +51,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one byte for
* length, and one for result code)
*/
- packet_len = msg->in_len + 3;
+ packet_len = msg->insize + 3;
in_buf = kzalloc(packet_len, GFP_KERNEL);
if (!in_buf)
goto done;
@@ -61,7 +62,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one for
* command code, one for length, and one for command version)
*/
- packet_len = msg->out_len + 4;
+ packet_len = msg->outsize + 4;
out_buf = kzalloc(packet_len, GFP_KERNEL);
if (!out_buf)
goto done;
@@ -69,16 +70,16 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
i2c_msg[0].buf = (char *)out_buf;
out_buf[0] = EC_CMD_VERSION0 + msg->version;
- out_buf[1] = msg->cmd;
- out_buf[2] = msg->out_len;
+ out_buf[1] = msg->command;
+ out_buf[2] = msg->outsize;
/* copy message payload and compute checksum */
sum = out_buf[0] + out_buf[1] + out_buf[2];
- for (i = 0; i < msg->out_len; i++) {
- out_buf[3 + i] = msg->out_buf[i];
+ for (i = 0; i < msg->outsize; i++) {
+ out_buf[3 + i] = msg->outdata[i];
sum += out_buf[3 + i];
}
- out_buf[3 + msg->out_len] = sum;
+ out_buf[3 + msg->outsize] = sum;
/* send command to EC and read answer */
ret = i2c_transfer(client->adapter, i2c_msg, 2);
@@ -92,28 +93,34 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
}
/* check response error code */
- if (i2c_msg[1].buf[0]) {
- dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- msg->cmd, i2c_msg[1].buf[0]);
- ret = -EINVAL;
+ msg->result = i2c_msg[1].buf[0];
+ ret = cros_ec_check_result(ec_dev, msg);
+ if (ret)
+ goto done;
+
+ len = in_buf[1];
+ if (len > msg->insize) {
+ dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
+ len, msg->insize);
+ ret = -ENOSPC;
goto done;
}
/* copy response packet payload and compute checksum */
sum = in_buf[0] + in_buf[1];
- for (i = 0; i < msg->in_len; i++) {
- msg->in_buf[i] = in_buf[2 + i];
+ for (i = 0; i < len; i++) {
+ msg->indata[i] = in_buf[2 + i];
sum += in_buf[2 + i];
}
dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
i2c_msg[1].len, in_buf, sum);
- if (sum != in_buf[2 + msg->in_len]) {
+ if (sum != in_buf[2 + len]) {
dev_err(ec_dev->dev, "bad packet checksum\n");
ret = -EBADMSG;
goto done;
}
- ret = 0;
+ ret = len;
done:
kfree(in_buf);
kfree(out_buf);
@@ -132,11 +139,10 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, ec_dev);
- ec_dev->name = "I2C";
ec_dev->dev = dev;
ec_dev->priv = client;
ec_dev->irq = client->irq;
- ec_dev->command_xfer = cros_ec_command_xfer;
+ ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
ec_dev->ec_name = client->name;
ec_dev->phys_name = client->adapter->name;
ec_dev->parent = &client->dev;
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 8c1c7cc373f8..588c700af39c 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -73,7 +73,7 @@
* if no record
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
* is sent when we want to turn off CS at the end of a transaction.
- * @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
+ * @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time
*/
struct cros_ec_spi {
struct spi_device *spi;
@@ -210,13 +210,13 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
}
/**
- * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
+ * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply
*
* @ec_dev: ChromeOS EC device
* @ec_msg: Message to transfer
*/
-static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *ec_msg)
+static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *ec_msg)
{
struct cros_ec_spi *ec_spi = ec_dev->priv;
struct spi_transfer trans;
@@ -258,23 +258,19 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* Get the response */
if (!ret) {
ret = cros_ec_spi_receive_response(ec_dev,
- ec_msg->in_len + EC_MSG_TX_PROTO_BYTES);
+ ec_msg->insize + EC_MSG_TX_PROTO_BYTES);
} else {
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
}
- /* turn off CS */
+ /*
+ * Turn off CS, possibly adding a delay to ensure the rising edge
+ * doesn't come too soon after the end of the data.
+ */
spi_message_init(&msg);
-
- if (ec_spi->end_of_msg_delay) {
- /*
- * Add delay for last transaction, to ensure the rising edge
- * doesn't come too soon after the end of the data.
- */
- memset(&trans, 0, sizeof(trans));
- trans.delay_usecs = ec_spi->end_of_msg_delay;
- spi_message_add_tail(&trans, &msg);
- }
+ memset(&trans, 0, sizeof(trans));
+ trans.delay_usecs = ec_spi->end_of_msg_delay;
+ spi_message_add_tail(&trans, &msg);
final_ret = spi_sync(ec_spi->spi, &msg);
ec_spi->last_transfer_ns = ktime_get_ns();
@@ -285,20 +281,19 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
goto exit;
}
- /* check response error code */
ptr = ec_dev->din;
- if (ptr[0]) {
- dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- ec_msg->cmd, ptr[0]);
- debug_packet(ec_dev->dev, "in_err", ptr, len);
- ret = -EINVAL;
+
+ /* check response error code */
+ ec_msg->result = ptr[0];
+ ret = cros_ec_check_result(ec_dev, ec_msg);
+ if (ret)
goto exit;
- }
+
len = ptr[1];
sum = ptr[0] + ptr[1];
- if (len > ec_msg->in_len) {
+ if (len > ec_msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
- len, ec_msg->in_len);
+ len, ec_msg->insize);
ret = -ENOSPC;
goto exit;
}
@@ -306,8 +301,8 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* copy response packet payload and compute checksum */
for (i = 0; i < len; i++) {
sum += ptr[i + 2];
- if (ec_msg->in_len)
- ec_msg->in_buf[i] = ptr[i + 2];
+ if (ec_msg->insize)
+ ec_msg->indata[i] = ptr[i + 2];
}
sum &= 0xff;
@@ -321,7 +316,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
goto exit;
}
- ret = 0;
+ ret = len;
exit:
mutex_unlock(&ec_spi->lock);
return ret;
@@ -364,11 +359,10 @@ static int cros_ec_spi_probe(struct spi_device *spi)
cros_ec_spi_dt_probe(ec_spi, dev);
spi_set_drvdata(spi, ec_dev);
- ec_dev->name = "SPI";
ec_dev->dev = dev;
ec_dev->priv = ec_spi;
ec_dev->irq = spi->irq;
- ec_dev->command_xfer = cros_ec_command_spi_xfer;
+ ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
ec_dev->ec_name = ec_spi->spi->modalias;
ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
ec_dev->parent = &ec_spi->spi->dev;
@@ -381,6 +375,8 @@ static int cros_ec_spi_probe(struct spi_device *spi)
return err;
}
+ device_init_wakeup(&spi->dev, true);
+
return 0;
}
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c
index e70ae315abc7..93db8bb8c8f0 100644
--- a/drivers/mfd/da9063-core.c
+++ b/drivers/mfd/da9063-core.c
@@ -153,9 +153,9 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
"Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
model, variant_id);
- if (variant_code != PMIC_DA9063_BB) {
- dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
- variant_code);
+ if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
+ dev_err(da9063->dev,
+ "Cannot support variant code: 0x%02X\n", variant_code);
return -ENODEV;
}
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c
index 8db5c805c64f..21fd8d9a217b 100644
--- a/drivers/mfd/da9063-i2c.c
+++ b/drivers/mfd/da9063-i2c.c
@@ -25,10 +25,10 @@
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
-static const struct regmap_range da9063_readable_ranges[] = {
+static const struct regmap_range da9063_ad_readable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_REG_SECOND_D,
+ .range_max = DA9063_AD_REG_SECOND_D,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
@@ -37,14 +37,14 @@ static const struct regmap_range da9063_readable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_T_OFFSET,
- .range_max = DA9063_REG_GP_ID_19,
+ .range_max = DA9063_AD_REG_GP_ID_19,
}, {
.range_min = DA9063_REG_CHIP_ID,
.range_max = DA9063_REG_CHIP_VARIANT,
},
};
-static const struct regmap_range da9063_writeable_ranges[] = {
+static const struct regmap_range da9063_ad_writeable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_PAGE_CON,
@@ -53,7 +53,7 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_VSYS_MON,
}, {
.range_min = DA9063_REG_COUNT_S,
- .range_max = DA9063_REG_ALARM_Y,
+ .range_max = DA9063_AD_REG_ALARM_Y,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
@@ -62,14 +62,14 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_CONFIG_I,
- .range_max = DA9063_REG_MON_REG_4,
+ .range_max = DA9063_AD_REG_MON_REG_4,
}, {
- .range_min = DA9063_REG_GP_ID_0,
- .range_max = DA9063_REG_GP_ID_19,
+ .range_min = DA9063_AD_REG_GP_ID_0,
+ .range_max = DA9063_AD_REG_GP_ID_19,
},
};
-static const struct regmap_range da9063_volatile_ranges[] = {
+static const struct regmap_range da9063_ad_volatile_ranges[] = {
{
.range_min = DA9063_REG_STATUS_A,
.range_max = DA9063_REG_EVENT_D,
@@ -81,26 +81,104 @@ static const struct regmap_range da9063_volatile_ranges[] = {
.range_max = DA9063_REG_ADC_MAN,
}, {
.range_min = DA9063_REG_ADC_RES_L,
- .range_max = DA9063_REG_SECOND_D,
+ .range_max = DA9063_AD_REG_SECOND_D,
}, {
- .range_min = DA9063_REG_MON_REG_5,
- .range_max = DA9063_REG_MON_REG_6,
+ .range_min = DA9063_AD_REG_MON_REG_5,
+ .range_max = DA9063_AD_REG_MON_REG_6,
},
};
-static const struct regmap_access_table da9063_readable_table = {
- .yes_ranges = da9063_readable_ranges,
- .n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
+static const struct regmap_access_table da9063_ad_readable_table = {
+ .yes_ranges = da9063_ad_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
};
-static const struct regmap_access_table da9063_writeable_table = {
- .yes_ranges = da9063_writeable_ranges,
- .n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
+static const struct regmap_access_table da9063_ad_writeable_table = {
+ .yes_ranges = da9063_ad_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
};
-static const struct regmap_access_table da9063_volatile_table = {
- .yes_ranges = da9063_volatile_ranges,
- .n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
+static const struct regmap_access_table da9063_ad_volatile_table = {
+ .yes_ranges = da9063_ad_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
+};
+
+static const struct regmap_range da9063_bb_readable_ranges[] = {
+ {
+ .range_min = DA9063_REG_PAGE_CON,
+ .range_max = DA9063_BB_REG_SECOND_D,
+ }, {
+ .range_min = DA9063_REG_SEQ,
+ .range_max = DA9063_REG_ID_32_31,
+ }, {
+ .range_min = DA9063_REG_SEQ_A,
+ .range_max = DA9063_REG_AUTO3_LOW,
+ }, {
+ .range_min = DA9063_REG_T_OFFSET,
+ .range_max = DA9063_BB_REG_GP_ID_19,
+ }, {
+ .range_min = DA9063_REG_CHIP_ID,
+ .range_max = DA9063_REG_CHIP_VARIANT,
+ },
+};
+
+static const struct regmap_range da9063_bb_writeable_ranges[] = {
+ {
+ .range_min = DA9063_REG_PAGE_CON,
+ .range_max = DA9063_REG_PAGE_CON,
+ }, {
+ .range_min = DA9063_REG_FAULT_LOG,
+ .range_max = DA9063_REG_VSYS_MON,
+ }, {
+ .range_min = DA9063_REG_COUNT_S,
+ .range_max = DA9063_BB_REG_ALARM_Y,
+ }, {
+ .range_min = DA9063_REG_SEQ,
+ .range_max = DA9063_REG_ID_32_31,
+ }, {
+ .range_min = DA9063_REG_SEQ_A,
+ .range_max = DA9063_REG_AUTO3_LOW,
+ }, {
+ .range_min = DA9063_REG_CONFIG_I,
+ .range_max = DA9063_BB_REG_MON_REG_4,
+ }, {
+ .range_min = DA9063_BB_REG_GP_ID_0,
+ .range_max = DA9063_BB_REG_GP_ID_19,
+ },
+};
+
+static const struct regmap_range da9063_bb_volatile_ranges[] = {
+ {
+ .range_min = DA9063_REG_STATUS_A,
+ .range_max = DA9063_REG_EVENT_D,
+ }, {
+ .range_min = DA9063_REG_CONTROL_F,
+ .range_max = DA9063_REG_CONTROL_F,
+ }, {
+ .range_min = DA9063_REG_ADC_MAN,
+ .range_max = DA9063_REG_ADC_MAN,
+ }, {
+ .range_min = DA9063_REG_ADC_RES_L,
+ .range_max = DA9063_BB_REG_SECOND_D,
+ }, {
+ .range_min = DA9063_BB_REG_MON_REG_5,
+ .range_max = DA9063_BB_REG_MON_REG_6,
+ },
+};
+
+static const struct regmap_access_table da9063_bb_readable_table = {
+ .yes_ranges = da9063_bb_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
+};
+
+static const struct regmap_access_table da9063_bb_writeable_table = {
+ .yes_ranges = da9063_bb_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
+};
+
+static const struct regmap_access_table da9063_bb_volatile_table = {
+ .yes_ranges = da9063_bb_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
};
static const struct regmap_range_cfg da9063_range_cfg[] = {
@@ -123,10 +201,6 @@ static struct regmap_config da9063_regmap_config = {
.max_register = DA9063_REG_CHIP_VARIANT,
.cache_type = REGCACHE_RBTREE,
-
- .rd_table = &da9063_readable_table,
- .wr_table = &da9063_writeable_table,
- .volatile_table = &da9063_volatile_table,
};
static int da9063_i2c_probe(struct i2c_client *i2c,
@@ -143,6 +217,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
da9063->dev = &i2c->dev;
da9063->chip_irq = i2c->irq;
+ if (da9063->variant_code == PMIC_DA9063_AD) {
+ da9063_regmap_config.rd_table = &da9063_ad_readable_table;
+ da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
+ da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
+ } else {
+ da9063_regmap_config.rd_table = &da9063_bb_readable_table;
+ da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
+ da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
+ }
+
da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
if (IS_ERR(da9063->regmap)) {
ret = PTR_ERR(da9063->regmap);
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 7a55c0071fa8..4c826f78acd0 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(dm355evm_msp_read);
* Many of the msp430 pins are just used as fixed-direction GPIOs.
* We could export a few more of them this way, if we wanted.
*/
-#define MSP_GPIO(bit,reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
+#define MSP_GPIO(bit, reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
static const u8 msp_gpios[] = {
/* eight leds */
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index 2ed774e7d342..5991faddd3c6 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -62,7 +62,7 @@ static int ezx_pcap_putget(struct pcap_chip *pcap, u32 *data)
struct spi_message m;
int status;
- memset(&t, 0, sizeof t);
+ memset(&t, 0, sizeof(t));
spi_message_init(&m);
t.len = sizeof(u32);
spi_message_add_tail(&t, &m);
@@ -211,7 +211,6 @@ static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
desc->irq_data.chip->irq_ack(&desc->irq_data);
queue_work(pcap->workqueue, &pcap->isr_work);
- return;
}
/* ADC */
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index d7b2a75aca3e..b44f0203983b 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -332,18 +332,13 @@ static int htcpld_setup_chip_irq(
int chip_index)
{
struct htcpld_data *htcpld;
- struct device *dev = &pdev->dev;
- struct htcpld_core_platform_data *pdata;
struct htcpld_chip *chip;
- struct htcpld_chip_platform_data *plat_chip_data;
unsigned int irq, irq_end;
int ret = 0;
/* Get the platform and driver data */
- pdata = dev_get_platdata(dev);
htcpld = platform_get_drvdata(pdev);
chip = &htcpld->chip[chip_index];
- plat_chip_data = &pdata->chip[chip_index];
/* Setup irq handlers */
irq_end = chip->irq_start + chip->nirqs;
diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
new file mode 100644
index 000000000000..2720922f90b4
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -0,0 +1,170 @@
+/*
+ * intel_soc_pmic_core.c - Intel SoC PMIC MFD Driver
+ *
+ * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ *
+ * 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 in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_soc_pmic_core.h"
+
+/*
+ * On some boards the PMIC interrupt may come from a GPIO line.
+ * Try to lookup the ACPI table and see if such connection exists. If not,
+ * return -ENOENT and use the IRQ provided by I2C.
+ */
+static int intel_soc_pmic_find_gpio_irq(struct device *dev)
+{
+ struct gpio_desc *desc;
+ int irq;
+
+ desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0);
+ if (IS_ERR(desc))
+ return -ENOENT;
+
+ irq = gpiod_to_irq(desc);
+ if (irq < 0)
+ dev_warn(dev, "Can't get irq: %d\n", irq);
+
+ return irq;
+}
+
+static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
+{
+ struct device *dev = &i2c->dev;
+ const struct acpi_device_id *id;
+ struct intel_soc_pmic_config *config;
+ struct intel_soc_pmic *pmic;
+ int ret;
+ int irq;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id || !id->driver_data)
+ return -ENODEV;
+
+ config = (struct intel_soc_pmic_config *)id->driver_data;
+
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+ dev_set_drvdata(dev, pmic);
+
+ pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
+
+ irq = intel_soc_pmic_find_gpio_irq(dev);
+ pmic->irq = (irq < 0) ? i2c->irq : irq;
+
+ ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+ config->irq_flags | IRQF_ONESHOT,
+ 0, config->irq_chip,
+ &pmic->irq_chip_data);
+ if (ret)
+ return ret;
+
+ ret = enable_irq_wake(pmic->irq);
+ if (ret)
+ dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
+
+ ret = mfd_add_devices(dev, -1, config->cell_dev,
+ config->n_cell_devs, NULL, 0,
+ regmap_irq_get_domain(pmic->irq_chip_data));
+ if (ret)
+ goto err_del_irq_chip;
+
+ return 0;
+
+err_del_irq_chip:
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+ return ret;
+}
+
+static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
+
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+
+ mfd_remove_devices(&i2c->dev);
+
+ return 0;
+}
+
+static void intel_soc_pmic_shutdown(struct i2c_client *i2c)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
+
+ disable_irq(pmic->irq);
+
+ return;
+}
+
+static int intel_soc_pmic_suspend(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ disable_irq(pmic->irq);
+
+ return 0;
+}
+
+static int intel_soc_pmic_resume(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ enable_irq(pmic->irq);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
+ intel_soc_pmic_resume);
+
+static const struct i2c_device_id intel_soc_pmic_i2c_id[] = {
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id);
+
+#if defined(CONFIG_ACPI)
+static struct acpi_device_id intel_soc_pmic_acpi_match[] = {
+ {"INT33FD", (kernel_ulong_t)&intel_soc_pmic_config_crc},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match);
+#endif
+
+static struct i2c_driver intel_soc_pmic_i2c_driver = {
+ .driver = {
+ .name = "intel_soc_pmic_i2c",
+ .owner = THIS_MODULE,
+ .pm = &intel_soc_pmic_pm_ops,
+ .acpi_match_table = ACPI_PTR(intel_soc_pmic_acpi_match),
+ },
+ .probe = intel_soc_pmic_i2c_probe,
+ .remove = intel_soc_pmic_i2c_remove,
+ .id_table = intel_soc_pmic_i2c_id,
+ .shutdown = intel_soc_pmic_shutdown,
+};
+
+module_i2c_driver(intel_soc_pmic_i2c_driver);
+
+MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
diff --git a/drivers/mfd/intel_soc_pmic_core.h b/drivers/mfd/intel_soc_pmic_core.h
new file mode 100644
index 000000000000..33aacd9baddc
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_core.h
@@ -0,0 +1,32 @@
+/*
+ * intel_soc_pmic_core.h - Intel SoC PMIC MFD Driver
+ *
+ * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
+ *
+ * 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 in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#ifndef __INTEL_SOC_PMIC_CORE_H__
+#define __INTEL_SOC_PMIC_CORE_H__
+
+struct intel_soc_pmic_config {
+ unsigned long irq_flags;
+ struct mfd_cell *cell_dev;
+ int n_cell_devs;
+ struct regmap_config *regmap_config;
+ struct regmap_irq_chip *irq_chip;
+};
+
+extern struct intel_soc_pmic_config intel_soc_pmic_config_crc;
+
+#endif /* __INTEL_SOC_PMIC_CORE_H__ */
diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c
new file mode 100644
index 000000000000..7107cab832e6
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_crc.c
@@ -0,0 +1,158 @@
+/*
+ * intel_soc_pmic_crc.c - Device access for Crystal Cove PMIC
+ *
+ * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ *
+ * 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 in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_soc_pmic_core.h"
+
+#define CRYSTAL_COVE_MAX_REGISTER 0xC6
+
+#define CRYSTAL_COVE_REG_IRQLVL1 0x02
+#define CRYSTAL_COVE_REG_MIRQLVL1 0x0E
+
+#define CRYSTAL_COVE_IRQ_PWRSRC 0
+#define CRYSTAL_COVE_IRQ_THRM 1
+#define CRYSTAL_COVE_IRQ_BCU 2
+#define CRYSTAL_COVE_IRQ_ADC 3
+#define CRYSTAL_COVE_IRQ_CHGR 4
+#define CRYSTAL_COVE_IRQ_GPIO 5
+#define CRYSTAL_COVE_IRQ_VHDMIOCP 6
+
+static struct resource gpio_resources[] = {
+ {
+ .name = "GPIO",
+ .start = CRYSTAL_COVE_IRQ_GPIO,
+ .end = CRYSTAL_COVE_IRQ_GPIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource pwrsrc_resources[] = {
+ {
+ .name = "PWRSRC",
+ .start = CRYSTAL_COVE_IRQ_PWRSRC,
+ .end = CRYSTAL_COVE_IRQ_PWRSRC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource adc_resources[] = {
+ {
+ .name = "ADC",
+ .start = CRYSTAL_COVE_IRQ_ADC,
+ .end = CRYSTAL_COVE_IRQ_ADC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource thermal_resources[] = {
+ {
+ .name = "THERMAL",
+ .start = CRYSTAL_COVE_IRQ_THRM,
+ .end = CRYSTAL_COVE_IRQ_THRM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource bcu_resources[] = {
+ {
+ .name = "BCU",
+ .start = CRYSTAL_COVE_IRQ_BCU,
+ .end = CRYSTAL_COVE_IRQ_BCU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell crystal_cove_dev[] = {
+ {
+ .name = "crystal_cove_pwrsrc",
+ .num_resources = ARRAY_SIZE(pwrsrc_resources),
+ .resources = pwrsrc_resources,
+ },
+ {
+ .name = "crystal_cove_adc",
+ .num_resources = ARRAY_SIZE(adc_resources),
+ .resources = adc_resources,
+ },
+ {
+ .name = "crystal_cove_thermal",
+ .num_resources = ARRAY_SIZE(thermal_resources),
+ .resources = thermal_resources,
+ },
+ {
+ .name = "crystal_cove_bcu",
+ .num_resources = ARRAY_SIZE(bcu_resources),
+ .resources = bcu_resources,
+ },
+ {
+ .name = "crystal_cove_gpio",
+ .num_resources = ARRAY_SIZE(gpio_resources),
+ .resources = gpio_resources,
+ },
+};
+
+static struct regmap_config crystal_cove_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CRYSTAL_COVE_MAX_REGISTER,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_irq crystal_cove_irqs[] = {
+ [CRYSTAL_COVE_IRQ_PWRSRC] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_PWRSRC),
+ },
+ [CRYSTAL_COVE_IRQ_THRM] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_THRM),
+ },
+ [CRYSTAL_COVE_IRQ_BCU] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_BCU),
+ },
+ [CRYSTAL_COVE_IRQ_ADC] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_ADC),
+ },
+ [CRYSTAL_COVE_IRQ_CHGR] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_CHGR),
+ },
+ [CRYSTAL_COVE_IRQ_GPIO] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_GPIO),
+ },
+ [CRYSTAL_COVE_IRQ_VHDMIOCP] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_VHDMIOCP),
+ },
+};
+
+static struct regmap_irq_chip crystal_cove_irq_chip = {
+ .name = "Crystal Cove",
+ .irqs = crystal_cove_irqs,
+ .num_irqs = ARRAY_SIZE(crystal_cove_irqs),
+ .num_regs = 1,
+ .status_base = CRYSTAL_COVE_REG_IRQLVL1,
+ .mask_base = CRYSTAL_COVE_REG_MIRQLVL1,
+};
+
+struct intel_soc_pmic_config intel_soc_pmic_config_crc = {
+ .irq_flags = IRQF_TRIGGER_RISING,
+ .cell_dev = crystal_cove_dev,
+ .n_cell_devs = ARRAY_SIZE(crystal_cove_dev),
+ .regmap_config = &crystal_cove_regmap_config,
+ .irq_chip = &crystal_cove_irq_chip,
+};
diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c
index 7e50fe0118e3..8df3266064e4 100644
--- a/drivers/mfd/ipaq-micro.c
+++ b/drivers/mfd/ipaq-micro.c
@@ -115,7 +115,7 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
} else {
dev_err(micro->dev,
"out of band RX message 0x%02x\n", id);
- if(!micro->msg)
+ if (!micro->msg)
dev_info(micro->dev, "no message queued\n");
else
dev_info(micro->dev, "expected message %02x\n",
@@ -126,13 +126,13 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
if (micro->key)
micro->key(micro->key_data, len, data);
else
- dev_dbg(micro->dev, "key message ignored, no handle \n");
+ dev_dbg(micro->dev, "key message ignored, no handle\n");
break;
case MSG_TOUCHSCREEN:
if (micro->ts)
micro->ts(micro->ts_data, len, data);
else
- dev_dbg(micro->dev, "touchscreen message ignored, no handle \n");
+ dev_dbg(micro->dev, "touchscreen message ignored, no handle\n");
break;
default:
dev_err(micro->dev,
@@ -154,7 +154,7 @@ static void micro_process_char(struct ipaq_micro *micro, u8 ch)
rx->state = STATE_ID; /* Next byte is the id and len */
break;
case STATE_ID: /* Looking for id and len byte */
- rx->id = (ch & 0xf0) >> 4 ;
+ rx->id = (ch & 0xf0) >> 4;
rx->len = (ch & 0x0f);
rx->index = 0;
rx->chksum = ch;
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index f7ff0188603d..bd2696136eee 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -24,7 +24,8 @@
#define MAX_ID_LEN 4
static char force_device_id[MAX_ID_LEN + 1] = "";
-module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0);
+module_param_string(force_device_id, force_device_id,
+ sizeof(force_device_id), 0);
MODULE_PARM_DESC(force_device_id, "Override detected product");
/*
@@ -36,7 +37,7 @@ static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
{
/* The mutex bit will read 1 until access has been granted */
while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
- msleep(1);
+ usleep_range(1000, 3000);
}
static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
@@ -499,7 +500,7 @@ static struct platform_driver kempld_driver = {
.remove = kempld_remove,
};
-static struct dmi_system_id __initdata kempld_dmi_table[] = {
+static struct dmi_system_id kempld_dmi_table[] __initdata = {
{
.ident = "BHL6",
.matches = {
@@ -736,7 +737,8 @@ static int __init kempld_init(void)
int ret;
if (force_device_id[0]) {
- for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
+ for (id = kempld_dmi_table;
+ id->matches[0].slot != DMI_NONE; id++)
if (strstr(id->ident, force_device_id))
if (id->callback && id->callback(id))
break;
diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c
index c84ded5f8ece..23982dbf014d 100644
--- a/drivers/mfd/lp8788-irq.c
+++ b/drivers/mfd/lp8788-irq.c
@@ -66,12 +66,14 @@ static inline u8 _irq_to_val(enum lp8788_int_id id, int enable)
static void lp8788_irq_enable(struct irq_data *data)
{
struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
irqd->enabled[data->hwirq] = 1;
}
static void lp8788_irq_disable(struct irq_data *data)
{
struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
irqd->enabled[data->hwirq] = 0;
}
diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c
deleted file mode 100644
index cdc3280e2ec7..000000000000
--- a/drivers/mfd/max77686-irq.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * max77686-irq.c - Interrupt controller support for MAX77686
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Chiwoong Byun <woong.byun@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This driver is based on max8997-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/mfd/max77686.h>
-#include <linux/mfd/max77686-private.h>
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-enum {
- MAX77686_DEBUG_IRQ_INFO = 1 << 0,
- MAX77686_DEBUG_IRQ_MASK = 1 << 1,
- MAX77686_DEBUG_IRQ_INT = 1 << 2,
-};
-
-static int debug_mask = 0;
-module_param(debug_mask, int, 0);
-MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)");
-
-static const u8 max77686_mask_reg[] = {
- [PMIC_INT1] = MAX77686_REG_INT1MSK,
- [PMIC_INT2] = MAX77686_REG_INT2MSK,
- [RTC_INT] = MAX77686_RTC_INTM,
-};
-
-static struct regmap *max77686_get_regmap(struct max77686_dev *max77686,
- enum max77686_irq_source src)
-{
- switch (src) {
- case PMIC_INT1 ... PMIC_INT2:
- return max77686->regmap;
- case RTC_INT:
- return max77686->rtc_regmap;
- default:
- return ERR_PTR(-EINVAL);
- }
-}
-
-struct max77686_irq_data {
- int mask;
- enum max77686_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask) \
- [(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max77686_irq_data max77686_irqs[] = {
- DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0),
- DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1),
- DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2),
- DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3),
- DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4),
- DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5),
- DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6),
- DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7),
- DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0),
- DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2),
- DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4),
- DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5),
-};
-
-static void max77686_irq_lock(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_info("%s\n", __func__);
-
- mutex_lock(&max77686->irqlock);
-}
-
-static void max77686_irq_sync_unlock(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
- int i;
-
- for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
- u8 mask_reg = max77686_mask_reg[i];
- struct regmap *map = max77686_get_regmap(max77686, i);
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n",
- __func__, i, mask_reg, max77686->irq_masks_cur[i]);
-
- if (mask_reg == MAX77686_REG_INVALID ||
- IS_ERR_OR_NULL(map))
- continue;
-
- max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i];
-
- regmap_write(map, max77686_mask_reg[i],
- max77686->irq_masks_cur[i]);
- }
-
- mutex_unlock(&max77686->irqlock);
-}
-
-static const inline struct max77686_irq_data *to_max77686_irq(int irq)
-{
- struct irq_data *data = irq_get_irq_data(irq);
- return &max77686_irqs[data->hwirq];
-}
-
-static void max77686_irq_mask(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
- const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
-
- max77686->irq_masks_cur[irq_data->group] |= irq_data->mask;
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_info("%s: group=%d, cur=0x%x\n",
- __func__, irq_data->group,
- max77686->irq_masks_cur[irq_data->group]);
-}
-
-static void max77686_irq_unmask(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
- const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
-
- max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_info("%s: group=%d, cur=0x%x\n",
- __func__, irq_data->group,
- max77686->irq_masks_cur[irq_data->group]);
-}
-
-static struct irq_chip max77686_irq_chip = {
- .name = "max77686",
- .irq_bus_lock = max77686_irq_lock,
- .irq_bus_sync_unlock = max77686_irq_sync_unlock,
- .irq_mask = max77686_irq_mask,
- .irq_unmask = max77686_irq_unmask,
-};
-
-static irqreturn_t max77686_irq_thread(int irq, void *data)
-{
- struct max77686_dev *max77686 = data;
- unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {};
- unsigned int irq_src;
- int ret;
- int i, cur_irq;
-
- ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src);
- if (ret < 0) {
- dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT)
- pr_info("%s: irq_src=0x%x\n", __func__, irq_src);
-
- if (irq_src == MAX77686_IRQSRC_PMIC) {
- ret = regmap_bulk_read(max77686->regmap,
- MAX77686_REG_INT1, irq_reg, 2);
- if (ret < 0) {
- dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT)
- pr_info("%s: int1=0x%x, int2=0x%x\n", __func__,
- irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]);
- }
-
- if (irq_src & MAX77686_IRQSRC_RTC) {
- ret = regmap_read(max77686->rtc_regmap,
- MAX77686_RTC_INT, &irq_reg[RTC_INT]);
- if (ret < 0) {
- dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT)
- pr_info("%s: rtc int=0x%x\n", __func__,
- irq_reg[RTC_INT]);
-
- }
-
- for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++)
- irq_reg[i] &= ~max77686->irq_masks_cur[i];
-
- for (i = 0; i < MAX77686_IRQ_NR; i++) {
- if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) {
- cur_irq = irq_find_mapping(max77686->irq_domain, i);
- if (cur_irq)
- handle_nested_irq(cur_irq);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hw)
-{
- struct max77686_dev *max77686 = d->host_data;
-
- irq_set_chip_data(irq, max77686);
- irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq);
- irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
- return 0;
-}
-
-static struct irq_domain_ops max77686_irq_domain_ops = {
- .map = max77686_irq_domain_map,
-};
-
-int max77686_irq_init(struct max77686_dev *max77686)
-{
- struct irq_domain *domain;
- int i;
- int ret;
- int val;
- struct regmap *map;
-
- mutex_init(&max77686->irqlock);
-
- if (max77686->irq_gpio && !max77686->irq) {
- max77686->irq = gpio_to_irq(max77686->irq_gpio);
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT) {
- ret = gpio_request(max77686->irq_gpio, "pmic_irq");
- if (ret < 0) {
- dev_err(max77686->dev,
- "Failed to request gpio %d with ret:"
- "%d\n", max77686->irq_gpio, ret);
- return IRQ_NONE;
- }
-
- gpio_direction_input(max77686->irq_gpio);
- val = gpio_get_value(max77686->irq_gpio);
- gpio_free(max77686->irq_gpio);
- pr_info("%s: gpio_irq=%x\n", __func__, val);
- }
- }
-
- if (!max77686->irq) {
- dev_err(max77686->dev, "irq is not specified\n");
- return -ENODEV;
- }
-
- /* Mask individual interrupt sources */
- for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
- max77686->irq_masks_cur[i] = 0xff;
- max77686->irq_masks_cache[i] = 0xff;
- map = max77686_get_regmap(max77686, i);
-
- if (IS_ERR_OR_NULL(map))
- continue;
- if (max77686_mask_reg[i] == MAX77686_REG_INVALID)
- continue;
-
- regmap_write(map, max77686_mask_reg[i], 0xff);
- }
- domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR,
- &max77686_irq_domain_ops, max77686);
- if (!domain) {
- dev_err(max77686->dev, "could not create irq domain\n");
- return -ENODEV;
- }
- max77686->irq_domain = domain;
-
- ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "max77686-irq", max77686);
-
- if (ret)
- dev_err(max77686->dev, "Failed to request IRQ %d: %d\n",
- max77686->irq, ret);
-
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INFO)
- pr_info("%s-\n", __func__);
-
- return 0;
-}
-
-void max77686_irq_exit(struct max77686_dev *max77686)
-{
- if (max77686->irq)
- free_irq(max77686->irq, max77686);
-}
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index ce869acf27ae..86e552348db4 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -1,5 +1,5 @@
/*
- * max77686.c - mfd core driver for the Maxim 77686
+ * max77686.c - mfd core driver for the Maxim 77686/802
*
* Copyright (C) 2012 Samsung Electronics
* Chiwoong Byun <woong.byun@smasung.com>
@@ -25,6 +25,8 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/mfd/core.h>
@@ -41,15 +43,166 @@ static const struct mfd_cell max77686_devs[] = {
{ .name = "max77686-clk", },
};
+static const struct mfd_cell max77802_devs[] = {
+ { .name = "max77802-pmic", },
+ { .name = "max77802-clk", },
+ { .name = "max77802-rtc", },
+};
+
+static bool max77802_pmic_is_accessible_reg(struct device *dev,
+ unsigned int reg)
+{
+ return (reg >= MAX77802_REG_DEVICE_ID && reg < MAX77802_REG_PMIC_END);
+}
+
+static bool max77802_rtc_is_accessible_reg(struct device *dev,
+ unsigned int reg)
+{
+ return (reg >= MAX77802_RTC_INT && reg < MAX77802_RTC_END);
+}
+
+static bool max77802_is_accessible_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_pmic_is_accessible_reg(dev, reg) ||
+ max77802_rtc_is_accessible_reg(dev, reg));
+}
+
+static bool max77802_pmic_is_precious_reg(struct device *dev, unsigned int reg)
+{
+ return (reg == MAX77802_REG_INTSRC || reg == MAX77802_REG_INT1 ||
+ reg == MAX77802_REG_INT2);
+}
+
+static bool max77802_rtc_is_precious_reg(struct device *dev, unsigned int reg)
+{
+ return (reg == MAX77802_RTC_INT ||
+ reg == MAX77802_RTC_UPDATE0 ||
+ reg == MAX77802_RTC_UPDATE1);
+}
+
+static bool max77802_is_precious_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_pmic_is_precious_reg(dev, reg) ||
+ max77802_rtc_is_precious_reg(dev, reg));
+}
+
+static bool max77802_pmic_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_is_precious_reg(dev, reg) ||
+ reg == MAX77802_REG_STATUS1 || reg == MAX77802_REG_STATUS2 ||
+ reg == MAX77802_REG_PWRON);
+}
+
+static bool max77802_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_rtc_is_precious_reg(dev, reg) ||
+ reg == MAX77802_RTC_SEC ||
+ reg == MAX77802_RTC_MIN ||
+ reg == MAX77802_RTC_HOUR ||
+ reg == MAX77802_RTC_WEEKDAY ||
+ reg == MAX77802_RTC_MONTH ||
+ reg == MAX77802_RTC_YEAR ||
+ reg == MAX77802_RTC_DATE);
+}
+
+static bool max77802_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_pmic_is_volatile_reg(dev, reg) ||
+ max77802_rtc_is_volatile_reg(dev, reg));
+}
+
static struct regmap_config max77686_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
-#ifdef CONFIG_OF
+static struct regmap_config max77686_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static struct regmap_config max77802_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = max77802_is_accessible_reg,
+ .readable_reg = max77802_is_accessible_reg,
+ .precious_reg = max77802_is_precious_reg,
+ .volatile_reg = max77802_is_volatile_reg,
+ .name = "max77802-pmic",
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq max77686_irqs[] = {
+ /* INT1 interrupts */
+ { .reg_offset = 0, .mask = MAX77686_INT1_PWRONF_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_PWRONR_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_JIGONBF_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_JIGONBR_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_ACOKBF_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_ACOKBR_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_ONKEY1S_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_MRSTB_MSK, },
+ /* INT2 interrupts */
+ { .reg_offset = 1, .mask = MAX77686_INT2_140C_MSK, },
+ { .reg_offset = 1, .mask = MAX77686_INT2_120C_MSK, },
+};
+
+static const struct regmap_irq_chip max77686_irq_chip = {
+ .name = "max77686-pmic",
+ .status_base = MAX77686_REG_INT1,
+ .mask_base = MAX77686_REG_INT1MSK,
+ .num_regs = 2,
+ .irqs = max77686_irqs,
+ .num_irqs = ARRAY_SIZE(max77686_irqs),
+};
+
+static const struct regmap_irq max77686_rtc_irqs[] = {
+ /* RTC interrupts */
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTC60S_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA1_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA2_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_SMPL_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTC1S_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_WTSR_MSK, },
+};
+
+static const struct regmap_irq_chip max77686_rtc_irq_chip = {
+ .name = "max77686-rtc",
+ .status_base = MAX77686_RTC_INT,
+ .mask_base = MAX77686_RTC_INTM,
+ .num_regs = 1,
+ .irqs = max77686_rtc_irqs,
+ .num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct regmap_irq_chip max77802_irq_chip = {
+ .name = "max77802-pmic",
+ .status_base = MAX77802_REG_INT1,
+ .mask_base = MAX77802_REG_INT1MSK,
+ .num_regs = 2,
+ .irqs = max77686_irqs, /* same masks as 77686 */
+ .num_irqs = ARRAY_SIZE(max77686_irqs),
+};
+
+static const struct regmap_irq_chip max77802_rtc_irq_chip = {
+ .name = "max77802-rtc",
+ .status_base = MAX77802_RTC_INT,
+ .mask_base = MAX77802_RTC_INTM,
+ .num_regs = 1,
+ .irqs = max77686_rtc_irqs, /* same masks as 77686 */
+ .num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
+};
+
static const struct of_device_id max77686_pmic_dt_match[] = {
- {.compatible = "maxim,max77686", .data = NULL},
- {},
+ {
+ .compatible = "maxim,max77686",
+ .data = (void *)TYPE_MAX77686,
+ },
+ {
+ .compatible = "maxim,max77802",
+ .data = (void *)TYPE_MAX77802,
+ },
+ { },
};
static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
@@ -58,53 +211,74 @@ static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
struct max77686_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- dev_err(dev, "could not allocate memory for pdata\n");
+ if (!pd)
return NULL;
- }
dev->platform_data = pd;
return pd;
}
-#else
-static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
- *dev)
-{
- return 0;
-}
-#endif
static int max77686_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max77686_dev *max77686 = NULL;
struct max77686_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ const struct of_device_id *match;
unsigned int data;
int ret = 0;
+ const struct regmap_config *config;
+ const struct regmap_irq_chip *irq_chip;
+ const struct regmap_irq_chip *rtc_irq_chip;
+ struct regmap **rtc_regmap;
+ const struct mfd_cell *cells;
+ int n_devs;
- if (i2c->dev.of_node)
+ if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node && !pdata)
pdata = max77686_i2c_parse_dt_pdata(&i2c->dev);
if (!pdata) {
dev_err(&i2c->dev, "No platform data found.\n");
- return -EIO;
+ return -EINVAL;
}
max77686 = devm_kzalloc(&i2c->dev,
sizeof(struct max77686_dev), GFP_KERNEL);
- if (max77686 == NULL)
+ if (!max77686)
return -ENOMEM;
+ if (i2c->dev.of_node) {
+ match = of_match_node(max77686_pmic_dt_match, i2c->dev.of_node);
+ if (!match)
+ return -EINVAL;
+
+ max77686->type = (unsigned long)match->data;
+ } else
+ max77686->type = id->driver_data;
+
i2c_set_clientdata(i2c, max77686);
max77686->dev = &i2c->dev;
max77686->i2c = i2c;
- max77686->type = id->driver_data;
max77686->wakeup = pdata->wakeup;
- max77686->irq_gpio = pdata->irq_gpio;
max77686->irq = i2c->irq;
- max77686->regmap = devm_regmap_init_i2c(i2c, &max77686_regmap_config);
+ if (max77686->type == TYPE_MAX77686) {
+ config = &max77686_regmap_config;
+ irq_chip = &max77686_irq_chip;
+ rtc_irq_chip = &max77686_rtc_irq_chip;
+ rtc_regmap = &max77686->rtc_regmap;
+ cells = max77686_devs;
+ n_devs = ARRAY_SIZE(max77686_devs);
+ } else {
+ config = &max77802_regmap_config;
+ irq_chip = &max77802_irq_chip;
+ rtc_irq_chip = &max77802_rtc_irq_chip;
+ rtc_regmap = &max77686->regmap;
+ cells = max77802_devs;
+ n_devs = ARRAY_SIZE(max77802_devs);
+ }
+
+ max77686->regmap = devm_regmap_init_i2c(i2c, config);
if (IS_ERR(max77686->regmap)) {
ret = PTR_ERR(max77686->regmap);
dev_err(max77686->dev, "Failed to allocate register map: %d\n",
@@ -112,30 +286,68 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
return ret;
}
- if (regmap_read(max77686->regmap,
- MAX77686_REG_DEVICE_ID, &data) < 0) {
+ ret = regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data);
+ if (ret < 0) {
dev_err(max77686->dev,
"device not found on this channel (this is not an error)\n");
return -ENODEV;
- } else
- dev_info(max77686->dev, "device found\n");
+ }
- max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
- if (!max77686->rtc) {
- dev_err(max77686->dev, "Failed to allocate I2C device for RTC\n");
- return -ENODEV;
+ if (max77686->type == TYPE_MAX77686) {
+ max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+ if (!max77686->rtc) {
+ dev_err(max77686->dev,
+ "Failed to allocate I2C device for RTC\n");
+ return -ENODEV;
+ }
+ i2c_set_clientdata(max77686->rtc, max77686);
+
+ max77686->rtc_regmap =
+ devm_regmap_init_i2c(max77686->rtc,
+ &max77686_rtc_regmap_config);
+ if (IS_ERR(max77686->rtc_regmap)) {
+ ret = PTR_ERR(max77686->rtc_regmap);
+ dev_err(max77686->dev,
+ "failed to allocate RTC regmap: %d\n",
+ ret);
+ goto err_unregister_i2c;
+ }
+ }
+
+ ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+ IRQF_SHARED, 0, irq_chip,
+ &max77686->irq_data);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
+ goto err_unregister_i2c;
}
- i2c_set_clientdata(max77686->rtc, max77686);
- max77686_irq_init(max77686);
+ ret = regmap_add_irq_chip(*rtc_regmap, max77686->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+ IRQF_SHARED, 0, rtc_irq_chip,
+ &max77686->rtc_irq_data);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add RTC irq chip: %d\n", ret);
+ goto err_del_irqc;
+ }
- ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
- ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
+ ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
if (ret < 0) {
- mfd_remove_devices(max77686->dev);
- i2c_unregister_device(max77686->rtc);
+ dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
+ goto err_del_rtc_irqc;
}
+ return 0;
+
+err_del_rtc_irqc:
+ regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
+err_del_irqc:
+ regmap_del_irq_chip(max77686->irq, max77686->irq_data);
+err_unregister_i2c:
+ if (max77686->type == TYPE_MAX77686)
+ i2c_unregister_device(max77686->rtc);
+
return ret;
}
@@ -144,7 +356,12 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
mfd_remove_devices(max77686->dev);
- i2c_unregister_device(max77686->rtc);
+
+ regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
+ regmap_del_irq_chip(max77686->irq, max77686->irq_data);
+
+ if (max77686->type == TYPE_MAX77686)
+ i2c_unregister_device(max77686->rtc);
return 0;
}
@@ -155,10 +372,50 @@ static const struct i2c_device_id max77686_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, max77686_i2c_id);
+#ifdef CONFIG_PM_SLEEP
+static int max77686_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(max77686->irq);
+
+ /*
+ * IRQ must be disabled during suspend because if it happens
+ * while suspended it will be handled before resuming I2C.
+ *
+ * When device is woken up from suspend (e.g. by RTC wake alarm),
+ * an interrupt occurs before resuming I2C bus controller.
+ * Interrupt handler tries to read registers but this read
+ * will fail because I2C is still suspended.
+ */
+ disable_irq(max77686->irq);
+
+ return 0;
+}
+
+static int max77686_resume(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(max77686->irq);
+
+ enable_irq(max77686->irq);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(max77686_pm, max77686_suspend, max77686_resume);
+
static struct i2c_driver max77686_i2c_driver = {
.driver = {
.name = "max77686",
.owner = THIS_MODULE,
+ .pm = &max77686_pm,
.of_match_table = of_match_ptr(max77686_pmic_dt_match),
},
.probe = max77686_i2c_probe,
@@ -179,6 +436,6 @@ static void __exit max77686_i2c_exit(void)
}
module_exit(max77686_i2c_exit);
-MODULE_DESCRIPTION("MAXIM 77686 multi-function core driver");
+MODULE_DESCRIPTION("MAXIM 77686/802 multi-function core driver");
MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index f3faf0c45ddd..97a787ab3d51 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -624,6 +624,7 @@ static void max8925_irq_sync_unlock(struct irq_data *data)
static void max8925_irq_enable(struct irq_data *data)
{
struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+
max8925_irqs[data->irq - chip->irq_base].enable
= max8925_irqs[data->irq - chip->irq_base].offs;
}
@@ -631,6 +632,7 @@ static void max8925_irq_enable(struct irq_data *data)
static void max8925_irq_disable(struct irq_data *data)
{
struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+
max8925_irqs[data->irq - chip->irq_base].enable = 0;
}
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index a83eed5c15ca..ecbe78ead3b6 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -257,9 +257,11 @@ static struct i2c_driver max8925_driver = {
static int __init max8925_i2c_init(void)
{
int ret;
+
ret = i2c_add_driver(&max8925_driver);
if (ret != 0)
pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
+
return ret;
}
subsys_initcall(max8925_i2c_init);
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index acf5dd712eb2..2b6bc868cd3d 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -10,106 +10,18 @@
* Free Software Foundation.
*/
-#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/mc13xxx.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include "mc13xxx.h"
#define MC13XXX_IRQSTAT0 0
-#define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0)
-#define MC13XXX_IRQSTAT0_ADCBISDONEI (1 << 1)
-#define MC13XXX_IRQSTAT0_TSI (1 << 2)
-#define MC13783_IRQSTAT0_WHIGHI (1 << 3)
-#define MC13783_IRQSTAT0_WLOWI (1 << 4)
-#define MC13XXX_IRQSTAT0_CHGDETI (1 << 6)
-#define MC13783_IRQSTAT0_CHGOVI (1 << 7)
-#define MC13XXX_IRQSTAT0_CHGREVI (1 << 8)
-#define MC13XXX_IRQSTAT0_CHGSHORTI (1 << 9)
-#define MC13XXX_IRQSTAT0_CCCVI (1 << 10)
-#define MC13XXX_IRQSTAT0_CHGCURRI (1 << 11)
-#define MC13XXX_IRQSTAT0_BPONI (1 << 12)
-#define MC13XXX_IRQSTAT0_LOBATLI (1 << 13)
-#define MC13XXX_IRQSTAT0_LOBATHI (1 << 14)
-#define MC13783_IRQSTAT0_UDPI (1 << 15)
-#define MC13783_IRQSTAT0_USBI (1 << 16)
-#define MC13783_IRQSTAT0_IDI (1 << 19)
-#define MC13783_IRQSTAT0_SE1I (1 << 21)
-#define MC13783_IRQSTAT0_CKDETI (1 << 22)
-#define MC13783_IRQSTAT0_UDMI (1 << 23)
-
#define MC13XXX_IRQMASK0 1
-#define MC13XXX_IRQMASK0_ADCDONEM MC13XXX_IRQSTAT0_ADCDONEI
-#define MC13XXX_IRQMASK0_ADCBISDONEM MC13XXX_IRQSTAT0_ADCBISDONEI
-#define MC13XXX_IRQMASK0_TSM MC13XXX_IRQSTAT0_TSI
-#define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI
-#define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI
-#define MC13XXX_IRQMASK0_CHGDETM MC13XXX_IRQSTAT0_CHGDETI
-#define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI
-#define MC13XXX_IRQMASK0_CHGREVM MC13XXX_IRQSTAT0_CHGREVI
-#define MC13XXX_IRQMASK0_CHGSHORTM MC13XXX_IRQSTAT0_CHGSHORTI
-#define MC13XXX_IRQMASK0_CCCVM MC13XXX_IRQSTAT0_CCCVI
-#define MC13XXX_IRQMASK0_CHGCURRM MC13XXX_IRQSTAT0_CHGCURRI
-#define MC13XXX_IRQMASK0_BPONM MC13XXX_IRQSTAT0_BPONI
-#define MC13XXX_IRQMASK0_LOBATLM MC13XXX_IRQSTAT0_LOBATLI
-#define MC13XXX_IRQMASK0_LOBATHM MC13XXX_IRQSTAT0_LOBATHI
-#define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI
-#define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI
-#define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI
-#define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I
-#define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI
-#define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI
-
#define MC13XXX_IRQSTAT1 3
-#define MC13XXX_IRQSTAT1_1HZI (1 << 0)
-#define MC13XXX_IRQSTAT1_TODAI (1 << 1)
-#define MC13783_IRQSTAT1_ONOFD1I (1 << 3)
-#define MC13783_IRQSTAT1_ONOFD2I (1 << 4)
-#define MC13783_IRQSTAT1_ONOFD3I (1 << 5)
-#define MC13XXX_IRQSTAT1_SYSRSTI (1 << 6)
-#define MC13XXX_IRQSTAT1_RTCRSTI (1 << 7)
-#define MC13XXX_IRQSTAT1_PCI (1 << 8)
-#define MC13XXX_IRQSTAT1_WARMI (1 << 9)
-#define MC13XXX_IRQSTAT1_MEMHLDI (1 << 10)
-#define MC13783_IRQSTAT1_PWRRDYI (1 << 11)
-#define MC13XXX_IRQSTAT1_THWARNLI (1 << 12)
-#define MC13XXX_IRQSTAT1_THWARNHI (1 << 13)
-#define MC13XXX_IRQSTAT1_CLKI (1 << 14)
-#define MC13783_IRQSTAT1_SEMAFI (1 << 15)
-#define MC13783_IRQSTAT1_MC2BI (1 << 17)
-#define MC13783_IRQSTAT1_HSDETI (1 << 18)
-#define MC13783_IRQSTAT1_HSLI (1 << 19)
-#define MC13783_IRQSTAT1_ALSPTHI (1 << 20)
-#define MC13783_IRQSTAT1_AHSSHORTI (1 << 21)
-
#define MC13XXX_IRQMASK1 4
-#define MC13XXX_IRQMASK1_1HZM MC13XXX_IRQSTAT1_1HZI
-#define MC13XXX_IRQMASK1_TODAM MC13XXX_IRQSTAT1_TODAI
-#define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I
-#define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I
-#define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I
-#define MC13XXX_IRQMASK1_SYSRSTM MC13XXX_IRQSTAT1_SYSRSTI
-#define MC13XXX_IRQMASK1_RTCRSTM MC13XXX_IRQSTAT1_RTCRSTI
-#define MC13XXX_IRQMASK1_PCM MC13XXX_IRQSTAT1_PCI
-#define MC13XXX_IRQMASK1_WARMM MC13XXX_IRQSTAT1_WARMI
-#define MC13XXX_IRQMASK1_MEMHLDM MC13XXX_IRQSTAT1_MEMHLDI
-#define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI
-#define MC13XXX_IRQMASK1_THWARNLM MC13XXX_IRQSTAT1_THWARNLI
-#define MC13XXX_IRQMASK1_THWARNHM MC13XXX_IRQSTAT1_THWARNHI
-#define MC13XXX_IRQMASK1_CLKM MC13XXX_IRQSTAT1_CLKI
-#define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI
-#define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI
-#define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI
-#define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI
-#define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI
-#define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI
#define MC13XXX_REVISION 7
#define MC13XXX_REVISION_REVMETAL (0x07 << 0)
@@ -189,45 +101,21 @@ EXPORT_SYMBOL(mc13xxx_reg_rmw);
int mc13xxx_irq_mask(struct mc13xxx *mc13xxx, int irq)
{
- int ret;
- unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
- u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
- u32 mask;
-
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
- return -EINVAL;
-
- ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
- if (ret)
- return ret;
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- if (mask & irqbit)
- /* already masked */
- return 0;
+ disable_irq_nosync(virq);
- return mc13xxx_reg_write(mc13xxx, offmask, mask | irqbit);
+ return 0;
}
EXPORT_SYMBOL(mc13xxx_irq_mask);
int mc13xxx_irq_unmask(struct mc13xxx *mc13xxx, int irq)
{
- int ret;
- unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
- u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
- u32 mask;
-
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
- return -EINVAL;
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
- if (ret)
- return ret;
+ enable_irq(virq);
- if (!(mask & irqbit))
- /* already unmasked */
- return 0;
-
- return mc13xxx_reg_write(mc13xxx, offmask, mask & ~irqbit);
+ return 0;
}
EXPORT_SYMBOL(mc13xxx_irq_unmask);
@@ -239,7 +127,7 @@ int mc13xxx_irq_status(struct mc13xxx *mc13xxx, int irq,
unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
+ if (irq < 0 || irq >= ARRAY_SIZE(mc13xxx->irqs))
return -EINVAL;
if (enabled) {
@@ -266,147 +154,26 @@ int mc13xxx_irq_status(struct mc13xxx *mc13xxx, int irq,
}
EXPORT_SYMBOL(mc13xxx_irq_status);
-int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq)
-{
- unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
- unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
-
- BUG_ON(irq < 0 || irq >= MC13XXX_NUM_IRQ);
-
- return mc13xxx_reg_write(mc13xxx, offstat, val);
-}
-EXPORT_SYMBOL(mc13xxx_irq_ack);
-
-int mc13xxx_irq_request_nounmask(struct mc13xxx *mc13xxx, int irq,
- irq_handler_t handler, const char *name, void *dev)
-{
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
- BUG_ON(!handler);
-
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
- return -EINVAL;
-
- if (mc13xxx->irqhandler[irq])
- return -EBUSY;
-
- mc13xxx->irqhandler[irq] = handler;
- mc13xxx->irqdata[irq] = dev;
-
- return 0;
-}
-EXPORT_SYMBOL(mc13xxx_irq_request_nounmask);
-
int mc13xxx_irq_request(struct mc13xxx *mc13xxx, int irq,
irq_handler_t handler, const char *name, void *dev)
{
- int ret;
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- ret = mc13xxx_irq_request_nounmask(mc13xxx, irq, handler, name, dev);
- if (ret)
- return ret;
-
- ret = mc13xxx_irq_unmask(mc13xxx, irq);
- if (ret) {
- mc13xxx->irqhandler[irq] = NULL;
- mc13xxx->irqdata[irq] = NULL;
- return ret;
- }
-
- return 0;
+ return devm_request_threaded_irq(mc13xxx->dev, virq, NULL, handler,
+ 0, name, dev);
}
EXPORT_SYMBOL(mc13xxx_irq_request);
int mc13xxx_irq_free(struct mc13xxx *mc13xxx, int irq, void *dev)
{
- int ret;
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ || !mc13xxx->irqhandler[irq] ||
- mc13xxx->irqdata[irq] != dev)
- return -EINVAL;
-
- ret = mc13xxx_irq_mask(mc13xxx, irq);
- if (ret)
- return ret;
-
- mc13xxx->irqhandler[irq] = NULL;
- mc13xxx->irqdata[irq] = NULL;
+ devm_free_irq(mc13xxx->dev, virq, dev);
return 0;
}
EXPORT_SYMBOL(mc13xxx_irq_free);
-static inline irqreturn_t mc13xxx_irqhandler(struct mc13xxx *mc13xxx, int irq)
-{
- return mc13xxx->irqhandler[irq](irq, mc13xxx->irqdata[irq]);
-}
-
-/*
- * returns: number of handled irqs or negative error
- * locking: holds mc13xxx->lock
- */
-static int mc13xxx_irq_handle(struct mc13xxx *mc13xxx,
- unsigned int offstat, unsigned int offmask, int baseirq)
-{
- u32 stat, mask;
- int ret = mc13xxx_reg_read(mc13xxx, offstat, &stat);
- int num_handled = 0;
-
- if (ret)
- return ret;
-
- ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
- if (ret)
- return ret;
-
- while (stat & ~mask) {
- int irq = __ffs(stat & ~mask);
-
- stat &= ~(1 << irq);
-
- if (likely(mc13xxx->irqhandler[baseirq + irq])) {
- irqreturn_t handled;
-
- handled = mc13xxx_irqhandler(mc13xxx, baseirq + irq);
- if (handled == IRQ_HANDLED)
- num_handled++;
- } else {
- dev_err(mc13xxx->dev,
- "BUG: irq %u but no handler\n",
- baseirq + irq);
-
- mask |= 1 << irq;
-
- ret = mc13xxx_reg_write(mc13xxx, offmask, mask);
- }
- }
-
- return num_handled;
-}
-
-static irqreturn_t mc13xxx_irq_thread(int irq, void *data)
-{
- struct mc13xxx *mc13xxx = data;
- irqreturn_t ret;
- int handled = 0;
-
- mc13xxx_lock(mc13xxx);
-
- ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT0,
- MC13XXX_IRQMASK0, 0);
- if (ret > 0)
- handled = 1;
-
- ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT1,
- MC13XXX_IRQMASK1, 24);
- if (ret > 0)
- handled = 1;
-
- mc13xxx_unlock(mc13xxx);
-
- return IRQ_RETVAL(handled);
-}
-
#define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask))
static void mc13xxx_print_revision(struct mc13xxx *mc13xxx, u32 revision)
{
@@ -475,8 +242,6 @@ static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
{
struct mc13xxx_adcdone_data *adcdone_data = data;
- mc13xxx_irq_ack(adcdone_data->mc13xxx, irq);
-
complete_all(&adcdone_data->done);
return IRQ_HANDLED;
@@ -544,7 +309,6 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__);
mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
mc13xxx_handler_adcdone, __func__, &adcdone_data);
- mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE);
mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
@@ -599,7 +363,8 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
if (!cell.name)
return -ENOMEM;
- return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL);
+ return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0,
+ regmap_irq_get_domain(mc13xxx->irq_data));
}
static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
@@ -640,8 +405,8 @@ int mc13xxx_common_init(struct device *dev)
{
struct mc13xxx_platform_data *pdata = dev_get_platdata(dev);
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
- int ret;
u32 revision;
+ int i, ret;
mc13xxx->dev = dev;
@@ -651,31 +416,32 @@ int mc13xxx_common_init(struct device *dev)
mc13xxx->variant->print_revision(mc13xxx, revision);
- /* mask all irqs */
- ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff);
- if (ret)
- return ret;
+ for (i = 0; i < ARRAY_SIZE(mc13xxx->irqs); i++) {
+ mc13xxx->irqs[i].reg_offset = i / MC13XXX_IRQ_PER_REG;
+ mc13xxx->irqs[i].mask = BIT(i % MC13XXX_IRQ_PER_REG);
+ }
- ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff);
+ mc13xxx->irq_chip.name = dev_name(dev);
+ mc13xxx->irq_chip.status_base = MC13XXX_IRQSTAT0;
+ mc13xxx->irq_chip.mask_base = MC13XXX_IRQMASK0;
+ mc13xxx->irq_chip.ack_base = MC13XXX_IRQSTAT0;
+ mc13xxx->irq_chip.irq_reg_stride = MC13XXX_IRQSTAT1 - MC13XXX_IRQSTAT0;
+ mc13xxx->irq_chip.init_ack_masked = true;
+ mc13xxx->irq_chip.use_ack = true;
+ mc13xxx->irq_chip.num_regs = MC13XXX_IRQ_REG_CNT;
+ mc13xxx->irq_chip.irqs = mc13xxx->irqs;
+ mc13xxx->irq_chip.num_irqs = ARRAY_SIZE(mc13xxx->irqs);
+
+ ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq, IRQF_ONESHOT,
+ 0, &mc13xxx->irq_chip, &mc13xxx->irq_data);
if (ret)
return ret;
mutex_init(&mc13xxx->lock);
- ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread,
- IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
- if (ret)
- return ret;
-
if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
mc13xxx->flags = pdata->flags;
- if (mc13xxx->flags & MC13XXX_USE_ADC)
- mc13xxx_add_subdevice(mc13xxx, "%s-adc");
-
- if (mc13xxx->flags & MC13XXX_USE_RTC)
- mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
-
if (pdata) {
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&pdata->regulators, sizeof(pdata->regulators));
@@ -699,6 +465,12 @@ int mc13xxx_common_init(struct device *dev)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");
}
+ if (mc13xxx->flags & MC13XXX_USE_ADC)
+ mc13xxx_add_subdevice(mc13xxx, "%s-adc");
+
+ if (mc13xxx->flags & MC13XXX_USE_RTC)
+ mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
+
return 0;
}
EXPORT_SYMBOL_GPL(mc13xxx_common_init);
@@ -707,8 +479,8 @@ int mc13xxx_common_exit(struct device *dev)
{
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
- free_irq(mc13xxx->irq, mc13xxx);
mfd_remove_devices(dev);
+ regmap_del_irq_chip(mc13xxx->irq, mc13xxx->irq_data);
mutex_destroy(&mc13xxx->lock);
return 0;
diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h
index ae7f1659f5d1..33677d1dcf66 100644
--- a/drivers/mfd/mc13xxx.h
+++ b/drivers/mfd/mc13xxx.h
@@ -13,7 +13,9 @@
#include <linux/regmap.h>
#include <linux/mfd/mc13xxx.h>
-#define MC13XXX_NUMREGS 0x3f
+#define MC13XXX_NUMREGS 0x3f
+#define MC13XXX_IRQ_REG_CNT 2
+#define MC13XXX_IRQ_PER_REG 24
struct mc13xxx;
@@ -33,13 +35,14 @@ struct mc13xxx {
struct device *dev;
const struct mc13xxx_variant *variant;
+ struct regmap_irq irqs[MC13XXX_IRQ_PER_REG * MC13XXX_IRQ_REG_CNT];
+ struct regmap_irq_chip irq_chip;
+ struct regmap_irq_chip_data *irq_data;
+
struct mutex lock;
int irq;
int flags;
- irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
- void *irqdata[MC13XXX_NUM_IRQ];
-
int adcflags;
};
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 62e5e3617eb0..7f5066e39752 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -137,6 +137,7 @@ EXPORT_SYMBOL(mcp_reg_read);
void mcp_enable(struct mcp *mcp)
{
unsigned long flags;
+
spin_lock_irqsave(&mcp->lock, flags);
if (mcp->use_count++ == 0)
mcp->ops->enable(mcp);
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index b48d80c367f9..33a9234b701c 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -445,7 +445,7 @@ static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap,
for (i = 0; i < omap->nports; i++) {
if (is_ehci_phy_mode(pdata->port_mode[i])) {
- reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
break;
}
}
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 41ab5e34d2ac..c87f7a0a53f8 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -244,20 +244,20 @@ static int pcf50633_probe(struct i2c_client *client,
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
struct platform_device *pdev;
+ int j;
pdev = platform_device_alloc("pcf50633-regulator", i);
- if (!pdev) {
- dev_err(pcf->dev, "Cannot create regulator %d\n", i);
- continue;
- }
+ if (!pdev)
+ return -ENOMEM;
pdev->dev.parent = pcf->dev;
- if (platform_device_add_data(pdev, &pdata->reg_init_data[i],
- sizeof(pdata->reg_init_data[i])) < 0) {
+ ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
+ sizeof(pdata->reg_init_data[i]));
+ if (ret) {
platform_device_put(pdev);
- dev_err(pcf->dev, "Out of memory for regulator parameters %d\n",
- i);
- continue;
+ for (j = 0; j < i; j++)
+ platform_device_put(pcf->regulator_pdev[j]);
+ return ret;
}
pcf->regulator_pdev[i] = pdev;
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 959513803542..39904f77c049 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -186,11 +186,9 @@ static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
- int irq_bit;
u8 block, config;
block = pmirq / 8;
- irq_bit = pmirq % 8;
config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
pm8xxx_config_irq(chip, block, config);
@@ -200,11 +198,9 @@ static void pm8xxx_irq_unmask(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
- int irq_bit;
u8 block, config;
block = pmirq / 8;
- irq_bit = pmirq % 8;
config = chip->config[pmirq];
pm8xxx_config_irq(chip, block, config);
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 1d15735f9ef9..d01b8c249231 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -337,40 +337,64 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read, int timeout)
{
- struct completion trans_done;
- u8 dir;
- int err = 0, i, count;
- long timeleft;
- unsigned long flags;
- struct scatterlist *sg;
- enum dma_data_direction dma_dir;
- u32 val;
- dma_addr_t addr;
- unsigned int len;
+ int err = 0, count;
dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+ count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
+ if (count < 1)
+ return -EINVAL;
+ dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
+
+ err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
+
+ rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int num_sg, bool read)
+{
+ enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- /* don't transfer data during abort processing */
if (pcr->remove_pci)
return -EINVAL;
if ((sglist == NULL) || (num_sg <= 0))
return -EINVAL;
- if (read) {
- dir = DEVICE_TO_HOST;
- dma_dir = DMA_FROM_DEVICE;
- } else {
- dir = HOST_TO_DEVICE;
- dma_dir = DMA_TO_DEVICE;
- }
+ return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
- count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
- if (count < 1) {
- dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
+void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int num_sg, bool read)
+{
+ enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
+
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int count, bool read, int timeout)
+{
+ struct completion trans_done;
+ struct scatterlist *sg;
+ dma_addr_t addr;
+ long timeleft;
+ unsigned long flags;
+ unsigned int len;
+ int i, err = 0;
+ u32 val;
+ u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
+
+ if (pcr->remove_pci)
+ return -ENODEV;
+
+ if ((sglist == NULL) || (count < 1))
return -EINVAL;
- }
- dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
pcr->sgi = 0;
@@ -400,12 +424,10 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
}
spin_lock_irqsave(&pcr->lock, flags);
-
if (pcr->trans_result == TRANS_RESULT_FAIL)
err = -EINVAL;
else if (pcr->trans_result == TRANS_NO_DEVICE)
err = -ENODEV;
-
spin_unlock_irqrestore(&pcr->lock, flags);
out:
@@ -413,8 +435,6 @@ out:
pcr->done = NULL;
spin_unlock_irqrestore(&pcr->lock, flags);
- dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
-
if ((err < 0) && (err != -ENODEV))
rtsx_pci_stop_cmd(pcr);
@@ -423,7 +443,7 @@ out:
return err;
}
-EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
{
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index be06d0abbf19..dba7e2b6f8e9 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -28,8 +28,10 @@
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
+#include <linux/regulator/machine.h>
#include <linux/regmap.h>
static const struct mfd_cell s5m8751_devs[] = {
@@ -89,6 +91,15 @@ static const struct mfd_cell s2mpa01_devs[] = {
},
};
+static const struct mfd_cell s2mpu02_devs[] = {
+ { .name = "s2mpu02-pmic", },
+ { .name = "s2mpu02-rtc", },
+ {
+ .name = "s2mpu02-clk",
+ .of_compatible = "samsung,s2mpu02-clk",
+ }
+};
+
#ifdef CONFIG_OF
static const struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic",
@@ -103,6 +114,9 @@ static const struct of_device_id sec_dt_match[] = {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
+ .compatible = "samsung,s2mpu02-pmic",
+ .data = (void *)S2MPU02,
+ }, {
/* Sentinel */
},
};
@@ -132,6 +146,18 @@ static bool s2mps11_volatile(struct device *dev, unsigned int reg)
}
}
+static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case S2MPU02_REG_INT1M:
+ case S2MPU02_REG_INT2M:
+ case S2MPU02_REG_INT3M:
+ return false;
+ default:
+ return true;
+ }
+}
+
static bool s5m8763_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -177,6 +203,15 @@ static const struct regmap_config s2mps14_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct regmap_config s2mpu02_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = S2MPU02_REG_DVSDATA,
+ .volatile_reg = s2mpu02_volatile,
+ .cache_type = REGCACHE_FLAT,
+};
+
static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -238,6 +273,7 @@ static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c,
#ifdef CONFIG_OF
if (i2c->dev.of_node) {
const struct of_device_id *match;
+
match = of_match_node(sec_dt_match, i2c->dev.of_node);
return (unsigned long)match->data;
}
@@ -250,9 +286,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
{
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
const struct regmap_config *regmap;
+ const struct mfd_cell *sec_devs;
struct sec_pmic_dev *sec_pmic;
unsigned long device_type;
- int ret;
+ int ret, num_sec_devs;
sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
GFP_KERNEL);
@@ -297,6 +334,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
+ case S2MPU02:
+ regmap = &s2mpu02_regmap_config;
+ break;
default:
regmap = &sec_regmap_config;
break;
@@ -319,34 +359,39 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S5M8751X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs,
- ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);
+ sec_devs = s5m8751_devs;
+ num_sec_devs = ARRAY_SIZE(s5m8751_devs);
break;
case S5M8763X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs,
- ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);
+ sec_devs = s5m8763_devs;
+ num_sec_devs = ARRAY_SIZE(s5m8763_devs);
break;
case S5M8767X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
- ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
+ sec_devs = s5m8767_devs;
+ num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
case S2MPA01:
- ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
- ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
+ sec_devs = s2mpa01_devs;
+ num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
break;
case S2MPS11X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
- ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
+ sec_devs = s2mps11_devs;
+ num_sec_devs = ARRAY_SIZE(s2mps11_devs);
break;
case S2MPS14X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs,
- ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL);
+ sec_devs = s2mps14_devs;
+ num_sec_devs = ARRAY_SIZE(s2mps14_devs);
+ break;
+ case S2MPU02:
+ sec_devs = s2mpu02_devs;
+ num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
break;
default:
/* If this happens the probe function is problem */
BUG();
}
-
+ ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL,
+ 0, NULL);
if (ret)
goto err_mfd;
@@ -387,6 +432,15 @@ static int sec_pmic_suspend(struct device *dev)
*/
disable_irq(sec_pmic->irq);
+ switch (sec_pmic->device_type) {
+ case S2MPS14X:
+ case S2MPU02:
+ regulator_suspend_prepare(PM_SUSPEND_MEM);
+ break;
+ default:
+ break;
+ }
+
return 0;
}
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 654e2c1dbf7a..f9a57869e3ec 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -20,6 +20,7 @@
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
@@ -161,6 +162,77 @@ static const struct regmap_irq s2mps14_irqs[] = {
},
};
+static const struct regmap_irq s2mpu02_irqs[] = {
+ [S2MPU02_IRQ_PWRONF] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_PWRONF_MASK,
+ },
+ [S2MPU02_IRQ_PWRONR] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_PWRONR_MASK,
+ },
+ [S2MPU02_IRQ_JIGONBF] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_JIGONBF_MASK,
+ },
+ [S2MPU02_IRQ_JIGONBR] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_JIGONBR_MASK,
+ },
+ [S2MPU02_IRQ_ACOKBF] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_ACOKBF_MASK,
+ },
+ [S2MPU02_IRQ_ACOKBR] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_ACOKBR_MASK,
+ },
+ [S2MPU02_IRQ_PWRON1S] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_PWRON1S_MASK,
+ },
+ [S2MPU02_IRQ_MRB] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_MRB_MASK,
+ },
+ [S2MPU02_IRQ_RTC60S] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTC60S_MASK,
+ },
+ [S2MPU02_IRQ_RTCA1] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTCA1_MASK,
+ },
+ [S2MPU02_IRQ_RTCA0] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTCA0_MASK,
+ },
+ [S2MPU02_IRQ_SMPL] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_SMPL_MASK,
+ },
+ [S2MPU02_IRQ_RTC1S] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTC1S_MASK,
+ },
+ [S2MPU02_IRQ_WTSR] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_WTSR_MASK,
+ },
+ [S2MPU02_IRQ_INT120C] = {
+ .reg_offset = 2,
+ .mask = S2MPS11_IRQ_INT120C_MASK,
+ },
+ [S2MPU02_IRQ_INT140C] = {
+ .reg_offset = 2,
+ .mask = S2MPS11_IRQ_INT140C_MASK,
+ },
+ [S2MPU02_IRQ_TSD] = {
+ .reg_offset = 2,
+ .mask = S2MPS14_IRQ_TSD_MASK,
+ },
+};
+
static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg_offset = 0,
@@ -327,6 +399,16 @@ static const struct regmap_irq_chip s2mps14_irq_chip = {
.ack_base = S2MPS14_REG_INT1,
};
+static const struct regmap_irq_chip s2mpu02_irq_chip = {
+ .name = "s2mpu02",
+ .irqs = s2mpu02_irqs,
+ .num_irqs = ARRAY_SIZE(s2mpu02_irqs),
+ .num_regs = 3,
+ .status_base = S2MPU02_REG_INT1,
+ .mask_base = S2MPU02_REG_INT1M,
+ .ack_base = S2MPU02_REG_INT1,
+};
+
static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767",
.irqs = s5m8767_irqs,
@@ -351,6 +433,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{
int ret = 0;
int type = sec_pmic->device_type;
+ const struct regmap_irq_chip *sec_irq_chip;
if (!sec_pmic->irq) {
dev_warn(sec_pmic->dev,
@@ -361,28 +444,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
switch (type) {
case S5M8763X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s5m8763_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s5m8763_irq_chip;
break;
case S5M8767X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s5m8767_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s5m8767_irq_chip;
break;
case S2MPS11X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s2mps11_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s2mps11_irq_chip;
break;
case S2MPS14X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s2mps14_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s2mps14_irq_chip;
+ break;
+ case S2MPU02:
+ sec_irq_chip = &s2mpu02_irq_chip;
break;
default:
dev_err(sec_pmic->dev, "Unknown device type %lu\n",
@@ -390,6 +464,10 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return -EINVAL;
}
+ ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ sec_pmic->irq_base, sec_irq_chip,
+ &sec_pmic->irq_data);
if (ret != 0) {
dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c
index 6f1ef63086c9..2086b4665288 100644
--- a/drivers/mfd/si476x-cmd.c
+++ b/drivers/mfd/si476x-cmd.c
@@ -1228,8 +1228,8 @@ static int si476x_core_cmd_fm_rsq_status_a10(struct si476x_core *core,
}
static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
- struct si476x_rsq_status_args *rsqargs,
- struct si476x_rsq_status_report *report)
+ struct si476x_rsq_status_args *rsqargs,
+ struct si476x_rsq_status_report *report)
{
int err;
u8 resp[CMD_FM_RSQ_STATUS_A10_NRESP];
@@ -1434,10 +1434,10 @@ typedef int (*tune_freq_func_t) (struct si476x_core *core,
struct si476x_tune_freq_args *tuneargs);
static struct {
- int (*power_up) (struct si476x_core *,
- struct si476x_power_up_args *);
- int (*power_down) (struct si476x_core *,
- struct si476x_power_down_args *);
+ int (*power_up)(struct si476x_core *,
+ struct si476x_power_up_args *);
+ int (*power_down)(struct si476x_core *,
+ struct si476x_power_down_args *);
tune_freq_func_t fm_tune_freq;
tune_freq_func_t am_tune_freq;
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index a45f9c0a330a..5c054031c3f8 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(of, stmpe_of_match);
static int
stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
- int partnum;
+ enum stmpe_partnum partnum;
const struct of_device_id *of_id;
i2c_ci.data = (void *)id;
@@ -85,7 +85,7 @@ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
dev_info(&i2c->dev, "matching on node name, compatible is preferred\n");
partnum = id->driver_data;
} else
- partnum = (int)of_id->data;
+ partnum = (enum stmpe_partnum)of_id->data;
return stmpe_probe(&i2c_ci, partnum);
}
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 3b6bfa7184ad..02a17c388e87 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1147,7 +1147,7 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
}
/* Called from client specific probe routines */
-int stmpe_probe(struct stmpe_client_info *ci, int partnum)
+int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
{
struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
struct device_node *np = ci->dev->of_node;
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index 9e4d21d37a11..2d045f26f193 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -97,7 +97,7 @@ struct stmpe_client_info {
void (*init)(struct stmpe *stmpe);
};
-int stmpe_probe(struct stmpe_client_info *ci, int partnum);
+int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum);
int stmpe_remove(struct stmpe *stmpe);
#define STMPE_ICR_LSB_HIGH (1 << 2)
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
index 718fc4d2adc0..283ab8d197e4 100644
--- a/drivers/mfd/sun6i-prcm.c
+++ b/drivers/mfd/sun6i-prcm.c
@@ -76,16 +76,46 @@ static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
},
};
+static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
+ {
+ .name = "sun8i-a23-apb0-clk",
+ .of_compatible = "allwinner,sun8i-a23-apb0-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res),
+ .resources = sun6i_a31_apb0_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-gates-clk",
+ .of_compatible = "allwinner,sun8i-a23-apb0-gates-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res),
+ .resources = sun6i_a31_apb0_gates_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-clock-reset",
+ .of_compatible = "allwinner,sun6i-a31-clock-reset",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
+ .resources = sun6i_a31_apb0_rstc_res,
+ },
+};
+
static const struct prcm_data sun6i_a31_prcm_data = {
.nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs),
.subdevs = sun6i_a31_prcm_subdevs,
};
+static const struct prcm_data sun8i_a23_prcm_data = {
+ .nsubdevs = ARRAY_SIZE(sun8i_a23_prcm_subdevs),
+ .subdevs = sun8i_a23_prcm_subdevs,
+};
+
static const struct of_device_id sun6i_prcm_dt_ids[] = {
{
.compatible = "allwinner,sun6i-a31-prcm",
.data = &sun6i_a31_prcm_data,
},
+ {
+ .compatible = "allwinner,sun8i-a23-prcm",
+ .data = &sun8i_a23_prcm_data,
+ },
{ /* sentinel */ },
};
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index bd83accc0f6d..0072e668c208 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -236,7 +236,7 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
static struct irq_domain_ops tc3589x_irq_ops = {
.map = tc3589x_irq_map,
.unmap = tc3589x_irq_unmap,
- .xlate = irq_domain_xlate_twocell,
+ .xlate = irq_domain_xlate_onecell,
};
static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 591a331d8d83..e71f88000ae5 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -147,11 +147,10 @@ static int tc6387xb_probe(struct platform_device *dev)
int irq, ret;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!iomem) {
+ if (!iomem)
return -EINVAL;
- }
- tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
+ tc6387xb = kzalloc(sizeof(*tc6387xb), GFP_KERNEL);
if (!tc6387xb)
return -ENOMEM;
@@ -189,7 +188,7 @@ static int tc6387xb_probe(struct platform_device *dev)
if (pdata && pdata->enable)
pdata->enable(dev);
- printk(KERN_INFO "Toshiba tc6387xb initialised\n");
+ dev_info(&dev->dev, "Toshiba tc6387xb initialised\n");
ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index b5dfa6e4e692..5de95c265c1a 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -141,7 +141,7 @@ static int tps6105x_probe(struct i2c_client *client,
int ret;
int i;
- tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL);
+ tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
if (!tps6105x)
return -ENOMEM;
@@ -154,7 +154,7 @@ static int tps6105x_probe(struct i2c_client *client,
ret = tps6105x_startup(tps6105x);
if (ret) {
dev_err(&client->dev, "chip initialization failed\n");
- goto fail;
+ return ret;
}
/* Remove warning texts when you implement new cell drivers */
@@ -187,16 +187,8 @@ static int tps6105x_probe(struct i2c_client *client,
tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
}
- ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
- ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
- if (ret)
- goto fail;
-
- return 0;
-
-fail:
- kfree(tps6105x);
- return ret;
+ return mfd_add_devices(&client->dev, 0, tps6105x_cells,
+ ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
}
static int tps6105x_remove(struct i2c_client *client)
@@ -210,7 +202,6 @@ static int tps6105x_remove(struct i2c_client *client)
TPS6105X_REG0_MODE_MASK,
TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
- kfree(tps6105x);
return 0;
}
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index f9e42ea1cb1a..f243e75d28f3 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -387,7 +387,7 @@ static const struct of_device_id tps65910_of_match[] = {
MODULE_DEVICE_TABLE(of, tps65910_of_match);
static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
- int *chip_id)
+ unsigned long *chip_id)
{
struct device_node *np = client->dev.of_node;
struct tps65910_board *board_info;
@@ -401,7 +401,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
return NULL;
}
- *chip_id = (int)match->data;
+ *chip_id = (unsigned long)match->data;
board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
GFP_KERNEL);
@@ -431,7 +431,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
#else
static inline
struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
- int *chip_id)
+ unsigned long *chip_id)
{
return NULL;
}
@@ -453,14 +453,14 @@ static void tps65910_power_off(void)
}
static int tps65910_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct tps65910 *tps65910;
struct tps65910_board *pmic_plat_data;
struct tps65910_board *of_pmic_plat_data = NULL;
struct tps65910_platform_data *init_data;
+ unsigned long chip_id = id->driver_data;
int ret = 0;
- int chip_id = id->driver_data;
pmic_plat_data = dev_get_platdata(&i2c->dev);
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index 69a5178bf152..de60ad98bd9f 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -32,10 +32,9 @@ static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr,
unsigned long spi_data = 1 << 23 | addr << 15 | *data;
struct spi_transfer xfer;
struct spi_message msg;
- u32 tx_buf, rx_buf;
+ u32 tx_buf;
tx_buf = spi_data;
- rx_buf = 0;
xfer.tx_buf = &tx_buf;
xfer.rx_buf = NULL;
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 596b1f657e21..b1dabba763cf 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -297,7 +297,7 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
ret = twl_i2c_read_u8(TWL_MODULE_PIH, &pih_isr,
REG_PIH_ISR_P1);
if (ret) {
- pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
+ pr_warn("twl4030: I2C error %d reading PIH ISR\n", ret);
return IRQ_NONE;
}
@@ -338,7 +338,7 @@ static int twl4030_init_sih_modules(unsigned line)
irq_line = line;
/* disable all interrupts on our line */
- memset(buf, 0xff, sizeof buf);
+ memset(buf, 0xff, sizeof(buf));
sih = sih_modules;
for (i = 0; i < nr_sih_modules; i++, sih++) {
/* skip USB -- it's funky */
@@ -646,7 +646,7 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base)
if (status < 0)
return status;
- agent = kzalloc(sizeof *agent, GFP_KERNEL);
+ agent = kzalloc(sizeof(*agent), GFP_KERNEL);
if (!agent)
return -ENOMEM;
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index a6bb17d908b8..2807e1a95663 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -70,7 +70,7 @@ static int twl6030_interrupt_mapping[24] = {
BATDETECT_INTR_OFFSET, /* Bit 9 BAT */
SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */
MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */
- RSV_INTR_OFFSET, /* Bit 12 Reserved */
+ RSV_INTR_OFFSET, /* Bit 12 Reserved */
MADC_INTR_OFFSET, /* Bit 13 GPADC_RT_EOC */
MADC_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */
GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */
@@ -245,6 +245,7 @@ int twl6030_interrupt_unmask(u8 bit_mask, u8 offset)
{
int ret;
u8 unmask_value;
+
ret = twl_i2c_read_u8(TWL_MODULE_PIH, &unmask_value,
REG_INT_STS_A + offset);
unmask_value &= (~(bit_mask));
@@ -258,6 +259,7 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset)
{
int ret;
u8 mask_value;
+
ret = twl_i2c_read_u8(TWL_MODULE_PIH, &mask_value,
REG_INT_STS_A + offset);
mask_value |= (bit_mask);
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index ae26d84b3a59..f9c06c542a41 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -700,7 +700,7 @@ static int twl6040_probe(struct i2c_client *client,
}
ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
- 0, &twl6040_irq_chip,&twl6040->irq_data);
+ 0, &twl6040_irq_chip, &twl6040->irq_data);
if (ret < 0)
goto gpio_err;
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index c8a993bd17ae..fb4d4bb0f47d 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -138,11 +138,11 @@ static const struct regmap_irq wm5102_irqs[ARIZONA_NUM_IRQ] = {
.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
},
[ARIZONA_IRQ_HPDET] = {
.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 41a7f6fb7802..9b98ee559188 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -340,11 +340,11 @@ static const struct regmap_irq wm5110_irqs[ARIZONA_NUM_IRQ] = {
.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
},
[ARIZONA_IRQ_HPDET] = {
.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
@@ -416,16 +416,28 @@ static const struct regmap_irq wm5110_irqs[ARIZONA_NUM_IRQ] = {
[ARIZONA_IRQ_ISRC2_CFG_ERR] = {
.reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1
},
+ [ARIZONA_IRQ_HP3R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+ },
[ARIZONA_IRQ_BOOT_DONE] = {
.reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
},
- [ARIZONA_IRQ_DCS_DAC_DONE] = {
- .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1
- },
- [ARIZONA_IRQ_DCS_HP_DONE] = {
- .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1
- },
[ARIZONA_IRQ_FLL2_CLOCK_OK] = {
.reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
},
@@ -445,6 +457,209 @@ const struct regmap_irq_chip wm5110_irq = {
};
EXPORT_SYMBOL_GPL(wm5110_irq);
+static const struct regmap_irq wm5110_revd_irqs[ARIZONA_NUM_IRQ] = {
+ [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 },
+ [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 },
+ [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
+ [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
+
+ [ARIZONA_IRQ_DSP4_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP4_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP3_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP3_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP2_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP2_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP1_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP1_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ8] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ8_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ7] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ7_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ6] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ6_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ5] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ5_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ4] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ4_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ3] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ3_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ2] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ2_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ1] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
+ },
+
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
+ },
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
+ },
+ [ARIZONA_IRQ_HPDET] = {
+ .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
+ },
+ [ARIZONA_IRQ_MICDET] = {
+ .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1
+ },
+ [ARIZONA_IRQ_WSEQ_DONE] = {
+ .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1
+ },
+ [ARIZONA_IRQ_DRC2_SIG_DET] = {
+ .reg_offset = 2, .mask = ARIZONA_DRC2_SIG_DET_EINT1
+ },
+ [ARIZONA_IRQ_DRC1_SIG_DET] = {
+ .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1
+ },
+ [ARIZONA_IRQ_ASRC2_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_ASRC2_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_ASRC1_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_ASRC1_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_UNDERCLOCKED] = {
+ .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1
+ },
+ [ARIZONA_IRQ_OVERCLOCKED] = {
+ .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1
+ },
+ [ARIZONA_IRQ_FLL2_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_FLL1_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_CLKGEN_ERR] = {
+ .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1
+ },
+ [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = {
+ .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1
+ },
+
+ [ARIZONA_IRQ_CTRLIF_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_CTRLIF_ERR_EINT1
+ },
+ [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_MIXER_DROPPED_SAMPLE_EINT1
+ },
+ [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ASYNC_CLK_ENA_LOW_EINT1
+ },
+ [ARIZONA_IRQ_SYSCLK_ENA_LOW] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_SYSCLK_ENA_LOW_EINT1
+ },
+ [ARIZONA_IRQ_ISRC1_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC1_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_ISRC2_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC2_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_ISRC3_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC3_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_HP3R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+ },
+
+ [ARIZONA_IRQ_BOOT_DONE] = {
+ .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
+ },
+ [ARIZONA_IRQ_ASRC_CFG_ERR] = {
+ .reg_offset = 4, .mask = ARIZONA_V2_ASRC_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_FLL2_CLOCK_OK] = {
+ .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
+ },
+ [ARIZONA_IRQ_FLL1_CLOCK_OK] = {
+ .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1
+ },
+
+ [ARIZONA_IRQ_DSP_SHARED_WR_COLL] = {
+ .reg_offset = 5, .mask = ARIZONA_DSP_SHARED_WR_COLL_EINT1
+ },
+ [ARIZONA_IRQ_SPK_SHUTDOWN] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ },
+ [ARIZONA_IRQ_SPK1R_SHORT] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK1R_SHORT_EINT1
+ },
+ [ARIZONA_IRQ_SPK1L_SHORT] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK1L_SHORT_EINT1
+ },
+ [ARIZONA_IRQ_HP3R_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3R_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP3R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3L_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3L_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2R_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2L_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2L_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1R_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1L_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1L_SC_POS_EINT1
+ },
+};
+
+const struct regmap_irq_chip wm5110_revd_irq = {
+ .name = "wm5110 IRQ",
+ .status_base = ARIZONA_INTERRUPT_STATUS_1,
+ .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK,
+ .ack_base = ARIZONA_INTERRUPT_STATUS_1,
+ .num_regs = 6,
+ .irqs = wm5110_revd_irqs,
+ .num_irqs = ARRAY_SIZE(wm5110_revd_irqs),
+};
+EXPORT_SYMBOL_GPL(wm5110_revd_irq);
+
static const struct reg_default wm5110_reg_default[] = {
{ 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */
{ 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */
@@ -1274,12 +1489,14 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */
{ 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */
{ 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */
+ { 0x00000D0D, 0xFFFF }, /* R3341 - Interrupt Status 6 Mask */
{ 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */
{ 0x00000D18, 0xFFFF }, /* R3352 - IRQ2 Status 1 Mask */
{ 0x00000D19, 0xFFFF }, /* R3353 - IRQ2 Status 2 Mask */
{ 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */
{ 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */
{ 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */
+ { 0x00000D1D, 0xFFFF }, /* R3357 - IRQ2 Status 6 Mask */
{ 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */
{ 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */
{ 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */
@@ -2311,22 +2528,26 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_STATUS_3:
case ARIZONA_INTERRUPT_STATUS_4:
case ARIZONA_INTERRUPT_STATUS_5:
+ case ARIZONA_INTERRUPT_STATUS_6:
case ARIZONA_INTERRUPT_STATUS_1_MASK:
case ARIZONA_INTERRUPT_STATUS_2_MASK:
case ARIZONA_INTERRUPT_STATUS_3_MASK:
case ARIZONA_INTERRUPT_STATUS_4_MASK:
case ARIZONA_INTERRUPT_STATUS_5_MASK:
+ case ARIZONA_INTERRUPT_STATUS_6_MASK:
case ARIZONA_INTERRUPT_CONTROL:
case ARIZONA_IRQ2_STATUS_1:
case ARIZONA_IRQ2_STATUS_2:
case ARIZONA_IRQ2_STATUS_3:
case ARIZONA_IRQ2_STATUS_4:
case ARIZONA_IRQ2_STATUS_5:
+ case ARIZONA_IRQ2_STATUS_6:
case ARIZONA_IRQ2_STATUS_1_MASK:
case ARIZONA_IRQ2_STATUS_2_MASK:
case ARIZONA_IRQ2_STATUS_3_MASK:
case ARIZONA_IRQ2_STATUS_4_MASK:
case ARIZONA_IRQ2_STATUS_5_MASK:
+ case ARIZONA_IRQ2_STATUS_6_MASK:
case ARIZONA_IRQ2_CONTROL:
case ARIZONA_INTERRUPT_RAW_STATUS_2:
case ARIZONA_INTERRUPT_RAW_STATUS_3:
@@ -2335,6 +2556,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_RAW_STATUS_6:
case ARIZONA_INTERRUPT_RAW_STATUS_7:
case ARIZONA_INTERRUPT_RAW_STATUS_8:
+ case ARIZONA_INTERRUPT_RAW_STATUS_9:
case ARIZONA_IRQ_PIN_STATUS:
case ARIZONA_AOD_WKUP_AND_TRIG:
case ARIZONA_AOD_IRQ1:
@@ -2610,11 +2832,13 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_STATUS_3:
case ARIZONA_INTERRUPT_STATUS_4:
case ARIZONA_INTERRUPT_STATUS_5:
+ case ARIZONA_INTERRUPT_STATUS_6:
case ARIZONA_IRQ2_STATUS_1:
case ARIZONA_IRQ2_STATUS_2:
case ARIZONA_IRQ2_STATUS_3:
case ARIZONA_IRQ2_STATUS_4:
case ARIZONA_IRQ2_STATUS_5:
+ case ARIZONA_IRQ2_STATUS_6:
case ARIZONA_INTERRUPT_RAW_STATUS_2:
case ARIZONA_INTERRUPT_RAW_STATUS_3:
case ARIZONA_INTERRUPT_RAW_STATUS_4:
@@ -2622,6 +2846,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_RAW_STATUS_6:
case ARIZONA_INTERRUPT_RAW_STATUS_7:
case ARIZONA_INTERRUPT_RAW_STATUS_8:
+ case ARIZONA_INTERRUPT_RAW_STATUS_9:
case ARIZONA_IRQ_PIN_STATUS:
case ARIZONA_AOD_WKUP_AND_TRIG:
case ARIZONA_AOD_IRQ1:
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index f919def05e24..6a16a8a6f9fa 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -58,10 +58,10 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8350_i2c_id[] = {
- { "wm8350", 0 },
- { "wm8351", 0 },
- { "wm8352", 0 },
- { }
+ { "wm8350", 0 },
+ { "wm8351", 0 },
+ { "wm8352", 0 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c
index cd01f7962dfd..813ff50f95b6 100644
--- a/drivers/mfd/wm8350-irq.c
+++ b/drivers/mfd/wm8350-irq.c
@@ -497,7 +497,8 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
if (pdata && pdata->irq_base > 0)
irq_base = pdata->irq_base;
- wm8350->irq_base = irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
+ wm8350->irq_base =
+ irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
if (wm8350->irq_base < 0) {
dev_warn(wm8350->dev, "Allocating irqs failed with %d\n",
wm8350->irq_base);
diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c
index 2fbce9c5950b..770a25696468 100644
--- a/drivers/mfd/wm8994-regmap.c
+++ b/drivers/mfd/wm8994-regmap.c
@@ -123,14 +123,23 @@ static struct reg_default wm1811_defaults[] = {
{ 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
{ 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
{ 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0411, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
{ 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
{ 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0422, 0x0200 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x0423, 0x0010 }, /* R1059 - AIF1 DAC2 Filters (2) */
{ 0x0430, 0x0068 }, /* R1072 - AIF1 DAC1 Noise Gate */
+ { 0x0431, 0x0068 }, /* R1073 - AIF1 DAC2 Noise Gate */
{ 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
{ 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
{ 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
{ 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
{ 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0450, 0x0098 }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x0451, 0x0845 }, /* R1105 - AIF1 DRC2 (2) */
+ { 0x0452, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x0453, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x0454, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
{ 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
{ 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
{ 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
@@ -152,6 +161,27 @@ static struct reg_default wm1811_defaults[] = {
{ 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
{ 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
{ 0x0494, 0x0000 }, /* R1172 - AIF1 DAC1 EQ Band 1 C */
+ { 0x04A0, 0x6318 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0x04A1, 0x6300 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0x04A2, 0x0FCA }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0x04A3, 0x0400 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0x04A4, 0x00D8 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0x04A5, 0x1EB5 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0x04A6, 0xF145 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0x04A7, 0x0B75 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0x04A8, 0x01C5 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0x04A9, 0x1C58 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0x04AA, 0xF373 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0x04AB, 0x0A54 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0x04AC, 0x0558 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0x04AD, 0x168E }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0x04AE, 0xF829 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0x04AF, 0x07AD }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0x04B0, 0x1103 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0x04B1, 0x0564 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0x04B2, 0x0559 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0x04B3, 0x4000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x04B4, 0x0000 }, /* R1204 - AIF1 DAC2 EQ Band 1 C */
{ 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
{ 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
{ 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
@@ -194,6 +224,8 @@ static struct reg_default wm1811_defaults[] = {
{ 0x0605, 0x0000 }, /* R1541 - AIF2ADC Right Mixer Routing */
{ 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
{ 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0608, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0609, 0x0000 }, /* R1545 - AIF1 ADC2 Right Mixer Routing */
{ 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
{ 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
{ 0x0612, 0x02C0 }, /* R1554 - AIF2TX Left Volume */
@@ -846,14 +878,23 @@ static bool wm1811_readable_register(struct device *dev, unsigned int reg)
case WM8994_AIF1_DAC1_LEFT_VOLUME:
case WM8994_AIF1_DAC1_RIGHT_VOLUME:
case WM8994_AIF1_ADC1_FILTERS:
+ case WM8994_AIF1_ADC2_FILTERS:
case WM8994_AIF1_DAC1_FILTERS_1:
case WM8994_AIF1_DAC1_FILTERS_2:
+ case WM8994_AIF1_DAC2_FILTERS_1:
+ case WM8994_AIF1_DAC2_FILTERS_2:
case WM8958_AIF1_DAC1_NOISE_GATE:
+ case WM8958_AIF1_DAC2_NOISE_GATE:
case WM8994_AIF1_DRC1_1:
case WM8994_AIF1_DRC1_2:
case WM8994_AIF1_DRC1_3:
case WM8994_AIF1_DRC1_4:
case WM8994_AIF1_DRC1_5:
+ case WM8994_AIF1_DRC2_1:
+ case WM8994_AIF1_DRC2_2:
+ case WM8994_AIF1_DRC2_3:
+ case WM8994_AIF1_DRC2_4:
+ case WM8994_AIF1_DRC2_5:
case WM8994_AIF1_DAC1_EQ_GAINS_1:
case WM8994_AIF1_DAC1_EQ_GAINS_2:
case WM8994_AIF1_DAC1_EQ_BAND_1_A:
@@ -875,6 +916,27 @@ static bool wm1811_readable_register(struct device *dev, unsigned int reg)
case WM8994_AIF1_DAC1_EQ_BAND_5_B:
case WM8994_AIF1_DAC1_EQ_BAND_5_PG:
case WM8994_AIF1_DAC1_EQ_BAND_1_C:
+ case WM8994_AIF1_DAC2_EQ_GAINS_1:
+ case WM8994_AIF1_DAC2_EQ_GAINS_2:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_C:
case WM8994_AIF2_ADC_LEFT_VOLUME:
case WM8994_AIF2_ADC_RIGHT_VOLUME:
case WM8994_AIF2_DAC_LEFT_VOLUME:
@@ -917,6 +979,8 @@ static bool wm1811_readable_register(struct device *dev, unsigned int reg)
case WM8994_DAC2_RIGHT_MIXER_ROUTING:
case WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING:
case WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING:
case WM8994_DAC1_LEFT_VOLUME:
case WM8994_DAC1_RIGHT_VOLUME:
case WM8994_DAC2_LEFT_VOLUME:
diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c
index c7a81da64ee1..510da3b52324 100644
--- a/drivers/mfd/wm8997-tables.c
+++ b/drivers/mfd/wm8997-tables.c
@@ -65,11 +65,11 @@ static const struct regmap_irq wm8997_irqs[ARIZONA_NUM_IRQ] = {
[ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
[ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
- [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
},
[ARIZONA_IRQ_HPDET] = {
.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
@@ -174,10 +174,10 @@ static const struct reg_default wm8997_reg_default[] = {
{ 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */
{ 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */
{ 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */
- { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 3 */
- { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */
- { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */
- { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */
+ { 0x00000068, 0x01FF }, /* R104 - AlwaysOn Triggers Seq Select 3 */
+ { 0x00000069, 0x01FF }, /* R105 - AlwaysOn Triggers Seq Select 4 */
+ { 0x0000006A, 0x01FF }, /* R106 - AlwaysOn Triggers Seq Select 5 */
+ { 0x0000006B, 0x01FF }, /* R107 - AlwaysOn Triggers Seq Select 6 */
{ 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */
{ 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
{ 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 0d519649b575..dfde4a210238 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -24,6 +24,7 @@
#include <linux/highmem.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
@@ -36,7 +37,10 @@ struct realtek_pci_sdmmc {
struct rtsx_pcr *pcr;
struct mmc_host *mmc;
struct mmc_request *mrq;
+ struct workqueue_struct *workq;
+#define SDMMC_WORKQ_NAME "rtsx_pci_sdmmc_workq"
+ struct work_struct work;
struct mutex host_mutex;
u8 ssc_depth;
@@ -48,6 +52,11 @@ struct realtek_pci_sdmmc {
int power_state;
#define SDMMC_POWER_ON 1
#define SDMMC_POWER_OFF 0
+
+ unsigned int sg_count;
+ s32 cookie;
+ unsigned int cookie_sg_count;
+ bool using_cookie;
};
static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
@@ -86,6 +95,77 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
#define sd_print_debug_regs(host)
#endif /* DEBUG */
+/*
+ * sd_pre_dma_transfer - do dma_map_sg() or using cookie
+ *
+ * @pre: if called in pre_req()
+ * return:
+ * 0 - do dma_map_sg()
+ * 1 - using cookie
+ */
+static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
+ struct mmc_data *data, bool pre)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int read = data->flags & MMC_DATA_READ;
+ int count = 0;
+ int using_cookie = 0;
+
+ if (!pre && data->host_cookie && data->host_cookie != host->cookie) {
+ dev_err(sdmmc_dev(host),
+ "error: data->host_cookie = %d, host->cookie = %d\n",
+ data->host_cookie, host->cookie);
+ data->host_cookie = 0;
+ }
+
+ if (pre || data->host_cookie != host->cookie) {
+ count = rtsx_pci_dma_map_sg(pcr, data->sg, data->sg_len, read);
+ } else {
+ count = host->cookie_sg_count;
+ using_cookie = 1;
+ }
+
+ if (pre) {
+ host->cookie_sg_count = count;
+ if (++host->cookie < 0)
+ host->cookie = 1;
+ data->host_cookie = host->cookie;
+ } else {
+ host->sg_count = count;
+ }
+
+ return using_cookie;
+}
+
+static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ bool is_first_req)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+
+ if (data->host_cookie) {
+ dev_err(sdmmc_dev(host),
+ "error: reset data->host_cookie = %d\n",
+ data->host_cookie);
+ data->host_cookie = 0;
+ }
+
+ sd_pre_dma_transfer(host, data, true);
+ dev_dbg(sdmmc_dev(host), "pre dma sg: %d\n", host->cookie_sg_count);
+}
+
+static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ int err)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ struct mmc_data *data = mrq->data;
+ int read = data->flags & MMC_DATA_READ;
+
+ rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
+ data->host_cookie = 0;
+}
+
static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
u8 *buf, int buf_len, int timeout)
{
@@ -415,7 +495,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
rtsx_pci_send_cmd_no_wait(pcr);
- err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+ err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000);
if (err < 0) {
sd_clear_error(host);
return err;
@@ -640,12 +720,24 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
return 0;
}
-static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+static inline int sd_rw_cmd(struct mmc_command *cmd)
{
- struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ return mmc_op_multi(cmd->opcode) ||
+ (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+ (cmd->opcode == MMC_WRITE_BLOCK);
+}
+
+static void sd_request(struct work_struct *work)
+{
+ struct realtek_pci_sdmmc *host = container_of(work,
+ struct realtek_pci_sdmmc, work);
struct rtsx_pcr *pcr = host->pcr;
+
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_request *mrq = host->mrq;
struct mmc_command *cmd = mrq->cmd;
struct mmc_data *data = mrq->data;
+
unsigned int data_size = 0;
int err;
@@ -677,13 +769,13 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
if (mrq->data)
data_size = data->blocks * data->blksz;
- if (!data_size || mmc_op_multi(cmd->opcode) ||
- (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
- (cmd->opcode == MMC_WRITE_BLOCK)) {
+ if (!data_size || sd_rw_cmd(cmd)) {
sd_send_cmd_get_rsp(host, cmd);
if (!cmd->error && data_size) {
sd_rw_multi(host, mrq);
+ if (!host->using_cookie)
+ sdmmc_post_req(host->mmc, host->mrq, 0);
if (mmc_op_multi(cmd->opcode) && mrq->stop)
sd_send_cmd_get_rsp(host, mrq->stop);
@@ -712,6 +804,21 @@ finish:
mmc_request_done(mmc, mrq);
}
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+
+ mutex_lock(&host->host_mutex);
+ host->mrq = mrq;
+ mutex_unlock(&host->host_mutex);
+
+ if (sd_rw_cmd(mrq->cmd))
+ host->using_cookie = sd_pre_dma_transfer(host, data, false);
+
+ queue_work(host->workq, &host->work);
+}
+
static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
unsigned char bus_width)
{
@@ -1146,6 +1253,8 @@ out:
}
static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+ .pre_req = sdmmc_pre_req,
+ .post_req = sdmmc_post_req,
.request = sdmmc_request,
.set_ios = sdmmc_set_ios,
.get_ro = sdmmc_get_ro,
@@ -1224,10 +1333,16 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
return -ENOMEM;
host = mmc_priv(mmc);
+ host->workq = create_singlethread_workqueue(SDMMC_WORKQ_NAME);
+ if (!host->workq) {
+ mmc_free_host(mmc);
+ return -ENOMEM;
+ }
host->pcr = pcr;
host->mmc = mmc;
host->pdev = pdev;
host->power_state = SDMMC_POWER_OFF;
+ INIT_WORK(&host->work, sd_request);
platform_set_drvdata(pdev, host);
pcr->slots[RTSX_SD_CARD].p_dev = pdev;
pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
@@ -1255,6 +1370,8 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
pcr->slots[RTSX_SD_CARD].card_event = NULL;
mmc = host->mmc;
+ cancel_work_sync(&host->work);
+
mutex_lock(&host->host_mutex);
if (host->mrq) {
dev_dbg(&(pdev->dev),
@@ -1273,6 +1390,10 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
mmc_remove_host(mmc);
host->eject = true;
+ flush_workqueue(host->workq);
+ destroy_workqueue(host->workq);
+ host->workq = NULL;
+
mmc_free_host(mmc);
dev_dbg(&(pdev->dev),
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 2b7e9e220497..b16c53a8272f 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -31,6 +31,7 @@
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
struct s2mps11_info {
unsigned int rdev_num;
@@ -40,11 +41,15 @@ struct s2mps11_info {
int ramp_delay16;
int ramp_delay7810;
int ramp_delay9;
+
+ enum sec_device_type dev_type;
+
/*
- * One bit for each S2MPS14 regulator whether the suspend mode
+ * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
* was enabled.
*/
- unsigned int s2mps14_suspend_state:30;
+ unsigned long long s2mps14_suspend_state:35;
+
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
};
@@ -415,12 +420,24 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int val;
- if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
- val = S2MPS14_ENABLE_SUSPEND;
- else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
- val = S2MPS14_ENABLE_EXT_CONTROL;
- else
- val = rdev->desc->enable_mask;
+ switch (s2mps11->dev_type) {
+ case S2MPS14X:
+ if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ val = S2MPS14_ENABLE_SUSPEND;
+ else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
+ val = S2MPS14_ENABLE_EXT_CONTROL;
+ else
+ val = rdev->desc->enable_mask;
+ break;
+ case S2MPU02:
+ if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ val = S2MPU02_ENABLE_SUSPEND;
+ else
+ val = rdev->desc->enable_mask;
+ break;
+ default:
+ return -EINVAL;
+ };
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val);
@@ -429,12 +446,38 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
{
int ret;
- unsigned int val;
+ unsigned int val, state;
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+ int rdev_id = rdev_get_id(rdev);
- /* LDO3 should be always on and does not support suspend mode */
- if (rdev_get_id(rdev) == S2MPS14_LDO3)
- return 0;
+ /* Below LDO should be always on or does not support suspend mode. */
+ switch (s2mps11->dev_type) {
+ case S2MPS14X:
+ switch (rdev_id) {
+ case S2MPS14_LDO3:
+ return 0;
+ default:
+ state = S2MPS14_ENABLE_SUSPEND;
+ break;
+ };
+ break;
+ case S2MPU02:
+ switch (rdev_id) {
+ case S2MPU02_LDO13:
+ case S2MPU02_LDO14:
+ case S2MPU02_LDO15:
+ case S2MPU02_LDO17:
+ case S2MPU02_BUCK7:
+ state = S2MPU02_DISABLE_SUSPEND;
+ break;
+ default:
+ state = S2MPU02_ENABLE_SUSPEND;
+ break;
+ };
+ break;
+ default:
+ return -EINVAL;
+ };
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
if (ret < 0)
@@ -452,7 +495,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
return 0;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
- rdev->desc->enable_mask, S2MPS14_ENABLE_SUSPEND);
+ rdev->desc->enable_mask, state);
}
static struct regulator_ops s2mps14_reg_ops = {
@@ -605,8 +648,7 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
}
static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
- struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
- enum sec_device_type dev_type)
+ struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
{
struct device_node *reg_np;
@@ -617,7 +659,7 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
}
of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
- if (dev_type == S2MPS14X)
+ if (s2mps11->dev_type == S2MPS14X)
s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
of_node_put(reg_np);
@@ -625,6 +667,238 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
return 0;
}
+static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ unsigned int ramp_val, ramp_shift, ramp_reg;
+
+ switch (rdev_get_id(rdev)) {
+ case S2MPU02_BUCK1:
+ ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT;
+ break;
+ case S2MPU02_BUCK2:
+ ramp_shift = S2MPU02_BUCK2_RAMP_SHIFT;
+ break;
+ case S2MPU02_BUCK3:
+ ramp_shift = S2MPU02_BUCK3_RAMP_SHIFT;
+ break;
+ case S2MPU02_BUCK4:
+ ramp_shift = S2MPU02_BUCK4_RAMP_SHIFT;
+ break;
+ default:
+ return 0;
+ }
+ ramp_reg = S2MPU02_REG_RAMP1;
+ ramp_val = get_ramp_delay(ramp_delay);
+
+ return regmap_update_bits(rdev->regmap, ramp_reg,
+ S2MPU02_BUCK1234_RAMP_MASK << ramp_shift,
+ ramp_val << ramp_shift);
+}
+
+static struct regulator_ops s2mpu02_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = s2mps14_regulator_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_disable = s2mps14_regulator_set_suspend_disable,
+};
+
+static struct regulator_ops s2mpu02_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = s2mps14_regulator_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_disable = s2mps14_regulator_set_suspend_disable,
+ .set_ramp_delay = s2mpu02_set_ramp_delay,
+};
+
+#define regulator_desc_s2mpu02_ldo1(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_900MV, \
+ .uV_step = S2MPU02_LDO_STEP_12_5MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP1_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L1CTRL, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L1CTRL, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo2(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_1050MV, \
+ .uV_step = S2MPU02_LDO_STEP_25MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP2_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L2CTRL1, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L2CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo3(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_900MV, \
+ .uV_step = S2MPU02_LDO_STEP_12_5MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP1_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo4(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_1050MV, \
+ .uV_step = S2MPU02_LDO_STEP_25MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP2_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo5(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_1600MV, \
+ .uV_step = S2MPU02_LDO_STEP_50MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP3_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+
+#define regulator_desc_s2mpu02_buck1234(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK1234_MIN_600MV, \
+ .uV_step = S2MPU02_BUCK1234_STEP_6_25MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK1234_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B1CTRL2 + (num - 1) * 2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B1CTRL1 + (num - 1) * 2, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_buck5(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK5_MIN_1081_25MV, \
+ .uV_step = S2MPU02_BUCK5_STEP_6_25MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK5_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B5CTRL2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B5CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_buck6(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK6_MIN_1700MV, \
+ .uV_step = S2MPU02_BUCK6_STEP_2_50MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK6_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B6CTRL2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B6CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_buck7(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK7_MIN_900MV, \
+ .uV_step = S2MPU02_BUCK7_STEP_6_25MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK7_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B7CTRL2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B7CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+
+static const struct regulator_desc s2mpu02_regulators[] = {
+ regulator_desc_s2mpu02_ldo1(1),
+ regulator_desc_s2mpu02_ldo2(2),
+ regulator_desc_s2mpu02_ldo4(3),
+ regulator_desc_s2mpu02_ldo5(4),
+ regulator_desc_s2mpu02_ldo4(5),
+ regulator_desc_s2mpu02_ldo3(6),
+ regulator_desc_s2mpu02_ldo3(7),
+ regulator_desc_s2mpu02_ldo4(8),
+ regulator_desc_s2mpu02_ldo5(9),
+ regulator_desc_s2mpu02_ldo3(10),
+ regulator_desc_s2mpu02_ldo4(11),
+ regulator_desc_s2mpu02_ldo5(12),
+ regulator_desc_s2mpu02_ldo5(13),
+ regulator_desc_s2mpu02_ldo5(14),
+ regulator_desc_s2mpu02_ldo5(15),
+ regulator_desc_s2mpu02_ldo5(16),
+ regulator_desc_s2mpu02_ldo4(17),
+ regulator_desc_s2mpu02_ldo5(18),
+ regulator_desc_s2mpu02_ldo3(19),
+ regulator_desc_s2mpu02_ldo4(20),
+ regulator_desc_s2mpu02_ldo5(21),
+ regulator_desc_s2mpu02_ldo5(22),
+ regulator_desc_s2mpu02_ldo5(23),
+ regulator_desc_s2mpu02_ldo4(24),
+ regulator_desc_s2mpu02_ldo5(25),
+ regulator_desc_s2mpu02_ldo4(26),
+ regulator_desc_s2mpu02_ldo5(27),
+ regulator_desc_s2mpu02_ldo5(28),
+ regulator_desc_s2mpu02_buck1234(1),
+ regulator_desc_s2mpu02_buck1234(2),
+ regulator_desc_s2mpu02_buck1234(3),
+ regulator_desc_s2mpu02_buck1234(4),
+ regulator_desc_s2mpu02_buck5(5),
+ regulator_desc_s2mpu02_buck6(6),
+ regulator_desc_s2mpu02_buck7(7),
+};
+
static int s2mps11_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -634,15 +908,14 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
struct s2mps11_info *s2mps11;
int i, ret = 0;
const struct regulator_desc *regulators;
- enum sec_device_type dev_type;
s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
GFP_KERNEL);
if (!s2mps11)
return -ENOMEM;
- dev_type = platform_get_device_id(pdev)->driver_data;
- switch (dev_type) {
+ s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
+ switch (s2mps11->dev_type) {
case S2MPS11X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
@@ -651,8 +924,13 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
break;
+ case S2MPU02:
+ s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
+ regulators = s2mpu02_regulators;
+ break;
default:
- dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
+ dev_err(&pdev->dev, "Invalid device type: %u\n",
+ s2mps11->dev_type);
return -EINVAL;
};
@@ -686,7 +964,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
for (i = 0; i < s2mps11->rdev_num; i++)
rdata[i].name = regulators[i].name;
- ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type);
+ ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11);
if (ret)
goto out;
@@ -739,6 +1017,7 @@ out:
static const struct platform_device_id s2mps11_pmic_id[] = {
{ "s2mps11-pmic", S2MPS11X},
{ "s2mps14-pmic", S2MPS14X},
+ { "s2mpu02-pmic", S2MPU02},
{ },
};
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index 595393098b09..731ed1a97f59 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -29,6 +29,8 @@
#define YEARS_FROM_DA9063(year) ((year) + 100)
#define MONTHS_FROM_DA9063(month) ((month) - 1)
+#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1)
+
#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
#define RTC_SEC 0
#define RTC_MIN 1
@@ -42,6 +44,10 @@ struct da9063_rtc {
struct da9063 *hw;
struct rtc_time alarm_time;
bool rtc_sync;
+ int alarm_year;
+ int alarm_start;
+ int alarm_len;
+ int data_start;
};
static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
@@ -83,7 +89,7 @@ static int da9063_rtc_stop_alarm(struct device *dev)
{
struct da9063_rtc *rtc = dev_get_drvdata(dev);
- return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+ return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, 0);
}
@@ -91,7 +97,7 @@ static int da9063_rtc_start_alarm(struct device *dev)
{
struct da9063_rtc *rtc = dev_get_drvdata(dev);
- return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+ return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, DA9063_ALARM_ON);
}
@@ -151,8 +157,9 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
int ret;
unsigned int val;
- ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S,
- &data[RTC_SEC], RTC_DATA_LEN);
+ data[RTC_SEC] = 0;
+ ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start,
+ &data[rtc->data_start], rtc->alarm_len);
if (ret < 0)
return ret;
@@ -186,14 +193,14 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
- ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S,
- data, RTC_DATA_LEN);
+ ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start,
+ &data[rtc->data_start], rtc->alarm_len);
if (ret < 0) {
dev_err(dev, "Failed to write alarm: %d\n", ret);
return ret;
}
- rtc->alarm_time = alrm->time;
+ da9063_data_to_tm(data, &rtc->alarm_time);
if (alrm->enabled) {
ret = da9063_rtc_start_alarm(dev);
@@ -218,7 +225,7 @@ static irqreturn_t da9063_alarm_event(int irq, void *data)
{
struct da9063_rtc *rtc = data;
- regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+ regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, 0);
rtc->rtc_sync = true;
@@ -257,7 +264,23 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ if (da9063->variant_code == PMIC_DA9063_AD) {
+ rtc->alarm_year = DA9063_AD_REG_ALARM_Y;
+ rtc->alarm_start = DA9063_AD_REG_ALARM_MI;
+ rtc->alarm_len = RTC_ALARM_DATA_LEN;
+ rtc->data_start = RTC_MIN;
+ } else {
+ rtc->alarm_year = DA9063_BB_REG_ALARM_Y;
+ rtc->alarm_start = DA9063_BB_REG_ALARM_S;
+ rtc->alarm_len = RTC_DATA_LEN;
+ rtc->data_start = RTC_SEC;
+ }
+
+ ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
0);
if (ret < 0) {
@@ -265,7 +288,7 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
+ ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_ALARM,
DA9063_ALARM_STATUS_ALARM);
if (ret < 0) {
@@ -273,25 +296,22 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y,
+ ret = regmap_update_bits(da9063->regmap, rtc->alarm_year,
DA9063_TICK_ON, 0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n");
goto err;
}
- ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S,
- data, RTC_DATA_LEN);
+ data[RTC_SEC] = 0;
+ ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start,
+ &data[rtc->data_start], rtc->alarm_len);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret);
goto err;
}
- rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
- if (!rtc)
- return -ENOMEM;
-
platform_set_drvdata(pdev, rtc);
irq_alarm = platform_get_irq_byname(pdev, "ALARM");
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 9efe118a28ba..d20a7f0786eb 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -492,16 +492,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
return ret;
}
-static struct regmap_config max77686_rtc_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-};
-
static int max77686_rtc_probe(struct platform_device *pdev)
{
struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent);
struct max77686_rtc_info *info;
- int ret, virq;
+ int ret;
dev_info(&pdev->dev, "%s\n", __func__);
@@ -514,14 +509,7 @@ static int max77686_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->max77686 = max77686;
info->rtc = max77686->rtc;
- info->max77686->rtc_regmap = devm_regmap_init_i2c(info->max77686->rtc,
- &max77686_rtc_regmap_config);
- if (IS_ERR(info->max77686->rtc_regmap)) {
- ret = PTR_ERR(info->max77686->rtc_regmap);
- dev_err(info->max77686->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
+
platform_set_drvdata(pdev, info);
ret = max77686_rtc_init_reg(info);
@@ -550,15 +538,16 @@ static int max77686_rtc_probe(struct platform_device *pdev)
ret = -EINVAL;
goto err_rtc;
}
- virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1);
- if (!virq) {
+
+ info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
+ MAX77686_RTCIRQ_RTCA1);
+ if (!info->virq) {
ret = -ENXIO;
goto err_rtc;
}
- info->virq = virq;
- ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
- max77686_rtc_alarm_irq, 0, "rtc-alarm0", info);
+ ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
+ max77686_rtc_alarm_irq, 0, "rtc-alarm1", info);
if (ret < 0)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->virq, ret);
OpenPOWER on IntegriCloud