summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 10:58:17 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 10:58:17 -0800
commitac26663572db5b64522b92f3941a58678a832a36 (patch)
tree3a8d27153de37cb3f3fb0ff6843a1e727c961005 /drivers
parentd4371f94bc003e912d4825f5c4bdf57959857073 (diff)
parent02915661dbb91b25b621ab3f387ab55311bded7f (diff)
Merge tag 'mfd-3.14-1' of git://git.linaro.org/people/ljones/mfd
Pull MFD changes from Lee Jones: "New drivers - Samsung Maxim 14577; Micro USB, Regulator, IRQ Controller and Battery Charger - TI/National Semiconductor LP3943 I2C GPIO Expander and PWM Generator Existing driver adaptions - Expansion of Wolfson Arizona DSP and High-Pass filter controls - TI TWL6040 default Regmap support and Regcache addition/bypass - Some nice Smatch catch fixes - Conversion of TI OMAP-USB and TI TWL6030 to endian neutralness - ChromeOS EC timing (delay) adaptions and added dependency on OF - Many constifications of 'struct {mfd_cell,regmap_irq,et.al}' - Watchdog support added for NVIDIA AS3722 - Convert functions to static in TI AM335x - Realigned previously defeated functionality in TI AM335x - IIO ADC-TSC concurrency dead-lock/timeout resolution - Addition of Power Management and Clock support for Samsung core - DEFINE_PCI_DEVICE_TABLE macro removal from MFD Subsystem - Greater use of irqdomain functionality in ST-E AB8500 - Removal of 'include/linux/mfd/abx500/ab8500-gpio.h' - Wolfson WM831x PMIC Power Management changes s/poweroff/shutdown/ - Device Tree documentation added for TI/Nat Semi LP3943 - Version detection and voltage tables for TI TPS6586x PMIC devices - Simplification of Freescale MC13XXX (de-)initialisation routines - Clean-up and simplification of the Realtek parent driver - Added support for RTL8402 Realtek PCI-Express card reader - Resource leak fix for Maxim 77686 - Possible suspend BUG() fix in OMAP USB TLL - Support for new Wolfson WM5110 Revision (D) - Testing of automatic assignment of of_node in mfd_add_device() - Reversion of the above when it started to cause issues - Remove legacy Platform Data from; TI TWL Core, Qualcomm SSBI and ST-E ABx500 Pinctrl - Clean-ups; tabbing issues, function name changes, 'drvdata = NULL' removal, unused uninitialised warning mitigation, error message clarity, removal of redundant/duplicate checks, licensing (GPL -> GPL2), coding consistency, duplicate function declaration, ret checks, commit corrections, redundant of_match_ptr() helper removal, spelling, #if-deffery removal and header guards name changes" * tag 'mfd-3.14-1' of git://git.linaro.org/people/ljones/mfd: (78 commits) mfd: wm5110: Add register patch for rev D chip mfd: omap-usb-tll: Don't hold lock during pm_runtime_get/put_sync() gpio: lp3943: Remove redundant of_match_ptr helper mfd: sta2x11-mfd: Use named constants for pci_power_t values Documentation: mfd: Fix LDO index in s2mps11.txt mfd: Cleanup mfd-mcp-sa11x0.h header mfd: max8997: Use "IS_ENABLED(CONFIG_OF)" for DT code. mfd: twl6030: Fix endianness problem in IRQ handler mfd: sec-core: Add cells for S5M8767-clocks mfd: max14577: Remove redundant of_match_ptr helper mfd: twl6040: Fix sparse non static symbol warning mfd: Revert "mfd: Always assign of_node in mfd_add_device()" mfd: rtsx: Fix sparse non static symbol warning mfd: max77693: Set proper maximum register for MUIC regmap mfd: max77686: Fix regmap resource leak on driver remove mfd: Represent correct filenames in file headers mfd: rtsx: Add support for card reader rtl8402 mfd: rtsx: Add set pull control macro and simplify rtl8411 mfd: max8997: Enforce mfd_add_devices() return value check mfd: mc13xxx: Simplify probe() & remove() ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-lp3943.c242
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c68
-rw-r--r--drivers/input/misc/Kconfig2
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c4
-rw-r--r--drivers/mfd/88pm800.c4
-rw-r--r--drivers/mfd/88pm805.c2
-rw-r--r--drivers/mfd/Kconfig30
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/ab8500-core.c16
-rw-r--r--drivers/mfd/ab8500-debugfs.c5
-rw-r--r--drivers/mfd/arizona-core.c8
-rw-r--r--drivers/mfd/as3722.c5
-rw-r--r--drivers/mfd/asic3.c4
-rw-r--r--drivers/mfd/cros_ec.c2
-rw-r--r--drivers/mfd/cros_ec_i2c.c8
-rw-r--r--drivers/mfd/cros_ec_spi.c56
-rw-r--r--drivers/mfd/cs5535-mfd.c2
-rw-r--r--drivers/mfd/da9052-core.c2
-rw-r--r--drivers/mfd/da9055-core.c2
-rw-r--r--drivers/mfd/da9063-core.c2
-rw-r--r--drivers/mfd/db8500-prcmu.c4
-rw-r--r--drivers/mfd/htc-pasic3.c2
-rw-r--r--drivers/mfd/intel_msic.c2
-rw-r--r--drivers/mfd/janz-cmodio.c2
-rw-r--r--drivers/mfd/jz4740-adc.c2
-rw-r--r--drivers/mfd/lp3943.c167
-rw-r--r--drivers/mfd/lp8788.c2
-rw-r--r--drivers/mfd/lpc_ich.c2
-rw-r--r--drivers/mfd/lpc_sch.c2
-rw-r--r--drivers/mfd/max14577.c245
-rw-r--r--drivers/mfd/max77686.c4
-rw-r--r--drivers/mfd/max77693.c10
-rw-r--r--drivers/mfd/max8907.c2
-rw-r--r--drivers/mfd/max8925-core.c8
-rw-r--r--drivers/mfd/max8997.c25
-rw-r--r--drivers/mfd/max8998.c4
-rw-r--r--drivers/mfd/mc13xxx-core.c41
-rw-r--r--drivers/mfd/mc13xxx-i2c.c18
-rw-r--r--drivers/mfd/mc13xxx-spi.c20
-rw-r--r--drivers/mfd/mc13xxx.h6
-rw-r--r--drivers/mfd/omap-usb-host.c8
-rw-r--r--drivers/mfd/omap-usb-tll.c44
-rw-r--r--drivers/mfd/rc5t583.c2
-rw-r--r--drivers/mfd/rdc321x-southbridge.c4
-rw-r--r--drivers/mfd/retu-mfd.c6
-rw-r--r--drivers/mfd/rtl8411.c101
-rw-r--r--drivers/mfd/rtsx_pcr.c7
-rw-r--r--drivers/mfd/rtsx_pcr.h9
-rw-r--r--drivers/mfd/sec-core.c62
-rw-r--r--drivers/mfd/sec-irq.c12
-rw-r--r--drivers/mfd/sm501.c2
-rw-r--r--drivers/mfd/ssbi.c16
-rw-r--r--drivers/mfd/sta2x11-mfd.c6
-rw-r--r--drivers/mfd/stmpe.c10
-rw-r--r--drivers/mfd/stmpe.h2
-rw-r--r--drivers/mfd/tc3589x.c4
-rw-r--r--drivers/mfd/tc6387xb.c2
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c71
-rw-r--r--drivers/mfd/timberdale.c14
-rw-r--r--drivers/mfd/tps6507x.c2
-rw-r--r--drivers/mfd/tps65090.c2
-rw-r--r--drivers/mfd/tps65217.c2
-rw-r--r--drivers/mfd/tps6586x.c52
-rw-r--r--drivers/mfd/tps65910.c2
-rw-r--r--drivers/mfd/tps65912-core.c2
-rw-r--r--drivers/mfd/tps80031.c2
-rw-r--r--drivers/mfd/twl-core.c213
-rw-r--r--drivers/mfd/twl6030-irq.c8
-rw-r--r--drivers/mfd/twl6040.c2
-rw-r--r--drivers/mfd/viperboard.c2
-rw-r--r--drivers/mfd/vx855.c4
-rw-r--r--drivers/mfd/wm5110-tables.c32
-rw-r--r--drivers/mfd/wm831x-core.c14
-rw-r--r--drivers/mfd/wm831x-i2c.c8
-rw-r--r--drivers/mfd/wm831x-spi.c8
-rw-r--r--drivers/mfd/wm8994-core.c4
-rw-r--r--drivers/pinctrl/pinctrl-abx500.c37
-rw-r--r--drivers/pinctrl/pinctrl-abx500.h12
-rw-r--r--drivers/pwm/Kconfig10
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-lp3943.c314
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/tps6586x-regulator.c93
86 files changed, 1669 insertions, 586 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 25ce03eff6a..50cc557abe4 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -406,6 +406,14 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
+config GPIO_LP3943
+ tristate "TI/National Semiconductor LP3943 GPIO expander"
+ depends on MFD_LP3943
+ help
+ GPIO driver for LP3943 MFD.
+ LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
+ Open drain outputs are required for this usage.
+
config GPIO_MAX7300
tristate "Maxim MAX7300 GPIO expander"
depends on I2C
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c44fffac951..0248471402e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
+obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c
new file mode 100644
index 00000000000..a0341c92bcb
--- /dev/null
+++ b/drivers/gpio/gpio-lp3943.c
@@ -0,0 +1,242 @@
+/*
+ * TI/National Semiconductor LP3943 GPIO driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.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; version 2.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum lp3943_gpios {
+ LP3943_GPIO1,
+ LP3943_GPIO2,
+ LP3943_GPIO3,
+ LP3943_GPIO4,
+ LP3943_GPIO5,
+ LP3943_GPIO6,
+ LP3943_GPIO7,
+ LP3943_GPIO8,
+ LP3943_GPIO9,
+ LP3943_GPIO10,
+ LP3943_GPIO11,
+ LP3943_GPIO12,
+ LP3943_GPIO13,
+ LP3943_GPIO14,
+ LP3943_GPIO15,
+ LP3943_GPIO16,
+ LP3943_MAX_GPIO,
+};
+
+struct lp3943_gpio {
+ struct gpio_chip chip;
+ struct lp3943 *lp3943;
+ u16 input_mask; /* 1 = GPIO is input direction, 0 = output */
+};
+
+static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip)
+{
+ return container_of(_chip, struct lp3943_gpio, chip);
+}
+
+static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+ struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+
+ /* Return an error if the pin is already assigned */
+ if (test_and_set_bit(offset, &lp3943->pin_used))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+ struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+
+ clear_bit(offset, &lp3943->pin_used);
+}
+
+static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
+ u8 val)
+{
+ struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+ const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+
+ return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
+ val << mux[offset].shift);
+}
+
+static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+ lp3943_gpio->input_mask |= BIT(offset);
+
+ return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
+}
+
+static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
+ struct gpio_chip *chip, unsigned offset)
+{
+ u8 addr, read;
+ int err;
+
+ switch (offset) {
+ case LP3943_GPIO1 ... LP3943_GPIO8:
+ addr = LP3943_REG_GPIO_A;
+ break;
+ case LP3943_GPIO9 ... LP3943_GPIO16:
+ addr = LP3943_REG_GPIO_B;
+ offset = offset - 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
+ if (err)
+ return err;
+
+ return !!(read & BIT(offset));
+}
+
+static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
+ struct gpio_chip *chip, unsigned offset)
+{
+ struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+ const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+ u8 read;
+ int err;
+
+ err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
+ if (err)
+ return err;
+
+ read = (read & mux[offset].mask) >> mux[offset].shift;
+
+ if (read == LP3943_GPIO_OUT_HIGH)
+ return 1;
+ else if (read == LP3943_GPIO_OUT_LOW)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+ /*
+ * Limitation:
+ * LP3943 doesn't have the GPIO direction register. It provides
+ * only input and output status registers.
+ * So, direction info is required to handle the 'get' operation.
+ * This variable is updated whenever the direction is changed and
+ * it is used here.
+ */
+
+ if (lp3943_gpio->input_mask & BIT(offset))
+ return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset);
+ else
+ return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset);
+}
+
+static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+ u8 data;
+
+ if (value)
+ data = LP3943_GPIO_OUT_HIGH;
+ else
+ data = LP3943_GPIO_OUT_LOW;
+
+ lp3943_gpio_set_mode(lp3943_gpio, offset, data);
+}
+
+static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+ lp3943_gpio_set(chip, offset, value);
+ lp3943_gpio->input_mask &= ~BIT(offset);
+
+ return 0;
+}
+
+static const struct gpio_chip lp3943_gpio_chip = {
+ .label = "lp3943",
+ .owner = THIS_MODULE,
+ .request = lp3943_gpio_request,
+ .free = lp3943_gpio_free,
+ .direction_input = lp3943_gpio_direction_input,
+ .get = lp3943_gpio_get,
+ .direction_output = lp3943_gpio_direction_output,
+ .set = lp3943_gpio_set,
+ .base = -1,
+ .ngpio = LP3943_MAX_GPIO,
+ .can_sleep = 1,
+};
+
+static int lp3943_gpio_probe(struct platform_device *pdev)
+{
+ struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
+ struct lp3943_gpio *lp3943_gpio;
+
+ lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio),
+ GFP_KERNEL);
+ if (!lp3943_gpio)
+ return -ENOMEM;
+
+ lp3943_gpio->lp3943 = lp3943;
+ lp3943_gpio->chip = lp3943_gpio_chip;
+ lp3943_gpio->chip.dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, lp3943_gpio);
+
+ return gpiochip_add(&lp3943_gpio->chip);
+}
+
+static int lp3943_gpio_remove(struct platform_device *pdev)
+{
+ struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
+
+ return gpiochip_remove(&lp3943_gpio->chip);
+}
+
+static const struct of_device_id lp3943_gpio_of_match[] = {
+ { .compatible = "ti,lp3943-gpio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match);
+
+static struct platform_driver lp3943_gpio_driver = {
+ .probe = lp3943_gpio_probe,
+ .remove = lp3943_gpio_remove,
+ .driver = {
+ .name = "lp3943-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = lp3943_gpio_of_match,
+ },
+};
+module_platform_driver(lp3943_gpio_driver);
+
+MODULE_DESCRIPTION("LP3943 GPIO driver");
+MODULE_ALIAS("platform:lp3943-gpio");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index d4d748214e4..31e786e3999 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -60,6 +60,24 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
return step_en;
}
+static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev,
+ struct iio_chan_spec const *chan)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
+ if (chan->channel == adc_dev->channel_line[i]) {
+ u32 step;
+
+ step = adc_dev->channel_step[i];
+ /* +1 for the charger */
+ return 1 << (step + 1);
+ }
+ }
+ WARN_ON(1);
+ return 0;
+}
+
static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
{
return 1 << adc_dev->channel_step[chan];
@@ -181,7 +199,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
enb |= (get_adc_step_bit(adc_dev, bit) << 1);
adc_dev->buffer_en_ch_steps = enb;
- am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+ am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
@@ -199,6 +217,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+ adc_dev->buffer_en_ch_steps = 0;
/* Flush FIFO of leftover data in the time it takes to disable adc */
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
@@ -328,34 +347,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
unsigned int fifo1count, read, stepid;
bool found = false;
u32 step_en;
- unsigned long timeout = jiffies + usecs_to_jiffies
- (IDLE_TIMEOUT * adc_dev->channels);
+ unsigned long timeout;
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
- step_en = get_adc_step_mask(adc_dev);
- am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+ step_en = get_adc_chan_step_mask(adc_dev, chan);
+ if (!step_en)
+ return -EINVAL;
+
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ while (fifo1count--)
+ tiadc_readl(adc_dev, REG_FIFO1);
+
+ am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
- /* Wait for ADC sequencer to complete sampling */
- while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
- if (time_after(jiffies, timeout))
+ timeout = jiffies + usecs_to_jiffies
+ (IDLE_TIMEOUT * adc_dev->channels);
+ /* Wait for Fifo threshold interrupt */
+ while (1) {
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ if (fifo1count)
+ break;
+
+ if (time_after(jiffies, timeout)) {
+ am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
return -EAGAIN;
}
+ }
map_val = chan->channel + TOTAL_CHANNELS;
/*
- * When the sub-system is first enabled,
- * the sequencer will always start with the
- * lowest step (1) and continue until step (16).
- * For ex: If we have enabled 4 ADC channels and
- * currently use only 1 out of them, the
- * sequencer still configures all the 4 steps,
- * leading to 3 unwanted data.
- * Hence we need to flush out this data.
+ * We check the complete FIFO. We programmed just one entry but in case
+ * something went wrong we left empty handed (-EAGAIN previously) and
+ * then the value apeared somehow in the FIFO we would have two entries.
+ * Therefore we read every item and keep only the latest version of the
+ * requested channel.
*/
-
- fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (i = 0; i < fifo1count; i++) {
read = tiadc_readl(adc_dev, REG_FIFO1);
stepid = read & FIFOREAD_CHNLID_MASK;
@@ -367,6 +395,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
*val = (u16) read;
}
}
+ am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
if (found == false)
return -EBUSY;
@@ -494,7 +523,8 @@ static int tiadc_resume(struct device *dev)
tiadc_writel(adc_dev, REG_CTRL, restore);
tiadc_step_config(indio_dev);
-
+ am335x_tsc_se_set_cache(adc_dev->mfd_tscadc,
+ adc_dev->buffer_en_ch_steps);
return 0;
}
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 5f4967d01bc..e2413acbbb1 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -168,7 +168,7 @@ config INPUT_MAX8997_HAPTIC
config INPUT_MC13783_PWRBUTTON
tristate "MC13783 ON buttons"
- depends on MFD_MC13783
+ depends on MFD_MC13XXX
help
Support the ON buttons of MC13783 PMIC as an input device
reporting power button status.
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 961d58d3264..07e9e82029d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -717,7 +717,7 @@ config TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_MC13783
tristate "Freescale MC13783 touchscreen input driver"
- depends on MFD_MC13783
+ depends on MFD_MC13XXX
help
Say Y here if you have an Freescale MC13783 PMIC on your
board and want to use its touchscreen
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 68beadaabce..2ca5a7bee04 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -198,7 +198,7 @@ static void titsc_step_config(struct titsc *ts_dev)
/* The steps1 … end and bit 0 for TS_Charge */
stepenable = (1 << (end_step + 2)) - 1;
ts_dev->step_mask = stepenable;
- am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
+ am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
}
static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -322,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
if (irqclr) {
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
- am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
+ am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
return IRQ_HANDLED;
}
return IRQ_NONE;
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index a65447d6560..7dca1e64097 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -148,7 +148,7 @@ static struct resource onkey_resources[] = {
},
};
-static struct mfd_cell onkey_devs[] = {
+static const struct mfd_cell onkey_devs[] = {
{
.name = "88pm80x-onkey",
.num_resources = 1,
@@ -157,7 +157,7 @@ static struct mfd_cell onkey_devs[] = {
},
};
-static struct mfd_cell regulator_devs[] = {
+static const struct mfd_cell regulator_devs[] = {
{
.name = "88pm80x-regulator",
.id = -1,
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 8a5b6ffb5af..64751c2a1ac 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -77,7 +77,7 @@ static struct resource codec_resources[] = {
},
};
-static struct mfd_cell codec_devs[] = {
+static const struct mfd_cell codec_devs[] = {
{
.name = "88pm80x-codec",
.num_resources = ARRAY_SIZE(codec_resources),
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index dd671582c9a..49bb445d846 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -80,7 +80,7 @@ config MFD_CROS_EC_I2C
config MFD_CROS_EC_SPI
tristate "ChromeOS Embedded Controller (SPI)"
- depends on MFD_CROS_EC && SPI
+ depends on MFD_CROS_EC && SPI && OF
---help---
If you say Y here, you get support for talking to the ChromeOS EC
@@ -163,14 +163,10 @@ config MFD_DA9063
Additional drivers must be enabled in order to use the functionality
of the device.
-config MFD_MC13783
- tristate
-
config MFD_MC13XXX
tristate
depends on (SPI_MASTER || I2C)
select MFD_CORE
- select MFD_MC13783
help
Enable support for the Freescale MC13783 and MC13892 PMICs.
This driver provides common support for accessing the device,
@@ -321,6 +317,19 @@ config MFD_88PM860X
select individual components like voltage regulators, RTC and
battery-charger under the corresponding menus.
+config MFD_MAX14577
+ bool "Maxim Semiconductor MAX14577 MUIC + Charger Support"
+ depends on I2C=y
+ select MFD_CORE
+ select REGMAP_I2C
+ select IRQ_DOMAIN
+ help
+ Say yes here to support for Maxim Semiconductor MAX14577.
+ This is a Micro-USB IC with Charger controls 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.
+
config MFD_MAX77686
bool "Maxim Semiconductor MAX77686 PMIC Support"
depends on I2C=y
@@ -725,6 +734,17 @@ config MFD_DM355EVM_MSP
boards. MSP430 firmware manages resets and power sequencing,
inputs from buttons and the IR remote, LEDs, an RTC, and more.
+config MFD_LP3943
+ tristate "TI/National Semiconductor LP3943 MFD Driver"
+ depends on I2C
+ select MFD_CORE
+ select REGMAP_I2C
+ help
+ Support for the TI/National Semiconductor LP3943.
+ This driver consists of GPIO and PWM drivers.
+ With these functionalities, it can be used for LED string control or
+ general usage such like a GPIO controller and a PWM controller.
+
config MFD_LP8788
bool "TI LP8788 Power Management Unit Driver"
depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8a28dc90fe7..5aea5ef0a62 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
+obj-$(CONFIG_MFD_LP3943) += lp3943.o
obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
da9055-objs := da9055-core.o da9055-i2c.o
@@ -110,6 +111,7 @@ obj-$(CONFIG_MFD_DA9055) += da9055.o
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_MAX77693) += max77693.o max77693-irq.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index b6c2cdc7609..aaff683cd37 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -491,7 +491,7 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
line += 1;
- handle_nested_irq(ab8500->irq_base + line);
+ handle_nested_irq(irq_create_mapping(ab8500->domain, line));
}
return 0;
@@ -1017,7 +1017,7 @@ static struct resource ab8500_temp_resources[] = {
},
};
-static struct mfd_cell ab8500_bm_devs[] = {
+static const struct mfd_cell ab8500_bm_devs[] = {
{
.name = "ab8500-charger",
.of_compatible = "stericsson,ab8500-charger",
@@ -1052,7 +1052,7 @@ static struct mfd_cell ab8500_bm_devs[] = {
},
};
-static struct mfd_cell ab8500_devs[] = {
+static const struct mfd_cell ab8500_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
@@ -1143,7 +1143,7 @@ static struct mfd_cell ab8500_devs[] = {
},
};
-static struct mfd_cell ab9540_devs[] = {
+static const struct mfd_cell ab9540_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
@@ -1214,7 +1214,7 @@ static struct mfd_cell ab9540_devs[] = {
};
/* Device list for ab8505 */
-static struct mfd_cell ab8505_devs[] = {
+static const struct mfd_cell ab8505_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
@@ -1275,7 +1275,7 @@ static struct mfd_cell ab8505_devs[] = {
},
};
-static struct mfd_cell ab8540_devs[] = {
+static const struct mfd_cell ab8540_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
@@ -1339,7 +1339,7 @@ static struct mfd_cell ab8540_devs[] = {
},
};
-static struct mfd_cell ab8540_cut1_devs[] = {
+static const struct mfd_cell ab8540_cut1_devs[] = {
{
.name = "ab8500-rtc",
.of_compatible = "stericsson,ab8500-rtc",
@@ -1348,7 +1348,7 @@ static struct mfd_cell ab8540_cut1_devs[] = {
},
};
-static struct mfd_cell ab8540_cut2_devs[] = {
+static const struct mfd_cell ab8540_cut2_devs[] = {
{
.name = "ab8540-rtc",
.of_compatible = "stericsson,ab8540-rtc",
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index e33e385af0a..d1a22aae2df 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -1600,7 +1600,6 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
for (line = 0; line < num_interrupt_lines; line++) {
struct irq_desc *desc = irq_to_desc(line + irq_first);
- struct irqaction *action = desc->action;
seq_printf(s, "%3i: %6i %4i", line,
num_interrupts[line],
@@ -1608,7 +1607,9 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
if (desc && desc->name)
seq_printf(s, "-%-8s", desc->name);
- if (action) {
+ if (desc && desc->action) {
+ struct irqaction *action = desc->action;
+
seq_printf(s, " %s", action->name);
while ((action = action->next) != NULL)
seq_printf(s, ", %s", action->name);
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 75e180ceecf..a45aab9f6bb 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -565,7 +565,7 @@ static inline int arizona_of_get_core_pdata(struct arizona *arizona)
}
#endif
-static struct mfd_cell early_devs[] = {
+static const struct mfd_cell early_devs[] = {
{ .name = "arizona-ldo1" },
};
@@ -577,7 +577,7 @@ static const char *wm5102_supplies[] = {
"SPKVDDR",
};
-static struct mfd_cell wm5102_devs[] = {
+static const struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
@@ -590,7 +590,7 @@ static struct mfd_cell wm5102_devs[] = {
},
};
-static struct mfd_cell wm5110_devs[] = {
+static const struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
@@ -609,7 +609,7 @@ static const char *wm8997_supplies[] = {
"SPKVDD",
};
-static struct mfd_cell wm8997_devs[] = {
+static const struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index f161f2e00df..c71ff0af154 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -54,7 +54,7 @@ static const struct resource as3722_adc_resource[] = {
},
};
-static struct mfd_cell as3722_devs[] = {
+static const struct mfd_cell as3722_devs[] = {
{
.name = "as3722-pinctrl",
},
@@ -74,6 +74,9 @@ static struct mfd_cell as3722_devs[] = {
{
.name = "as3722-power-off",
},
+ {
+ .name = "as3722-wdt",
+ },
};
static const struct regmap_irq as3722_irqs[] = {
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index fa22154c84e..9f6294f2a07 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -695,7 +695,7 @@ static int ds1wm_disable(struct platform_device *pdev)
return 0;
}
-static struct mfd_cell asic3_cell_ds1wm = {
+static const struct mfd_cell asic3_cell_ds1wm = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
@@ -797,7 +797,7 @@ static int asic3_mmc_disable(struct platform_device *pdev)
return 0;
}
-static struct mfd_cell asic3_cell_mmc = {
+static const struct mfd_cell asic3_cell_mmc = {
.name = "tmio-mmc",
.enable = asic3_mmc_enable,
.disable = asic3_mmc_disable,
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 1f36885d674..783fe2e73e1 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -84,7 +84,7 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static struct mfd_cell cros_devs[] = {
+static const struct mfd_cell cros_devs[] = {
{
.name = "cros-ec-keyb",
.id = 1,
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 123044608b6..4f71be99a18 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -120,7 +120,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
return ret;
}
-static int cros_ec_probe_i2c(struct i2c_client *client,
+static int cros_ec_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct device *dev = &client->dev;
@@ -150,7 +150,7 @@ static int cros_ec_probe_i2c(struct i2c_client *client,
return 0;
}
-static int cros_ec_remove_i2c(struct i2c_client *client)
+static int cros_ec_i2c_remove(struct i2c_client *client)
{
struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
@@ -190,8 +190,8 @@ static struct i2c_driver cros_ec_driver = {
.owner = THIS_MODULE,
.pm = &cros_ec_i2c_pm_ops,
},
- .probe = cros_ec_probe_i2c,
- .remove = cros_ec_remove_i2c,
+ .probe = cros_ec_i2c_probe,
+ .remove = cros_ec_i2c_remove,
.id_table = cros_ec_i2c_id,
};
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 367ccb58ecb..84af8d7a429 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
@@ -50,10 +51,11 @@
/*
* Time between raising the SPI chip select (for the end of a
* transaction) and dropping it again (for the next transaction).
- * If we go too fast, the EC will miss the transaction. It seems
- * that 50us is enough with the 16MHz STM32 EC.
+ * If we go too fast, the EC will miss the transaction. We know that we
+ * need at least 70 us with the 16 MHz STM32 EC, so go with 200 us to be
+ * safe.
*/
-#define EC_SPI_RECOVERY_TIME_NS (50 * 1000)
+#define EC_SPI_RECOVERY_TIME_NS (200 * 1000)
/**
* struct cros_ec_spi - information about a SPI-connected EC
@@ -61,10 +63,13 @@
* @spi: SPI device we are connected to
* @last_transfer_ns: time that we last finished a transfer, or 0 if there
* 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.
*/
struct cros_ec_spi {
struct spi_device *spi;
s64 last_transfer_ns;
+ unsigned int end_of_msg_delay;
};
static void debug_packet(struct device *dev, const char *name, u8 *ptr,
@@ -75,7 +80,9 @@ static void debug_packet(struct device *dev, const char *name, u8 *ptr,
dev_dbg(dev, "%s: ", name);
for (i = 0; i < len; i++)
- dev_cont(dev, " %02x", ptr[i]);
+ pr_cont(" %02x", ptr[i]);
+
+ pr_cont("\n");
#endif
}
@@ -105,7 +112,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
/* Receive data until we see the header byte */
deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS);
do {
- memset(&trans, '\0', sizeof(trans));
+ memset(&trans, 0, sizeof(trans));
trans.cs_change = 1;
trans.rx_buf = ptr = ec_dev->din;
trans.len = EC_MSG_PREAMBLE_COUNT;
@@ -157,7 +164,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%zd\n",
todo, need_len, ptr - ec_dev->din);
- memset(&trans, '\0', sizeof(trans));
+ memset(&trans, 0, sizeof(trans));
trans.cs_change = 1;
trans.rx_buf = ptr;
trans.len = todo;
@@ -217,7 +224,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* Transmit phase - send our message */
debug_packet(ec_dev->dev, "out", ec_dev->dout, len);
- memset(&trans, '\0', sizeof(trans));
+ memset(&trans, 0, sizeof(trans));
trans.tx_buf = ec_dev->dout;
trans.len = len;
trans.cs_change = 1;
@@ -235,6 +242,17 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* turn off CS */
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);
+ }
+
final_ret = spi_sync(ec_spi->spi, &msg);
ktime_get_ts(&ts);
ec_spi->last_transfer_ns = timespec_to_ns(&ts);
@@ -281,7 +299,18 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
return 0;
}
-static int cros_ec_probe_spi(struct spi_device *spi)
+static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ u32 val;
+ int ret;
+
+ ret = of_property_read_u32(np, "google,cros-ec-spi-msg-delay", &val);
+ if (!ret)
+ ec_spi->end_of_msg_delay = val;
+}
+
+static int cros_ec_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
struct cros_ec_device *ec_dev;
@@ -302,6 +331,9 @@ static int cros_ec_probe_spi(struct spi_device *spi)
if (!ec_dev)
return -ENOMEM;
+ /* Check for any DT properties */
+ cros_ec_spi_dt_probe(ec_spi, dev);
+
spi_set_drvdata(spi, ec_dev);
ec_dev->name = "SPI";
ec_dev->dev = dev;
@@ -323,7 +355,7 @@ static int cros_ec_probe_spi(struct spi_device *spi)
return 0;
}
-static int cros_ec_remove_spi(struct spi_device *spi)
+static int cros_ec_spi_remove(struct spi_device *spi)
{
struct cros_ec_device *ec_dev;
@@ -364,12 +396,12 @@ static struct spi_driver cros_ec_driver_spi = {
.owner = THIS_MODULE,
.pm = &cros_ec_spi_pm_ops,
},
- .probe = cros_ec_probe_spi,
- .remove = cros_ec_remove_spi,
+ .probe = cros_ec_spi_probe,
+ .remove = cros_ec_spi_remove,
.id_table = cros_ec_spi_id,
};
module_spi_driver(cros_ec_driver_spi);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)");
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 2e4752a9220..17c13012686 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -172,7 +172,7 @@ static void cs5535_mfd_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(cs5535_mfd_pci_tbl) = {
+static const struct pci_device_id cs5535_mfd_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
{ 0, }
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index ea28a33576e..25838f10b35 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -427,7 +427,7 @@ int da9052_adc_read_temp(struct da9052 *da9052)
}
EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
-static struct mfd_cell da9052_subdev_info[] = {
+static const struct mfd_cell da9052_subdev_info[] = {
{
.name = "da9052-regulator",
.id = 1,
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
index d3670cd3c3c..caf8dcffd0a 100644
--- a/drivers/mfd/da9055-core.c
+++ b/drivers/mfd/da9055-core.c
@@ -294,7 +294,7 @@ static struct resource da9055_ld05_6_resource = {
.flags = IORESOURCE_IRQ,
};
-static struct mfd_cell da9055_devs[] = {
+static const struct mfd_cell da9055_devs[] = {
{
.of_compatible = "dialog,da9055-gpio",
.name = "da9055-gpio",
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c
index c9cf8d98840..26937cd0107 100644
--- a/drivers/mfd/da9063-core.c
+++ b/drivers/mfd/da9063-core.c
@@ -75,7 +75,7 @@ static struct resource da9063_hwmon_resources[] = {
};
-static struct mfd_cell da9063_devs[] = {
+static const struct mfd_cell da9063_devs[] = {
{
.name = DA9063_DRVNAME_REGULATORS,
.num_resources = ARRAY_SIZE(da9063_regulators_resources),
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index b9ce60c301d..e43e6e82111 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -3070,7 +3070,7 @@ static struct db8500_thsens_platform_data db8500_thsens_data = {
.num_trips = 4,
};
-static struct mfd_cell common_prcmu_devs[] = {
+static const struct mfd_cell common_prcmu_devs[] = {
{
.name = "ux500_wdt",
.platform_data = &db8500_wdt_pdata,
@@ -3079,7 +3079,7 @@ static struct mfd_cell common_prcmu_devs[] = {
},
};
-static struct mfd_cell db8500_prcmu_devs[] = {
+static const struct mfd_cell db8500_prcmu_devs[] = {
{
.name = "db8500-prcmu-regulators",
.of_compatible = "stericsson,db8500-prcmu-regulator",
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 6bf92a507b9..e88d4f6fef4 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -114,7 +114,7 @@ static struct resource ds1wm_resources[] __initdata = {
},
};
-static struct mfd_cell ds1wm_cell __initdata = {
+static const struct mfd_cell ds1wm_cell __initconst = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 9203d47cdbb..049fd23af54 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -178,7 +178,7 @@ static struct mfd_cell msic_devs[] = {
* These devices appear only after the MSIC driver itself is initialized so
* we can guarantee that the SCU IPC interface is ready.
*/
-static struct mfd_cell msic_other_devs[] = {
+static const struct mfd_cell msic_other_devs[] = {
/* Audio codec in the MSIC */
{
.id = -1,
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index fcbb2e9dfd3..81b7d88af31 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -265,7 +265,7 @@ static void cmodio_pci_remove(struct pci_dev *dev)
#define PCI_VENDOR_ID_JANZ 0x13c3
/* The list of devices that this module will support */
-static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = {
+static const struct pci_device_id cmodio_pci_ids[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
{ 0, }
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index 3c0e8cf6916..7a51c0d0d4f 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -181,7 +181,7 @@ static struct resource jz4740_battery_resources[] = {
},
};
-static struct mfd_cell jz4740_adc_cells[] = {
+static const struct mfd_cell jz4740_adc_cells[] = {
{
.id = 0,
.name = "jz4740-hwmon",
diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c
new file mode 100644
index 00000000000..e32226836fb
--- /dev/null
+++ b/drivers/mfd/lp3943.c
@@ -0,0 +1,167 @@
+/*
+ * TI/National Semiconductor LP3943 MFD Core Driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver structure:
+ * LP3943 is an integrated device capable of driving 16 output channels.
+ * It can be used for a GPIO expander and PWM generators.
+ *
+ * LED control General usage for a device
+ * ___________ ____________________________
+ *
+ * LP3943 MFD ---- GPIO expander leds-gpio eg) HW enable pin
+ * |
+ * --- PWM generator leds-pwm eg) PWM input
+ *
+ * Internal two PWM channels are used for LED dimming effect.
+ * And each output pin can be used as a GPIO as well.
+ * The LED functionality can work with GPIOs or PWMs.
+ * LEDs can be controlled with legacy leds-gpio(static brightness) or
+ * leds-pwm drivers(dynamic brightness control).
+ * Alternatively, it can be used for generic GPIO and PWM controller.
+ * For example, a GPIO is HW enable pin of a device.
+ * A PWM is input pin of a backlight device.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define LP3943_MAX_REGISTERS 0x09
+
+/* Register configuration for pin MUX */
+static const struct lp3943_reg_cfg lp3943_mux_cfg[] = {
+ /* address, mask, shift */
+ { LP3943_REG_MUX0, 0x03, 0 },
+ { LP3943_REG_MUX0, 0x0C, 2 },
+ { LP3943_REG_MUX0, 0x30, 4 },
+ { LP3943_REG_MUX0, 0xC0, 6 },
+ { LP3943_REG_MUX1, 0x03, 0 },
+ { LP3943_REG_MUX1, 0x0C, 2 },
+ { LP3943_REG_MUX1, 0x30, 4 },
+ { LP3943_REG_MUX1, 0xC0, 6 },
+ { LP3943_REG_MUX2, 0x03, 0 },
+ { LP3943_REG_MUX2, 0x0C, 2 },
+ { LP3943_REG_MUX2, 0x30, 4 },
+ { LP3943_REG_MUX2, 0xC0, 6 },
+ { LP3943_REG_MUX3, 0x03, 0 },
+ { LP3943_REG_MUX3, 0x0C, 2 },
+ { LP3943_REG_MUX3, 0x30, 4 },
+ { LP3943_REG_MUX3, 0xC0, 6 },
+};
+
+static struct mfd_cell lp3943_devs[] = {
+ {
+ .name = "lp3943-pwm",
+ .of_compatible = "ti,lp3943-pwm",
+ },
+ {
+ .name = "lp3943-gpio",
+ .of_compatible = "ti,lp3943-gpio",
+ },
+};
+
+int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(lp3943->regmap, reg, &val);
+ if (ret < 0)
+ return ret;
+
+ *read = (u8)val;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lp3943_read_byte);
+
+int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data)
+{
+ return regmap_write(lp3943->regmap, reg, data);
+}
+EXPORT_SYMBOL_GPL(lp3943_write_byte);
+
+int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data)
+{
+ return regmap_update_bits(lp3943->regmap, reg, mask, data);
+}
+EXPORT_SYMBOL_GPL(lp3943_update_bits);
+
+static const struct regmap_config lp3943_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = LP3943_MAX_REGISTERS,
+};
+
+static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+ struct lp3943 *lp3943;
+ struct device *dev = &cl->dev;
+
+ lp3943 = devm_kzalloc(dev, sizeof(*lp3943), GFP_KERNEL);
+ if (!lp3943)
+ return -ENOMEM;
+
+ lp3943->regmap = devm_regmap_init_i2c(cl, &lp3943_regmap_config);
+ if (IS_ERR(lp3943->regmap))
+ return PTR_ERR(lp3943->regmap);
+
+ lp3943->pdata = dev_get_platdata(dev);
+ lp3943->dev = dev;
+ lp3943->mux_cfg = lp3943_mux_cfg;
+ i2c_set_clientdata(cl, lp3943);
+
+ return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs),
+ NULL, 0, NULL);
+}
+
+static int lp3943_remove(struct i2c_client *cl)
+{
+ struct lp3943 *lp3943 = i2c_get_clientdata(cl);
+
+ mfd_remove_devices(lp3943->dev);
+ return 0;
+}
+
+static const struct i2c_device_id lp3943_ids[] = {
+ { "lp3943", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lp3943_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id lp3943_of_match[] = {
+ { .compatible = "ti,lp3943", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_of_match);
+#endif
+
+static struct i2c_driver lp3943_driver = {
+ .probe = lp3943_probe,
+ .remove = lp3943_remove,
+ .driver = {
+ .name = "lp3943",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lp3943_of_match),
+ },
+ .id_table = lp3943_ids,
+};
+
+module_i2c_driver(lp3943_driver);
+
+MODULE_DESCRIPTION("LP3943 MFD Core Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index 0f122191101..a30bc15fe5b 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -71,7 +71,7 @@ static struct resource rtc_irqs[] = {
},
};
-static struct mfd_cell lp8788_devs[] = {
+static const struct mfd_cell lp8788_devs[] = {
/* 4 bucks */
MFD_DEV_WITH_ID(BUCK, 1),
MFD_DEV_WITH_ID(BUCK, 2),
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 37edf9e989b..be93fa261de 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -517,7 +517,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
* pci_driver, because the I/O Controller Hub has also other
* functions that probably will be registered by other drivers.
*/
-static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
+static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
{ PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
{ PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index fbfbf0b7f97..3bb05c03c68 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -76,7 +76,7 @@ static struct mfd_cell wdt_sch_cell = {
.ignore_resource_conflicts = true,
};
-static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
+static const struct pci_device_id lpc_sch_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) },
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
new file mode 100644
index 00000000000..ac514fb2b87
--- /dev/null
+++ b/drivers/mfd/max14577.c
@@ -0,0 +1,245 @@
+/*
+ * max14577.c - mfd core driver for the Maxim 14577
+ *
+ * Copyright (C) 2013 Samsung Electrnoics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ * Krzysztof Kozlowski <k.kozlowski@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.
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max14577.h>
+#include <linux/mfd/max14577-private.h>
+
+static struct mfd_cell max14577_devs[] = {
+ { .name = "max14577-muic", },
+ {
+ .name = "max14577-regulator",
+ .of_compatible = "maxim,max14577-regulator",
+ },
+ { .name = "max14577-charger", },
+};
+
+static bool max14577_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static const struct regmap_config max14577_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_reg = max14577_volatile_reg,
+ .max_register = MAX14577_REG_END,
+};
+
+static const struct regmap_irq max14577_irqs[] = {
+ /* INT1 interrupts */
+ { .reg_offset = 0, .mask = INT1_ADC_MASK, },
+ { .reg_offset = 0, .mask = INT1_ADCLOW_MASK, },
+ { .reg_offset = 0, .mask = INT1_ADCERR_MASK, },
+ /* INT2 interrupts */
+ { .reg_offset = 1, .mask = INT2_CHGTYP_MASK, },
+ { .reg_offset = 1, .mask = INT2_CHGDETRUN_MASK, },
+ { .reg_offset = 1, .mask = INT2_DCDTMR_MASK, },
+ { .reg_offset = 1, .mask = INT2_DBCHG_MASK, },
+ { .reg_offset = 1, .mask = INT2_VBVOLT_MASK, },
+ /* INT3 interrupts */
+ { .reg_offset = 2, .mask = INT3_EOC_MASK, },
+ { .reg_offset = 2, .mask = INT3_CGMBC_MASK, },
+ { .reg_offset = 2, .mask = INT3_OVP_MASK, },
+ { .reg_offset = 2, .mask = INT3_MBCCHGERR_MASK, },
+};
+
+static const struct regmap_irq_chip max14577_irq_chip = {
+ .name = "max14577",
+ .status_base = MAX14577_REG_INT1,
+ .mask_base = MAX14577_REG_INTMASK1,
+ .mask_invert = 1,
+ .num_regs = 3,
+ .irqs = max14577_irqs,
+ .num_irqs = ARRAY_SIZE(max14577_irqs),
+};
+
+static int max14577_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct max14577 *max14577;
+ struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct device_node *np = i2c->dev.of_node;
+ u8 reg_data;
+ int ret = 0;
+
+ if (np) {
+ pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ i2c->dev.platform_data = pdata;
+ }
+
+ if (!pdata) {
+ dev_err(&i2c->dev, "No platform data found.\n");
+ return -EINVAL;
+ }
+
+ max14577 = devm_kzalloc(&i2c->dev, sizeof(*max14577), GFP_KERNEL);
+ if (!max14577)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, max14577);
+ max14577->dev = &i2c->dev;
+ max14577->i2c = i2c;
+ max14577->irq = i2c->irq;
+
+ max14577->regmap = devm_regmap_init_i2c(i2c, &max14577_regmap_config);
+ if (IS_ERR(max14577->regmap)) {
+ ret = PTR_ERR(max14577->regmap);
+ dev_err(max14577->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID,
+ &reg_data);
+ if (ret) {
+ dev_err(max14577->dev, "Device not found on this channel: %d\n",
+ ret);
+ return ret;
+ }
+ max14577->vendor_id = ((reg_data & DEVID_VENDORID_MASK) >>
+ DEVID_VENDORID_SHIFT);
+ max14577->device_id = ((reg_data & DEVID_DEVICEID_MASK) >>
+ DEVID_DEVICEID_SHIFT);
+ dev_info(max14577->dev, "Device ID: 0x%x, vendor: 0x%x\n",
+ max14577->device_id, max14577->vendor_id);
+
+ ret = regmap_add_irq_chip(max14577->regmap, max14577->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0,
+ &max14577_irq_chip,
+ &max14577->irq_data);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ max14577->irq, ret);
+ return ret;
+ }
+
+ ret = mfd_add_devices(max14577->dev, -1, max14577_devs,
+ ARRAY_SIZE(max14577_devs), NULL, 0,
+ regmap_irq_get_domain(max14577->irq_data));
+ if (ret < 0)
+ goto err_mfd;
+
+ device_init_wakeup(max14577->dev, 1);
+
+ return 0;
+
+err_mfd:
+ regmap_del_irq_chip(max14577->irq, max14577->irq_data);
+
+ return ret;
+}
+
+static int max14577_i2c_remove(struct i2c_client *i2c)
+{
+ struct max14577 *max14577 = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(max14577->dev);
+ regmap_del_irq_chip(max14577->irq, max14577->irq_data);
+
+ return 0;
+}
+
+static const struct i2c_device_id max14577_i2c_id[] = {
+ { "max14577", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
+
+static int max14577_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct max14577 *max14577 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(max14577->irq);
+ /*
+ * MUIC IRQ must be disabled during suspend if this is
+ * a wake up source because it will be handled before
+ * resuming I2C.
+ *
+ * When device is woken up from suspend (e.g. by ADC change),
+ * 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(max14577->irq);
+ }
+
+ return 0;
+}
+
+static int max14577_resume(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct max14577 *max14577 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(max14577->irq);
+ enable_irq(max14577->irq);
+ }
+
+ return 0;
+}
+
+static struct of_device_id max14577_dt_match[] = {
+ { .compatible = "maxim,max14577", },
+ {},
+};
+
+static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume);
+
+static struct i2c_driver max14577_i2c_driver = {
+ .driver = {
+ .name = "max14577",
+ .owner = THIS_MODULE,
+ .pm = &max14577_pm,
+ .of_match_table = max14577_dt_match,
+ },
+ .probe = max14577_i2c_probe,
+ .remove = max14577_i2c_remove,
+ .id_table = max14577_i2c_id,
+};
+
+static int __init max14577_i2c_init(void)
+{
+ return i2c_add_driver(&max14577_i2c_driver);
+}
+subsys_initcall(max14577_i2c_init);
+
+static void __exit max14577_i2c_exit(void)
+{
+ i2c_del_driver(&max14577_i2c_driver);
+}
+module_exit(max14577_i2c_exit);
+
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
+MODULE_DESCRIPTION("MAXIM 14577 multi-function core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index 34520cbe8af..f53d5823a3f 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -35,7 +35,7 @@
#define I2C_ADDR_RTC (0x0C >> 1)
-static struct mfd_cell max77686_devs[] = {
+static const struct mfd_cell max77686_devs[] = {
{ .name = "max77686-pmic", },
{ .name = "max77686-rtc", },
{ .name = "max77686-clk", },
@@ -104,7 +104,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
max77686->irq_gpio = pdata->irq_gpio;
max77686->irq = i2c->irq;
- max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
+ max77686->regmap = devm_regmap_init_i2c(i2c, &max77686_regmap_config);
if (IS_ERR(max77686->regmap)) {
ret = PTR_ERR(max77686->regmap);
dev_err(max77686->dev, "Failed to allocate register map: %d\n",
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 9f92463f4f7..e0859987ab6 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -41,7 +41,7 @@
#define I2C_ADDR_MUIC (0x4A >> 1)
#define I2C_ADDR_HAPTIC (0x90 >> 1)
-static struct mfd_cell max77693_devs[] = {
+static const struct mfd_cell max77693_devs[] = {
{ .name = "max77693-pmic", },
{ .name = "max77693-charger", },
{ .name = "max77693-flash", },
@@ -107,6 +107,12 @@ static const struct regmap_config max77693_regmap_config = {
.max_register = MAX77693_PMIC_REG_END,
};
+static const struct regmap_config max77693_regmap_muic_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX77693_MUIC_REG_END,
+};
+
static int max77693_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -153,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
* before call max77693-muic probe() function.
*/
max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic,
- &max77693_regmap_config);
+ &max77693_regmap_muic_config);
if (IS_ERR(max77693->regmap_muic)) {
ret = PTR_ERR(max77693->regmap_muic);
dev_err(max77693->dev,
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 3bbfedc07f4..07740314b29 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -22,7 +22,7 @@
#include <linux/regmap.h>
#include <linux/slab.h>
-static struct mfd_cell max8907_cells[] = {
+static const struct mfd_cell max8907_cells[] = {
{ .name = "max8907-regulator", },
{ .name = "max8907-rtc", },
};
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index f0cc40296d8..f3faf0c45dd 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -45,7 +45,7 @@ static struct resource touch_resources[] = {
},
};
-static struct mfd_cell touch_devs[] = {
+static const struct mfd_cell touch_devs[] = {
{
.name = "max8925-touch",
.num_resources = 1,
@@ -63,7 +63,7 @@ static struct resource power_supply_resources[] = {
},
};
-static struct mfd_cell power_devs[] = {
+static const struct mfd_cell power_devs[] = {
{
.name = "max8925-power",
.num_resources = 1,
@@ -81,7 +81,7 @@ static struct resource rtc_resources[] = {
},
};
-static struct mfd_cell rtc_devs[] = {
+static const struct mfd_cell rtc_devs[] = {
{
.name = "max8925-rtc",
.num_resources = 1,
@@ -104,7 +104,7 @@ static struct resource onkey_resources[] = {
},
};
-static struct mfd_cell onkey_devs[] = {
+static const struct mfd_cell onkey_devs[] = {
{
.name = "max8925-onkey",
.num_resources = 2,
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 791aea3e96c..be88a3bf7b8 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -40,7 +40,7 @@
#define I2C_ADDR_RTC (0x0C >> 1)
#define I2C_ADDR_HAPTIC (0x90 >> 1)
-static struct mfd_cell max8997_devs[] = {
+static const struct mfd_cell max8997_devs[] = {
{ .name = "max8997-pmic", },
{ .name = "max8997-rtc", },
{ .name = "max8997-battery", },
@@ -133,7 +133,6 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
}
EXPORT_SYMBOL_GPL(max8997_update_reg);
-#ifdef CONFIG_OF
/*
* Only the common platform data elements for max8997 are parsed here from the
* device tree. Other sub-modules of max8997 such as pmic, rtc and others have
@@ -164,24 +163,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
return pd;
}
-#else
-static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
- struct device *dev)
-{
- return 0;
-}
-#endif
static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
-#ifdef CONFIG_OF
- if (i2c->dev.of_node) {
+ if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
return (int)match->data;
}
-#endif
return (int)id->driver_data;
}
@@ -203,7 +193,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
max8997->type = max8997_i2c_get_driver_data(i2c, id);
max8997->irq = i2c->irq;
- if (max8997->dev->of_node) {
+ if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) {
pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
@@ -228,18 +218,19 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
max8997_irq_init(max8997);
- mfd_add_devices(max8997->dev, -1, max8997_devs,
+ ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
ARRAY_SIZE(max8997_devs),
NULL, 0, NULL);
+ if (ret < 0) {
+ dev_err(max8997->dev, "failed to add MFD devices %d\n", ret);
+ goto err_mfd;
+ }
/*
* TODO: enable others (flash, muic, rtc, battery, ...) and
* check the return value
*/
- if (ret < 0)
- goto err_mfd;
-
/* MAX8997 has a power button input. */
device_init_wakeup(max8997->dev, pdata->wakeup);
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index fe6332dcabe..f47eaa70eae 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -37,7 +37,7 @@
#define RTC_I2C_ADDR (0x0c >> 1)
-static struct mfd_cell max8998_devs[] = {
+static const struct mfd_cell max8998_devs[] = {
{
.name = "max8998-pmic",
}, {
@@ -47,7 +47,7 @@ static struct mfd_cell max8998_devs[] = {
},
};
-static struct mfd_cell lp3974_devs[] = {
+static const struct mfd_cell lp3974_devs[] = {
{
.name = "lp3974-pmic",
}, {
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index dbbf8ee3f59..06e64b6fcb8 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -158,9 +158,6 @@ int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val)
{
int ret;
- if (offset > MC13XXX_NUMREGS)
- return -EINVAL;
-
ret = regmap_read(mc13xxx->regmap, offset, val);
dev_vdbg(mc13xxx->dev, "[0x%02x] -> 0x%06x\n", offset, *val);
@@ -172,7 +169,7 @@ int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val)
{
dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val);
- if (offset > MC13XXX_NUMREGS || val > 0xffffff)
+ if (val >= BIT(24))
return -EINVAL;
return regmap_write(mc13xxx->regmap, offset, val);
@@ -639,42 +636,36 @@ static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
}
#endif
-int mc13xxx_common_init(struct mc13xxx *mc13xxx,
- struct mc13xxx_platform_data *pdata, int irq)
+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;
- mc13xxx_lock(mc13xxx);
+ mc13xxx->dev = dev;
ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision);
if (ret)
- goto err_revision;
+ return ret;
mc13xxx->variant->print_revision(mc13xxx, revision);
/* mask all irqs */
ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff);
if (ret)
- goto err_mask;
+ return ret;
ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff);
if (ret)
- goto err_mask;
+ return ret;
- ret = request_threaded_irq(irq, NULL, mc13xxx_irq_thread,
+ ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
-
- if (ret) {
-err_mask:
-err_revision:
- mc13xxx_unlock(mc13xxx);
+ if (ret)
return ret;
- }
- mc13xxx->irq = irq;
-
- mc13xxx_unlock(mc13xxx);
+ mutex_init(&mc13xxx->lock);
if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
mc13xxx->flags = pdata->flags;
@@ -710,13 +701,17 @@ err_revision:
}
EXPORT_SYMBOL_GPL(mc13xxx_common_init);
-void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx)
+int mc13xxx_common_exit(struct device *dev)
{
+ struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
+
free_irq(mc13xxx->irq, mc13xxx);
+ mfd_remove_devices(dev);
+ mutex_destroy(&mc13xxx->lock);
- mfd_remove_devices(mc13xxx->dev);
+ return 0;
}
-EXPORT_SYMBOL_GPL(mc13xxx_common_cleanup);
+EXPORT_SYMBOL_GPL(mc13xxx_common_exit);
MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC");
MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
index 898bd335cd8..ae3addb153a 100644
--- a/drivers/mfd/mc13xxx-i2c.c
+++ b/drivers/mfd/mc13xxx-i2c.c
@@ -10,7 +10,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/mutex.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mc13xxx.h>
#include <linux/of.h>
@@ -60,7 +59,6 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mc13xxx *mc13xxx;
- struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev);
int ret;
mc13xxx = devm_kzalloc(&client->dev, sizeof(*mc13xxx), GFP_KERNEL);
@@ -69,15 +67,13 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
dev_set_drvdata(&client->dev, mc13xxx);
- mc13xxx->dev = &client->dev;
- mutex_init(&mc13xxx->lock);
+ mc13xxx->irq = client->irq;
mc13xxx->regmap = devm_regmap_init_i2c(client,
&mc13xxx_regmap_i2c_config);
if (IS_ERR(mc13xxx->regmap)) {
ret = PTR_ERR(mc13xxx->regmap);
- dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
- ret);
+ dev_err(&client->dev, "Failed to initialize regmap: %d\n", ret);
return ret;
}
@@ -89,18 +85,12 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
mc13xxx->variant = (void *)id->driver_data;
}
- ret = mc13xxx_common_init(mc13xxx, pdata, client->irq);
-
- return ret;
+ return mc13xxx_common_init(&client->dev);
}
static int mc13xxx_i2c_remove(struct i2c_client *client)
{
- struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
-
- mc13xxx_common_cleanup(mc13xxx);
-
- return 0;
+ return mc13xxx_common_exit(&client->dev);
}
static struct i2c_driver mc13xxx_i2c_driver = {
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 5f14ef6693c..38ab6782979 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -13,7 +13,6 @@
#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>
@@ -129,27 +128,24 @@ static struct regmap_bus regmap_mc13xxx_bus = {
static int mc13xxx_spi_probe(struct spi_device *spi)
{
struct mc13xxx *mc13xxx;
- struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
int ret;
mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL);
if (!mc13xxx)
return -ENOMEM;
- spi_set_drvdata(spi, mc13xxx);
+ dev_set_drvdata(&spi->dev, mc13xxx);
+
spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
- mc13xxx->dev = &spi->dev;
- mutex_init(&mc13xxx->lock);
+ mc13xxx->irq = spi->irq;
mc13xxx->regmap = devm_regmap_init(&spi->dev, &regmap_mc13xxx_bus,
&spi->dev,
&mc13xxx_regmap_spi_config);
if (IS_ERR(mc13xxx->regmap)) {
ret = PTR_ERR(mc13xxx->regmap);
- dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
- ret);
- spi_set_drvdata(spi, NULL);
+ dev_err(&spi->dev, "Failed to initialize regmap: %d\n", ret);
return ret;
}
@@ -164,16 +160,12 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
mc13xxx->variant = (void *)id_entry->driver_data;
}
- return mc13xxx_common_init(mc13xxx, pdata, spi->irq);
+ return mc13xxx_common_init(&spi->dev);
}
static int mc13xxx_spi_remove(struct spi_device *spi)
{
- struct mc13xxx *mc13xxx = spi_get_drvdata(spi);
-
- mc13xxx_common_cleanup(mc13xxx);
-
- return 0;
+ return mc13xxx_common_exit(&spi->dev);
}
static struct spi_driver mc13xxx_spi_driver = {
diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h
index 460ec5c7b18..ae7f1659f5d 100644
--- a/drivers/mfd/mc13xxx.h
+++ b/drivers/mfd/mc13xxx.h
@@ -43,9 +43,7 @@ struct mc13xxx {
int adcflags;
};
-int mc13xxx_common_init(struct mc13xxx *mc13xxx,
- struct mc13xxx_platform_data *pdata, int irq);
-
-void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx);
+int mc13xxx_common_init(struct device *dev);
+int mc13xxx_common_exit(struct device *dev);
#endif /* __DRIVERS_MFD_MC13XXX_H */
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 142650fdc05..90b630ccc8b 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -121,22 +121,22 @@ static u64 usbhs_dmamask = DMA_BIT_MASK(32);
static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
{
- __raw_writel(val, base + reg);
+ writel_relaxed(val, base + reg);
}
static inline u32 usbhs_read(void __iomem *base, u32 reg)
{
- return __raw_readl(base + reg);
+ return readl_relaxed(base + reg);
}
static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val)
{
- __raw_writeb(val, base + reg);
+ writeb_relaxed(val, base + reg);
}
static inline u8 usbhs_readb(void __iomem *base, u8 reg)
{
- return __raw_readb(base + reg);
+ return readb_relaxed(base + reg);
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 0d946ae1445..5ee50f779ef 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -121,22 +121,22 @@ static DEFINE_SPINLOCK(tll_lock); /* serialize access to tll_dev */
static inline void usbtll_write(void __iomem *base, u32 reg, u32 val)
{
- __raw_writel(val, base + reg);
+ writel_relaxed(val, base + reg);
}
static inline u32 usbtll_read(void __iomem *base, u32 reg)
{
- return __raw_readl(base + reg);
+ return readl_relaxed(base + reg);
}
static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val)
{
- __raw_writeb(val, base + reg);
+ writeb_relaxed(val, base + reg);
}
static inline u8 usbtll_readb(void __iomem *base, u8 reg)
{
- return __raw_readb(base + reg);
+ return readb_relaxed(base + reg);
}
/*-------------------------------------------------------------------------*/
@@ -333,21 +333,17 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
unsigned reg;
struct usbtll_omap *tll;
- spin_lock(&tll_lock);
-
- if (!tll_dev) {
- spin_unlock(&tll_lock);
+ if (!tll_dev)
return -ENODEV;
- }
- tll = dev_get_drvdata(tll_dev);
+ pm_runtime_get_sync(tll_dev);
+ spin_lock(&tll_lock);
+ tll = dev_get_drvdata(tll_dev);
needs_tll = false;
for (i = 0; i < tll->nch; i++)
needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]);
- pm_runtime_get_sync(tll_dev);
-
if (needs_tll) {
void __iomem *base = tll->base;
@@ -398,9 +394,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
}
}
- pm_runtime_put_sync(tll_dev);
-
spin_unlock(&tll_lock);
+ pm_runtime_put_sync(tll_dev);
return 0;
}
@@ -411,17 +406,14 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata)
int i;
struct usbtll_omap *tll;
- spin_lock(&tll_lock);
-
- if (!tll_dev) {
- spin_unlock(&tll_lock);
+ if (!tll_dev)
return -ENODEV;
- }
-
- tll = dev_get_drvdata(tll_dev);
pm_runtime_get_sync(tll_dev);
+ spin_lock(&tll_lock);
+ tll = dev_get_drvdata(tll_dev);
+
for (i = 0; i < tll->nch; i++) {
if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
int r;
@@ -448,13 +440,10 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
int i;
struct usbtll_omap *tll;
- spin_lock(&tll_lock);
-
- if (!tll_dev) {
- spin_unlock(&tll_lock);
+ if (!tll_dev)
return -ENODEV;
- }
+ spin_lock(&tll_lock);
tll = dev_get_drvdata(tll_dev);
for (i = 0; i < tll->nch; i++) {
@@ -464,9 +453,8 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
}
}
- pm_runtime_put_sync(tll_dev);
-
spin_unlock(&tll_lock);
+ pm_runtime_put_sync(tll_dev);
return 0;
}
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index 346330176af..df276ad9f40 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -74,7 +74,7 @@ static struct deepsleep_control_data deepsleep_data[] = {
#define EXT_PWR_REQ \
(RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
-static struct mfd_cell rc5t583_subdevs[] = {
+static const struct mfd_cell rc5t583_subdevs[] = {
{.name = "rc5t583-gpio",},
{.name = "rc5t583-regulator",},
{.name = "rc5t583-rtc", },
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index 21b7bef7350..d346146249a 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -56,7 +56,7 @@ static struct resource rdc321x_gpio_resources[] = {
}
};
-static struct mfd_cell rdc321x_sb_cells[] = {
+static const struct mfd_cell rdc321x_sb_cells[] = {
{
.name = "rdc321x-wdt",
.resources = rdc321x_wdt_resource,
@@ -96,7 +96,7 @@ static void rdc321x_sb_remove(struct pci_dev *pdev)
mfd_remove_devices(&pdev->dev);
}
-static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = {
+static const struct pci_device_id rdc321x_sb_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
{}
};
diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
index a1830986eeb..c8f345f7e9a 100644
--- a/drivers/mfd/retu-mfd.c
+++ b/drivers/mfd/retu-mfd.c
@@ -55,7 +55,7 @@ static struct resource retu_pwrbutton_res[] = {
},
};
-static struct mfd_cell retu_devs[] = {
+static const struct mfd_cell retu_devs[] = {
{
.name = "retu-wdt"
},
@@ -94,7 +94,7 @@ static struct resource tahvo_usb_res[] = {
},
};
-static struct mfd_cell tahvo_devs[] = {
+static const struct mfd_cell tahvo_devs[] = {
{
.name = "tahvo-usb",
.resources = tahvo_usb_res,
@@ -122,7 +122,7 @@ static const struct retu_data {
char *chip_name;
char *companion_name;
struct regmap_irq_chip *irq_chip;
- struct mfd_cell *children;
+ const struct mfd_cell *children;
int nchildren;
} retu_data[] = {
[0] = {
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
index 52801351864..fdd34c883d8 100644
--- a/drivers/mfd/rtl8411.c
+++ b/drivers/mfd/rtl8411.c
@@ -49,8 +49,8 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
- u32 reg1;
- u8 reg3;
+ u32 reg1 = 0;
+ u8 reg3 = 0;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
@@ -71,7 +71,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
- u32 reg;
+ u32 reg = 0;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
@@ -191,24 +191,25 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
BPP_LDO_POWB, BPP_LDO_SUSPEND);
}
-static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage,
+ int bpp_tuned18_shift, int bpp_asic_1v8)
{
u8 mask, val;
int err;
- mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
+ mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK;
if (voltage == OUTPUT_3V3) {
err = rtsx_pci_write_register(pcr,
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
if (err < 0)
return err;
- val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
+ val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3;
} else if (voltage == OUTPUT_1V8) {
err = rtsx_pci_write_register(pcr,
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
if (err < 0)
return err;
- val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
+ val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8;
} else {
return -EINVAL;
}
@@ -216,6 +217,18 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
}
+static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+ return rtl8411_do_switch_output_voltage(pcr, voltage,
+ BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8);
+}
+
+static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+ return rtl8411_do_switch_output_voltage(pcr, voltage,
+ BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0);
+}
+
static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
{
unsigned int card_exist;
@@ -295,6 +308,22 @@ static const struct pcr_ops rtl8411_pcr_ops = {
.force_power_down = rtl8411_force_power_down,
};
+static const struct pcr_ops rtl8402_pcr_ops = {
+ .fetch_vendor_settings = rtl8411_fetch_vendor_settings,
+ .extra_init_hw = rtl8411_extra_init_hw,
+ .optimize_phy = NULL,
+ .turn_on_led = rtl8411_turn_on_led,
+ .turn_off_led = rtl8411_turn_off_led,
+ .enable_auto_blink = rtl8411_enable_auto_blink,
+ .disable_auto_blink = rtl8411_disable_auto_blink,
+ .card_power_on = rtl8411_card_power_on,
+ .card_power_off = rtl8411_card_power_off,
+ .switch_output_voltage = rtl8402_switch_output_voltage,
+ .cd_deglitch = rtl8411_cd_deglitch,
+ .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
+ .force_power_down = rtl8411_force_power_down,
+};
+
static const struct pcr_ops rtl8411b_pcr_ops = {
.fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
.extra_init_hw = rtl8411b_extra_init_hw,
@@ -441,12 +470,10 @@ static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
0,
};
-void rtl8411_init_params(struct rtsx_pcr *pcr)
+static void rtl8411_init_common_params(struct rtsx_pcr *pcr)
{
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
pcr->num_slots = 2;
- pcr->ops = &rtl8411_pcr_ops;
-
pcr->flags = 0;
pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
@@ -454,47 +481,29 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
-
pcr->ic_version = rtl8411_get_ic_version(pcr);
- pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
- pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
- pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
- pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
+}
+
+void rtl8411_init_params(struct rtsx_pcr *pcr)
+{
+ rtl8411_init_common_params(pcr);
+ pcr->ops = &rtl8411_pcr_ops;
+ set_pull_ctrl_tables(pcr, rtl8411);
}
void rtl8411b_init_params(struct rtsx_pcr *pcr)
{
- pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
- pcr->num_slots = 2;
+ rtl8411_init_common_params(pcr);
pcr->ops = &rtl8411b_pcr_ops;
+ if (rtl8411b_is_qfn48(pcr))
+ set_pull_ctrl_tables(pcr, rtl8411b_qfn48);
+ else
+ set_pull_ctrl_tables(pcr, rtl8411b_qfn64);
+}
- pcr->flags = 0;
- pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
- pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
- pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
- pcr->aspm_en = ASPM_L1_EN;
- pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
- pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
-
- pcr->ic_version = rtl8411_get_ic_version(pcr);
-
- if (rtl8411b_is_qfn48(pcr)) {
- pcr->sd_pull_ctl_enable_tbl =
- rtl8411b_qfn48_sd_pull_ctl_enable_tbl;
- pcr->sd_pull_ctl_disable_tbl =
- rtl8411b_qfn48_sd_pull_ctl_disable_tbl;
- pcr->ms_pull_ctl_enable_tbl =
- rtl8411b_qfn48_ms_pull_ctl_enable_tbl;
- pcr->ms_pull_ctl_disable_tbl =
- rtl8411b_qfn48_ms_pull_ctl_disable_tbl;
- } else {
- pcr->sd_pull_ctl_enable_tbl =
- rtl8411b_qfn64_sd_pull_ctl_enable_tbl;
- pcr->sd_pull_ctl_disable_tbl =
- rtl8411b_qfn64_sd_pull_ctl_disable_tbl;
- pcr->ms_pull_ctl_enable_tbl =
- rtl8411b_qfn64_ms_pull_ctl_enable_tbl;
- pcr->ms_pull_ctl_disable_tbl =
- rtl8411b_qfn64_ms_pull_ctl_disable_tbl;
- }
+void rtl8402_init_params(struct rtsx_pcr *pcr)
+{
+ rtl8411_init_common_params(pcr);
+ pcr->ops = &rtl8402_pcr_ops;
+ set_pull_ctrl_tables(pcr, rtl8411);
}
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 705698fd2c7..1d15735f9ef 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -50,13 +50,14 @@ static struct mfd_cell rtsx_pcr_cells[] = {
},
};
-static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
+static const struct pci_device_id rtsx_pci_ids[] = {
{ PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ 0, }
};
@@ -1061,6 +1062,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
case 0x5287:
rtl8411b_init_params(pcr);
break;
+
+ case 0x5286:
+ rtl8402_init_params(pcr);
+ break;
}
dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
index 947e79b05ce..07e4c2ebf05 100644
--- a/drivers/mfd/rtsx_pcr.h
+++ b/drivers/mfd/rtsx_pcr.h
@@ -30,6 +30,7 @@
void rts5209_init_params(struct rtsx_pcr *pcr);
void rts5229_init_params(struct rtsx_pcr *pcr);
void rtl8411_init_params(struct rtsx_pcr *pcr);
+void rtl8402_init_params(struct rtsx_pcr *pcr);
void rts5227_init_params(struct rtsx_pcr *pcr);
void rts5249_init_params(struct rtsx_pcr *pcr);
void rtl8411b_init_params(struct rtsx_pcr *pcr);
@@ -63,4 +64,12 @@ static inline u8 map_sd_drive(int idx)
#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07)
#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x03)
+#define set_pull_ctrl_tables(pcr, __device) \
+do { \
+ pcr->sd_pull_ctl_enable_tbl = __device##_sd_pull_ctl_enable_tbl; \
+ pcr->sd_pull_ctl_disable_tbl = __device##_sd_pull_ctl_disable_tbl; \
+ pcr->ms_pull_ctl_enable_tbl = __device##_ms_pull_ctl_enable_tbl; \
+ pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
+} while (0)
+
#endif
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 54cc2554659..e4671088f07 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -31,7 +31,7 @@
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h>
-static struct mfd_cell s5m8751_devs[] = {
+static const struct mfd_cell s5m8751_devs[] = {
{
.name = "s5m8751-pmic",
}, {
@@ -41,7 +41,7 @@ static struct mfd_cell s5m8751_devs[] = {
},
};
-static struct mfd_cell s5m8763_devs[] = {
+static const struct mfd_cell s5m8763_devs[] = {
{
.name = "s5m8763-pmic",
}, {
@@ -51,15 +51,17 @@ static struct mfd_cell s5m8763_devs[] = {
},
};
-static struct mfd_cell s5m8767_devs[] = {
+static const struct mfd_cell s5m8767_devs[] = {
{
.name = "s5m8767-pmic",
}, {
.name = "s5m-rtc",
- },
+ }, {
+ .name = "s5m8767-clk",
+ }
};
-static struct mfd_cell s2mps11_devs[] = {
+static const struct mfd_cell s2mps11_devs[] = {
{
.name = "s2mps11-pmic",
}, {
@@ -134,12 +136,12 @@ static bool s5m8763_volatile(struct device *dev, unsigned int reg)
}
}
-static struct regmap_config sec_regmap_config = {
+static const struct regmap_config sec_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
-static struct regmap_config s2mps11_regmap_config = {
+static const struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -148,7 +150,7 @@ static struct regmap_config s2mps11_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
-static struct regmap_config s5m8763_regmap_config = {
+static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -157,7 +159,7 @@ static struct regmap_config s5m8763_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
-static struct regmap_config s5m8767_regmap_config = {
+static const struct regmap_config s5m8767_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -204,7 +206,7 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
struct device *dev)
{
- return 0;
+ return NULL;
}
#endif
@@ -323,6 +325,8 @@ static int sec_pmic_probe(struct i2c_client *i2c,
if (ret)
goto err;
+ device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
+
return ret;
err:
@@ -341,6 +345,43 @@ static int sec_pmic_remove(struct i2c_client *i2c)
return 0;
}
+static int sec_pmic_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(sec_pmic->irq);
+ /*
+ * PMIC IRQ must be disabled during suspend for RTC alarm
+ * to work properly.
+ * When device is woken up from suspend by RTC Alarm, an
+ * interrupt occurs before resuming I2C bus controller.
+ * The interrupt is handled by regmap_irq_thread which tries
+ * to read RTC registers. This read fails (I2C is still
+ * suspended) and RTC Alarm interrupt is disabled.
+ */
+ disable_irq(sec_pmic->irq);
+ }
+
+ return 0;
+}
+
+static int sec_pmic_resume(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(sec_pmic->irq);
+ enable_irq(sec_pmic->irq);
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
+
static const struct i2c_device_id sec_pmic_id[] = {
{ "sec_pmic", 0 },
{ }
@@ -351,6 +392,7 @@ static struct i2c_driver sec_pmic_driver = {
.driver = {
.name = "sec_pmic",
.owner = THIS_MODULE,
+ .pm = &sec_pmic_pm_ops,
.of_match_table = of_match_ptr(sec_dt_match),
},
.probe = sec_pmic_probe,
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index b441b1be27c..4de494f51d4 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -22,7 +22,7 @@
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
-static struct regmap_irq s2mps11_irqs[] = {
+static const struct regmap_irq s2mps11_irqs[] = {
[S2MPS11_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONF_MASK,
@@ -90,7 +90,7 @@ static struct regmap_irq s2mps11_irqs[] = {
};
-static struct regmap_irq s5m8767_irqs[] = {
+static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_PWRR_MASK,
@@ -161,7 +161,7 @@ static struct regmap_irq s5m8767_irqs[] = {
},
};
-static struct regmap_irq s5m8763_irqs[] = {
+static const struct regmap_irq s5m8763_irqs[] = {
[S5M8763_IRQ_DCINF] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_DCINF_MASK,
@@ -236,7 +236,7 @@ static struct regmap_irq s5m8763_irqs[] = {
},
};
-static struct regmap_irq_chip s2mps11_irq_chip = {
+static const struct regmap_irq_chip s2mps11_irq_chip = {
.name = "s2mps11",
.irqs = s2mps11_irqs,
.num_irqs = ARRAY_SIZE(s2mps11_irqs),
@@ -246,7 +246,7 @@ static struct regmap_irq_chip s2mps11_irq_chip = {
.ack_base = S2MPS11_REG_INT1,
};
-static struct regmap_irq_chip s5m8767_irq_chip = {
+static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767",
.irqs = s5m8767_irqs,
.num_irqs = ARRAY_SIZE(s5m8767_irqs),
@@ -256,7 +256,7 @@ static struct regmap_irq_chip s5m8767_irq_chip = {
.ack_base = S5M8767_REG_INT1,
};
-static struct regmap_irq_chip s5m8763_irq_chip = {
+static const struct regmap_irq_chip s5m8763_irq_chip = {
.name = "s5m8763",
.irqs = s5m8763_irqs,
.num_irqs = ARRAY_SIZE(s5m8763_irqs),
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index c2c8c91c6c7..e7dc441a8f8 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1710,7 +1710,7 @@ static int sm501_plat_remove(struct platform_device *dev)
return 0;
}
-static DEFINE_PCI_DEVICE_TABLE(sm501_pci_tbl) = {
+static const struct pci_device_id sm501_pci_tbl[] = {
{ 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, },
};
diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c
index 102a2284429..b78942ed4c6 100644
--- a/drivers/mfd/ssbi.c
+++ b/drivers/mfd/ssbi.c
@@ -65,13 +65,19 @@
#define SSBI_TIMEOUT_US 100
+enum ssbi_controller_type {
+ MSM_SBI_CTRL_SSBI = 0,
+ MSM_SBI_CTRL_SSBI2,
+ MSM_SBI_CTRL_PMIC_ARBITER,
+};
+
struct ssbi {
struct device *slave;
void __iomem *base;
spinlock_t lock;
enum ssbi_controller_type controller_type;
int (*read)(struct ssbi *, u16 addr, u8 *buf, int len);
- int (*write)(struct ssbi *, u16 addr, u8 *buf, int len);
+ int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len);
};
#define to_ssbi(dev) platform_get_drvdata(to_platform_device(dev))
@@ -140,7 +146,7 @@ err:
}
static int
-ssbi_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
+ssbi_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len)
{
int ret = 0;
@@ -217,7 +223,7 @@ err:
}
static int
-ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
+ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len)
{
u32 cmd;
int ret = 0;
@@ -249,7 +255,7 @@ int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len)
}
EXPORT_SYMBOL_GPL(ssbi_read);
-int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len)
+int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len)
{
struct ssbi *ssbi = to_ssbi(dev);
unsigned long flags;
@@ -311,7 +317,7 @@ static int ssbi_probe(struct platform_device *pdev)
return of_platform_populate(np, NULL, NULL, &pdev->dev);
}
-static struct of_device_id ssbi_match_table[] = {
+static const struct of_device_id ssbi_match_table[] = {
{ .compatible = "qcom,ssbi" },
{}
};
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index 65c6fa671ac..5b72db07d9d 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -339,7 +339,7 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
regmap_config->cache_type = REGCACHE_NONE;
mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
regmap_config);
- WARN_ON(!mfd->regmap[index]);
+ WARN_ON(IS_ERR(mfd->regmap[index]));
return 0;
}
@@ -529,7 +529,7 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev)
{
int err;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
err = pci_enable_device(pdev);
if (err)
return err;
@@ -642,7 +642,7 @@ err_disable:
return err;
}
-static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = {
+static const struct pci_device_id sta2x11_mfd_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
{0,},
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index fff63a41862..42ccd054451 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -297,14 +297,14 @@ static struct resource stmpe_gpio_resources[] = {
},
};
-static struct mfd_cell stmpe_gpio_cell = {
+static const struct mfd_cell stmpe_gpio_cell = {
.name = "stmpe-gpio",
.of_compatible = "st,stmpe-gpio",
.resources = stmpe_gpio_resources,
.num_resources = ARRAY_SIZE(stmpe_gpio_resources),
};
-static struct mfd_cell stmpe_gpio_cell_noirq = {
+static const struct mfd_cell stmpe_gpio_cell_noirq = {
.name = "stmpe-gpio",
.of_compatible = "st,stmpe-gpio",
/* gpio cell resources consist of an irq only so no resources here */
@@ -325,7 +325,7 @@ static struct resource stmpe_keypad_resources[] = {
},
};
-static struct mfd_cell stmpe_keypad_cell = {
+static const struct mfd_cell stmpe_keypad_cell = {
.name = "stmpe-keypad",
.of_compatible = "st,stmpe-keypad",
.resources = stmpe_keypad_resources,
@@ -409,7 +409,7 @@ static struct resource stmpe_ts_resources[] = {
},
};
-static struct mfd_cell stmpe_ts_cell = {
+static const struct mfd_cell stmpe_ts_cell = {
.name = "stmpe-ts",
.of_compatible = "st,stmpe-ts",
.resources = stmpe_ts_resources,
@@ -1064,7 +1064,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
}
-static int stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell)
+static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
NULL, stmpe->irq_base, stmpe->domain);
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index ff2b09ba879..6639f1b0fef 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -38,7 +38,7 @@ static inline void stmpe_dump_bytes(const char *str, const void *buf,
* enable and altfunc callbacks
*/
struct stmpe_variant_block {
- struct mfd_cell *cell;
+ const struct mfd_cell *cell;
int irq;
enum stmpe_block block;
};
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 87ea51dc623..2cf636c267d 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -155,7 +155,7 @@ static struct resource keypad_resources[] = {
},
};
-static struct mfd_cell tc3589x_dev_gpio[] = {
+static const struct mfd_cell tc3589x_dev_gpio[] = {
{
.name = "tc3589x-gpio",
.num_resources = ARRAY_SIZE(gpio_resources),
@@ -164,7 +164,7 @@ static struct mfd_cell tc3589x_dev_gpio[] = {
},
};
-static struct mfd_cell tc3589x_dev_keypad[] = {
+static const struct mfd_cell tc3589x_dev_keypad[] = {
{
.name = "tc3589x-keypad",
.num_resources = ARRAY_SIZE(keypad_resources),
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index acd0f3a4104..591a331d8d8 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -126,7 +126,7 @@ static struct tmio_mmc_data tc6387xb_mmc_data = {
/*--------------------------------------------------------------------------*/
-static struct mfd_cell tc6387xb_cells[] = {
+static const struct mfd_cell tc6387xb_cells[] = {
[TC6387XB_CELL_MMC] = {
.name = "tmio-mmc",
.enable = tc6387xb_mmc_enable,
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 88718abfb9b..d4e860413bb 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -24,6 +24,7 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/sched.h>
#include <linux/mfd/ti_am335x_tscadc.h>
@@ -48,32 +49,79 @@ static const struct regmap_config tscadc_regmap_config = {
.val_bits = 32,
};
-void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
+void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
{
- tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tsadc->reg_lock, flags);
+ tsadc->reg_se_cache = val;
+ if (tsadc->adc_waiting)
+ wake_up(&tsadc->reg_se_wait);
+ else if (!tsadc->adc_in_use)
+ tscadc_writel(tsadc, REG_SE, val);
+
+ spin_unlock_irqrestore(&tsadc->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
+
+static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
+{
+ DEFINE_WAIT(wait);
+ u32 reg;
+
+ /*
+ * disable TSC steps so it does not run while the ADC is using it. If
+ * write 0 while it is running (it just started or was already running)
+ * then it completes all steps that were enabled and stops then.
+ */
+ tscadc_writel(tsadc, REG_SE, 0);
+ reg = tscadc_readl(tsadc, REG_ADCFSM);
+ if (reg & SEQ_STATUS) {
+ tsadc->adc_waiting = true;
+ prepare_to_wait(&tsadc->reg_se_wait, &wait,
+ TASK_UNINTERRUPTIBLE);
+ spin_unlock_irq(&tsadc->reg_lock);
+
+ schedule();
+
+ spin_lock_irq(&tsadc->reg_lock);
+ finish_wait(&tsadc->reg_se_wait, &wait);
+
+ reg = tscadc_readl(tsadc, REG_ADCFSM);
+ WARN_ON(reg & SEQ_STATUS);
+ tsadc->adc_waiting = false;
+ }
+ tsadc->adc_in_use = true;
+}
+
+void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
+{
+ spin_lock_irq(&tsadc->reg_lock);
+ am335x_tscadc_need_adc(tsadc);
+
+ tscadc_writel(tsadc, REG_SE, val);
+ spin_unlock_irq(&tsadc->reg_lock);
}
-EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
-void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
+void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc)
{
unsigned long flags;
spin_lock_irqsave(&tsadc->reg_lock, flags);
- tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
- tsadc->reg_se_cache |= val;
- am335x_tsc_se_update(tsadc);
+ tsadc->adc_in_use = false;
+ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
}
-EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
+EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
{
unsigned long flags;
spin_lock_irqsave(&tsadc->reg_lock, flags);
- tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
tsadc->reg_se_cache &= ~val;
- am335x_tsc_se_update(tsadc);
+ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
@@ -181,6 +229,8 @@ static int ti_tscadc_probe(struct platform_device *pdev)
}
spin_lock_init(&tscadc->reg_lock);
+ init_waitqueue_head(&tscadc->reg_se_wait);
+
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
@@ -302,7 +352,6 @@ static int tscadc_resume(struct device *dev)
if (tscadc_dev->tsc_cell != -1)
tscadc_idle_config(tscadc_dev);
- am335x_tsc_se_update(tscadc_dev);
restore = tscadc_readl(tscadc_dev, REG_CTRL);
tscadc_writel(tscadc_dev, REG_CTRL,
(restore | CNTRLREG_TSCSSENB));
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index dbb34f94e5e..2bc5cfb8520 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -374,7 +374,7 @@ static const struct resource timberdale_dma_resources[] = {
},
};
-static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg0[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -431,7 +431,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
},
};
-static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg1[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -498,7 +498,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
},
};
-static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg2[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -548,7 +548,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
},
};
-static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg3[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -619,7 +619,7 @@ static const struct resource timberdale_sdhc_resources[] = {
},
};
-static struct mfd_cell timberdale_cells_bar1[] = {
+static const struct mfd_cell timberdale_cells_bar1[] = {
{
.name = "sdhci",
.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -627,7 +627,7 @@ static struct mfd_cell timberdale_cells_bar1[] = {
},
};
-static struct mfd_cell timberdale_cells_bar2[] = {
+static const struct mfd_cell timberdale_cells_bar2[] = {
{
.name = "sdhci",
.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -851,7 +851,7 @@ static void timb_remove(struct pci_dev *dev)
kfree(priv);
}
-static DEFINE_PCI_DEVICE_TABLE(timberdale_pci_tbl) = {
+static const struct pci_device_id timberdale_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
{ 0 }
};
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c
index a081b925d10..3b27482a174 100644
--- a/drivers/mfd/tps6507x.c
+++ b/drivers/mfd/tps6507x.c
@@ -24,7 +24,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/tps6507x.h>
-static struct mfd_cell tps6507x_devs[] = {
+static const struct mfd_cell tps6507x_devs[] = {
{
.name = "tps6507x-pmic",
},
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index e6f03a73387..ba1a25d758c 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -64,7 +64,7 @@ static struct resource charger_resources[] = {
}
};
-static struct mfd_cell tps65090s[] = {
+static const struct mfd_cell tps65090s[] = {
{
.name = "tps65090-pmic",
},
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index b7be0b29557..6939ae56c2e 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -30,7 +30,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/tps65217.h>
-static struct mfd_cell tps65217s[] = {
+static const struct mfd_cell tps65217s[] = {
{
.name = "tps65217-pmic",
},
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index ee61fd7c198..bbd54414a75 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -103,7 +103,7 @@ static struct resource tps6586x_rtc_resources[] = {
},
};
-static struct mfd_cell tps6586x_cell[] = {
+static const struct mfd_cell tps6586x_cell[] = {
{
.name = "tps6586x-gpio",
},
@@ -124,6 +124,7 @@ struct tps6586x {
struct device *dev;
struct i2c_client *client;
struct regmap *regmap;
+ int version;
int irq;
struct irq_chip irq_chip;
@@ -208,6 +209,14 @@ int tps6586x_irq_get_virq(struct device *dev, int irq)
}
EXPORT_SYMBOL_GPL(tps6586x_irq_get_virq);
+int tps6586x_get_version(struct device *dev)
+{
+ struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+ return tps6586x->version;
+}
+EXPORT_SYMBOL_GPL(tps6586x_get_version);
+
static int __remove_subdev(struct device *dev, void *unused)
{
platform_device_unregister(to_platform_device(dev));
@@ -472,12 +481,38 @@ static void tps6586x_power_off(void)
tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
}
+static void tps6586x_print_version(struct i2c_client *client, int version)
+{
+ const char *name;
+
+ switch (version) {
+ case TPS658621A:
+ name = "TPS658621A";
+ break;
+ case TPS658621CD:
+ name = "TPS658621C/D";
+ break;
+ case TPS658623:
+ name = "TPS658623";
+ break;
+ case TPS658643:
+ name = "TPS658643";
+ break;
+ default:
+ name = "TPS6586X";
+ break;
+ }
+
+ dev_info(&client->dev, "Found %s, VERSIONCRC is %02x\n", name, version);
+}
+
static int tps6586x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev);
struct tps6586x *tps6586x;
int ret;
+ int version;
if (!pdata && client->dev.of_node)
pdata = tps6586x_parse_dt(client);
@@ -487,19 +522,18 @@ static int tps6586x_i2c_probe(struct i2c_client *client,
return -ENOTSUPP;
}
- ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
- if (ret < 0) {
- dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
+ version = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
+ if (version < 0) {
+ dev_err(&client->dev, "Chip ID read failed: %d\n", version);
return -EIO;
}
- dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
-
tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL);
- if (tps6586x == NULL) {
- dev_err(&client->dev, "memory for tps6586x alloc failed\n");
+ if (!tps6586x)
return -ENOMEM;
- }
+
+ tps6586x->version = version;
+ tps6586x_print_version(client, tps6586x->version);
tps6586x->client = client;
tps6586x->dev = &client->dev;
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index c0f608e3ca9..1f142d76cbb 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -36,7 +36,7 @@ static struct resource rtc_resources[] = {
}
};
-static struct mfd_cell tps65910s[] = {
+static const struct mfd_cell tps65910s[] = {
{
.name = "tps65910-gpio",
},
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
index 925a044cbdf..27a518e0eec 100644
--- a/drivers/mfd/tps65912-core.c
+++ b/drivers/mfd/tps65912-core.c
@@ -21,7 +21,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/tps65912.h>
-static struct mfd_cell tps65912s[] = {
+static const struct mfd_cell tps65912s[] = {
{
.name = "tps65912-pmic",
},
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index f15ee6d5cfb..ed6c5b0956e 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -44,7 +44,7 @@ static struct resource tps80031_rtc_resources[] = {
};
/* TPS80031 sub mfd devices */
-static struct mfd_cell tps80031_cell[] = {
+static const struct mfd_cell tps80031_cell[] = {
{
.name = "tps80031-pmic",
},
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 6ef7685a4cf..ed718328eff 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -837,62 +837,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
usb3v1[0].dev_name = dev_name(child);
}
}
- if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb &&
- twl_class_is_6030()) {
-
- static struct regulator_consumer_supply usb3v3;
- int regulator;
-
- if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
- /* this is a template that gets copied */
- struct regulator_init_data usb_fixed = {
- .constraints.valid_modes_mask =
- REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .constraints.valid_ops_mask =
- REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- };
-
- if (features & TWL6032_SUBCLASS) {
- usb3v3.supply = "ldousb";
- regulator = TWL6032_REG_LDOUSB;
- } else {
- usb3v3.supply = "vusb";
- regulator = TWL6030_REG_VUSB;
- }
- child = add_regulator_linked(regulator, &usb_fixed,
- &usb3v3, 1,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
- }
-
- pdata->usb->features = features;
-
- child = add_child(TWL_MODULE_USB, "twl6030_usb",
- pdata->usb, sizeof(*pdata->usb), true,
- /* irq1 = VBUS_PRES, irq0 = USB ID */
- irq_base + USBOTG_INTR_OFFSET,
- irq_base + USB_PRES_INTR_OFFSET);
-
- if (IS_ERR(child))
- return PTR_ERR(child);
- /* we need to connect regulators to this transceiver */
- if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child)
- usb3v3.dev_name = dev_name(child);
- } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
- twl_class_is_6030()) {
- if (features & TWL6032_SUBCLASS)
- child = add_regulator(TWL6032_REG_LDOUSB,
- pdata->ldousb, features);
- else
- child = add_regulator(TWL6030_REG_VUSB,
- pdata->vusb, features);
-
- if (IS_ERR(child))
- return PTR_ERR(child);
- }
if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
@@ -1006,148 +950,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
return PTR_ERR(child);
}
- /* twl6030 regulators */
- if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
- !(features & TWL6032_SUBCLASS)) {
- child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_V1V8, pdata->v1v8,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
- }
-
- /* 6030 and 6025 share this regulator */
- if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) {
- child = add_regulator(TWL6030_REG_VANA, pdata->vana,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
- }
-
- /* twl6032 regulators */
- if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
- (features & TWL6032_SUBCLASS)) {
- child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- child = add_regulator(TWL6032_REG_VIO, pdata->vio6025,
- features);
- if (IS_ERR(child))
- return PTR_ERR(child);
-
- }
-
if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
!(features & (TPS_SUBSET | TWL5031))) {
child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
@@ -1269,6 +1071,11 @@ static int twl_remove(struct i2c_client *client)
return 0;
}
+static struct of_dev_auxdata twl_auxdata_lookup[] = {
+ OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
+ { /* sentinel */ },
+};
+
/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
static int
twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -1407,10 +1214,14 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
}
- if (node)
- status = of_platform_populate(node, NULL, NULL, &client->dev);
- else
+ if (node) {
+ if (pdata)
+ twl_auxdata_lookup[0].platform_data = pdata->gpio;
+ status = of_platform_populate(node, NULL, twl_auxdata_lookup,
+ &client->dev);
+ } else {
status = add_children(pdata, irq_base, id->driver_data);
+ }
fail:
if (status < 0)
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 517eda832f7..18a607e2ca0 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -176,8 +176,9 @@ static irqreturn_t twl6030_irq_thread(int irq, void *data)
int i, ret;
union {
u8 bytes[4];
- u32 int_sts;
+ __le32 int_sts;
} sts;
+ u32 int_sts; /* sts.int_sts converted to CPU endianness */
struct twl6030_irq *pdata = data;
/* read INT_STS_A, B and C in one shot using a burst read */
@@ -196,8 +197,9 @@ static irqreturn_t twl6030_irq_thread(int irq, void *data)
if (sts.bytes[2] & 0x10)
sts.bytes[2] |= 0x08;
- for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++)
- if (sts.int_sts & 0x1) {
+ int_sts = le32_to_cpu(sts.int_sts);
+ for (i = 0; int_sts; int_sts >>= 1, i++)
+ if (int_sts & 0x1) {
int module_irq =
irq_find_mapping(pdata->irq_domain,
pdata->irq_mapping_tbl[i]);
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index 51b6df1a794..75316fb3344 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -86,7 +86,7 @@ static struct reg_default twl6040_defaults[] = {
{ 0x2E, 0x00 }, /* REG_STATUS (ro) */
};
-struct reg_default twl6040_patch[] = {
+static struct reg_default twl6040_patch[] = {
/* Select I2C bus access to dual access registers */
{ TWL6040_REG_ACCCTL, 0x09 },
};
diff --git a/drivers/mfd/viperboard.c b/drivers/mfd/viperboard.c
index af2a6703f34..e00f5340ed8 100644
--- a/drivers/mfd/viperboard.c
+++ b/drivers/mfd/viperboard.c
@@ -37,7 +37,7 @@ static const struct usb_device_id vprbrd_table[] = {
MODULE_DEVICE_TABLE(usb, vprbrd_table);
-static struct mfd_cell vprbrd_devs[] = {
+static const struct mfd_cell vprbrd_devs[] = {
{
.name = "viperboard-gpio",
},
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
index 757ecc63338..84f01da4875 100644
--- a/drivers/mfd/vx855.c
+++ b/drivers/mfd/vx855.c
@@ -60,7 +60,7 @@ static struct resource vx855_gpio_resources[] = {
},
};
-static struct mfd_cell vx855_cells[] = {
+static const struct mfd_cell vx855_cells[] = {
{
.name = "vx855_gpio",
.num_resources = ARRAY_SIZE(vx855_gpio_resources),
@@ -118,7 +118,7 @@ static void vx855_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(vx855_pci_tbl) = {
+static const struct pci_device_id vx855_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
{ 0, }
};
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 4a4432eb499..11632f135e8 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -224,6 +224,31 @@ static const struct reg_default wm5110_revb_patch[] = {
{ 0x80, 0x0 },
};
+static const struct reg_default wm5110_revd_patch[] = {
+ { 0x80, 0x3 },
+ { 0x80, 0x3 },
+ { 0x393, 0x27 },
+ { 0x394, 0x27 },
+ { 0x395, 0x27 },
+ { 0x396, 0x27 },
+ { 0x397, 0x27 },
+ { 0x398, 0x26 },
+ { 0x221, 0x90 },
+ { 0x211, 0x8 },
+ { 0x36c, 0x1fb },
+ { 0x26e, 0x64 },
+ { 0x26f, 0xea },
+ { 0x270, 0x1f16 },
+ { 0x51b, 0x1 },
+ { 0x55b, 0x1 },
+ { 0x59b, 0x1 },
+ { 0x4f0, 0x633 },
+ { 0x441, 0xc059 },
+ { 0x209, 0x27 },
+ { 0x80, 0x0 },
+ { 0x80, 0x0 },
+};
+
/* We use a function so we can use ARRAY_SIZE() */
int wm5110_patch(struct arizona *arizona)
{
@@ -236,7 +261,10 @@ int wm5110_patch(struct arizona *arizona)
return regmap_register_patch(arizona->regmap,
wm5110_revb_patch,
ARRAY_SIZE(wm5110_revb_patch));
-
+ case 3:
+ return regmap_register_patch(arizona->regmap,
+ wm5110_revd_patch,
+ ARRAY_SIZE(wm5110_revd_patch));
default:
return 0;
}
@@ -505,7 +533,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
{ 0x00000210, 0x0184 }, /* R528 - LDO1 Control 1 */
- { 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */
+ { 0x00000213, 0x03E4 }, /* R531 - LDO2 Control 1 */
{ 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */
{ 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 5c459f46922..28366a90e1a 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1011,7 +1011,7 @@ static struct resource wm831x_wdt_resources[] = {
},
};
-static struct mfd_cell wm8310_devs[] = {
+static const struct mfd_cell wm8310_devs[] = {
{
.name = "wm831x-backup",
},
@@ -1165,7 +1165,7 @@ static struct mfd_cell wm8310_devs[] = {
},
};
-static struct mfd_cell wm8311_devs[] = {
+static const struct mfd_cell wm8311_devs[] = {
{
.name = "wm831x-backup",
},
@@ -1295,7 +1295,7 @@ static struct mfd_cell wm8311_devs[] = {
},
};
-static struct mfd_cell wm8312_devs[] = {
+static const struct mfd_cell wm8312_devs[] = {
{
.name = "wm831x-backup",
},
@@ -1449,7 +1449,7 @@ static struct mfd_cell wm8312_devs[] = {
},
};
-static struct mfd_cell wm8320_devs[] = {
+static const struct mfd_cell wm8320_devs[] = {
{
.name = "wm831x-backup",
},
@@ -1578,7 +1578,7 @@ static struct mfd_cell wm8320_devs[] = {
},
};
-static struct mfd_cell touch_devs[] = {
+static const struct mfd_cell touch_devs[] = {
{
.name = "wm831x-touch",
.num_resources = ARRAY_SIZE(wm831x_touch_resources),
@@ -1586,7 +1586,7 @@ static struct mfd_cell touch_devs[] = {
},
};
-static struct mfd_cell rtc_devs[] = {
+static const struct mfd_cell rtc_devs[] = {
{
.name = "wm831x-rtc",
.num_resources = ARRAY_SIZE(wm831x_rtc_resources),
@@ -1594,7 +1594,7 @@ static struct mfd_cell rtc_devs[] = {
},
};
-static struct mfd_cell backlight_devs[] = {
+static const struct mfd_cell backlight_devs[] = {
{
.name = "wm831x-backlight",
},
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index 2b29caebc9c..a4cbefe5430 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -64,11 +64,13 @@ static int wm831x_i2c_suspend(struct device *dev)
return wm831x_device_suspend(wm831x);
}
-static void wm831x_i2c_shutdown(struct i2c_client *i2c)
+static int wm831x_i2c_poweroff(struct device *dev)
{
- struct wm831x *wm831x = i2c_get_clientdata(i2c);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
wm831x_device_shutdown(wm831x);
+
+ return 0;
}
static const struct i2c_device_id wm831x_i2c_id[] = {
@@ -85,6 +87,7 @@ MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
static const struct dev_pm_ops wm831x_pm_ops = {
.suspend = wm831x_i2c_suspend,
+ .poweroff = wm831x_i2c_poweroff,
};
static struct i2c_driver wm831x_i2c_driver = {
@@ -95,7 +98,6 @@ static struct i2c_driver wm831x_i2c_driver = {
},
.probe = wm831x_i2c_probe,
.remove = wm831x_i2c_remove,
- .shutdown = wm831x_i2c_shutdown,
.id_table = wm831x_i2c_id,
};
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 07de3cc5a0d..b8a5e3b34ec 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -66,16 +66,19 @@ static int wm831x_spi_suspend(struct device *dev)
return wm831x_device_suspend(wm831x);
}
-static void wm831x_spi_shutdown(struct spi_device *spi)
+static int wm831x_spi_poweroff(struct device *dev)
{
- struct wm831x *wm831x = spi_get_drvdata(spi);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
wm831x_device_shutdown(wm831x);
+
+ return 0;
}
static const struct dev_pm_ops wm831x_spi_pm = {
.freeze = wm831x_spi_suspend,
.suspend = wm831x_spi_suspend,
+ .poweroff = wm831x_spi_poweroff,
};
static const struct spi_device_id wm831x_spi_ids[] = {
@@ -99,7 +102,6 @@ static struct spi_driver wm831x_spi_driver = {
.id_table = wm831x_spi_ids,
.probe = wm831x_spi_probe,
.remove = wm831x_spi_remove,
- .shutdown = wm831x_spi_shutdown,
};
static int __init wm831x_spi_init(void)
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 03082751166..ba04f1bc70e 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -33,7 +33,7 @@
#include "wm8994.h"
-static struct mfd_cell wm8994_regulator_devs[] = {
+static const struct mfd_cell wm8994_regulator_devs[] = {
{
.name = "wm8994-ldo",
.id = 1,
@@ -62,7 +62,7 @@ static struct resource wm8994_gpio_resources[] = {
},
};
-static struct mfd_cell wm8994_devs[] = {
+static const struct mfd_cell wm8994_devs[] = {
{
.name = "wm8994-codec",
.num_resources = ARRAY_SIZE(wm8994_codec_resources),
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c
index 5183e7bb8de..163da9c3ea0 100644
--- a/drivers/pinctrl/pinctrl-abx500.c
+++ b/drivers/pinctrl/pinctrl-abx500.c
@@ -24,7 +24,6 @@
#include <linux/bitops.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinmux.h>
@@ -1218,21 +1217,15 @@ static const struct of_device_id abx500_gpio_match[] = {
static int abx500_gpio_probe(struct platform_device *pdev)
{
- struct ab8500_platform_data *abx500_pdata =
- dev_get_platdata(pdev->dev.parent);
- struct abx500_gpio_platform_data *pdata = NULL;
struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
struct abx500_pinctrl *pct;
- const struct platform_device_id *platid = platform_get_device_id(pdev);
unsigned int id = -1;
int ret, err;
int i;
- if (abx500_pdata)
- pdata = abx500_pdata->gpio;
-
- if (!(pdata || np)) {
- dev_err(&pdev->dev, "gpio dt and platform data missing\n");
+ if (!np) {
+ dev_err(&pdev->dev, "gpio dt node missing\n");
return -ENODEV;
}
@@ -1248,17 +1241,14 @@ static int abx500_gpio_probe(struct platform_device *pdev)
pct->parent = dev_get_drvdata(pdev->dev.parent);
pct->chip = abx500gpio_chip;
pct->chip.dev = &pdev->dev;
- pct->chip.base = (np) ? -1 : pdata->gpio_base;
-
- if (platid)
- id = platid->driver_data;
- else if (np) {
- const struct of_device_id *match;
+ pct->chip.base = -1; /* Dynamic allocation */
- match = of_match_device(abx500_gpio_match, &pdev->dev);
- if (match)
- id = (unsigned long)match->data;
+ match = of_match_device(abx500_gpio_match, &pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "gpio dt not matching\n");
+ return -ENODEV;
}
+ id = (unsigned long)match->data;
/* Poke in other ASIC variants here */
switch (id) {
@@ -1349,14 +1339,6 @@ static int abx500_gpio_remove(struct platform_device *pdev)
return 0;
}
-static const struct platform_device_id abx500_pinctrl_id[] = {
- { "pinctrl-ab8500", PINCTRL_AB8500 },
- { "pinctrl-ab8540", PINCTRL_AB8540 },
- { "pinctrl-ab9540", PINCTRL_AB9540 },
- { "pinctrl-ab8505", PINCTRL_AB8505 },
- { },
-};
-
static struct platform_driver abx500_gpio_driver = {
.driver = {
.name = "abx500-gpio",
@@ -1365,7 +1347,6 @@ static struct platform_driver abx500_gpio_driver = {
},
.probe = abx500_gpio_probe,
.remove = abx500_gpio_remove,
- .id_table = abx500_pinctrl_id,
};
static int __init abx500_gpio_init(void)
diff --git a/drivers/pinctrl/pinctrl-abx500.h b/drivers/pinctrl/pinctrl-abx500.h
index 82293806e84..2beef3bfe9c 100644
--- a/drivers/pinctrl/pinctrl-abx500.h
+++ b/drivers/pinctrl/pinctrl-abx500.h
@@ -15,6 +15,18 @@ enum abx500_pin_func {
ABX500_ALT_C,
};
+enum abx500_gpio_pull_updown {
+ ABX500_GPIO_PULL_DOWN = 0x0,
+ ABX500_GPIO_PULL_NONE = 0x1,
+ ABX500_GPIO_PULL_UP = 0x3,
+};
+
+enum abx500_gpio_vinsel {
+ ABX500_GPIO_VINSEL_VBAT = 0x0,
+ ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
+ ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
+};
+
/**
* struct abx500_function - ABx500 pinctrl mux function
* @name: The name of the function, exported to pinctrl core.
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index eece329d787..7acab93d5a4 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -90,6 +90,16 @@ config PWM_JZ4740
To compile this driver as a module, choose M here: the module
will be called pwm-jz4740.
+config PWM_LP3943
+ tristate "TI/National Semiconductor LP3943 PWM support"
+ depends on MFD_LP3943
+ help
+ Generic PWM framework driver for LP3943 which supports two PWM
+ channels.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-lp3943.
+
config PWM_LPC32XX
tristate "LPC32XX PWM support"
depends on ARCH_LPC32XX
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 8b754e4dba4..4abf337dcd0 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
+obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o
obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
new file mode 100644
index 00000000000..8a843a04c22
--- /dev/null
+++ b/drivers/pwm/pwm-lp3943.c
@@ -0,0 +1,314 @@
+/*
+ * TI/National Semiconductor LP3943 PWM driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.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; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define LP3943_MAX_DUTY 255
+#define LP3943_MIN_PERIOD 6250
+#define LP3943_MAX_PERIOD 1600000
+
+struct lp3943_pwm {
+ struct pwm_chip chip;
+ struct lp3943 *lp3943;
+ struct lp3943_platform_data *pdata;
+};
+
+static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip)
+{
+ return container_of(_chip, struct lp3943_pwm, chip);
+}
+
+static struct lp3943_pwm_map *
+lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
+{
+ struct lp3943_platform_data *pdata = lp3943_pwm->pdata;
+ struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+ struct lp3943_pwm_map *pwm_map;
+ int i, offset;
+
+ pwm_map = kzalloc(sizeof(*pwm_map), GFP_KERNEL);
+ if (!pwm_map)
+ return ERR_PTR(-ENOMEM);
+
+ pwm_map->output = pdata->pwms[hwpwm]->output;
+ pwm_map->num_outputs = pdata->pwms[hwpwm]->num_outputs;
+
+ for (i = 0; i < pwm_map->num_outputs; i++) {
+ offset = pwm_map->output[i];
+
+ /* Return an error if the pin is already assigned */
+ if (test_and_set_bit(offset, &lp3943->pin_used))
+ return ERR_PTR(-EBUSY);
+ }
+
+ return pwm_map;
+}
+
+static int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+ struct lp3943_pwm_map *pwm_map;
+
+ pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm);
+ if (IS_ERR(pwm_map))
+ return PTR_ERR(pwm_map);
+
+ return pwm_set_chip_data(pwm, pwm_map);
+}
+
+static void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm,
+ struct lp3943_pwm_map *pwm_map)
+{
+ struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+ int i, offset;
+
+ for (i = 0; i < pwm_map->num_outputs; i++) {
+ offset = pwm_map->output[i];
+ clear_bit(offset, &lp3943->pin_used);
+ }
+
+ kfree(pwm_map);
+}
+
+static void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+ struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
+
+ lp3943_pwm_free_map(lp3943_pwm, pwm_map);
+}
+
+static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+ struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+ u8 val, reg_duty, reg_prescale;
+ int err;
+
+ /*
+ * How to configure the LP3943 PWMs
+ *
+ * 1) Period = 6250 ~ 1600000
+ * 2) Prescale = period / 6250 -1
+ * 3) Duty = input duty
+ *
+ * Prescale and duty are register values
+ */
+
+ if (pwm->hwpwm == 0) {
+ reg_prescale = LP3943_REG_PRESCALE0;
+ reg_duty = LP3943_REG_PWM0;
+ } else {
+ reg_prescale = LP3943_REG_PRESCALE1;
+ reg_duty = LP3943_REG_PWM1;
+ }
+
+ period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD);
+ val = (u8)(period_ns / LP3943_MIN_PERIOD - 1);
+
+ err = lp3943_write_byte(lp3943, reg_prescale, val);
+ if (err)
+ return err;
+
+ val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
+
+ return lp3943_write_byte(lp3943, reg_duty, val);
+}
+
+static int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm,
+ struct lp3943_pwm_map *pwm_map,
+ u8 val)
+{
+ struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+ const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+ int i, index, err;
+
+ for (i = 0; i < pwm_map->num_outputs; i++) {
+ index = pwm_map->output[i];
+ err = lp3943_update_bits(lp3943, mux[index].reg,
+ mux[index].mask,
+ val << mux[index].shift);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+ struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
+ u8 val;
+
+ if (pwm->hwpwm == 0)
+ val = LP3943_DIM_PWM0;
+ else
+ val = LP3943_DIM_PWM1;
+
+ /*
+ * Each PWM generator is set to control any of outputs of LP3943.
+ * To enable/disable the PWM, these output pins should be configured.
+ */
+
+ return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val);
+}
+
+static void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+ struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
+
+ /*
+ * LP3943 outputs are open-drain, so the pin should be configured
+ * when the PWM is disabled.
+ */
+
+ lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH);
+}
+
+static const struct pwm_ops lp3943_pwm_ops = {
+ .request = lp3943_pwm_request,
+ .free = lp3943_pwm_free,
+ .config = lp3943_pwm_config,
+ .enable = lp3943_pwm_enable,
+ .disable = lp3943_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static int lp3943_pwm_parse_dt(struct device *dev,
+ struct lp3943_pwm *lp3943_pwm)
+{
+ static const char * const name[] = { "ti,pwm0", "ti,pwm1", };
+ struct device_node *node = dev->of_node;
+ struct lp3943_platform_data *pdata;
+ struct lp3943_pwm_map *pwm_map;
+ enum lp3943_pwm_output *output;
+ int i, err, proplen, count = 0;
+ u32 num_outputs;
+
+ if (!node)
+ return -EINVAL;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ /*
+ * Read the output map configuration from the device tree.
+ * Each of the two PWM generators can drive zero or more outputs.
+ */
+
+ for (i = 0; i < LP3943_NUM_PWMS; i++) {
+ if (!of_get_property(node, name[i], &proplen))
+ continue;
+
+ num_outputs = proplen / sizeof(u32);
+ if (num_outputs == 0)
+ continue;
+
+ output = devm_kzalloc(dev, sizeof(*output) * num_outputs,
+ GFP_KERNEL);
+ if (!output)
+ return -ENOMEM;
+
+ err = of_property_read_u32_array(node, name[i], output,
+ num_outputs);
+ if (err)
+ return err;
+
+ pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL);
+ if (!pwm_map)
+ return -ENOMEM;
+
+ pwm_map->output = output;
+ pwm_map->num_outputs = num_outputs;
+ pdata->pwms[i] = pwm_map;
+
+ count++;
+ }
+
+ if (count == 0)
+ return -ENODATA;
+
+ lp3943_pwm->pdata = pdata;
+ return 0;
+}
+
+static int lp3943_pwm_probe(struct platform_device *pdev)
+{
+ struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
+ struct lp3943_pwm *lp3943_pwm;
+ int ret;
+
+ lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL);
+ if (!lp3943_pwm)
+ return -ENOMEM;
+
+ lp3943_pwm->pdata = lp3943->pdata;
+ if (!lp3943_pwm->pdata) {
+ if (IS_ENABLED(CONFIG_OF))
+ ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm);
+ else
+ ret = -ENODEV;
+
+ if (ret)
+ return ret;
+ }
+
+ lp3943_pwm->lp3943 = lp3943;
+ lp3943_pwm->chip.dev = &pdev->dev;
+ lp3943_pwm->chip.ops = &lp3943_pwm_ops;
+ lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
+
+ platform_set_drvdata(pdev, lp3943_pwm);
+
+ return pwmchip_add(&lp3943_pwm->chip);
+}
+
+static int lp3943_pwm_remove(struct platform_device *pdev)
+{
+ struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev);
+
+ return pwmchip_remove(&lp3943_pwm->chip);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id lp3943_pwm_of_match[] = {
+ { .compatible = "ti,lp3943-pwm", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
+#endif
+
+static struct platform_driver lp3943_pwm_driver = {
+ .probe = lp3943_pwm_probe,
+ .remove = lp3943_pwm_remove,
+ .driver = {
+ .name = "lp3943-pwm",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lp3943_pwm_of_match),
+ },
+};
+module_platform_driver(lp3943_pwm_driver);
+
+MODULE_DESCRIPTION("LP3943 PWM driver");
+MODULE_ALIAS("platform:lp3943-pwm");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index ce785f48128..db9ae6fa240 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -343,7 +343,7 @@ config REGULATOR_MC13XXX_CORE
config REGULATOR_MC13783
tristate "Freescale MC13783 regulator driver"
- depends on MFD_MC13783
+ depends on MFD_MC13XXX
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13783
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index e8e3a8afd3e..0485d47f0d8 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -93,6 +93,8 @@ static const unsigned int tps6586x_ldo4_voltages[] = {
2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
};
+#define tps658623_sm2_voltages tps6586x_ldo4_voltages
+
static const unsigned int tps6586x_ldo_voltages[] = {
1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
};
@@ -104,6 +106,13 @@ static const unsigned int tps6586x_sm2_voltages[] = {
4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
};
+static const unsigned int tps658643_sm2_voltages[] = {
+ 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000,
+ 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000,
+ 1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000,
+ 1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000,
+};
+
static const unsigned int tps6586x_dvm_voltages[] = {
725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
@@ -119,8 +128,8 @@ static const unsigned int tps6586x_dvm_voltages[] = {
.ops = &tps6586x_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = TPS6586X_ID_##_id, \
- .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \
- .volt_table = tps6586x_##vdata##_voltages, \
+ .n_voltages = ARRAY_SIZE(vdata##_voltages), \
+ .volt_table = vdata##_voltages, \
.owner = THIS_MODULE, \
.enable_reg = TPS6586X_SUPPLY##ereg0, \
.enable_mask = 1 << (ebit0), \
@@ -162,27 +171,47 @@ static const unsigned int tps6586x_dvm_voltages[] = {
static struct tps6586x_regulator tps6586x_regulator[] = {
TPS6586X_SYS_REGULATOR(),
- TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
- TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
- TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
- TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
- TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
- TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
- TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
- TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
- TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
- TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
-
- TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
+ TPS6586X_LDO(LDO_0, "vinldo01", tps6586x_ldo0, SUPPLYV1, 5, 3, ENC, 0,
+ END, 0),
+ TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo, SUPPLYV4, 0, 3, ENC, 2,
+ END, 2),
+ TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo, SUPPLYV6, 0, 3, ENE, 6,
+ ENE, 6),
+ TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo, SUPPLYV3, 0, 3, ENC, 4,
+ END, 4),
+ TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo, SUPPLYV3, 3, 3, ENC, 5,
+ END, 5),
+ TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo, SUPPLYV2, 5, 3, ENC, 6,
+ END, 6),
+ TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo, SUPPLYV6, 3, 3, ENE, 7,
+ ENE, 7),
+ TPS6586X_LDO(LDO_RTC, "REG-SYS", tps6586x_ldo, SUPPLYV4, 3, 3, V4, 7,
+ V4, 7),
+ TPS6586X_LDO(LDO_1, "vinldo01", tps6586x_dvm, SUPPLYV1, 0, 5, ENC, 1,
+ END, 1),
+ TPS6586X_LDO(SM_2, "vin-sm2", tps6586x_sm2, SUPPLYV2, 0, 5, ENC, 7,
+ END, 7),
+
+ TPS6586X_DVM(LDO_2, "vinldo23", tps6586x_dvm, LDO2BV1, 0, 5, ENA, 3,
ENB, 3, TPS6586X_VCC2, BIT(6)),
- TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
+ TPS6586X_DVM(LDO_4, "vinldo4", tps6586x_ldo4, LDO4V1, 0, 5, ENC, 3,
END, 3, TPS6586X_VCC1, BIT(6)),
- TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1,
+ TPS6586X_DVM(SM_0, "vin-sm0", tps6586x_dvm, SM0V1, 0, 5, ENA, 1,
ENB, 1, TPS6586X_VCC1, BIT(2)),
- TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0,
+ TPS6586X_DVM(SM_1, "vin-sm1", tps6586x_dvm, SM1V1, 0, 5, ENA, 0,
ENB, 0, TPS6586X_VCC1, BIT(0)),
};
+static struct tps6586x_regulator tps658623_regulator[] = {
+ TPS6586X_LDO(SM_2, "vin-sm2", tps658623_sm2, SUPPLYV2, 0, 5, ENC, 7,
+ END, 7),
+};
+
+static struct tps6586x_regulator tps658643_regulator[] = {
+ TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7,
+ END, 7),
+};
+
/*
* TPS6586X has 2 enable bits that are OR'ed to determine the actual
* regulator state. Clearing one of this bits allows switching
@@ -254,11 +283,33 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
}
-static inline struct tps6586x_regulator *find_regulator_info(int id)
+static struct tps6586x_regulator *find_regulator_info(int id, int version)
{
struct tps6586x_regulator *ri;
+ struct tps6586x_regulator *table = NULL;
+ int num;
int i;
+ switch (version) {
+ case TPS658623:
+ table = tps658623_regulator;
+ num = ARRAY_SIZE(tps658623_regulator);
+ break;
+ case TPS658643:
+ table = tps658643_regulator;
+ num = ARRAY_SIZE(tps658643_regulator);
+ break;
+ }
+
+ /* Search version specific table first */
+ if (table) {
+ for (i = 0; i < num; i++) {
+ ri = &table[i];
+ if (ri->desc.id == id)
+ return ri;
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
ri = &tps6586x_regulator[i];
if (ri->desc.id == id)
@@ -351,6 +402,7 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
struct regulator_init_data *reg_data;
struct tps6586x_platform_data *pdata;
struct of_regulator_match *tps6586x_reg_matches = NULL;
+ int version;
int id;
int err;
@@ -373,10 +425,13 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ version = tps6586x_get_version(pdev->dev.parent);
+
for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
reg_data = pdata->reg_init_data[id];
- ri = find_regulator_info(id);
+ ri = find_regulator_info(id, version);
+
if (!ri) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
return -EINVAL;