diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-07 17:17:39 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-07 17:17:39 -0700 |
commit | 54c72d5987ff9f3cf59529d5d4f5cf19eae3f695 (patch) | |
tree | 3fee972d54926627895aa07684ddb2e2388e4614 /drivers | |
parent | 66bb0aa077978dbb76e6283531eb3cc7a878de38 (diff) | |
parent | 7caa79917ad4c1f91366b11f18e48623554aaa52 (diff) |
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')
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, ®value); 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); |