diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-08 23:07:52 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-08 23:07:52 +0300 |
commit | 3a9b0a46e1708b6b3c298f2cf22923cc5a2ca63f (patch) | |
tree | 144677dc0c9012808297820e54eee9dd81b46129 /drivers | |
parent | d20f7a09e5eeeeef5db679adc9a490fecb6a4c87 (diff) | |
parent | 5dc6dafe62099ade0e7232ce9db4013b7673d860 (diff) | |
download | linux-3a9b0a46e1708b6b3c298f2cf22923cc5a2ca63f.tar.xz |
Merge tag 'mfd-next-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Removed Drivers:
- Remove support for TI TPS80031/TPS80032 PMICs
New Device Support:
- Add support for Magnetic Reader to TI AM335x
- Add support for DA9063_EA to Dialog DA9063
- Add support for SC2730 PMIC to Spreadtrum SC27xx
- Add support for MacBookPro16,2 ICL-N UART Intel LPSS PCI
- Add support for lots of new PMICS in QCom SPMI PMIC
- Add support for ADC to Diolan DLN2
New Functionality:
- Add support for Power Off to Rockchip RK817
Fix-ups:
- Simplify Regmap passing to child devices in hi6421-spmi-pmic
- SPDX licensing updates in ti_am335x_tscadc
- Improve error handling in ti_am335x_tscadc
- Expedite clock search in ti_am335x_tscadc
- Generic simplifications in ti_am335x_tscadc
- Use generic macros/defines in ti_am335x_tscadc
- Remove unused code in ti_am335x_tscadc, cros_ec_dev
- Convert to GPIOD in wcd934x
- Add namespacing in ti_am335x_tscadc
- Restrict compilation to relevant arches in intel_pmt
- Provide better description/documentation in exynos_lpass
- Add SPI device ID table in altera-a10sr, motorola-cpcap,
sprd-sc27xx-spi
- Change IRQ handling in qcom-pm8xxx
- Split out I2C and SPI code in arizona
- Explicitly include used headers in altera-a10sr
- Convert sysfs show() function to in sysfs_emit
- Standardise *_exit() and *_remove() return values in mc13xxx,
stmpe, tps65912
- Trivial (style/spelling/whitespace) fixups in ti_am335x_tscadc,
qcom-spmi-pmic, max77686-private
- Device Tree fix-ups in ti,am3359-tscadc, samsung,s2mps11,
samsung,s2mpa01, samsung,s5m8767, brcm,misc, brcm,cru, syscon,
qcom,tcsr, xylon,logicvc, max77686, x-powers,ac100,
x-powers,axp152, x-powers,axp209-gpio, syscon, qcom,spmi-pmic
Bug Fixes:
- Balance refcounting (get/put) in ti_am335x_tscadc, mfd-core
- Fix IRQ trigger type in sec-irq, max77693, max14577
- Repair off-by-one in altera-sysmgr
- Add explicit 'select MFD_CORE' to MFD_SIMPLE_MFD_I2C"
* tag 'mfd-next-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (95 commits)
mfd: simple-mfd-i2c: Select MFD_CORE to fix build error
mfd: tps80031: Remove driver
mfd: max77686: Correct tab-based alignment of register addresses
mfd: wcd934x: Replace legacy gpio interface for gpiod
dt-bindings: mfd: qcom: pm8xxx: Add pm8018 compatible
mfd: dln2: Add cell for initializing DLN2 ADC
mfd: qcom-spmi-pmic: Add missing PMICs supported by socinfo
mfd: qcom-spmi-pmic: Document ten more PMICs in the binding
mfd: qcom-spmi-pmic: Sort compatibles in the driver
mfd: qcom-spmi-pmic: Sort the compatibles in the binding
mfd: janz-cmoio: Replace snprintf in show functions with sysfs_emit
mfd: altera-a10sr: Include linux/module.h
mfd: tps65912: Make tps65912_device_exit() return void
mfd: stmpe: Make stmpe_remove() return void
mfd: mc13xxx: Make mc13xxx_common_exit() return void
dt-bindings: mfd: syscon: Add samsung,exynosautov9-sysreg compatible
mfd: altera-sysmgr: Fix a mistake caused by resource_size conversion
dt-bindings: gpio: Convert X-Powers AXP209 GPIO binding to a schema
dt-bindings: mfd: syscon: Add rk3368 QoS register compatible
mfd: arizona: Split of_match table into I2C and SPI versions
...
Diffstat (limited to 'drivers')
42 files changed, 458 insertions, 863 deletions
diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c index 46c0add99570..6e97a541cfd3 100644 --- a/drivers/clk/ti/clk-43xx.c +++ b/drivers/clk/ti/clk-43xx.c @@ -116,6 +116,7 @@ static const struct omap_clkctrl_reg_data am4_l3s_clkctrl_regs[] __initconst = { { AM4_L3S_VPFE0_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk" }, { AM4_L3S_VPFE1_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk" }, { AM4_L3S_GPMC_CLKCTRL, NULL, CLKF_SW_SUP, "l3s_gclk" }, + { AM4_L3S_ADC1_CLKCTRL, NULL, CLKF_SW_SUP, "l3s_gclk" }, { AM4_L3S_MCASP0_CLKCTRL, NULL, CLKF_SW_SUP, "mcasp0_fck" }, { AM4_L3S_MCASP1_CLKCTRL, NULL, CLKF_SW_SUP, "mcasp1_fck" }, { AM4_L3S_MMC3_CLKCTRL, NULL, CLKF_SW_SUP, "mmc_clk" }, diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 855cc2d64ac8..dbdc1ef48566 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * TI ADC MFD driver * * Copyright (C) 2012 Texas Instruments Incorporated - https://www.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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/kernel.h> @@ -25,6 +17,7 @@ #include <linux/of_device.h> #include <linux/iio/machine.h> #include <linux/iio/driver.h> +#include <linux/iopoll.h> #include <linux/mfd/ti_am335x_tscadc.h> #include <linux/iio/buffer.h> @@ -65,7 +58,7 @@ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) } static void tiadc_writel(struct tiadc_device *adc, unsigned int reg, - unsigned int val) + unsigned int val) { writel(val, adc->mfd_tscadc->tscadc_base + reg); } @@ -80,7 +73,7 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev) } static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev, - struct iio_chan_spec const *chan) + struct iio_chan_spec const *chan) { int i; @@ -102,10 +95,18 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) return 1 << adc_dev->channel_step[chan]; } +static int tiadc_wait_idle(struct tiadc_device *adc_dev) +{ + u32 val; + + return readl_poll_timeout(adc_dev->mfd_tscadc->tscadc_base + REG_ADCFSM, + val, !(val & SEQ_STATUS), 10, + IDLE_TIMEOUT_MS * 1000 * adc_dev->channels); +} + static void tiadc_step_config(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); - struct device *dev = adc_dev->mfd_tscadc->dev; unsigned int stepconfig; int i, steps = 0; @@ -118,23 +119,14 @@ static void tiadc_step_config(struct iio_dev *indio_dev) * Channel would represent which analog input * needs to be given to ADC to digitalize data. */ - - for (i = 0; i < adc_dev->channels; i++) { int chan; chan = adc_dev->channel_line[i]; - if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) { - dev_warn(dev, "chan %d step_avg truncating to %d\n", - chan, STEPCONFIG_AVG_16); - adc_dev->step_avg[i] = STEPCONFIG_AVG_16; - } - if (adc_dev->step_avg[i]) - stepconfig = - STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) | - STEPCONFIG_FIFO1; + stepconfig = STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) | + STEPCONFIG_FIFO1; else stepconfig = STEPCONFIG_FIFO1; @@ -142,26 +134,13 @@ static void tiadc_step_config(struct iio_dev *indio_dev) stepconfig |= STEPCONFIG_MODE_SWCNT; tiadc_writel(adc_dev, REG_STEPCONFIG(steps), - stepconfig | STEPCONFIG_INP(chan) | - STEPCONFIG_INM_ADCREFM | - STEPCONFIG_RFP_VREFP | - STEPCONFIG_RFM_VREFN); - - if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) { - dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n", - chan); - adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK; - } - - if (adc_dev->sample_delay[i] > 0xFF) { - dev_warn(dev, "chan %d sample delay truncating to 0xFF\n", - chan); - adc_dev->sample_delay[i] = 0xFF; - } + stepconfig | STEPCONFIG_INP(chan) | + STEPCONFIG_INM_ADCREFM | STEPCONFIG_RFP_VREFP | + STEPCONFIG_RFM_VREFN); tiadc_writel(adc_dev, REG_STEPDELAY(steps), - STEPDELAY_OPEN(adc_dev->open_delay[i]) | - STEPDELAY_SAMPLE(adc_dev->sample_delay[i])); + STEPDELAY_OPEN(adc_dev->open_delay[i]) | + STEPDELAY_SAMPLE(adc_dev->sample_delay[i])); adc_dev->channel_step[i] = steps; steps++; @@ -184,12 +163,14 @@ static irqreturn_t tiadc_irq_h(int irq, void *private) if (status & IRQENB_FIFO1OVRRUN) { /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */ config = tiadc_readl(adc_dev, REG_CTRL); - config &= ~(CNTRLREG_TSCSSENB); + config &= ~(CNTRLREG_SSENB); tiadc_writel(adc_dev, REG_CTRL, config); - tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN - | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES); + tiadc_writel(adc_dev, REG_IRQSTATUS, + IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW | + IRQENB_FIFO1THRES); - /* wait for idle state. + /* + * Wait for the idle state. * ADC needs to finish the current conversion * before disabling the module */ @@ -197,7 +178,7 @@ static irqreturn_t tiadc_irq_h(int irq, void *private) adc_fsm = tiadc_readl(adc_dev, REG_ADCFSM); } while (adc_fsm != 0x10 && count++ < 100); - tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB)); + tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_SSENB)); return IRQ_HANDLED; } else if (status & IRQENB_FIFO1THRES) { /* Disable irq and wake worker thread */ @@ -217,11 +198,11 @@ static irqreturn_t tiadc_worker_h(int irq, void *private) fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); for (k = 0; k < fifo1count; k = k + i) { - for (i = 0; i < (indio_dev->scan_bytes)/2; i++) { + for (i = 0; i < indio_dev->scan_bytes / 2; i++) { read = tiadc_readl(adc_dev, REG_FIFO1); data[i] = read & FIFOREAD_DATA_MASK; } - iio_push_to_buffers(indio_dev, (u8 *) data); + iio_push_to_buffers(indio_dev, (u8 *)data); } tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES); @@ -254,6 +235,7 @@ static int tiadc_start_dma(struct iio_dev *indio_dev) struct dma_async_tx_descriptor *desc; dma->current_period = 0; /* We start to fill period 0 */ + /* * Make the fifo thresh as the multiple of total number of * channels enabled, so make sure that cyclic DMA period @@ -263,9 +245,10 @@ static int tiadc_start_dma(struct iio_dev *indio_dev) */ dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1, adc_dev->total_ch_enabled) - 1; + /* Make sure that period length is multiple of fifo thresh level */ dma->period_size = rounddown(DMA_BUFFER_SIZE / 2, - (dma->fifo_thresh + 1) * sizeof(u16)); + (dma->fifo_thresh + 1) * sizeof(u16)); dma->conf.src_maxburst = dma->fifo_thresh + 1; dmaengine_slave_config(dma->chan, &dma->conf); @@ -295,10 +278,15 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); int i, fifo1count; + int ret; + + ret = tiadc_wait_idle(adc_dev); + if (ret) + return ret; - tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | - IRQENB_FIFO1OVRRUN | - IRQENB_FIFO1UNDRFLW)); + tiadc_writel(adc_dev, REG_IRQCLR, + IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | + IRQENB_FIFO1UNDRFLW); /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); @@ -328,8 +316,9 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev) am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb); - tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES - | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); + tiadc_writel(adc_dev, REG_IRQSTATUS, + IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | + IRQENB_FIFO1UNDRFLW); irq_enable = IRQENB_FIFO1OVRRUN; if (!dma->chan) @@ -345,8 +334,9 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev) struct tiadc_dma *dma = &adc_dev->dma; int fifo1count, i; - tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | - IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); + 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; adc_dev->total_ch_enabled = 0; @@ -378,12 +368,11 @@ static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = { }; static int tiadc_iio_buffered_hardware_setup(struct device *dev, - struct iio_dev *indio_dev, - irqreturn_t (*pollfunc_bh)(int irq, void *p), - irqreturn_t (*pollfunc_th)(int irq, void *p), - int irq, - unsigned long flags, - const struct iio_buffer_setup_ops *setup_ops) + struct iio_dev *indio_dev, + irqreturn_t (*pollfunc_bh)(int irq, void *p), + irqreturn_t (*pollfunc_th)(int irq, void *p), + int irq, unsigned long flags, + const struct iio_buffer_setup_ops *setup_ops) { int ret; @@ -394,7 +383,7 @@ static int tiadc_iio_buffered_hardware_setup(struct device *dev, return ret; return devm_request_threaded_irq(dev, irq, pollfunc_th, pollfunc_bh, - flags, indio_dev->name, indio_dev); + flags, indio_dev->name, indio_dev); } static const char * const chan_name_ain[] = { @@ -419,16 +408,16 @@ static int tiadc_channel_init(struct device *dev, struct iio_dev *indio_dev, indio_dev->num_channels = channels; chan_array = devm_kcalloc(dev, channels, sizeof(*chan_array), GFP_KERNEL); - if (chan_array == NULL) + if (!chan_array) return -ENOMEM; chan = chan_array; for (i = 0; i < channels; i++, chan++) { - chan->type = IIO_VOLTAGE; chan->indexed = 1; chan->channel = adc_dev->channel_line[i]; chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); chan->datasheet_name = chan_name_ain[chan->channel]; chan->scan_index = i; chan->scan_type.sign = 'u'; @@ -442,16 +431,33 @@ static int tiadc_channel_init(struct device *dev, struct iio_dev *indio_dev, } static int tiadc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) { struct tiadc_device *adc_dev = iio_priv(indio_dev); - int ret = IIO_VAL_INT; int i, map_val; unsigned int fifo1count, read, stepid; bool found = false; u32 step_en; unsigned long timeout; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_VOLTAGE: + *val = 1800; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } if (iio_buffer_enabled(indio_dev)) return -EBUSY; @@ -461,15 +467,19 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, return -EINVAL; mutex_lock(&adc_dev->fifo1_lock); + + ret = tiadc_wait_idle(adc_dev); + if (ret) + goto err_unlock; + 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); - timeout = jiffies + msecs_to_jiffies - (IDLE_TIMEOUT * adc_dev->channels); /* Wait for Fifo threshold interrupt */ + timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT_MS * adc_dev->channels); while (1) { fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); if (fifo1count) @@ -481,6 +491,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, goto err_unlock; } } + map_val = adc_dev->channel_step[chan->scan_index]; /* @@ -498,17 +509,18 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, if (stepid == map_val) { read = read & FIFOREAD_DATA_MASK; found = true; - *val = (u16) read; + *val = (u16)read; } } + am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); if (!found) - ret = -EBUSY; + ret = -EBUSY; err_unlock: mutex_unlock(&adc_dev->fifo1_lock); - return ret; + return ret ? ret : IIO_VAL_INT; } static const struct iio_info tiadc_info = { @@ -545,6 +557,7 @@ static int tiadc_request_dma(struct platform_device *pdev, goto err; return 0; + err: dma_release_channel(dma->chan); return -ENOMEM; @@ -558,6 +571,7 @@ static int tiadc_parse_dt(struct platform_device *pdev, const __be32 *cur; int channels = 0; u32 val; + int i; of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { adc_dev->channel_line[channels] = val; @@ -570,6 +584,8 @@ static int tiadc_parse_dt(struct platform_device *pdev, channels++; } + adc_dev->channels = channels; + of_property_read_u32_array(node, "ti,chan-step-avg", adc_dev->step_avg, channels); of_property_read_u32_array(node, "ti,chan-step-opendelay", @@ -577,7 +593,33 @@ static int tiadc_parse_dt(struct platform_device *pdev, of_property_read_u32_array(node, "ti,chan-step-sampledelay", adc_dev->sample_delay, channels); - adc_dev->channels = channels; + for (i = 0; i < adc_dev->channels; i++) { + int chan; + + chan = adc_dev->channel_line[i]; + + if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) { + dev_warn(&pdev->dev, + "chan %d: wrong step avg, truncated to %ld\n", + chan, STEPCONFIG_AVG_16); + adc_dev->step_avg[i] = STEPCONFIG_AVG_16; + } + + if (adc_dev->open_delay[i] > STEPCONFIG_MAX_OPENDLY) { + dev_warn(&pdev->dev, + "chan %d: wrong open delay, truncated to 0x%lX\n", + chan, STEPCONFIG_MAX_OPENDLY); + adc_dev->open_delay[i] = STEPCONFIG_MAX_OPENDLY; + } + + if (adc_dev->sample_delay[i] > STEPCONFIG_MAX_SAMPLE) { + dev_warn(&pdev->dev, + "chan %d: wrong sample delay, truncated to 0x%lX\n", + chan, STEPCONFIG_MAX_SAMPLE); + adc_dev->sample_delay[i] = STEPCONFIG_MAX_SAMPLE; + } + } + return 0; } @@ -594,7 +636,7 @@ static int tiadc_probe(struct platform_device *pdev) } indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev)); - if (indio_dev == NULL) { + if (!indio_dev) { dev_err(&pdev->dev, "failed to allocate iio device\n"); return -ENOMEM; } @@ -616,18 +658,17 @@ static int tiadc_probe(struct platform_device *pdev) return err; err = tiadc_iio_buffered_hardware_setup(&pdev->dev, indio_dev, - &tiadc_worker_h, - &tiadc_irq_h, - adc_dev->mfd_tscadc->irq, - IRQF_SHARED, - &tiadc_buffer_setup_ops); - + &tiadc_worker_h, + &tiadc_irq_h, + adc_dev->mfd_tscadc->irq, + IRQF_SHARED, + &tiadc_buffer_setup_ops); if (err) - goto err_free_channels; + return err; err = iio_device_register(indio_dev); if (err) - goto err_buffer_unregister; + return err; platform_set_drvdata(pdev, indio_dev); @@ -639,8 +680,7 @@ static int tiadc_probe(struct platform_device *pdev) err_dma: iio_device_unregister(indio_dev); -err_buffer_unregister: -err_free_channels: + return err; } @@ -671,9 +711,8 @@ static int __maybe_unused tiadc_suspend(struct device *dev) unsigned int idle; idle = tiadc_readl(adc_dev, REG_CTRL); - idle &= ~(CNTRLREG_TSCSSENB); - tiadc_writel(adc_dev, REG_CTRL, (idle | - CNTRLREG_POWERDOWN)); + idle &= ~(CNTRLREG_SSENB); + tiadc_writel(adc_dev, REG_CTRL, idle | CNTRLREG_POWERDOWN); return 0; } @@ -686,12 +725,12 @@ static int __maybe_unused tiadc_resume(struct device *dev) /* Make sure ADC is powered up */ restore = tiadc_readl(adc_dev, REG_CTRL); - restore &= ~(CNTRLREG_POWERDOWN); + restore &= ~CNTRLREG_POWERDOWN; 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); + adc_dev->buffer_en_ch_steps); return 0; } @@ -699,6 +738,7 @@ static SIMPLE_DEV_PM_OPS(tiadc_pm_ops, tiadc_suspend, tiadc_resume); static const struct of_device_id ti_adc_dt_ids[] = { { .compatible = "ti,am3359-adc", }, + { .compatible = "ti,am4372-adc", }, { } }; MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ca0edab91aeb..3fb480818599 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -93,7 +93,7 @@ config PMIC_ADP5520 bool "Analog Devices ADP5520/01 MFD PMIC Core Support" depends on I2C=y help - Say yes here to add support for Analog Devices AD5520 and ADP5501, + Say yes here to add support for Analog Devices ADP5520 and ADP5501, Multifunction Power Management IC. This includes the I2C driver and the core APIs _only_, you have to select individual components like LCD backlight, LEDs, GPIOs and Kepad @@ -417,7 +417,9 @@ config MFD_EXYNOS_LPASS select REGMAP_MMIO help Select this option to enable support for Samsung Exynos Low Power - Audio Subsystem. + Audio Subsystem present on some of Samsung Exynos + SoCs (e.g. Exynos5433). + Choose Y here only if you build for such Samsung SoC. config MFD_GATEWORKS_GSC tristate "Gateworks System Controller" @@ -692,7 +694,7 @@ config MFD_INTEL_PMC_BXT config MFD_INTEL_PMT tristate "Intel Platform Monitoring Technology (PMT) support" - depends on PCI + depends on X86 && PCI select MFD_CORE help The Intel Platform Monitoring Technology (PMT) is an interface that @@ -1194,6 +1196,7 @@ config MFD_SI476X_CORE config MFD_SIMPLE_MFD_I2C tristate depends on I2C + select MFD_CORE select REGMAP_I2C help This driver creates a single register map with the intention for it @@ -1622,20 +1625,6 @@ config MFD_TPS65912_SPI If you say yes here you get support for the TPS65912 series of PM chips with SPI interface. -config MFD_TPS80031 - bool "TI TPS80031/TPS80032 Power Management chips" - depends on I2C=y - select MFD_CORE - select REGMAP_I2C - select REGMAP_IRQ - help - If you say yes here you get support for the Texas Instruments - TPS80031/ TPS80032 Fully Integrated Power Management with Power - Path and Battery Charger. The device provides five configurable - step-down converters, 11 general purpose LDOs, USB OTG Module, - ADC, RTC, 2 PWM, System Voltage Regulator/Battery Charger with - Power Path from USB, 32K clock generator. - config TWL4030_CORE bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2ba6646e874c..0b1b629aef3e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -105,7 +105,6 @@ obj-$(CONFIG_MFD_TPS65910) += tps65910.o obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o -obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o diff --git a/drivers/mfd/altera-a10sr.c b/drivers/mfd/altera-a10sr.c index a3bf64f9afd1..34ef526f4aee 100644 --- a/drivers/mfd/altera-a10sr.c +++ b/drivers/mfd/altera-a10sr.c @@ -14,6 +14,7 @@ #include <linux/mfd/altera-a10sr.h> #include <linux/mfd/core.h> #include <linux/init.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/spi/spi.h> @@ -150,6 +151,13 @@ static const struct of_device_id altr_a10sr_spi_of_match[] = { { .compatible = "altr,a10sr" }, { }, }; +MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match); + +static const struct spi_device_id altr_a10sr_spi_ids[] = { + { .name = "a10sr" }, + { }, +}; +MODULE_DEVICE_TABLE(spi, altr_a10sr_spi_ids); static struct spi_driver altr_a10sr_spi_driver = { .probe = altr_a10sr_spi_probe, @@ -157,5 +165,6 @@ static struct spi_driver altr_a10sr_spi_driver = { .name = "altr_a10sr", .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), }, + .id_table = altr_a10sr_spi_ids, }; builtin_driver(altr_a10sr_spi_driver, spi_register_driver) diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index 20cb294c7512..5d3715a28b28 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -153,7 +153,7 @@ static int sysmgr_probe(struct platform_device *pdev) if (!base) return -ENOMEM; - sysmgr_config.max_register = resource_size(res) - 3; + sysmgr_config.max_register = resource_size(res) - 4; regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config); } diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 9323b1e3a69e..cbf1dd90b70d 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -845,19 +845,6 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) return 0; } - -const struct of_device_id arizona_of_match[] = { - { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, - { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, - { .compatible = "wlf,wm8280", .data = (void *)WM8280 }, - { .compatible = "wlf,wm8997", .data = (void *)WM8997 }, - { .compatible = "wlf,wm8998", .data = (void *)WM8998 }, - { .compatible = "wlf,wm1814", .data = (void *)WM1814 }, - { .compatible = "wlf,wm1831", .data = (void *)WM1831 }, - { .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 }, - {}, -}; -EXPORT_SYMBOL_GPL(arizona_of_match); #else static inline int arizona_of_get_core_pdata(struct arizona *arizona) { diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 5e83b730c4ce..3ed810e81f63 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -104,11 +104,23 @@ static const struct i2c_device_id arizona_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, arizona_i2c_id); +#ifdef CONFIG_OF +const struct of_device_id arizona_i2c_of_match[] = { + { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, + { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, + { .compatible = "wlf,wm8280", .data = (void *)WM8280 }, + { .compatible = "wlf,wm8997", .data = (void *)WM8997 }, + { .compatible = "wlf,wm8998", .data = (void *)WM8998 }, + { .compatible = "wlf,wm1814", .data = (void *)WM1814 }, + {}, +}; +#endif + static struct i2c_driver arizona_i2c_driver = { .driver = { .name = "arizona", .pm = &arizona_pm_ops, - .of_match_table = of_match_ptr(arizona_of_match), + .of_match_table = of_match_ptr(arizona_i2c_of_match), }, .probe = arizona_i2c_probe, .remove = arizona_i2c_remove, diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index aa1d6f94ae53..9fe06dda3782 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -225,11 +225,22 @@ static const struct spi_device_id arizona_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, arizona_spi_ids); +#ifdef CONFIG_OF +const struct of_device_id arizona_spi_of_match[] = { + { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, + { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, + { .compatible = "wlf,wm8280", .data = (void *)WM8280 }, + { .compatible = "wlf,wm1831", .data = (void *)WM1831 }, + { .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 }, + {}, +}; +#endif + static struct spi_driver arizona_spi_driver = { .driver = { .name = "arizona", .pm = &arizona_pm_ops, - .of_match_table = of_match_ptr(arizona_of_match), + .of_match_table = of_match_ptr(arizona_spi_of_match), .acpi_match_table = ACPI_PTR(arizona_acpi_match), }, .probe = arizona_spi_probe, diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h index 801cbbcd71cb..66d6092d0851 100644 --- a/drivers/mfd/arizona.h +++ b/drivers/mfd/arizona.h @@ -28,8 +28,6 @@ extern const struct regmap_config wm8998_i2c_regmap; extern const struct dev_pm_ops arizona_pm_ops; -extern const struct of_device_id arizona_of_match[]; - extern const struct regmap_irq_chip wm5102_aod; extern const struct regmap_irq_chip wm5102_irq; diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 8c08d1c55726..81cee1a5daa6 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -326,7 +326,6 @@ static void __exit cros_ec_dev_exit(void) module_init(cros_ec_dev_init); module_exit(cros_ec_dev_exit); -MODULE_ALIAS("platform:" DRV_NAME); MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>"); MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller"); MODULE_VERSION("1.0"); diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 4b7f707b7952..343ed6e96d87 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c @@ -391,6 +391,7 @@ static int da9063_i2c_probe(struct i2c_client *i2c, &da9063_bb_da_volatile_table; break; case PMIC_DA9063_DA: + case PMIC_DA9063_EA: da9063_regmap_config.rd_table = &da9063_da_readable_table; da9063_regmap_config.wr_table = @@ -416,6 +417,7 @@ static int da9063_i2c_probe(struct i2c_client *i2c, &da9063l_bb_da_volatile_table; break; case PMIC_DA9063_DA: + case PMIC_DA9063_EA: da9063_regmap_config.rd_table = &da9063l_da_readable_table; da9063_regmap_config.wr_table = diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 83e676a096dc..852129ea0766 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -50,6 +50,7 @@ enum dln2_handle { DLN2_HANDLE_GPIO, DLN2_HANDLE_I2C, DLN2_HANDLE_SPI, + DLN2_HANDLE_ADC, DLN2_HANDLES }; @@ -653,6 +654,7 @@ enum { DLN2_ACPI_MATCH_GPIO = 0, DLN2_ACPI_MATCH_I2C = 1, DLN2_ACPI_MATCH_SPI = 2, + DLN2_ACPI_MATCH_ADC = 3, }; static struct dln2_platform_data dln2_pdata_gpio = { @@ -683,6 +685,16 @@ static struct mfd_cell_acpi_match dln2_acpi_match_spi = { .adr = DLN2_ACPI_MATCH_SPI, }; +/* Only one ADC port supported */ +static struct dln2_platform_data dln2_pdata_adc = { + .handle = DLN2_HANDLE_ADC, + .port = 0, +}; + +static struct mfd_cell_acpi_match dln2_acpi_match_adc = { + .adr = DLN2_ACPI_MATCH_ADC, +}; + static const struct mfd_cell dln2_devs[] = { { .name = "dln2-gpio", @@ -702,6 +714,12 @@ static const struct mfd_cell dln2_devs[] = { .platform_data = &dln2_pdata_spi, .pdata_size = sizeof(struct dln2_platform_data), }, + { + .name = "dln2-adc", + .acpi_match = &dln2_acpi_match_adc, + .platform_data = &dln2_pdata_adc, + .pdata_size = sizeof(struct dln2_platform_data), + }, }; static void dln2_stop(struct dln2_dev *dln2) diff --git a/drivers/mfd/hi6421-spmi-pmic.c b/drivers/mfd/hi6421-spmi-pmic.c index 4f136826681b..c9c0c3d7011f 100644 --- a/drivers/mfd/hi6421-spmi-pmic.c +++ b/drivers/mfd/hi6421-spmi-pmic.c @@ -8,7 +8,6 @@ */ #include <linux/mfd/core.h> -#include <linux/mfd/hi6421-spmi-pmic.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -30,19 +29,14 @@ static const struct regmap_config regmap_config = { static int hi6421_spmi_pmic_probe(struct spmi_device *sdev) { struct device *dev = &sdev->dev; + struct regmap *regmap; int ret; - struct hi6421_spmi_pmic *ddata; - ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); - if (!ddata) - return -ENOMEM; - ddata->regmap = devm_regmap_init_spmi_ext(sdev, ®map_config); - if (IS_ERR(ddata->regmap)) - return PTR_ERR(ddata->regmap); + regmap = devm_regmap_init_spmi_ext(sdev, ®map_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - ddata->dev = dev; - - dev_set_drvdata(&sdev->dev, ddata); + dev_set_drvdata(&sdev->dev, regmap); ret = devm_mfd_add_devices(&sdev->dev, PLATFORM_DEVID_NONE, hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs), diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index c54d19fb184c..a872b4485eac 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -253,6 +253,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info }, + /* ICL-N */ + { PCI_VDEVICE(INTEL, 0x38a8), (kernel_ulong_t)&bxt_uart_info }, /* TGL-H */ { PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info }, diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 70eba4ce496f..add3bc04185b 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -154,7 +154,7 @@ static ssize_t modulbus_number_show(struct device *dev, { struct cmodio_device *priv = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex); + return sysfs_emit(buf, "%x\n", priv->hex); } static DEVICE_ATTR_RO(modulbus_number); diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index be185e9d5f16..6c487fa14e9c 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -332,7 +332,7 @@ static int max77836_init(struct max14577 *max14577) } ret = regmap_add_irq_chip(max14577->regmap_pmic, max14577->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED, + IRQF_ONESHOT | IRQF_SHARED, 0, &max77836_pmic_irq_chip, &max14577->irq_data_pmic); if (ret != 0) { @@ -418,14 +418,14 @@ static int max14577_i2c_probe(struct i2c_client *i2c, irq_chip = &max77836_muic_irq_chip; mfd_devs = max77836_devs; mfd_devs_size = ARRAY_SIZE(max77836_devs); - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED; + irq_flags = IRQF_ONESHOT | IRQF_SHARED; break; case MAXIM_DEVICE_TYPE_MAX14577: default: irq_chip = &max14577_irq_chip; mfd_devs = max14577_devs; mfd_devs_size = ARRAY_SIZE(max14577_devs); - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + irq_flags = IRQF_ONESHOT; break; } diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 2ad554b921d9..f9e12ab2bc75 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -209,8 +209,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c) ret = devm_regmap_add_irq_chip(&i2c->dev, max77686->regmap, max77686->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT | - IRQF_SHARED, 0, irq_chip, + IRQF_ONESHOT | IRQF_SHARED, 0, irq_chip, &max77686->irq_data); if (ret < 0) { dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret); diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 596ed85cab3b..4e6244e17559 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -222,8 +222,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, } ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, - IRQF_ONESHOT | IRQF_SHARED | - IRQF_TRIGGER_FALLING, 0, + IRQF_ONESHOT | IRQF_SHARED, 0, &max77693_led_irq_chip, &max77693->irq_data_led); if (ret) { @@ -232,8 +231,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, } ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, - IRQF_ONESHOT | IRQF_SHARED | - IRQF_TRIGGER_FALLING, 0, + IRQF_ONESHOT | IRQF_SHARED, 0, &max77693_topsys_irq_chip, &max77693->irq_data_topsys); if (ret) { @@ -242,8 +240,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, } ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, - IRQF_ONESHOT | IRQF_SHARED | - IRQF_TRIGGER_FALLING, 0, + IRQF_ONESHOT | IRQF_SHARED, 0, &max77693_charger_irq_chip, &max77693->irq_data_chg); if (ret) { @@ -252,8 +249,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, } ret = regmap_add_irq_chip(max77693->regmap_muic, max77693->irq, - IRQF_ONESHOT | IRQF_SHARED | - IRQF_TRIGGER_FALLING, 0, + IRQF_ONESHOT | IRQF_SHARED, 0, &max77693_muic_irq_chip, &max77693->irq_data_muic); if (ret) { diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 1abe7432aad8..8a4f1d90dcfd 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -496,15 +496,13 @@ int mc13xxx_common_init(struct device *dev) } EXPORT_SYMBOL_GPL(mc13xxx_common_init); -int mc13xxx_common_exit(struct device *dev) +void mc13xxx_common_exit(struct device *dev) { struct mc13xxx *mc13xxx = dev_get_drvdata(dev); mfd_remove_devices(dev); regmap_del_irq_chip(mc13xxx->irq, mc13xxx->irq_data); mutex_destroy(&mc13xxx->lock); - - return 0; } EXPORT_SYMBOL_GPL(mc13xxx_common_exit); diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index 65b4dd8e5afb..fb937f66277e 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -87,7 +87,8 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, static int mc13xxx_i2c_remove(struct i2c_client *client) { - return mc13xxx_common_exit(&client->dev); + mc13xxx_common_exit(&client->dev); + return 0; } static struct i2c_driver mc13xxx_i2c_driver = { diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 286ddcf5ddc6..4d8913d647e6 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -168,7 +168,8 @@ static int mc13xxx_spi_probe(struct spi_device *spi) static int mc13xxx_spi_remove(struct spi_device *spi) { - return mc13xxx_common_exit(&spi->dev); + mc13xxx_common_exit(&spi->dev); + return 0; } static struct spi_driver mc13xxx_spi_driver = { diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h index ce6eec52e8eb..bd5ba9a0e14f 100644 --- a/drivers/mfd/mc13xxx.h +++ b/drivers/mfd/mc13xxx.h @@ -44,6 +44,6 @@ struct mc13xxx { }; int mc13xxx_common_init(struct device *dev); -int mc13xxx_common_exit(struct device *dev); +void mc13xxx_common_exit(struct device *dev); #endif /* __DRIVERS_MFD_MC13XXX_H */ diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 79f5c6a18815..684a011a6396 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -198,6 +198,7 @@ static int mfd_add_device(struct device *parent, int id, if (of_device_is_compatible(np, cell->of_compatible)) { /* Ignore 'disabled' devices error free */ if (!of_device_is_available(np)) { + of_node_put(np); ret = 0; goto fail_alias; } @@ -205,6 +206,7 @@ static int mfd_add_device(struct device *parent, int id, ret = mfd_match_of_node_to_dev(pdev, np, cell); if (ret == -EAGAIN) continue; + of_node_put(np); if (ret) goto fail_alias; diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index 6fb206da2729..265464b5d7cc 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -202,6 +202,13 @@ static const struct of_device_id cpcap_of_match[] = { }; MODULE_DEVICE_TABLE(of, cpcap_of_match); +static const struct spi_device_id cpcap_spi_ids[] = { + { .name = "cpcap", }, + { .name = "6556002", }, + {}, +}; +MODULE_DEVICE_TABLE(spi, cpcap_spi_ids); + static const struct regmap_config cpcap_regmap_config = { .reg_bits = 16, .reg_stride = 4, @@ -342,6 +349,7 @@ static struct spi_driver cpcap_driver = { .pm = &cpcap_pm, }, .probe = cpcap_probe, + .id_table = cpcap_spi_ids, }; module_spi_driver(cpcap_driver); diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c index ec18a04de355..2f2734ba5273 100644 --- a/drivers/mfd/qcom-pm8xxx.c +++ b/drivers/mfd/qcom-pm8xxx.c @@ -65,7 +65,7 @@ struct pm_irq_data { int num_irqs; struct irq_chip *irq_chip; - void (*irq_handler)(struct irq_desc *desc); + irq_handler_t irq_handler; }; struct pm_irq_chip { @@ -169,19 +169,16 @@ static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master) return ret; } -static void pm8xxx_irq_handler(struct irq_desc *desc) +static irqreturn_t pm8xxx_irq_handler(int irq, void *data) { - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); + struct pm_irq_chip *chip = data; unsigned int root; int i, ret, masters = 0; - chained_irq_enter(irq_chip, desc); - ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root); if (ret) { pr_err("Can't read root status ret=%d\n", ret); - return; + return IRQ_NONE; } /* on pm8xxx series masters start from bit 1 of the root */ @@ -192,7 +189,7 @@ static void pm8xxx_irq_handler(struct irq_desc *desc) if (masters & (1 << i)) pm8xxx_irq_master_handler(chip, i); - chained_irq_exit(irq_chip, desc); + return IRQ_HANDLED; } static void pm8821_irq_block_handler(struct pm_irq_chip *chip, @@ -230,19 +227,17 @@ static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip, pm8821_irq_block_handler(chip, master, block); } -static void pm8821_irq_handler(struct irq_desc *desc) +static irqreturn_t pm8821_irq_handler(int irq, void *data) { - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); + struct pm_irq_chip *chip = data; unsigned int master; int ret; - chained_irq_enter(irq_chip, desc); ret = regmap_read(chip->regmap, PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master); if (ret) { pr_err("Failed to read master 0 ret=%d\n", ret); - goto done; + return IRQ_NONE; } /* bits 1 through 7 marks the first 7 blocks in master 0 */ @@ -251,19 +246,18 @@ static void pm8821_irq_handler(struct irq_desc *desc) /* bit 0 marks if master 1 contains any bits */ if (!(master & BIT(0))) - goto done; + return IRQ_NONE; ret = regmap_read(chip->regmap, PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master); if (ret) { pr_err("Failed to read master 1 ret=%d\n", ret); - goto done; + return IRQ_NONE; } pm8821_irq_master_handler(chip, 1, master); -done: - chained_irq_exit(irq_chip, desc); + return IRQ_HANDLED; } static void pm8xxx_irq_mask_ack(struct irq_data *d) @@ -574,14 +568,15 @@ static int pm8xxx_probe(struct platform_device *pdev) if (!chip->irqdomain) return -ENODEV; - irq_set_chained_handler_and_data(irq, data->irq_handler, chip); + rc = devm_request_irq(&pdev->dev, irq, data->irq_handler, 0, dev_name(&pdev->dev), chip); + if (rc) + return rc; + irq_set_irq_wake(irq, 1); rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - if (rc) { - irq_set_chained_handler_and_data(irq, NULL, NULL); + if (rc) irq_domain_remove(chip->irqdomain); - } return rc; } @@ -594,11 +589,9 @@ static int pm8xxx_remove_child(struct device *dev, void *unused) static int pm8xxx_remove(struct platform_device *pdev) { - int irq = platform_get_irq(pdev, 0); struct pm_irq_chip *chip = platform_get_drvdata(pdev); device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child); - irq_set_chained_handler_and_data(irq, NULL, NULL); irq_domain_remove(chip->irqdomain); return 0; diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c index a35d5cf16faa..1cacc00aa6c9 100644 --- a/drivers/mfd/qcom-spmi-pmic.c +++ b/drivers/mfd/qcom-spmi-pmic.c @@ -31,6 +31,8 @@ #define PM8916_SUBTYPE 0x0b #define PM8004_SUBTYPE 0x0c #define PM8909_SUBTYPE 0x0d +#define PM8028_SUBTYPE 0x0e +#define PM8901_SUBTYPE 0x0f #define PM8950_SUBTYPE 0x10 #define PMI8950_SUBTYPE 0x11 #define PM8998_SUBTYPE 0x14 @@ -38,29 +40,44 @@ #define PM8005_SUBTYPE 0x18 #define PM660L_SUBTYPE 0x1A #define PM660_SUBTYPE 0x1B +#define PM8150_SUBTYPE 0x1E +#define PM8150L_SUBTYPE 0x1f +#define PM8150B_SUBTYPE 0x20 +#define PMK8002_SUBTYPE 0x21 +#define PM8009_SUBTYPE 0x24 +#define PM8150C_SUBTYPE 0x26 +#define SMB2351_SUBTYPE 0x29 static const struct of_device_id pmic_spmi_id_table[] = { - { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, - { .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE }, - { .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE }, + { .compatible = "qcom,pm660", .data = (void *)PM660_SUBTYPE }, + { .compatible = "qcom,pm660l", .data = (void *)PM660L_SUBTYPE }, + { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, + { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, { .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE }, - { .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE }, + { .compatible = "qcom,pm8028", .data = (void *)PM8028_SUBTYPE }, { .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE }, - { .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE }, - { .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE }, - { .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE }, - { .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE }, - { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, - { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, - { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, + { .compatible = "qcom,pm8150", .data = (void *)PM8150_SUBTYPE }, + { .compatible = "qcom,pm8150b", .data = (void *)PM8150B_SUBTYPE }, + { .compatible = "qcom,pm8150c", .data = (void *)PM8150C_SUBTYPE }, + { .compatible = "qcom,pm8150l", .data = (void *)PM8150L_SUBTYPE }, + { .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE }, + { .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE }, + { .compatible = "qcom,pm8901", .data = (void *)PM8901_SUBTYPE }, { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, + { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, + { .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE }, { .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE }, - { .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE }, + { .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE }, { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE }, + { .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE }, + { .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE }, + { .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE }, + { .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE }, + { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, - { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, - { .compatible = "qcom,pm660l", .data = (void *)PM660L_SUBTYPE }, - { .compatible = "qcom,pm660", .data = (void *)PM660_SUBTYPE }, + { .compatible = "qcom,pmk8002", .data = (void *)PMK8002_SUBTYPE }, + { .compatible = "qcom,smb2351", .data = (void *)SMB2351_SUBTYPE }, + { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, { } }; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 77ccd31ca1d9..b181fe401330 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -543,6 +543,10 @@ static void rk808_pm_power_off(void) reg = RK808_DEVCTRL_REG, bit = DEV_OFF_RST; break; + case RK817_ID: + reg = RK817_SYS_CFG(3); + bit = DEV_OFF; + break; case RK818_ID: reg = RK818_DEVCTRL_REG; bit = DEV_OFF; diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index e473c2fb42d5..f5f59fdc72fe 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -479,8 +479,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) } ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, - sec_pmic->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + sec_pmic->irq, IRQF_ONESHOT, 0, sec_irq_chip, &sec_pmic->irq_data); if (ret != 0) { dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index 6b7956604a0f..55d2c31bdfb2 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -18,6 +18,9 @@ #define SPRD_PMIC_INT_RAW_STATUS 0x4 #define SPRD_PMIC_INT_EN 0x8 +#define SPRD_SC2730_IRQ_BASE 0x80 +#define SPRD_SC2730_IRQ_NUMS 10 +#define SPRD_SC2730_CHG_DET 0x1b9c #define SPRD_SC2731_IRQ_BASE 0x140 #define SPRD_SC2731_IRQ_NUMS 16 #define SPRD_SC2731_CHG_DET 0xedc @@ -52,6 +55,12 @@ struct sprd_pmic_data { * base address and irq number, we should save irq number and irq base * in the device data structure. */ +static const struct sprd_pmic_data sc2730_data = { + .irq_base = SPRD_SC2730_IRQ_BASE, + .num_irqs = SPRD_SC2730_IRQ_NUMS, + .charger_det = SPRD_SC2730_CHG_DET, +}; + static const struct sprd_pmic_data sc2731_data = { .irq_base = SPRD_SC2731_IRQ_BASE, .num_irqs = SPRD_SC2731_IRQ_NUMS, @@ -232,10 +241,17 @@ static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume); static const struct of_device_id sprd_pmic_match[] = { { .compatible = "sprd,sc2731", .data = &sc2731_data }, + { .compatible = "sprd,sc2730", .data = &sc2730_data }, {}, }; MODULE_DEVICE_TABLE(of, sprd_pmic_match); +static const struct spi_device_id sprd_pmic_spi_ids[] = { + { .name = "sc2731", .driver_data = (unsigned long)&sc2731_data }, + {}, +}; +MODULE_DEVICE_TABLE(spi, sprd_pmic_spi_ids); + static struct spi_driver sprd_pmic_driver = { .driver = { .name = "sc27xx-pmic", @@ -243,6 +259,7 @@ static struct spi_driver sprd_pmic_driver = { .pm = &sprd_pmic_pm_ops, }, .probe = sprd_pmic_probe, + .id_table = sprd_pmic_spi_ids, }; static int __init sprd_pmic_init(void) diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index cd2f45257dc1..d3eedf3d607e 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -95,7 +95,9 @@ static int stmpe_i2c_remove(struct i2c_client *i2c) { struct stmpe *stmpe = dev_get_drvdata(&i2c->dev); - return stmpe_remove(stmpe); + stmpe_remove(stmpe); + + return 0; } static const struct i2c_device_id stmpe_i2c_id[] = { diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index 7351734f7593..6c5915016be5 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c @@ -106,7 +106,9 @@ static int stmpe_spi_remove(struct spi_device *spi) { struct stmpe *stmpe = spi_get_drvdata(spi); - return stmpe_remove(stmpe); + stmpe_remove(stmpe); + + return 0; } static const struct of_device_id stmpe_spi_of_match[] = { diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 58d09c615e67..e928df95e316 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -1496,7 +1496,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) return ret; } -int stmpe_remove(struct stmpe *stmpe) +void stmpe_remove(struct stmpe *stmpe) { if (!IS_ERR(stmpe->vio)) regulator_disable(stmpe->vio); @@ -1506,8 +1506,6 @@ int stmpe_remove(struct stmpe *stmpe) __stmpe_disable(stmpe, STMPE_BLOCK_ADC); mfd_remove_devices(stmpe->dev); - - return 0; } #ifdef CONFIG_PM diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h index 83491e99ba3c..1b4f91d03bbf 100644 --- a/drivers/mfd/stmpe.h +++ b/drivers/mfd/stmpe.h @@ -98,7 +98,7 @@ struct stmpe_client_info { }; int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum); -int stmpe_remove(struct stmpe *stmpe); +void stmpe_remove(struct stmpe *stmpe); #define STMPE_ICR_LSB_HIGH (1 << 2) #define STMPE_ICR_LSB_EDGE (1 << 1) diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 55adc379f94b..07825cfd8aa8 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * TI Touch Screen / ADC MFD driver * * Copyright (C) 2012 Texas Instruments Incorporated - https://www.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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/module.h> @@ -113,70 +105,99 @@ static void tscadc_idle_config(struct ti_tscadc_dev *tscadc) { unsigned int idleconfig; - idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | - STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; + idleconfig = STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM; + if (ti_adc_with_touchscreen(tscadc)) + idleconfig |= STEPCONFIG_YNN | STEPCONFIG_YPN; regmap_write(tscadc->regmap, REG_IDLECONFIG, idleconfig); } static int ti_tscadc_probe(struct platform_device *pdev) { - struct ti_tscadc_dev *tscadc; - struct resource *res; - struct clk *clk; - struct device_node *node; - struct mfd_cell *cell; - struct property *prop; - const __be32 *cur; - u32 val; - int err, ctrl; - int clock_rate; - int tsc_wires = 0, adc_channels = 0, total_channels; - int readouts = 0; + struct ti_tscadc_dev *tscadc; + struct resource *res; + struct clk *clk; + struct device_node *node; + struct mfd_cell *cell; + struct property *prop; + const __be32 *cur; + bool use_tsc = false, use_mag = false; + u32 val; + int err; + int tscmag_wires = 0, adc_channels = 0, cell_idx = 0, total_channels; + int readouts = 0, mag_tracks = 0; + + /* Allocate memory for device */ + tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL); + if (!tscadc) + return -ENOMEM; + + tscadc->dev = &pdev->dev; if (!pdev->dev.of_node) { dev_err(&pdev->dev, "Could not find valid DT data.\n"); return -EINVAL; } - node = of_get_child_by_name(pdev->dev.of_node, "tsc"); - of_property_read_u32(node, "ti,wires", &tsc_wires); - of_property_read_u32(node, "ti,coordiante-readouts", &readouts); + tscadc->data = of_device_get_match_data(&pdev->dev); + + if (ti_adc_with_touchscreen(tscadc)) { + node = of_get_child_by_name(pdev->dev.of_node, "tsc"); + of_property_read_u32(node, "ti,wires", &tscmag_wires); + err = of_property_read_u32(node, "ti,coordinate-readouts", + &readouts); + if (err < 0) + of_property_read_u32(node, "ti,coordiante-readouts", + &readouts); + + of_node_put(node); + + if (tscmag_wires) + use_tsc = true; + } else { + /* + * When adding support for the magnetic stripe reader, here is + * the place to look for the number of tracks used from device + * tree. Let's default to 0 for now. + */ + mag_tracks = 0; + tscmag_wires = mag_tracks * 2; + if (tscmag_wires) + use_mag = true; + } node = of_get_child_by_name(pdev->dev.of_node, "adc"); of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { adc_channels++; if (val > 7) { dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n", - val); + val); + of_node_put(node); return -EINVAL; } } - total_channels = tsc_wires + adc_channels; + + of_node_put(node); + + total_channels = tscmag_wires + adc_channels; if (total_channels > 8) { dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); return -EINVAL; } + if (total_channels == 0) { - dev_err(&pdev->dev, "Need atleast one channel.\n"); + dev_err(&pdev->dev, "Need at least one channel.\n"); return -EINVAL; } - if (readouts * 2 + 2 + adc_channels > 16) { + if (use_tsc && (readouts * 2 + 2 + adc_channels > 16)) { dev_err(&pdev->dev, "Too many step configurations requested\n"); return -EINVAL; } - /* Allocate memory for device */ - tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL); - if (!tscadc) - return -ENOMEM; - - tscadc->dev = &pdev->dev; - err = platform_get_irq(pdev, 0); if (err < 0) - goto ret; + return err; else tscadc->irq = err; @@ -187,11 +208,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) tscadc->tscadc_phys_base = res->start; tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, - tscadc->tscadc_base, &tscadc_regmap_config); + tscadc->tscadc_base, + &tscadc_regmap_config); if (IS_ERR(tscadc->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); - err = PTR_ERR(tscadc->regmap); - goto ret; + return PTR_ERR(tscadc->regmap); } spin_lock_init(&tscadc->reg_lock); @@ -201,71 +222,70 @@ static int ti_tscadc_probe(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); /* - * The TSC_ADC_Subsystem has 2 clock domains - * OCP_CLK and ADC_CLK. - * The ADC clock is expected to run at target of 3MHz, - * and expected to capture 12-bit data at a rate of 200 KSPS. - * The TSC_ADC_SS controller design assumes the OCP clock is - * at least 6x faster than the ADC clock. + * The TSC_ADC_Subsystem has 2 clock domains: OCP_CLK and ADC_CLK. + * ADCs produce a 12-bit sample every 15 ADC_CLK cycles. + * am33xx ADCs expect to capture 200ksps. + * am47xx ADCs expect to capture 867ksps. + * We need ADC clocks respectively running at 3MHz and 13MHz. + * These frequencies are valid since TSC_ADC_SS controller design + * assumes the OCP clock is at least 6x faster than the ADC clock. */ - clk = devm_clk_get(&pdev->dev, "adc_tsc_fck"); + clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { - dev_err(&pdev->dev, "failed to get TSC fck\n"); + dev_err(&pdev->dev, "failed to get fck\n"); err = PTR_ERR(clk); goto err_disable_clk; } - clock_rate = clk_get_rate(clk); - tscadc->clk_div = clock_rate / ADC_CLK; - /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ - tscadc->clk_div--; + tscadc->clk_div = (clk_get_rate(clk) / tscadc->data->target_clk_rate) - 1; regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); - /* Set the control register bits */ - ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc->regmap, REG_CTRL, ctrl); - - /* Set register bits for Idle Config Mode */ - if (tsc_wires > 0) { - tscadc->tsc_wires = tsc_wires; - if (tsc_wires == 5) - ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; - else - ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; - tscadc_idle_config(tscadc); + /* + * Set the control register bits. tscadc->ctrl stores the configuration + * of the CTRL register but not the subsystem enable bit which must be + * added manually when timely. + */ + tscadc->ctrl = CNTRLREG_STEPID; + if (ti_adc_with_touchscreen(tscadc)) { + tscadc->ctrl |= CNTRLREG_TSC_STEPCONFIGWRT; + if (use_tsc) { + tscadc->ctrl |= CNTRLREG_TSC_ENB; + if (tscmag_wires == 5) + tscadc->ctrl |= CNTRLREG_TSC_5WIRE; + else + tscadc->ctrl |= CNTRLREG_TSC_4WIRE; + } + } else { + tscadc->ctrl |= CNTRLREG_MAG_PREAMP_PWRDOWN | + CNTRLREG_MAG_PREAMP_BYPASS; } + regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl); + + tscadc_idle_config(tscadc); /* Enable the TSC module enable bit */ - ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc->regmap, REG_CTRL, ctrl); - - tscadc->used_cells = 0; - tscadc->tsc_cell = -1; - tscadc->adc_cell = -1; - - /* TSC Cell */ - if (tsc_wires > 0) { - tscadc->tsc_cell = tscadc->used_cells; - cell = &tscadc->cells[tscadc->used_cells++]; - cell->name = "TI-am335x-tsc"; - cell->of_compatible = "ti,am3359-tsc"; + regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl | CNTRLREG_SSENB); + + /* TSC or MAG Cell */ + if (use_tsc || use_mag) { + cell = &tscadc->cells[cell_idx++]; + cell->name = tscadc->data->secondary_feature_name; + cell->of_compatible = tscadc->data->secondary_feature_compatible; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); } /* ADC Cell */ if (adc_channels > 0) { - tscadc->adc_cell = tscadc->used_cells; - cell = &tscadc->cells[tscadc->used_cells++]; - cell->name = "TI-am335x-adc"; - cell->of_compatible = "ti,am3359-adc"; + cell = &tscadc->cells[cell_idx++]; + cell->name = tscadc->data->adc_feature_name; + cell->of_compatible = tscadc->data->adc_feature_compatible; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); } err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, - tscadc->cells, tscadc->used_cells, NULL, - 0, NULL); + tscadc->cells, cell_idx, NULL, 0, NULL); if (err < 0) goto err_disable_clk; @@ -275,13 +295,13 @@ static int ti_tscadc_probe(struct platform_device *pdev) err_disable_clk: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); -ret: + return err; } static int ti_tscadc_remove(struct platform_device *pdev) { - struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); + struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); regmap_write(tscadc->regmap, REG_SE, 0x00); @@ -300,7 +320,7 @@ static int __maybe_unused ti_tscadc_can_wakeup(struct device *dev, void *data) static int __maybe_unused tscadc_suspend(struct device *dev) { - struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); regmap_write(tscadc->regmap, REG_SE, 0x00); if (device_for_each_child(dev, NULL, ti_tscadc_can_wakeup)) { @@ -308,7 +328,7 @@ static int __maybe_unused tscadc_suspend(struct device *dev) regmap_read(tscadc->regmap, REG_CTRL, &ctrl); ctrl &= ~(CNTRLREG_POWERDOWN); - ctrl |= CNTRLREG_TSCSSENB; + ctrl |= CNTRLREG_SSENB; regmap_write(tscadc->regmap, REG_CTRL, ctrl); } pm_runtime_put_sync(dev); @@ -318,34 +338,39 @@ static int __maybe_unused tscadc_suspend(struct device *dev) static int __maybe_unused tscadc_resume(struct device *dev) { - struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); - u32 ctrl; + struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); pm_runtime_get_sync(dev); - /* context restore */ - ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc->regmap, REG_CTRL, ctrl); - - if (tscadc->tsc_cell != -1) { - if (tscadc->tsc_wires == 5) - ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; - else - ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; - tscadc_idle_config(tscadc); - } - ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc->regmap, REG_CTRL, ctrl); - regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl); + tscadc_idle_config(tscadc); + regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl | CNTRLREG_SSENB); return 0; } static SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume); +static const struct ti_tscadc_data tscdata = { + .adc_feature_name = "TI-am335x-adc", + .adc_feature_compatible = "ti,am3359-adc", + .secondary_feature_name = "TI-am335x-tsc", + .secondary_feature_compatible = "ti,am3359-tsc", + .target_clk_rate = TSC_ADC_CLK, +}; + +static const struct ti_tscadc_data magdata = { + .adc_feature_name = "TI-am43xx-adc", + .adc_feature_compatible = "ti,am4372-adc", + .secondary_feature_name = "TI-am43xx-mag", + .secondary_feature_compatible = "ti,am4372-mag", + .target_clk_rate = MAG_ADC_CLK, +}; + static const struct of_device_id ti_tscadc_dt_ids[] = { - { .compatible = "ti,am3359-tscadc", }, + { .compatible = "ti,am3359-tscadc", .data = &tscdata }, + { .compatible = "ti,am4372-magadc", .data = &magdata }, { } }; MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids); @@ -363,6 +388,6 @@ static struct platform_driver ti_tscadc_driver = { module_platform_driver(ti_tscadc_driver); -MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver"); +MODULE_DESCRIPTION("TI touchscreen/magnetic stripe reader/ADC MFD controller driver"); MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index b55b1d5d6955..c282a05e7146 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -115,11 +115,9 @@ int tps65912_device_init(struct tps65912 *tps) } EXPORT_SYMBOL_GPL(tps65912_device_init); -int tps65912_device_exit(struct tps65912 *tps) +void tps65912_device_exit(struct tps65912 *tps) { regmap_del_irq_chip(tps->irq, tps->irq_data); - - return 0; } EXPORT_SYMBOL_GPL(tps65912_device_exit); diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c index f7c22ea7b36c..06eb2784d322 100644 --- a/drivers/mfd/tps65912-i2c.c +++ b/drivers/mfd/tps65912-i2c.c @@ -55,7 +55,9 @@ static int tps65912_i2c_remove(struct i2c_client *client) { struct tps65912 *tps = i2c_get_clientdata(client); - return tps65912_device_exit(tps); + tps65912_device_exit(tps); + + return 0; } static const struct i2c_device_id tps65912_i2c_id_table[] = { diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index 21a8d6ac5c4a..d701926aa46e 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -54,7 +54,9 @@ static int tps65912_spi_remove(struct spi_device *spi) { struct tps65912 *tps = spi_get_drvdata(spi); - return tps65912_device_exit(tps); + tps65912_device_exit(tps); + + return 0; } static const struct spi_device_id tps65912_spi_id_table[] = { diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c deleted file mode 100644 index 3c4e62c3406a..000000000000 --- a/drivers/mfd/tps80031.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * tps80031.c -- TI TPS80031/TPS80032 mfd core driver. - * - * MFD core driver for TI TPS80031/TPS80032 Fully Integrated - * Power Management with Power Path and Battery Charger - * - * Copyright (c) 2012, NVIDIA Corporation. - * - * Author: Laxman Dewangan <ldewangan@nvidia.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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -#include <linux/err.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mfd/core.h> -#include <linux/mfd/tps80031.h> -#include <linux/pm.h> -#include <linux/regmap.h> -#include <linux/slab.h> - -static const struct resource tps80031_rtc_resources[] = { - DEFINE_RES_IRQ(TPS80031_INT_RTC_ALARM), -}; - -/* TPS80031 sub mfd devices */ -static const struct mfd_cell tps80031_cell[] = { - { - .name = "tps80031-pmic", - }, - { - .name = "tps80031-clock", - }, - { - .name = "tps80031-rtc", - .num_resources = ARRAY_SIZE(tps80031_rtc_resources), - .resources = tps80031_rtc_resources, - }, - { - .name = "tps80031-gpadc", - }, - { - .name = "tps80031-fuel-gauge", - }, - { - .name = "tps80031-charger", - }, -}; - -static int tps80031_slave_address[TPS80031_NUM_SLAVES] = { - TPS80031_I2C_ID0_ADDR, - TPS80031_I2C_ID1_ADDR, - TPS80031_I2C_ID2_ADDR, - TPS80031_I2C_ID3_ADDR, -}; - -struct tps80031_pupd_data { - u8 reg; - u8 pullup_bit; - u8 pulldown_bit; -}; - -#define TPS80031_IRQ(_reg, _mask) \ - { \ - .reg_offset = (TPS80031_INT_MSK_LINE_##_reg) - \ - TPS80031_INT_MSK_LINE_A, \ - .mask = BIT(_mask), \ - } - -static const struct regmap_irq tps80031_main_irqs[] = { - [TPS80031_INT_PWRON] = TPS80031_IRQ(A, 0), - [TPS80031_INT_RPWRON] = TPS80031_IRQ(A, 1), - [TPS80031_INT_SYS_VLOW] = TPS80031_IRQ(A, 2), - [TPS80031_INT_RTC_ALARM] = TPS80031_IRQ(A, 3), - [TPS80031_INT_RTC_PERIOD] = TPS80031_IRQ(A, 4), - [TPS80031_INT_HOT_DIE] = TPS80031_IRQ(A, 5), - [TPS80031_INT_VXX_SHORT] = TPS80031_IRQ(A, 6), - [TPS80031_INT_SPDURATION] = TPS80031_IRQ(A, 7), - [TPS80031_INT_WATCHDOG] = TPS80031_IRQ(B, 0), - [TPS80031_INT_BAT] = TPS80031_IRQ(B, 1), - [TPS80031_INT_SIM] = TPS80031_IRQ(B, 2), - [TPS80031_INT_MMC] = TPS80031_IRQ(B, 3), - [TPS80031_INT_RES] = TPS80031_IRQ(B, 4), - [TPS80031_INT_GPADC_RT] = TPS80031_IRQ(B, 5), - [TPS80031_INT_GPADC_SW2_EOC] = TPS80031_IRQ(B, 6), - [TPS80031_INT_CC_AUTOCAL] = TPS80031_IRQ(B, 7), - [TPS80031_INT_ID_WKUP] = TPS80031_IRQ(C, 0), - [TPS80031_INT_VBUSS_WKUP] = TPS80031_IRQ(C, 1), - [TPS80031_INT_ID] = TPS80031_IRQ(C, 2), - [TPS80031_INT_VBUS] = TPS80031_IRQ(C, 3), - [TPS80031_INT_CHRG_CTRL] = TPS80031_IRQ(C, 4), - [TPS80031_INT_EXT_CHRG] = TPS80031_IRQ(C, 5), - [TPS80031_INT_INT_CHRG] = TPS80031_IRQ(C, 6), - [TPS80031_INT_RES2] = TPS80031_IRQ(C, 7), -}; - -static struct regmap_irq_chip tps80031_irq_chip = { - .name = "tps80031", - .irqs = tps80031_main_irqs, - .num_irqs = ARRAY_SIZE(tps80031_main_irqs), - .num_regs = 3, - .status_base = TPS80031_INT_STS_A, - .mask_base = TPS80031_INT_MSK_LINE_A, -}; - -#define PUPD_DATA(_reg, _pulldown_bit, _pullup_bit) \ - { \ - .reg = TPS80031_CFG_INPUT_PUPD##_reg, \ - .pulldown_bit = _pulldown_bit, \ - .pullup_bit = _pullup_bit, \ - } - -static const struct tps80031_pupd_data tps80031_pupds[] = { - [TPS80031_PREQ1] = PUPD_DATA(1, BIT(0), BIT(1)), - [TPS80031_PREQ2A] = PUPD_DATA(1, BIT(2), BIT(3)), - [TPS80031_PREQ2B] = PUPD_DATA(1, BIT(4), BIT(5)), - [TPS80031_PREQ2C] = PUPD_DATA(1, BIT(6), BIT(7)), - [TPS80031_PREQ3] = PUPD_DATA(2, BIT(0), BIT(1)), - [TPS80031_NRES_WARM] = PUPD_DATA(2, 0, BIT(2)), - [TPS80031_PWM_FORCE] = PUPD_DATA(2, BIT(5), 0), - [TPS80031_CHRG_EXT_CHRG_STATZ] = PUPD_DATA(2, 0, BIT(6)), - [TPS80031_SIM] = PUPD_DATA(3, BIT(0), BIT(1)), - [TPS80031_MMC] = PUPD_DATA(3, BIT(2), BIT(3)), - [TPS80031_GPADC_START] = PUPD_DATA(3, BIT(4), 0), - [TPS80031_DVSI2C_SCL] = PUPD_DATA(4, 0, BIT(0)), - [TPS80031_DVSI2C_SDA] = PUPD_DATA(4, 0, BIT(1)), - [TPS80031_CTLI2C_SCL] = PUPD_DATA(4, 0, BIT(2)), - [TPS80031_CTLI2C_SDA] = PUPD_DATA(4, 0, BIT(3)), -}; -static struct tps80031 *tps80031_power_off_dev; - -int tps80031_ext_power_req_config(struct device *dev, - unsigned long ext_ctrl_flag, int preq_bit, - int state_reg_add, int trans_reg_add) -{ - u8 res_ass_reg = 0; - int preq_mask_bit = 0; - int ret; - - if (!(ext_ctrl_flag & TPS80031_EXT_PWR_REQ)) - return 0; - - if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ1) { - res_ass_reg = TPS80031_PREQ1_RES_ASS_A + (preq_bit >> 3); - preq_mask_bit = 5; - } else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ2) { - res_ass_reg = TPS80031_PREQ2_RES_ASS_A + (preq_bit >> 3); - preq_mask_bit = 6; - } else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ3) { - res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (preq_bit >> 3); - preq_mask_bit = 7; - } - - /* Configure REQ_ASS registers */ - ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1, res_ass_reg, - BIT(preq_bit & 0x7)); - if (ret < 0) { - dev_err(dev, "reg 0x%02x setbit failed, err = %d\n", - res_ass_reg, ret); - return ret; - } - - /* Unmask the PREQ */ - ret = tps80031_clr_bits(dev, TPS80031_SLAVE_ID1, - TPS80031_PHOENIX_MSK_TRANSITION, BIT(preq_mask_bit)); - if (ret < 0) { - dev_err(dev, "reg 0x%02x clrbit failed, err = %d\n", - TPS80031_PHOENIX_MSK_TRANSITION, ret); - return ret; - } - - /* Switch regulator control to resource now */ - if (ext_ctrl_flag & (TPS80031_PWR_REQ_INPUT_PREQ2 | - TPS80031_PWR_REQ_INPUT_PREQ3)) { - ret = tps80031_update(dev, TPS80031_SLAVE_ID1, state_reg_add, - 0x0, TPS80031_STATE_MASK); - if (ret < 0) - dev_err(dev, "reg 0x%02x update failed, err = %d\n", - state_reg_add, ret); - } else { - ret = tps80031_update(dev, TPS80031_SLAVE_ID1, trans_reg_add, - TPS80031_TRANS_SLEEP_OFF, - TPS80031_TRANS_SLEEP_MASK); - if (ret < 0) - dev_err(dev, "reg 0x%02x update failed, err = %d\n", - trans_reg_add, ret); - } - return ret; -} -EXPORT_SYMBOL_GPL(tps80031_ext_power_req_config); - -static void tps80031_power_off(void) -{ - dev_info(tps80031_power_off_dev->dev, "switching off PMU\n"); - tps80031_write(tps80031_power_off_dev->dev, TPS80031_SLAVE_ID1, - TPS80031_PHOENIX_DEV_ON, TPS80031_DEVOFF); -} - -static void tps80031_pupd_init(struct tps80031 *tps80031, - struct tps80031_platform_data *pdata) -{ - struct tps80031_pupd_init_data *pupd_init_data = pdata->pupd_init_data; - int data_size = pdata->pupd_init_data_size; - int i; - - for (i = 0; i < data_size; ++i) { - struct tps80031_pupd_init_data *pupd_init = &pupd_init_data[i]; - const struct tps80031_pupd_data *pupd = - &tps80031_pupds[pupd_init->input_pin]; - u8 update_value = 0; - u8 update_mask = pupd->pulldown_bit | pupd->pullup_bit; - - if (pupd_init->setting == TPS80031_PUPD_PULLDOWN) - update_value = pupd->pulldown_bit; - else if (pupd_init->setting == TPS80031_PUPD_PULLUP) - update_value = pupd->pullup_bit; - - tps80031_update(tps80031->dev, TPS80031_SLAVE_ID1, pupd->reg, - update_value, update_mask); - } -} - -static int tps80031_init_ext_control(struct tps80031 *tps80031, - struct tps80031_platform_data *pdata) -{ - struct device *dev = tps80031->dev; - int ret; - int i; - - /* Clear all external control for this rail */ - for (i = 0; i < 9; ++i) { - ret = tps80031_write(dev, TPS80031_SLAVE_ID1, - TPS80031_PREQ1_RES_ASS_A + i, 0); - if (ret < 0) { - dev_err(dev, "reg 0x%02x write failed, err = %d\n", - TPS80031_PREQ1_RES_ASS_A + i, ret); - return ret; - } - } - - /* Mask the PREQ */ - ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1, - TPS80031_PHOENIX_MSK_TRANSITION, 0x7 << 5); - if (ret < 0) { - dev_err(dev, "reg 0x%02x set_bits failed, err = %d\n", - TPS80031_PHOENIX_MSK_TRANSITION, ret); - return ret; - } - return ret; -} - -static int tps80031_irq_init(struct tps80031 *tps80031, int irq, int irq_base) -{ - struct device *dev = tps80031->dev; - int i, ret; - - /* - * The MASK register used for updating status register when - * interrupt occurs and LINE register used to pass the status - * to actual interrupt line. As per datasheet: - * When INT_MSK_LINE [i] is set to 1, the associated interrupt - * number i is INT line masked, which means that no interrupt is - * generated on the INT line. - * When INT_MSK_LINE [i] is set to 0, the associated interrupt - * number i is line enabled: An interrupt is generated on the - * INT line. - * In any case, the INT_STS [i] status bit may or may not be updated, - * only linked to the INT_MSK_STS [i] configuration register bit. - * - * When INT_MSK_STS [i] is set to 1, the associated interrupt number - * i is status masked, which means that no interrupt is stored in - * the INT_STS[i] status bit. Note that no interrupt number i is - * generated on the INT line, even if the INT_MSK_LINE [i] register - * bit is set to 0. - * When INT_MSK_STS [i] is set to 0, the associated interrupt number i - * is status enabled: An interrupt status is updated in the INT_STS [i] - * register. The interrupt may or may not be generated on the INT line, - * depending on the INT_MSK_LINE [i] configuration register bit. - */ - for (i = 0; i < 3; i++) - tps80031_write(dev, TPS80031_SLAVE_ID2, - TPS80031_INT_MSK_STS_A + i, 0x00); - - ret = regmap_add_irq_chip(tps80031->regmap[TPS80031_SLAVE_ID2], irq, - IRQF_ONESHOT, irq_base, - &tps80031_irq_chip, &tps80031->irq_data); - if (ret < 0) { - dev_err(dev, "add irq failed, err = %d\n", ret); - return ret; - } - return ret; -} - -static bool rd_wr_reg_id0(struct device *dev, unsigned int reg) -{ - switch (reg) { - case TPS80031_SMPS1_CFG_FORCE ... TPS80031_SMPS2_CFG_VOLTAGE: - return true; - default: - return false; - } -} - -static bool rd_wr_reg_id1(struct device *dev, unsigned int reg) -{ - switch (reg) { - case TPS80031_SECONDS_REG ... TPS80031_RTC_RESET_STATUS_REG: - case TPS80031_VALIDITY0 ... TPS80031_VALIDITY7: - case TPS80031_PHOENIX_START_CONDITION ... TPS80031_KEY_PRESS_DUR_CFG: - case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE: - case TPS80031_BROADCAST_ADDR_ALL ... TPS80031_BROADCAST_ADDR_CLK_RST: - case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE: - case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE: - case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C: - case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING: - case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD: - case TPS80031_BACKUP_REG: - return true; - default: - return false; - } -} - -static bool is_volatile_reg_id1(struct device *dev, unsigned int reg) -{ - switch (reg) { - case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE: - case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE: - case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE: - case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C: - case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING: - case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD: - return true; - default: - return false; - } -} - -static bool rd_wr_reg_id2(struct device *dev, unsigned int reg) -{ - switch (reg) { - case TPS80031_USB_VENDOR_ID_LSB ... TPS80031_USB_OTG_REVISION: - case TPS80031_GPADC_CTRL ... TPS80031_CTRL_P1: - case TPS80031_RTCH0_LSB ... TPS80031_GPCH0_MSB: - case TPS80031_TOGGLE1 ... TPS80031_VIBMODE: - case TPS80031_PWM1ON ... TPS80031_PWM2OFF: - case TPS80031_FG_REG_00 ... TPS80031_FG_REG_11: - case TPS80031_INT_STS_A ... TPS80031_INT_MSK_STS_C: - case TPS80031_CONTROLLER_CTRL2 ... TPS80031_LED_PWM_CTRL2: - return true; - default: - return false; - } -} - -static bool rd_wr_reg_id3(struct device *dev, unsigned int reg) -{ - switch (reg) { - case TPS80031_GPADC_TRIM0 ... TPS80031_GPADC_TRIM18: - return true; - default: - return false; - } -} - -static const struct regmap_config tps80031_regmap_configs[] = { - { - .reg_bits = 8, - .val_bits = 8, - .writeable_reg = rd_wr_reg_id0, - .readable_reg = rd_wr_reg_id0, - .max_register = TPS80031_MAX_REGISTER, - }, - { - .reg_bits = 8, - .val_bits = 8, - .writeable_reg = rd_wr_reg_id1, - .readable_reg = rd_wr_reg_id1, - .volatile_reg = is_volatile_reg_id1, - .max_register = TPS80031_MAX_REGISTER, - }, - { - .reg_bits = 8, - .val_bits = 8, - .writeable_reg = rd_wr_reg_id2, - .readable_reg = rd_wr_reg_id2, - .max_register = TPS80031_MAX_REGISTER, - }, - { - .reg_bits = 8, - .val_bits = 8, - .writeable_reg = rd_wr_reg_id3, - .readable_reg = rd_wr_reg_id3, - .max_register = TPS80031_MAX_REGISTER, - }, -}; - -static int tps80031_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct tps80031_platform_data *pdata = dev_get_platdata(&client->dev); - struct tps80031 *tps80031; - int ret; - uint8_t es_version; - uint8_t ep_ver; - int i; - - if (!pdata) { - dev_err(&client->dev, "tps80031 requires platform data\n"); - return -EINVAL; - } - - tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL); - if (!tps80031) - return -ENOMEM; - - for (i = 0; i < TPS80031_NUM_SLAVES; i++) { - if (tps80031_slave_address[i] == client->addr) - tps80031->clients[i] = client; - else - tps80031->clients[i] = devm_i2c_new_dummy_device(&client->dev, - client->adapter, tps80031_slave_address[i]); - if (IS_ERR(tps80031->clients[i])) { - dev_err(&client->dev, "can't attach client %d\n", i); - return PTR_ERR(tps80031->clients[i]); - } - - i2c_set_clientdata(tps80031->clients[i], tps80031); - tps80031->regmap[i] = devm_regmap_init_i2c(tps80031->clients[i], - &tps80031_regmap_configs[i]); - if (IS_ERR(tps80031->regmap[i])) { - ret = PTR_ERR(tps80031->regmap[i]); - dev_err(&client->dev, - "regmap %d init failed, err %d\n", i, ret); - return ret; - } - } - - ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3, - TPS80031_JTAGVERNUM, &es_version); - if (ret < 0) { - dev_err(&client->dev, - "Silicon version number read failed: %d\n", ret); - return ret; - } - - ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3, - TPS80031_EPROM_REV, &ep_ver); - if (ret < 0) { - dev_err(&client->dev, - "Silicon eeprom version read failed: %d\n", ret); - return ret; - } - - dev_info(&client->dev, "ES version 0x%02x and EPROM version 0x%02x\n", - es_version, ep_ver); - tps80031->es_version = es_version; - tps80031->dev = &client->dev; - i2c_set_clientdata(client, tps80031); - tps80031->chip_info = id->driver_data; - - ret = tps80031_irq_init(tps80031, client->irq, pdata->irq_base); - if (ret) { - dev_err(&client->dev, "IRQ init failed: %d\n", ret); - return ret; - } - - tps80031_pupd_init(tps80031, pdata); - - tps80031_init_ext_control(tps80031, pdata); - - ret = mfd_add_devices(tps80031->dev, -1, - tps80031_cell, ARRAY_SIZE(tps80031_cell), - NULL, 0, - regmap_irq_get_domain(tps80031->irq_data)); - if (ret < 0) { - dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); - goto fail_mfd_add; - } - - if (pdata->use_power_off && !pm_power_off) { - tps80031_power_off_dev = tps80031; - pm_power_off = tps80031_power_off; - } - return 0; - -fail_mfd_add: - regmap_del_irq_chip(client->irq, tps80031->irq_data); - return ret; -} - -static const struct i2c_device_id tps80031_id_table[] = { - { "tps80031", TPS80031 }, - { "tps80032", TPS80032 }, - { } -}; - -static struct i2c_driver tps80031_driver = { - .driver = { - .name = "tps80031", - .suppress_bind_attrs = true, - }, - .probe = tps80031_probe, - .id_table = tps80031_id_table, -}; - -static int __init tps80031_init(void) -{ - return i2c_add_driver(&tps80031_driver); -} -subsys_initcall(tps80031_init); diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c index aa19a6a4fdbf..68e2fa2fda99 100644 --- a/drivers/mfd/wcd934x.c +++ b/drivers/mfd/wcd934x.c @@ -2,14 +2,13 @@ // Copyright (c) 2019, Linaro Limited #include <linux/clk.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/mfd/core.h> #include <linux/mfd/wcd934x/registers.h> #include <linux/mfd/wcd934x/wcd934x.h> #include <linux/module.h> -#include <linux/of_gpio.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/platform_device.h> @@ -210,7 +209,8 @@ static int wcd934x_slim_probe(struct slim_device *sdev) struct device *dev = &sdev->dev; struct device_node *np = dev->of_node; struct wcd934x_ddata *ddata; - int reset_gpio, ret; + struct gpio_desc *reset_gpio; + int ret; ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); if (!ddata) @@ -221,13 +221,6 @@ static int wcd934x_slim_probe(struct slim_device *sdev) return dev_err_probe(ddata->dev, ddata->irq, "Failed to get IRQ\n"); - reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); - if (reset_gpio < 0) { - dev_err(dev, "Failed to get reset gpio: err = %d\n", - reset_gpio); - return reset_gpio; - } - ddata->extclk = devm_clk_get(dev, "extclk"); if (IS_ERR(ddata->extclk)) { dev_err(dev, "Failed to get extclk"); @@ -258,9 +251,13 @@ static int wcd934x_slim_probe(struct slim_device *sdev) * SYS_RST_N shouldn't be pulled high during this time */ usleep_range(600, 650); - gpio_direction_output(reset_gpio, 0); + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(reset_gpio)) { + return dev_err_probe(dev, PTR_ERR(reset_gpio), + "Failed to get reset gpio: err = %ld\n", PTR_ERR(reset_gpio)); + } msleep(20); - gpio_set_value(reset_gpio, 1); + gpiod_set_value(reset_gpio, 1); msleep(20); ddata->dev = dev; diff --git a/drivers/misc/hi6421v600-irq.c b/drivers/misc/hi6421v600-irq.c index 08535e97ff43..1c763796cf1f 100644 --- a/drivers/misc/hi6421v600-irq.c +++ b/drivers/misc/hi6421v600-irq.c @@ -10,7 +10,6 @@ #include <linux/bitops.h> #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/mfd/hi6421-spmi-pmic.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/platform_device.h> @@ -220,7 +219,7 @@ static int hi6421v600_irq_probe(struct platform_device *pdev) struct platform_device *pmic_pdev; struct device *dev = &pdev->dev; struct hi6421v600_irq *priv; - struct hi6421_spmi_pmic *pmic; + struct regmap *regmap; unsigned int virq; int i, ret; @@ -229,8 +228,8 @@ static int hi6421v600_irq_probe(struct platform_device *pdev) * which should first set drvdata. If this doesn't happen, hit * a warn on and return. */ - pmic = dev_get_drvdata(pmic_dev); - if (WARN_ON(!pmic)) + regmap = dev_get_drvdata(pmic_dev); + if (WARN_ON(!regmap)) return -ENODEV; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -238,7 +237,7 @@ static int hi6421v600_irq_probe(struct platform_device *pdev) return -ENOMEM; priv->dev = dev; - priv->regmap = pmic->regmap; + priv->regmap = regmap; spin_lock_init(&priv->lock); diff --git a/drivers/regulator/hi6421v600-regulator.c b/drivers/regulator/hi6421v600-regulator.c index 662d87ae61cb..4671678f6b19 100644 --- a/drivers/regulator/hi6421v600-regulator.c +++ b/drivers/regulator/hi6421v600-regulator.c @@ -9,8 +9,8 @@ // Guodong Xu <guodong.xu@linaro.org> #include <linux/delay.h> -#include <linux/mfd/hi6421-spmi-pmic.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> @@ -237,7 +237,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev) struct hi6421_spmi_reg_priv *priv; struct hi6421_spmi_reg_info *info; struct device *dev = &pdev->dev; - struct hi6421_spmi_pmic *pmic; + struct regmap *regmap; struct regulator_dev *rdev; int i; @@ -246,8 +246,8 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev) * which should first set drvdata. If this doesn't happen, hit * a warn on and return. */ - pmic = dev_get_drvdata(pmic_dev); - if (WARN_ON(!pmic)) + regmap = dev_get_drvdata(pmic_dev); + if (WARN_ON(!regmap)) return -ENODEV; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -261,7 +261,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev) config.dev = pdev->dev.parent; config.driver_data = priv; - config.regmap = pmic->regmap; + config.regmap = regmap; rdev = devm_regulator_register(dev, &info->desc, &config); if (IS_ERR(rdev)) { |