From 43e30f23b589642a7eaff005bc30444a5247976c Mon Sep 17 00:00:00 2001 From: David Jander Date: Mon, 2 Sep 2013 09:46:11 +0200 Subject: mfd: da9052: Avoid multiwrite mode due to silicon errata DA9053 (up to revision bc) can corrupt internal registers when multi-write mode is enabled and power is removed or during shutdown. Signed-off-by: David Jander Signed-off-by: Lee Jones --- drivers/mfd/da9052-i2c.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 6a9fec40d018..c319c4ef5d49 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -86,7 +86,11 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) return 0; } -static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) +/* + * According to errata item 24, multiwrite mode should be avoided + * in order to prevent register data corruption after power-down. + */ +static int da9052_i2c_disable_multiwrite(struct da9052 *da9052) { int reg_val, ret; @@ -94,8 +98,8 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) if (ret < 0) return ret; - if (reg_val & DA9052_CONTROL_B_WRITEMODE) { - reg_val &= ~DA9052_CONTROL_B_WRITEMODE; + if (!(reg_val & DA9052_CONTROL_B_WRITEMODE)) { + reg_val |= DA9052_CONTROL_B_WRITEMODE; ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG, reg_val); if (ret < 0) @@ -154,7 +158,7 @@ static int da9052_i2c_probe(struct i2c_client *client, return ret; } - ret = da9052_i2c_enable_multiwrite(da9052); + ret = da9052_i2c_disable_multiwrite(da9052); if (ret < 0) return ret; -- cgit v1.2.3 From 8a8320c2e78d1b619a8fa8eb5ae946b8691de604 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 8 Sep 2013 00:25:36 -0700 Subject: mfd: sm501: dbg_regs attribute must be read-only Fix: sm501 sm501: SM501 At b3e00000: Version 050100a0, 8 Mb, IRQ 100 Attribute dbg_regs: write permission without 'store' ------------[ cut here ]------------ WARNING: at drivers/base/core.c:620 dbg_regs does not have a write function and must therefore be marked as read-only. Signed-off-by: Guenter Roeck Signed-off-by: Lee Jones --- drivers/mfd/sm501.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 33f040c558d0..3799a3d64415 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1232,7 +1232,7 @@ static ssize_t sm501_dbg_regs(struct device *dev, } -static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL); +static DEVICE_ATTR(dbg_regs, 0444, sm501_dbg_regs, NULL); /* sm501_init_reg * -- cgit v1.2.3 From b5f90240e1ef0568a8c666da3c3be4c6a682c5a6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 6 Sep 2013 16:14:28 +0100 Subject: mfd: wm8994: Inline register I/O functions Since the register I/O functions are all simple wrappers for the regmap equivalents inline them to provide a small code size saving and an example of good practice. Signed-off-by: Mark Brown Signed-off-by: Lee Jones --- drivers/mfd/wm8994-core.c | 78 ----------------------------------------------- 1 file changed, 78 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index e1c283e6d4e5..030827511667 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -33,84 +33,6 @@ #include "wm8994.h" -/** - * wm8994_reg_read: Read a single WM8994 register. - * - * @wm8994: Device to read from. - * @reg: Register to read. - */ -int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg) -{ - unsigned int val; - int ret; - - ret = regmap_read(wm8994->regmap, reg, &val); - - if (ret < 0) - return ret; - else - return val; -} -EXPORT_SYMBOL_GPL(wm8994_reg_read); - -/** - * wm8994_bulk_read: Read multiple WM8994 registers - * - * @wm8994: Device to read from - * @reg: First register - * @count: Number of registers - * @buf: Buffer to fill. The data will be returned big endian. - */ -int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, - int count, u16 *buf) -{ - return regmap_bulk_read(wm8994->regmap, reg, buf, count); -} - -/** - * wm8994_reg_write: Write a single WM8994 register. - * - * @wm8994: Device to write to. - * @reg: Register to write to. - * @val: Value to write. - */ -int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, - unsigned short val) -{ - return regmap_write(wm8994->regmap, reg, val); -} -EXPORT_SYMBOL_GPL(wm8994_reg_write); - -/** - * wm8994_bulk_write: Write multiple WM8994 registers - * - * @wm8994: Device to write to - * @reg: First register - * @count: Number of registers - * @buf: Buffer to write from. Data must be big-endian formatted. - */ -int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg, - int count, const u16 *buf) -{ - return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16)); -} -EXPORT_SYMBOL_GPL(wm8994_bulk_write); - -/** - * wm8994_set_bits: Set the value of a bitfield in a WM8994 register - * - * @wm8994: Device to write to. - * @reg: Register to write to. - * @mask: Mask of bits to set. - * @val: Value to set (unshifted) - */ -int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, - unsigned short mask, unsigned short val) -{ - return regmap_update_bits(wm8994->regmap, reg, mask, val); -} -EXPORT_SYMBOL_GPL(wm8994_set_bits); - static struct mfd_cell wm8994_regulator_devs[] = { { .name = "wm8994-ldo", -- cgit v1.2.3 From 234506ad3f28d5eea85f739f637cde6d9e8f5a88 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Sep 2013 17:17:13 -0600 Subject: mfd: tps6586x: Implement irq_set_wake rtc-tps6586x calls enable/disable_irq_wake() during suspend/resume. Since the main tps6586x irq_chip doesn't implement .irq_set_wake, this causes the RTC's enable_irq_wake() to fail, and the disable_irq_wake() to spew a WARN about unbalanced wake disable. Solve this by implementing .irq_set_wake. Also, I assume that enable_irq_wake() shouldn't be called unconditionally in tps6586x_irq_init(), since this is now triggered by IRQ children setting up their cascaded IRQs for wake. So, remove that. Signed-off-by: Stephen Warren Signed-off-by: Lee Jones --- drivers/mfd/tps6586x.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index f54fe4d4f77b..68906b17ee52 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -124,6 +124,7 @@ struct tps6586x { struct i2c_client *client; struct regmap *regmap; + int irq; struct irq_chip irq_chip; struct mutex irq_lock; int irq_base; @@ -261,12 +262,23 @@ static void tps6586x_irq_sync_unlock(struct irq_data *data) mutex_unlock(&tps6586x->irq_lock); } +#ifdef CONFIG_PM_SLEEP +static int tps6586x_irq_set_wake(struct irq_data *irq_data, unsigned int on) +{ + struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data); + return irq_set_irq_wake(tps6586x->irq, on); +} +#else +#define tps6586x_irq_set_wake NULL +#endif + static struct irq_chip tps6586x_irq_chip = { .name = "tps6586x", .irq_bus_lock = tps6586x_irq_lock, .irq_bus_sync_unlock = tps6586x_irq_sync_unlock, .irq_disable = tps6586x_irq_disable, .irq_enable = tps6586x_irq_enable, + .irq_set_wake = tps6586x_irq_set_wake, }; static int tps6586x_irq_map(struct irq_domain *h, unsigned int virq, @@ -331,6 +343,8 @@ static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq, int new_irq_base; int irq_num = ARRAY_SIZE(tps6586x_irqs); + tps6586x->irq = irq; + mutex_init(&tps6586x->irq_lock); for (i = 0; i < 5; i++) { tps6586x->mask_reg[i] = 0xff; @@ -360,10 +374,8 @@ static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq, ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT, "tps6586x", tps6586x); - if (!ret) { + if (!ret) device_init_wakeup(tps6586x->dev, 1); - enable_irq_wake(irq); - } return ret; } -- cgit v1.2.3 From ecf67ac335bba0867ce7c6470ae4a3574e0f2838 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 10 Sep 2013 16:25:50 +0530 Subject: mfd: aat2870: Fix sparse error Fixes the following error: drivers/mfd/aat2870-core.c:296:20: error: incompatible types in comparison expression (different type sizes) Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/aat2870-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 6f68472e0ca6..14d9542a4eed 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -293,7 +293,7 @@ static ssize_t aat2870_reg_write_file(struct file *file, unsigned long addr, val; int ret; - buf_size = min(count, (sizeof(buf)-1)); + buf_size = min(count, (size_t)(sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) { dev_err(aat2870->dev, "Failed to copy from user\n"); return -EFAULT; -- cgit v1.2.3 From 18fefda9ee13e377cf6c5542818b7be066972843 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 11 Sep 2013 19:20:37 +0800 Subject: mfd: ucb1x00-core: Fix error return code in ucb1x00_probe() Fix to return a negative error code in the irq alloc error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Lee Jones --- drivers/mfd/ucb1x00-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index d5966e6b5a7d..0313f839e8fa 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -553,6 +553,7 @@ static int ucb1x00_probe(struct mcp *mcp) if (ucb->irq_base < 0) { dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n", ucb->irq_base); + ret = ucb->irq_base; goto err_irq_alloc; } -- cgit v1.2.3 From 1fcd5d815e12eafa7304f1dd39900eaa332085eb Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 12 Sep 2013 15:41:32 +0900 Subject: mfd: lpc_ich: Remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Lee Jones --- drivers/mfd/lpc_ich.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 9483bc8472a5..316af07ede3f 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -969,7 +969,6 @@ static int lpc_ich_probe(struct pci_dev *dev, if (!cell_added) { dev_warn(&dev->dev, "No MFD cells added\n"); lpc_ich_restore_config_space(dev); - pci_set_drvdata(dev, NULL); return -ENODEV; } @@ -980,7 +979,6 @@ static void lpc_ich_remove(struct pci_dev *dev) { mfd_remove_devices(&dev->dev); lpc_ich_restore_config_space(dev); - pci_set_drvdata(dev, NULL); } static struct pci_driver lpc_ich_driver = { -- cgit v1.2.3 From 928dfb2c750da3e1db181742198da4d9026012b0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 12 Sep 2013 15:43:07 +0900 Subject: mfd: sm501: Remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Lee Jones --- drivers/mfd/sm501.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 3799a3d64415..c2c8c91c6c7b 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1660,7 +1660,6 @@ static int sm501_pci_probe(struct pci_dev *dev, err3: pci_disable_device(dev); err2: - pci_set_drvdata(dev, NULL); kfree(sm); err1: return err; @@ -1695,7 +1694,6 @@ static void sm501_pci_remove(struct pci_dev *dev) release_resource(sm->regs_claim); kfree(sm->regs_claim); - pci_set_drvdata(dev, NULL); pci_disable_device(dev); } -- cgit v1.2.3 From 7902fe8cbc58ae2bd3dad1a8ecf28ce83b1ba3a8 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 13 Sep 2013 11:23:57 +0900 Subject: mfd: timberdale: Remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. It also removes unnecessary label such as 'err_request'. Signed-off-by: Jingoo Han Signed-off-by: Lee Jones --- drivers/mfd/timberdale.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index a6755ec7bd6a..dbb34f94e5e3 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -678,7 +678,7 @@ static int timb_probe(struct pci_dev *dev, priv->ctl_mapbase = mapbase + CHIPCTLOFFSET; if (!request_mem_region(priv->ctl_mapbase, CHIPCTLSIZE, "timb-ctl")) { dev_err(&dev->dev, "Failed to request ctl mem\n"); - goto err_request; + goto err_start; } priv->ctl_membase = ioremap(priv->ctl_mapbase, CHIPCTLSIZE); @@ -828,13 +828,10 @@ err_config: iounmap(priv->ctl_membase); err_ioremap: release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); -err_request: - pci_set_drvdata(dev, NULL); err_start: pci_disable_device(dev); err_enable: kfree(priv); - pci_set_drvdata(dev, NULL); return -ENODEV; } @@ -851,7 +848,6 @@ static void timb_remove(struct pci_dev *dev) pci_disable_msix(dev); pci_disable_device(dev); - pci_set_drvdata(dev, NULL); kfree(priv); } -- cgit v1.2.3 From 26b818511c6562ce372566c219a2ef1afea35fe6 Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Fri, 13 Sep 2013 17:45:43 +0800 Subject: mfd: rtsx: Modify rts5249_optimize_phy In some platforms, specially Thinkpad series, rts5249 won't be initialized properly. So we need adjust some phy parameters to improve the compatibility issue. It is a little different between simulation and real chip. We have no idea about which configuration is better before tape-out. We set default settings according to simulation, but need to tune these parameters after getting the real chip. I can't explain every change in detail here. The below information is just a rough description: PHY_REG_REV: Disable internal clkreq_tx, enable rx_pwst PHY_BPCR: No change, just turn the magic number to macro definitions PHY_PCR: Change OOBS sensitivity, from 60mV to 90mV PHY_RCR2: Control charge-pump current automatically PHY_FLD4: Use TX cmu reference clock PHY_RDR: Change RXDSEL from 30nF to 1.9nF PHY_RCR1: Change the duration between adp_st and asserting cp_en from 0.32 us to 0.64us PHY_FLD3: Adjust internal timers PHY_TUNE: Fine tune the regulator12 output voltage Signed-off-by: Wei WANG Signed-off-by: Lee Jones --- drivers/mfd/rts5249.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index 3b835f593e35..573de7bfcced 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -130,13 +130,57 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr) { int err; - err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, 0xFE46); + err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, + PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED | + PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN | + PHY_REG_REV_RX_PWST | PHY_REG_REV_CLKREQ_DLY_TIMER_1_0 | + PHY_REG_REV_STOP_CLKRD | PHY_REG_REV_STOP_CLKWR); if (err < 0) return err; msleep(1); - return rtsx_pci_write_phy_register(pcr, PHY_BPCR, 0x05C0); + err = rtsx_pci_write_phy_register(pcr, PHY_BPCR, + PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL | + PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_PCR, + PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 | + PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 | + PHY_PCR_RSSI_EN); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_RCR2, + PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR | + PHY_RCR2_CDR_CP_10 | PHY_RCR2_CDR_SR_2 | + PHY_RCR2_FREQSEL_12 | PHY_RCR2_CPADJEN | + PHY_RCR2_CDR_SC_8 | PHY_RCR2_CALIB_LATE); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_FLD4, + PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF | + PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA | + PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER | + PHY_FLD4_BER_CHK_EN); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_RDR, PHY_RDR_RXDSEL_1_9); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_RCR1, + PHY_RCR1_ADP_TIME | PHY_RCR1_VCO_COARSE); + if (err < 0) + return err; + err = rtsx_pci_write_phy_register(pcr, PHY_FLD3, + PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 | + PHY_FLD3_RXDELINK); + if (err < 0) + return err; + return rtsx_pci_write_phy_register(pcr, PHY_TUNE, + PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 | + PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 | + PHY_TUNE_TUNED12); } static int rts5249_turn_on_led(struct rtsx_pcr *pcr) -- cgit v1.2.3 From 9875555e449cc46610cdf10302e3e66365a41e94 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 17 Sep 2013 15:23:04 +0100 Subject: mfd: arizona: Update registers for WM5110 DSP DSPx_CONTROL_1 and DSPx_CLOCKING_1 are not volatile registers and are incorrectly marked as such, fix this. Also add the DSP scratch registers, which are frequently used to output debug info from the DSP core. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 3113e39b318e..a8a9bb972cfe 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -2291,21 +2291,37 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_DSP1_STATUS_1: case ARIZONA_DSP1_STATUS_2: case ARIZONA_DSP1_STATUS_3: + case ARIZONA_DSP1_SCRATCH_0: + case ARIZONA_DSP1_SCRATCH_1: + case ARIZONA_DSP1_SCRATCH_2: + case ARIZONA_DSP1_SCRATCH_3: case ARIZONA_DSP2_CONTROL_1: case ARIZONA_DSP2_CLOCKING_1: case ARIZONA_DSP2_STATUS_1: case ARIZONA_DSP2_STATUS_2: case ARIZONA_DSP2_STATUS_3: + case ARIZONA_DSP2_SCRATCH_0: + case ARIZONA_DSP2_SCRATCH_1: + case ARIZONA_DSP2_SCRATCH_2: + case ARIZONA_DSP2_SCRATCH_3: case ARIZONA_DSP3_CONTROL_1: case ARIZONA_DSP3_CLOCKING_1: case ARIZONA_DSP3_STATUS_1: case ARIZONA_DSP3_STATUS_2: case ARIZONA_DSP3_STATUS_3: + case ARIZONA_DSP3_SCRATCH_0: + case ARIZONA_DSP3_SCRATCH_1: + case ARIZONA_DSP3_SCRATCH_2: + case ARIZONA_DSP3_SCRATCH_3: case ARIZONA_DSP4_CONTROL_1: case ARIZONA_DSP4_CLOCKING_1: case ARIZONA_DSP4_STATUS_1: case ARIZONA_DSP4_STATUS_2: case ARIZONA_DSP4_STATUS_3: + case ARIZONA_DSP4_SCRATCH_0: + case ARIZONA_DSP4_SCRATCH_1: + case ARIZONA_DSP4_SCRATCH_2: + case ARIZONA_DSP4_SCRATCH_3: return true; default: return false; @@ -2352,20 +2368,34 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_FX_CTRL2: case ARIZONA_ASRC_STATUS: case ARIZONA_DSP_STATUS: - case ARIZONA_DSP1_CONTROL_1: - case ARIZONA_DSP1_CLOCKING_1: case ARIZONA_DSP1_STATUS_1: case ARIZONA_DSP1_STATUS_2: case ARIZONA_DSP1_STATUS_3: + case ARIZONA_DSP1_SCRATCH_0: + case ARIZONA_DSP1_SCRATCH_1: + case ARIZONA_DSP1_SCRATCH_2: + case ARIZONA_DSP1_SCRATCH_3: case ARIZONA_DSP2_STATUS_1: case ARIZONA_DSP2_STATUS_2: case ARIZONA_DSP2_STATUS_3: + case ARIZONA_DSP2_SCRATCH_0: + case ARIZONA_DSP2_SCRATCH_1: + case ARIZONA_DSP2_SCRATCH_2: + case ARIZONA_DSP2_SCRATCH_3: case ARIZONA_DSP3_STATUS_1: case ARIZONA_DSP3_STATUS_2: case ARIZONA_DSP3_STATUS_3: + case ARIZONA_DSP3_SCRATCH_0: + case ARIZONA_DSP3_SCRATCH_1: + case ARIZONA_DSP3_SCRATCH_2: + case ARIZONA_DSP3_SCRATCH_3: case ARIZONA_DSP4_STATUS_1: case ARIZONA_DSP4_STATUS_2: case ARIZONA_DSP4_STATUS_3: + case ARIZONA_DSP4_SCRATCH_0: + case ARIZONA_DSP4_SCRATCH_1: + case ARIZONA_DSP4_SCRATCH_2: + case ARIZONA_DSP4_SCRATCH_3: return true; default: return false; -- cgit v1.2.3 From bef781617691488472f31ca9e5978de5bd064c56 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 17 Sep 2013 15:44:20 +0100 Subject: mfd: wm5110: Update noise gate default to match the patch file The default value for the noise gate control register is changed in the patch file, we need to reflect this in the defaults array, this patch does so. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index a8a9bb972cfe..f71bd9b3d0a2 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -592,7 +592,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x0000043E, 0x0080 }, /* R1086 - DAC Volume Limit 6R */ { 0x0000043F, 0x0800 }, /* R1087 - Noise Gate Select 6R */ { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ - { 0x00000458, 0x0001 }, /* R1112 - Noise Gate Control */ + { 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */ { 0x00000480, 0x0040 }, /* R1152 - Class W ANC Threshold 1 */ { 0x00000481, 0x0040 }, /* R1153 - Class W ANC Threshold 2 */ { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ -- cgit v1.2.3 From af1192d769a146328cabfe11916f107f35561ae8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 20 Sep 2013 14:19:34 +0530 Subject: mfd: mc12xx-i2c: rtsx_pcr: ti-ssp: Remove redundant dev_set_drvdata Driver core sets driver data to NULL upon failure or remove. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/mc13xxx-i2c.c | 1 - drivers/mfd/rtsx_pcr.c | 5 +---- drivers/mfd/ti-ssp.c | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index f745e27ee874..898bd335cd8e 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -78,7 +78,6 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", ret); - dev_set_drvdata(&client->dev, NULL); return ret; } diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index e6ae7720f9e1..11e20afbdcac 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -1149,7 +1149,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, pcr->remap_addr = ioremap_nocache(base, len); if (!pcr->remap_addr) { ret = -ENOMEM; - goto free_host; + goto free_handle; } pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev), @@ -1209,8 +1209,6 @@ disable_msi: pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr); unmap: iounmap(pcr->remap_addr); -free_host: - dev_set_drvdata(&pcidev->dev, NULL); free_handle: kfree(handle); free_pcr: @@ -1242,7 +1240,6 @@ static void rtsx_pci_remove(struct pci_dev *pcidev) pci_disable_msi(pcr->pci); iounmap(pcr->remap_addr); - dev_set_drvdata(&pcidev->dev, NULL); pci_release_regions(pcidev); pci_disable_device(pcidev); diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c index 1c2b994e1f6c..71e3e0c5bf73 100644 --- a/drivers/mfd/ti-ssp.c +++ b/drivers/mfd/ti-ssp.c @@ -445,7 +445,6 @@ static int ti_ssp_remove(struct platform_device *pdev) iounmap(ssp->regs); release_mem_region(ssp->res->start, resource_size(ssp->res)); kfree(ssp); - dev_set_drvdata(dev, NULL); return 0; } -- cgit v1.2.3 From 60013b94d9530346db963474f7fde8aecabaff25 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 22 Sep 2013 21:49:18 +0200 Subject: mfd: Add STw481x driver This adds a driver for the STw481x PMICs found in the Nomadik family of platforms. This one uses pure device tree probing. Print some of the OTP registers on boot and register a regulator MFD child. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 10 ++ drivers/mfd/Makefile | 1 + drivers/mfd/stw481x.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 drivers/mfd/stw481x.c (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 914c3d142f78..d078fe4a82ef 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1151,6 +1151,16 @@ config MFD_WM8994 core support for the WM8994, in order to use the actual functionaltiy of the device other drivers must be enabled. +config MFD_STW481X + bool "Support for ST Microelectronics STw481x" + depends on I2C && ARCH_NOMADIK + select REGMAP_I2C + select MFD_CORE + help + Select this option to enable the STw481x chip driver used + in various ST Microelectronics and ST-Ericsson embedded + Nomadik series. + endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 15b905c6553c..656cec90a1e5 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -162,3 +162,4 @@ obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o obj-$(CONFIG_MFD_RETU) += retu-mfd.o obj-$(CONFIG_MFD_AS3711) += as3711.o +obj-$(CONFIG_MFD_STW481X) += stw481x.o diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c new file mode 100644 index 000000000000..1243d5c6a448 --- /dev/null +++ b/drivers/mfd/stw481x.c @@ -0,0 +1,250 @@ +/* + * Core driver for STw4810/STw4811 + * + * Copyright (C) 2013 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * + * Author: Linus Walleij + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This driver can only access the non-USB portions of STw4811, the register + * range 0x00-0x10 dealing with USB is bound to the two special I2C pins used + * for USB control. + */ + +/* Registers inside the power control address space */ +#define STW_PC_VCORE_SEL 0x05U +#define STW_PC_VAUX_SEL 0x06U +#define STW_PC_VPLL_SEL 0x07U + +/** + * stw481x_get_pctl_reg() - get a power control register + * @stw481x: handle to the stw481x chip + * @reg: power control register to fetch + * + * The power control registers is a set of one-time-programmable registers + * in its own register space, accessed by writing addess bits to these + * two registers: bits 7,6,5 of PCTL_REG_LO corresponds to the 3 LSBs of + * the address and bits 8,9 of PCTL_REG_HI corresponds to the 2 MSBs of + * the address, forming an address space of 5 bits, i.e. 32 registers + * 0x00 ... 0x1f can be obtained. + */ +static int stw481x_get_pctl_reg(struct stw481x *stw481x, u8 reg) +{ + u8 msb = (reg >> 3) & 0x03; + u8 lsb = (reg << 5) & 0xe0; + unsigned int val; + u8 vrfy; + int ret; + + ret = regmap_write(stw481x->map, STW_PCTL_REG_HI, msb); + if (ret) + return ret; + ret = regmap_write(stw481x->map, STW_PCTL_REG_LO, lsb); + if (ret) + return ret; + ret = regmap_read(stw481x->map, STW_PCTL_REG_HI, &val); + if (ret) + return ret; + vrfy = (val & 0x03) << 3; + ret = regmap_read(stw481x->map, STW_PCTL_REG_LO, &val); + if (ret) + return ret; + vrfy |= ((val >> 5) & 0x07); + if (vrfy != reg) + return -EIO; + return (val >> 1) & 0x0f; +} + +static int stw481x_startup(struct stw481x *stw481x) +{ + /* Voltages multiplied by 100 */ + u8 vcore_val[] = { 100, 105, 110, 115, 120, 122, 124, 126, 128, + 130, 132, 134, 136, 138, 140, 145 }; + u8 vpll_val[] = { 105, 120, 130, 180 }; + u8 vaux_val[] = { 15, 18, 25, 28 }; + u8 vcore; + u8 vcore_slp; + u8 vpll; + u8 vaux; + bool vaux_en; + bool it_warn; + int ret; + unsigned int val; + + ret = regmap_read(stw481x->map, STW_CONF1, &val); + if (ret) + return ret; + vaux_en = !!(val & STW_CONF1_PDN_VAUX); + it_warn = !!(val & STW_CONF1_IT_WARN); + + dev_info(&stw481x->client->dev, "voltages %s\n", + (val & STW_CONF1_V_MONITORING) ? "OK" : "LOW"); + dev_info(&stw481x->client->dev, "MMC level shifter %s\n", + (val & STW_CONF1_MMC_LS_STATUS) ? "high impedance" : "ON"); + dev_info(&stw481x->client->dev, "VMMC: %s\n", + (val & STW_CONF1_PDN_VMMC) ? "ON" : "disabled"); + + dev_info(&stw481x->client->dev, "STw481x power control registers:\n"); + + ret = stw481x_get_pctl_reg(stw481x, STW_PC_VCORE_SEL); + if (ret < 0) + return ret; + vcore = ret & 0x0f; + + ret = stw481x_get_pctl_reg(stw481x, STW_PC_VAUX_SEL); + if (ret < 0) + return ret; + vaux = (ret >> 2) & 3; + vpll = (ret >> 4) & 1; /* Save bit 4 */ + + ret = stw481x_get_pctl_reg(stw481x, STW_PC_VPLL_SEL); + if (ret < 0) + return ret; + vpll |= (ret >> 1) & 2; + + dev_info(&stw481x->client->dev, "VCORE: %u.%uV %s\n", + vcore_val[vcore] / 100, vcore_val[vcore] % 100, + (ret & 4) ? "ON" : "OFF"); + + dev_info(&stw481x->client->dev, "VPLL: %u.%uV %s\n", + vpll_val[vpll] / 100, vpll_val[vpll] % 100, + (ret & 0x10) ? "ON" : "OFF"); + + dev_info(&stw481x->client->dev, "VAUX: %u.%uV %s\n", + vaux_val[vaux] / 10, vaux_val[vaux] % 10, + vaux_en ? "ON" : "OFF"); + + ret = regmap_read(stw481x->map, STW_CONF2, &val); + if (ret) + return ret; + + dev_info(&stw481x->client->dev, "TWARN: %s threshold, %s\n", + it_warn ? "below" : "above", + (val & STW_CONF2_MASK_TWARN) ? + "enabled" : "mask through VDDOK"); + dev_info(&stw481x->client->dev, "VMMC: %s\n", + (val & STW_CONF2_VMMC_EXT) ? "internal" : "external"); + dev_info(&stw481x->client->dev, "IT WAKE UP: %s\n", + (val & STW_CONF2_MASK_IT_WAKE_UP) ? "enabled" : "masked"); + dev_info(&stw481x->client->dev, "GPO1: %s\n", + (val & STW_CONF2_GPO1) ? "low" : "high impedance"); + dev_info(&stw481x->client->dev, "GPO2: %s\n", + (val & STW_CONF2_GPO2) ? "low" : "high impedance"); + + ret = regmap_read(stw481x->map, STW_VCORE_SLEEP, &val); + if (ret) + return ret; + vcore_slp = val & 0x0f; + dev_info(&stw481x->client->dev, "VCORE SLEEP: %u.%uV\n", + vcore_val[vcore_slp] / 100, vcore_val[vcore_slp] % 100); + + return 0; +} + +/* + * MFD cells - we have one cell which is selected operation + * mode, and we always have a GPIO cell. + */ +static struct mfd_cell stw481x_cells[] = { + { + .of_compatible = "st,stw481x-vmmc", + .name = "stw481x-vmmc-regulator", + .id = -1, + }, +}; + +const struct regmap_config stw481x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int stw481x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct stw481x *stw481x; + int ret; + int i; + + stw481x = devm_kzalloc(&client->dev, sizeof(*stw481x), GFP_KERNEL); + if (!stw481x) + return -ENOMEM; + + i2c_set_clientdata(client, stw481x); + stw481x->client = client; + stw481x->map = devm_regmap_init_i2c(client, &stw481x_regmap_config); + + ret = stw481x_startup(stw481x); + if (ret) { + dev_err(&client->dev, "chip initialization failed\n"); + return ret; + } + + /* Set up and register the platform devices. */ + for (i = 0; i < ARRAY_SIZE(stw481x_cells); i++) { + /* One state holder for all drivers, this is simple */ + stw481x_cells[i].platform_data = stw481x; + stw481x_cells[i].pdata_size = sizeof(*stw481x); + } + + ret = mfd_add_devices(&client->dev, 0, stw481x_cells, + ARRAY_SIZE(stw481x_cells), NULL, 0, NULL); + if (ret) + return ret; + + dev_info(&client->dev, "initialized STw481x device\n"); + + return ret; +} + +static int stw481x_remove(struct i2c_client *client) +{ + mfd_remove_devices(&client->dev); + return 0; +} + +/* + * This ID table is completely unused, as this is a pure + * device-tree probed driver, but it has to be here due to + * the structure of the I2C core. + */ +static const struct i2c_device_id stw481x_id[] = { + { "stw481x", 0 }, + { }, +}; + +static const struct of_device_id stw481x_match[] = { + { .compatible = "st,stw4810", }, + { .compatible = "st,stw4811", }, + { }, +}; +MODULE_DEVICE_TABLE(of, stw481x_match); + +static struct i2c_driver stw481x_driver = { + .driver = { + .name = "stw481x", + .of_match_table = stw481x_match, + }, + .probe = stw481x_probe, + .remove = stw481x_remove, + .id_table = stw481x_id, +}; + +module_i2c_driver(stw481x_driver); + +MODULE_AUTHOR("Linus Walleij"); +MODULE_DESCRIPTION("STw481x PMIC driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From e90f875419967589d75d1a3e2b89c5f2720e794e Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Mon, 23 Sep 2013 22:43:29 +0200 Subject: mfd: ti_am335x_tscadc: Restore clock divider on resume The ADC clock divider needs to be restored on resume as the register content is lost when the ADC is powered down Signed-off-by: Matthias Kaehlcke Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index baaf5a8123bb..a3685d6ef674 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -95,7 +95,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) const __be32 *cur; u32 val; int err, ctrl; - int clk_value, clock_rate; + int clock_rate; int tsc_wires = 0, adc_channels = 0, total_channels; int readouts = 0; @@ -196,11 +196,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) } clock_rate = clk_get_rate(clk); clk_put(clk); - clk_value = clock_rate / ADC_CLK; + tscadc->clk_div = clock_rate / ADC_CLK; /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ - clk_value = clk_value - 1; - tscadc_writel(tscadc, REG_CLKDIV, clk_value); + tscadc->clk_div--; + tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div); /* Set the control register bits */ ctrl = CNTRLREG_STEPCONFIGWRT | @@ -303,6 +303,8 @@ static int tscadc_resume(struct device *dev) tscadc_writel(tscadc_dev, REG_CTRL, (restore | CNTRLREG_TSCSSENB)); + tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div); + return 0; } -- cgit v1.2.3 From 89720264a1f0870e45f583583357ee986e216157 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 25 Sep 2013 15:37:45 +0800 Subject: mfd: ezx-pcap: Drop devm_free_irq of devm_ allocated irq The devm_request_irq function allocates irq that is released when a driver detaches. Thus, there is no reason to explicitly call devm_free_irq in probe or remove functions. Signed-off-by: Wei Yongjun Signed-off-by: Lee Jones --- drivers/mfd/ezx-pcap.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 7245b0c5b794..2ed774e7d342 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -394,16 +394,12 @@ static int pcap_add_subdev(struct pcap_chip *pcap, static int ezx_pcap_remove(struct spi_device *spi) { struct pcap_chip *pcap = spi_get_drvdata(spi); - struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev); - int i, adc_irq; + int i; /* remove all registered subdevs */ device_for_each_child(&spi->dev, NULL, pcap_remove_subdev); /* cleanup ADC */ - adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ? - PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE); - devm_free_irq(&spi->dev, adc_irq, pcap); mutex_lock(&pcap->adc_mutex); for (i = 0; i < PCAP_ADC_MAXQ; i++) kfree(pcap->adc_queue[i]); @@ -509,8 +505,6 @@ static int ezx_pcap_probe(struct spi_device *spi) remove_subdevs: device_for_each_child(&spi->dev, NULL, pcap_remove_subdev); -/* free_adc: */ - devm_free_irq(&spi->dev, adc_irq, pcap); free_irqchip: for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) irq_set_chip_and_handler(i, NULL, NULL); -- cgit v1.2.3 From fc5ee96fefae8d38602c79a16205d4b1c8e01da5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 25 Sep 2013 15:37:15 +0800 Subject: mfd: twl6040: Drop devm_free_irq of devm_ allocated irq The devm_request_irq function allocates irq that is released when a driver detaches. Thus, there is no reason to explicitly call devm_free_irq in probe or remove functions. Signed-off-by: Wei Yongjun Signed-off-by: Lee Jones --- drivers/mfd/twl6040.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index daf66942071c..7361dbe96be8 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -619,7 +619,7 @@ static int twl6040_probe(struct i2c_client *client, "twl6040_irq_th", twl6040); if (ret) { dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret); - goto thirq_err; + goto readyirq_err; } /* dual-access registers controlled by I2C only */ @@ -659,14 +659,10 @@ static int twl6040_probe(struct i2c_client *client, ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0, NULL); if (ret) - goto mfd_err; + goto readyirq_err; return 0; -mfd_err: - devm_free_irq(&client->dev, twl6040->irq_th, twl6040); -thirq_err: - devm_free_irq(&client->dev, twl6040->irq_ready, twl6040); readyirq_err: regmap_del_irq_chip(twl6040->irq, twl6040->irq_data); gpio_err: @@ -684,8 +680,6 @@ static int twl6040_remove(struct i2c_client *client) if (twl6040->power_count) twl6040_power(twl6040, 0); - devm_free_irq(&client->dev, twl6040->irq_ready, twl6040); - devm_free_irq(&client->dev, twl6040->irq_th, twl6040); regmap_del_irq_chip(twl6040->irq, twl6040->irq_data); mfd_remove_devices(&client->dev); -- cgit v1.2.3 From b264a70eef880aff31652a10ffee9c03e949b69b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Sep 2013 19:14:31 +0100 Subject: mfd: mc13xxx: Don't require lock for simple register I/O Since the conversion to regmap there has been no need for device level locking for I/O as regmap provides locking so remove the locks. Signed-off-by: Mark Brown Signed-off-by: Lee Jones --- drivers/mfd/mc13xxx-core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 2a9b100c4825..dbbf8ee3f592 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -158,8 +158,6 @@ int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val) { int ret; - BUG_ON(!mutex_is_locked(&mc13xxx->lock)); - if (offset > MC13XXX_NUMREGS) return -EINVAL; @@ -172,8 +170,6 @@ EXPORT_SYMBOL(mc13xxx_reg_read); int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val) { - BUG_ON(!mutex_is_locked(&mc13xxx->lock)); - dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val); if (offset > MC13XXX_NUMREGS || val > 0xffffff) @@ -186,7 +182,6 @@ EXPORT_SYMBOL(mc13xxx_reg_write); int mc13xxx_reg_rmw(struct mc13xxx *mc13xxx, unsigned int offset, u32 mask, u32 val) { - BUG_ON(!mutex_is_locked(&mc13xxx->lock)); BUG_ON(val & ~mask); dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x (mask: 0x%06x)\n", offset, val, mask); -- cgit v1.2.3 From 0248b4bfe56f0545c051e6230939ca8b95f1b037 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Sep 2013 19:14:32 +0100 Subject: mfd: mc13xxx: Move SPI erratum workaround into SPI I/O function Move the workaround for double sending AUDIO_CODEC and AUDIO_DAC writes into the SPI core, aiding refactoring to eliminate the ASoC custom I/O functions and avoiding the extra writes for I2C. Signed-off-by: Mark Brown Signed-off-by: Lee Jones --- drivers/mfd/mc13xxx-spi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 77189daadf1e..5f14ef6693c2 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -94,10 +94,15 @@ static int mc13xxx_spi_write(void *context, const void *data, size_t count) { struct device *dev = context; struct spi_device *spi = to_spi_device(dev); + const char *reg = data; if (count != 4) return -ENOTSUPP; + /* include errata fix for spi audio problems */ + if (*reg == MC13783_AUDIO_CODEC || *reg == MC13783_AUDIO_DAC) + spi_write(spi, data, count); + return spi_write(spi, data, count); } -- cgit v1.2.3 From 4233a0aafb72985a4692a9e6af5c528811226ac1 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 21 Aug 2013 18:53:33 +0200 Subject: mfd: max77693: Remove device wakeup from driver The patch removes wakeup related code from the driver and plaftorm data - it is already handled by i2c core using I2C_CLIENT_WAKE flag from struct i2c_board_info. As a result MFD itself do not requires platform data. Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Signed-off-by: Lee Jones --- drivers/mfd/max77693.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index c04723efc707..27f5da3bc63a 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -110,15 +110,9 @@ static int max77693_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct max77693_dev *max77693; - struct max77693_platform_data *pdata = dev_get_platdata(&i2c->dev); u8 reg_data; int ret = 0; - if (!pdata) { - dev_err(&i2c->dev, "No platform data found.\n"); - return -EINVAL; - } - max77693 = devm_kzalloc(&i2c->dev, sizeof(struct max77693_dev), GFP_KERNEL); if (max77693 == NULL) @@ -138,8 +132,6 @@ static int max77693_i2c_probe(struct i2c_client *i2c, return ret; } - max77693->wakeup = pdata->wakeup; - ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, ®_data); if (ret < 0) { @@ -179,8 +171,6 @@ static int max77693_i2c_probe(struct i2c_client *i2c, if (ret < 0) goto err_mfd; - device_init_wakeup(max77693->dev, pdata->wakeup); - return ret; err_mfd: -- cgit v1.2.3 From 4657185c3c6d928a07185f63f3558d9483e09d7e Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 27 Sep 2013 09:27:46 +0200 Subject: mfd: max77693: Added device tree support This patch adds only of_match_table. There are no device specific properties. Reviewed-by: Sylwester Nawrocki Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Signed-off-by: Lee Jones --- drivers/mfd/max77693.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 27f5da3bc63a..4d81ed285fa2 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -225,11 +225,19 @@ static const struct dev_pm_ops max77693_pm = { .resume = max77693_resume, }; +#ifdef CONFIG_OF +static struct of_device_id max77693_dt_match[] = { + { .compatible = "maxim,max77693" }, + {}, +}; +#endif + static struct i2c_driver max77693_i2c_driver = { .driver = { .name = "max77693", .owner = THIS_MODULE, .pm = &max77693_pm, + .of_match_table = of_match_ptr(max77693_dt_match), }, .probe = max77693_i2c_probe, .remove = max77693_i2c_remove, -- cgit v1.2.3 From ca471660a263f437696bd6459c29395cb176a94a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 26 Sep 2013 19:03:48 +0530 Subject: mfd: palmas: Remove call of mfd_remove_devices The driver only support the device tree and sub modules are populated through platform, the registration of sub devices through mfd_add_devices has been removed. Hence in remove path of the driver, it is not require to call mfd_remove_devices. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/palmas.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 135afabe4ae2..9607d24259d0 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -567,7 +567,6 @@ static int palmas_i2c_remove(struct i2c_client *i2c) { struct palmas *palmas = i2c_get_clientdata(i2c); - mfd_remove_devices(palmas->dev); regmap_del_irq_chip(palmas->irq, palmas->irq_data); return 0; -- cgit v1.2.3 From 2d8edaf028ad2bc71c07c7338bfb0ef7cb46e78d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 26 Sep 2013 19:03:49 +0530 Subject: mfd: palmas: Add MODULE_DEVICE_TABLE for of_device table Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/palmas.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 9607d24259d0..3b63139fe563 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -368,6 +368,7 @@ static const struct of_device_id of_palmas_match_tbl[] = { }, { }, }; +MODULE_DEVICE_TABLE(of, of_palmas_match_tbl); static int palmas_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) -- cgit v1.2.3 From 7178347e1c675aefefce09357c988db0a9bf6e96 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 26 Sep 2013 19:03:50 +0530 Subject: mfd: palmas: Reset pm_power_off if it is set for the device If Palams supports the system power controller and pm_power_off is implemented through the Palmas driver then reset the pm_power_off in driver remove. This will avoid the call of Palmas driver after removal of driver. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/palmas.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 3b63139fe563..6aab016f4c37 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -570,6 +570,11 @@ static int palmas_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(palmas->irq, palmas->irq_data); + if (palmas == palmas_dev) { + pm_power_off = NULL; + palmas_dev = NULL; + } + return 0; } -- cgit v1.2.3 From 5e172d751869ca6756a7276168e11d641dc6b58a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 26 Sep 2013 19:03:51 +0530 Subject: mfd: palmas: Fix resource leak of i2c_dummy devices Palmas device supports multiple i2c device address and the client for these addressed are created in the driver as i2c_new_dummy(). The new devices are not getting released in error or removal path and so it is causing resource leak. Add the unregister of these newly created dummy devices to avoid resource leaks. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/palmas.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 6aab016f4c37..ae9147873b4a 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -422,7 +422,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, dev_err(palmas->dev, "can't attach client %d\n", i); ret = -ENOMEM; - goto err; + goto err_i2c; } palmas->i2c_clients[i]->dev.of_node = of_node_get(node); } @@ -433,7 +433,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, dev_err(palmas->dev, "Failed to allocate regmap %d, err: %d\n", i, ret); - goto err; + goto err_i2c; } } @@ -452,7 +452,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, reg); if (ret < 0) { dev_err(palmas->dev, "POLARITY_CTRL updat failed: %d\n", ret); - goto err; + goto err_i2c; } /* Change IRQ into clear on read mode for efficiency */ @@ -466,7 +466,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, IRQF_ONESHOT | pdata->irq_flags, 0, &palmas_irq_chip, &palmas->irq_data); if (ret < 0) - goto err; + goto err_i2c; no_irq: slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); @@ -552,7 +552,6 @@ no_irq: } else if (pdata->pm_off && !pm_power_off) { palmas_dev = palmas; pm_power_off = palmas_power_off; - return ret; } } @@ -560,16 +559,26 @@ no_irq: err_irq: regmap_del_irq_chip(palmas->irq, palmas->irq_data); -err: +err_i2c: + for (i = 1; i < PALMAS_NUM_CLIENTS; i++) { + if (palmas->i2c_clients[i]) + i2c_unregister_device(palmas->i2c_clients[i]); + } return ret; } static int palmas_i2c_remove(struct i2c_client *i2c) { struct palmas *palmas = i2c_get_clientdata(i2c); + int i; regmap_del_irq_chip(palmas->irq, palmas->irq_data); + for (i = 1; i < PALMAS_NUM_CLIENTS; i++) { + if (palmas->i2c_clients[i]) + i2c_unregister_device(palmas->i2c_clients[i]); + } + if (palmas == palmas_dev) { pm_power_off = NULL; palmas_dev = NULL; -- cgit v1.2.3 From 22d7dc8aba3bf34fdf324f43718c238075cc7cf7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 27 Sep 2013 14:25:55 +0100 Subject: mfd: arizona: Only attempt to parse DT if platform data was not passed If platform data is passed when probing the device then it should take precedence over Device Tree. This patch saves cycles in the pdata case and prevents error messages when DT is not passed. Reported-by: Mark Brown Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 5ac3aa48473b..a2f5beff99d7 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -607,11 +607,11 @@ int arizona_dev_init(struct arizona *arizona) dev_set_drvdata(arizona->dev, arizona); mutex_init(&arizona->clk_lock); - arizona_of_get_core_pdata(arizona); - if (dev_get_platdata(arizona->dev)) memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), sizeof(arizona->pdata)); + else + arizona_of_get_core_pdata(arizona); regcache_cache_only(arizona->regmap, true); -- cgit v1.2.3 From 91c739359ac9946a8e74a9640527a3f1034a76a7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 3 Oct 2013 16:16:01 +0100 Subject: mfd: arizona: Correct handling of device tree gpio defaults When setting GPIO defaults we are required to make a distinction between writing 0x0000 to the registers and leaving them untouched. When we receive between 0x0000 and 0xFFFF (inclusive) from either Platform Data or Device Tree, we should write the provided configuration to the device. Conversely, when we receive >0xFFFF we should leave the device configuration at its default setting. This patch fixes a bug and ensures that configuration 0x0000 isn't mistakenly written when the intention was to keep the default one. Reported-by: Heather Lomond Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index a2f5beff99d7..ba808b744238 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -540,7 +540,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { if (arizona->pdata.gpio_defaults[i] > 0xffff) arizona->pdata.gpio_defaults[i] = 0; - if (arizona->pdata.gpio_defaults[i] == 0) + else if (arizona->pdata.gpio_defaults[i] == 0) arizona->pdata.gpio_defaults[i] = 0x10000; } } else { -- cgit v1.2.3 From 2212e680db06bba383893d3df3fbe3f2267bf83d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 14 Oct 2013 09:09:00 +0100 Subject: mfd: arizona: Mark missing AOD registers as volatile This registers ARIZONA_AOD_WKUP_AND_TRIG and ARIZONA_AOD_IRQ_RAW_STATUS contain interrupt status bits and thus should be volatile. They are correctly marked on wm5102 but not on wm5110, this patch changes this. Furthermore volatile registers don't need defaults so remove those. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5102-tables.c | 1 - drivers/mfd/wm5110-tables.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 802dd3cb18cf..1e9a4b2102f9 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -903,7 +903,6 @@ static const struct reg_default wm5102_reg_default[] = { { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ - { 0x00000D50, 0x0000 }, /* R3408 - AOD wkup and trig */ { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index f71bd9b3d0a2..c5c116a7b5ff 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1204,7 +1204,6 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ - { 0x00000D50, 0x0000 }, /* R3408 - AOD wkup and trig */ { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ @@ -2363,8 +2362,10 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_INTERRUPT_RAW_STATUS_7: case ARIZONA_INTERRUPT_RAW_STATUS_8: case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: case ARIZONA_AOD_IRQ1: case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: case ARIZONA_FX_CTRL2: case ARIZONA_ASRC_STATUS: case ARIZONA_DSP_STATUS: -- cgit v1.2.3 From 52c2c6ebfe476016db18293545244f4ed38f2572 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 15 Oct 2013 09:18:46 +0530 Subject: mfd: max8925: Remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/max8925-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index de7fb80a6052..176aa26fc787 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -238,7 +238,7 @@ static struct i2c_driver max8925_driver = { .name = "max8925", .owner = THIS_MODULE, .pm = &max8925_pm_ops, - .of_match_table = of_match_ptr(max8925_dt_ids), + .of_match_table = max8925_dt_ids, }, .probe = max8925_probe, .remove = max8925_remove, -- cgit v1.2.3 From a351451acd4ce6ccfca6d5439bb1473fd1b1344a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 15 Oct 2013 09:18:47 +0530 Subject: mfd: tps65217: Remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index b8f48647661e..b7be0b295575 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -245,7 +245,7 @@ static struct i2c_driver tps65217_driver = { .driver = { .name = "tps65217", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(tps65217_of_match), + .of_match_table = tps65217_of_match, }, .id_table = tps65217_id_table, .probe = tps65217_probe, -- cgit v1.2.3 From cd2a55321f4b6548daaf14997a8a77c7513d5bae Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 15 Oct 2013 09:18:48 +0530 Subject: mfd: 88pm860x: Remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/88pm860x-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 7ebe9ef1eba6..c9b1f6422941 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1247,7 +1247,7 @@ static struct i2c_driver pm860x_driver = { .name = "88PM860x", .owner = THIS_MODULE, .pm = &pm860x_pm_ops, - .of_match_table = of_match_ptr(pm860x_dt_ids), + .of_match_table = pm860x_dt_ids, }, .probe = pm860x_probe, .remove = pm860x_remove, -- cgit v1.2.3 From 131221bc5e317d9d24d7f3922cc798058cf8aadd Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 15 Oct 2013 09:18:49 +0530 Subject: mfd: ti_am335x_tscadc: Remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index a3685d6ef674..e5a40e8a0904 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -328,7 +328,7 @@ static struct platform_driver ti_tscadc_driver = { .name = "ti_am3359-tscadc", .owner = THIS_MODULE, .pm = TSCADC_PM_OPS, - .of_match_table = of_match_ptr(ti_tscadc_dt_ids), + .of_match_table = ti_tscadc_dt_ids, }, .probe = ti_tscadc_probe, .remove = ti_tscadc_remove, -- cgit v1.2.3 From 0f54e1e129aa0c0b6fd5763295ef60ea5af13256 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 15 Oct 2013 09:18:50 +0530 Subject: mfd: omap-usb: Remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 2 +- drivers/mfd/omap-usb-tll.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 29ee54d68512..1b65ffe08ff9 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -893,7 +893,7 @@ static struct platform_driver usbhs_omap_driver = { .name = (char *)usbhs_driver_name, .owner = THIS_MODULE, .pm = &usbhsomap_dev_pm_ops, - .of_match_table = of_match_ptr(usbhs_omap_dt_ids), + .of_match_table = usbhs_omap_dt_ids, }, .remove = usbhs_omap_remove, }; diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index e59ac4cbac96..b8f6401cbc22 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -320,7 +320,7 @@ static struct platform_driver usbtll_omap_driver = { .driver = { .name = (char *)usbtll_driver_name, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(usbtll_omap_dt_ids), + .of_match_table = usbtll_omap_dt_ids, }, .probe = usbtll_omap_probe, .remove = usbtll_omap_remove, -- cgit v1.2.3 From 84195b77364af8c7a25631450d9f2cad6f5daa1f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 15 Oct 2013 09:18:51 +0530 Subject: mfd: palmas: Remove redundant of_match_ptr 'of_palmas_match_tbl' is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/palmas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index ae9147873b4a..d280d789e55a 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -403,7 +403,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, palmas->dev = &i2c->dev; palmas->irq = i2c->irq; - match = of_match_device(of_match_ptr(of_palmas_match_tbl), &i2c->dev); + match = of_match_device(of_palmas_match_tbl, &i2c->dev); if (!match) return -ENODATA; -- cgit v1.2.3 From 0af6f271d0f27334cad2102aa3ac2044a3f3926a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:48 +0530 Subject: mfd: as3711: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/as3711.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c index abd3ab7c0908..ec684fcedb42 100644 --- a/drivers/mfd/as3711.c +++ b/drivers/mfd/as3711.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 3d6d1d1cd3e9aa4528f82936a01ad46c0e54969b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:56 +0530 Subject: mfd: arizona: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/arizona-i2c.c | 1 + drivers/mfd/arizona-spi.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 51dbabf7c021..beccb790c9ba 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -17,6 +17,7 @@ #include #include #include +#include #include diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 47be7b35b5c5..1ca554b18bef 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From 1fead3f399ce7b508b05d0cc9d06d534ffac952c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:55 +0530 Subject: mfd: tps65910: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/tps65910.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index d79277204835..72f2e789ab83 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -25,6 +25,7 @@ #include #include #include +#include #include static struct resource rtc_resources[] = { -- cgit v1.2.3 From 06bf3c2f11d380d8c5c322f5c45cd189af6f733e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:54 +0530 Subject: mfd: tps6586x: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/tps6586x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 68906b17ee52..ee61fd7c198d 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 5c8c87940204f1839a8730b228fc5ed1e86d324c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:53 +0530 Subject: mfd: tps6507x: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/tps6507x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 5ad4b772b097..a081b925d10b 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 1c5a099b29c26c0a7dd525d6c4ed0daa5206b956 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:52 +0530 Subject: mfd: sec-core: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index f530e4b73f19..34c18fb8c089 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From fb7d4a53f59966a76447cdacdc6b2a71675c1d91 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:51 +0530 Subject: mfd: max8997: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/max8997.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index cee098c0dae3..791aea3e96ce 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From e4081da476e5e741c4e469a0f8470e9f4169794e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:50 +0530 Subject: mfd: max8907: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/max8907.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c index e9b1c93a3ade..3bbfedc07f41 100644 --- a/drivers/mfd/max8907.c +++ b/drivers/mfd/max8907.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 2a048d3b787e154e06a21f5f0951a319b6ada4fb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 16 Oct 2013 14:26:49 +0530 Subject: mfd: max77686: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/max77686.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 522be67b2e68..34520cbe8afb 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -31,6 +31,7 @@ #include #include #include +#include #define I2C_ADDR_RTC (0x0C >> 1) -- cgit v1.2.3 From b0e5992612a1079ddcc1810b786ab8ca438cddae Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 15 Oct 2013 15:30:34 +0300 Subject: mfd: omap-usb: prepare/unprepare clock while enable/disable This should fix the following warning at boot on OMAP5 uEVM [ 8.783155] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:883 __clk_enable+0x94/0xa4() Signed-off-by: Roger Quadros Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 16 ++++++++-------- drivers/mfd/omap-usb-tll.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 1b65ffe08ff9..142650fdc058 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -328,13 +328,13 @@ static int usbhs_runtime_resume(struct device *dev) omap_tll_enable(pdata); if (!IS_ERR(omap->ehci_logic_fck)) - clk_enable(omap->ehci_logic_fck); + clk_prepare_enable(omap->ehci_logic_fck); for (i = 0; i < omap->nports; i++) { switch (pdata->port_mode[i]) { case OMAP_EHCI_PORT_MODE_HSIC: if (!IS_ERR(omap->hsic60m_clk[i])) { - r = clk_enable(omap->hsic60m_clk[i]); + r = clk_prepare_enable(omap->hsic60m_clk[i]); if (r) { dev_err(dev, "Can't enable port %d hsic60m clk:%d\n", @@ -343,7 +343,7 @@ static int usbhs_runtime_resume(struct device *dev) } if (!IS_ERR(omap->hsic480m_clk[i])) { - r = clk_enable(omap->hsic480m_clk[i]); + r = clk_prepare_enable(omap->hsic480m_clk[i]); if (r) { dev_err(dev, "Can't enable port %d hsic480m clk:%d\n", @@ -354,7 +354,7 @@ static int usbhs_runtime_resume(struct device *dev) case OMAP_EHCI_PORT_MODE_TLL: if (!IS_ERR(omap->utmi_clk[i])) { - r = clk_enable(omap->utmi_clk[i]); + r = clk_prepare_enable(omap->utmi_clk[i]); if (r) { dev_err(dev, "Can't enable port %d clk : %d\n", @@ -382,15 +382,15 @@ static int usbhs_runtime_suspend(struct device *dev) switch (pdata->port_mode[i]) { case OMAP_EHCI_PORT_MODE_HSIC: if (!IS_ERR(omap->hsic60m_clk[i])) - clk_disable(omap->hsic60m_clk[i]); + clk_disable_unprepare(omap->hsic60m_clk[i]); if (!IS_ERR(omap->hsic480m_clk[i])) - clk_disable(omap->hsic480m_clk[i]); + clk_disable_unprepare(omap->hsic480m_clk[i]); /* Fall through as utmi_clks were used in HSIC mode */ case OMAP_EHCI_PORT_MODE_TLL: if (!IS_ERR(omap->utmi_clk[i])) - clk_disable(omap->utmi_clk[i]); + clk_disable_unprepare(omap->utmi_clk[i]); break; default: break; @@ -398,7 +398,7 @@ static int usbhs_runtime_suspend(struct device *dev) } if (!IS_ERR(omap->ehci_logic_fck)) - clk_disable(omap->ehci_logic_fck); + clk_disable_unprepare(omap->ehci_logic_fck); omap_tll_disable(pdata); diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index b8f6401cbc22..0d946ae14453 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -429,7 +429,7 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata) if (IS_ERR(tll->ch_clk[i])) continue; - r = clk_enable(tll->ch_clk[i]); + r = clk_prepare_enable(tll->ch_clk[i]); if (r) { dev_err(tll_dev, "Error enabling ch %d clock: %d\n", i, r); @@ -460,7 +460,7 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata) for (i = 0; i < tll->nch; i++) { if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { if (!IS_ERR(tll->ch_clk[i])) - clk_disable(tll->ch_clk[i]); + clk_disable_unprepare(tll->ch_clk[i]); } } -- cgit v1.2.3 From e64c1eb47352d62f5bb06284bae72261d934faa8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 18 Oct 2013 11:51:45 +0200 Subject: mfd: tc3589x: Detect the precise version Instead of detecting the "tc3589x" and hard-coding the number of GPIO pins to 24, encode all the possible subtypes and set the number of GPIO pins from the type. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/tc3589x.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 70f4909fee13..87ea51dc6234 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -16,6 +16,19 @@ #include #include +/** + * enum tc3589x_version - indicates the TC3589x version + */ +enum tc3589x_version { + TC3589X_TC35890, + TC3589X_TC35892, + TC3589X_TC35893, + TC3589X_TC35894, + TC3589X_TC35895, + TC3589X_TC35896, + TC3589X_UNKNOWN, +}; + #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0 #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0) @@ -361,7 +374,21 @@ static int tc3589x_probe(struct i2c_client *i2c, tc3589x->i2c = i2c; tc3589x->pdata = pdata; tc3589x->irq_base = pdata->irq_base; - tc3589x->num_gpio = id->driver_data; + + switch (id->driver_data) { + case TC3589X_TC35893: + case TC3589X_TC35895: + case TC3589X_TC35896: + tc3589x->num_gpio = 20; + break; + case TC3589X_TC35890: + case TC3589X_TC35892: + case TC3589X_TC35894: + case TC3589X_UNKNOWN: + default: + tc3589x->num_gpio = 24; + break; + } i2c_set_clientdata(i2c, tc3589x); @@ -432,7 +459,13 @@ static int tc3589x_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume); static const struct i2c_device_id tc3589x_id[] = { - { "tc3589x", 24 }, + { "tc35890", TC3589X_TC35890 }, + { "tc35892", TC3589X_TC35892 }, + { "tc35893", TC3589X_TC35893 }, + { "tc35894", TC3589X_TC35894 }, + { "tc35895", TC3589X_TC35895 }, + { "tc35896", TC3589X_TC35896 }, + { "tc3589x", TC3589X_UNKNOWN }, { } }; MODULE_DEVICE_TABLE(i2c, tc3589x_id); -- cgit v1.2.3 From 71c7f93ea0036eddb86ccd268945555419bb1cbb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 18 Oct 2013 16:11:57 +0530 Subject: mfd: max77693: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid build breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/max77693.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 4d81ed285fa2..9f92463f4f7e 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From d460a6f3d67a8558fb58299518077888b7dbf5f3 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 22 Oct 2013 13:08:46 +0530 Subject: mfd: Add support for ams AS3722 PMIC The ams AS3722 is a compact system PMU suitable for mobile phones, tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down controller, 11 LDOs, RTC, automatic battery, temperature and over-current monitoring, 8 GPIOs, ADC and a watchdog. Add MFD core driver for the AS3722 to support core functionality. Acked-by: Stephen Warren Signed-off-by: Laxman Dewangan Signed-off-by: Florian Lobmaier Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 12 ++ drivers/mfd/Makefile | 1 + drivers/mfd/as3722.c | 449 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 462 insertions(+) create mode 100644 drivers/mfd/as3722.c (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d078fe4a82ef..b7c74a73d371 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -27,6 +27,18 @@ config MFD_AS3711 help Support for the AS3711 PMIC from AMS +config MFD_AS3722 + bool "ams AS3722 Power Management IC" + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + depends on I2C && OF + help + The ams AS3722 is a compact system PMU suitable for mobile phones, + tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down + controllers, 11 LDOs, RTC, automatic battery, temperature and + over current monitoring, GPIOs, ADC and a watchdog. + config PMIC_ADP5520 bool "Analog Devices ADP5520/01 MFD PMIC Core Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 656cec90a1e5..8a28dc90fe78 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -162,4 +162,5 @@ obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o obj-$(CONFIG_MFD_RETU) += retu-mfd.o obj-$(CONFIG_MFD_AS3711) += as3711.o +obj-$(CONFIG_MFD_AS3722) += as3722.o obj-$(CONFIG_MFD_STW481X) += stw481x.o diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c new file mode 100644 index 000000000000..cd8ee593cfa8 --- /dev/null +++ b/drivers/mfd/as3722.c @@ -0,0 +1,449 @@ +/* + * Core driver for ams AS3722 PMICs + * + * Copyright (C) 2013 AMS AG + * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. + * + * Author: Florian Lobmaier + * Author: Laxman Dewangan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AS3722_DEVICE_ID 0x0C + +static const struct resource as3722_rtc_resource[] = { + { + .name = "as3722-rtc-alarm", + .start = AS3722_IRQ_RTC_ALARM, + .end = AS3722_IRQ_RTC_ALARM, + .flags = IORESOURCE_IRQ, + }, +}; + +static const struct resource as3722_adc_resource[] = { + { + .name = "as3722-adc", + .start = AS3722_IRQ_ADC, + .end = AS3722_IRQ_ADC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell as3722_devs[] = { + { + .name = "as3722-pinctrl", + }, + { + .name = "as3722-regulator", + }, + { + .name = "as3722-rtc", + .num_resources = ARRAY_SIZE(as3722_rtc_resource), + .resources = as3722_rtc_resource, + }, + { + .name = "as3722-adc", + .num_resources = ARRAY_SIZE(as3722_adc_resource), + .resources = as3722_adc_resource, + }, + { + .name = "as3722-power-off", + }, +}; + +static const struct regmap_irq as3722_irqs[] = { + /* INT1 IRQs */ + [AS3722_IRQ_LID] = { + .mask = AS3722_INTERRUPT_MASK1_LID, + }, + [AS3722_IRQ_ACOK] = { + .mask = AS3722_INTERRUPT_MASK1_ACOK, + }, + [AS3722_IRQ_ENABLE1] = { + .mask = AS3722_INTERRUPT_MASK1_ENABLE1, + }, + [AS3722_IRQ_OCCUR_ALARM_SD0] = { + .mask = AS3722_INTERRUPT_MASK1_OCURR_ALARM_SD0, + }, + [AS3722_IRQ_ONKEY_LONG_PRESS] = { + .mask = AS3722_INTERRUPT_MASK1_ONKEY_LONG, + }, + [AS3722_IRQ_ONKEY] = { + .mask = AS3722_INTERRUPT_MASK1_ONKEY, + }, + [AS3722_IRQ_OVTMP] = { + .mask = AS3722_INTERRUPT_MASK1_OVTMP, + }, + [AS3722_IRQ_LOWBAT] = { + .mask = AS3722_INTERRUPT_MASK1_LOWBAT, + }, + + /* INT2 IRQs */ + [AS3722_IRQ_SD0_LV] = { + .mask = AS3722_INTERRUPT_MASK2_SD0_LV, + .reg_offset = 1, + }, + [AS3722_IRQ_SD1_LV] = { + .mask = AS3722_INTERRUPT_MASK2_SD1_LV, + .reg_offset = 1, + }, + [AS3722_IRQ_SD2_LV] = { + .mask = AS3722_INTERRUPT_MASK2_SD2345_LV, + .reg_offset = 1, + }, + [AS3722_IRQ_PWM1_OV_PROT] = { + .mask = AS3722_INTERRUPT_MASK2_PWM1_OV_PROT, + .reg_offset = 1, + }, + [AS3722_IRQ_PWM2_OV_PROT] = { + .mask = AS3722_INTERRUPT_MASK2_PWM2_OV_PROT, + .reg_offset = 1, + }, + [AS3722_IRQ_ENABLE2] = { + .mask = AS3722_INTERRUPT_MASK2_ENABLE2, + .reg_offset = 1, + }, + [AS3722_IRQ_SD6_LV] = { + .mask = AS3722_INTERRUPT_MASK2_SD6_LV, + .reg_offset = 1, + }, + [AS3722_IRQ_RTC_REP] = { + .mask = AS3722_INTERRUPT_MASK2_RTC_REP, + .reg_offset = 1, + }, + + /* INT3 IRQs */ + [AS3722_IRQ_RTC_ALARM] = { + .mask = AS3722_INTERRUPT_MASK3_RTC_ALARM, + .reg_offset = 2, + }, + [AS3722_IRQ_GPIO1] = { + .mask = AS3722_INTERRUPT_MASK3_GPIO1, + .reg_offset = 2, + }, + [AS3722_IRQ_GPIO2] = { + .mask = AS3722_INTERRUPT_MASK3_GPIO2, + .reg_offset = 2, + }, + [AS3722_IRQ_GPIO3] = { + .mask = AS3722_INTERRUPT_MASK3_GPIO3, + .reg_offset = 2, + }, + [AS3722_IRQ_GPIO4] = { + .mask = AS3722_INTERRUPT_MASK3_GPIO4, + .reg_offset = 2, + }, + [AS3722_IRQ_GPIO5] = { + .mask = AS3722_INTERRUPT_MASK3_GPIO5, + .reg_offset = 2, + }, + [AS3722_IRQ_WATCHDOG] = { + .mask = AS3722_INTERRUPT_MASK3_WATCHDOG, + .reg_offset = 2, + }, + [AS3722_IRQ_ENABLE3] = { + .mask = AS3722_INTERRUPT_MASK3_ENABLE3, + .reg_offset = 2, + }, + + /* INT4 IRQs */ + [AS3722_IRQ_TEMP_SD0_SHUTDOWN] = { + .mask = AS3722_INTERRUPT_MASK4_TEMP_SD0_SHUTDOWN, + .reg_offset = 3, + }, + [AS3722_IRQ_TEMP_SD1_SHUTDOWN] = { + .mask = AS3722_INTERRUPT_MASK4_TEMP_SD1_SHUTDOWN, + .reg_offset = 3, + }, + [AS3722_IRQ_TEMP_SD2_SHUTDOWN] = { + .mask = AS3722_INTERRUPT_MASK4_TEMP_SD6_SHUTDOWN, + .reg_offset = 3, + }, + [AS3722_IRQ_TEMP_SD0_ALARM] = { + .mask = AS3722_INTERRUPT_MASK4_TEMP_SD0_ALARM, + .reg_offset = 3, + }, + [AS3722_IRQ_TEMP_SD1_ALARM] = { + .mask = AS3722_INTERRUPT_MASK4_TEMP_SD1_ALARM, + .reg_offset = 3, + }, + [AS3722_IRQ_TEMP_SD6_ALARM] = { + .mask = AS3722_INTERRUPT_MASK4_TEMP_SD6_ALARM, + .reg_offset = 3, + }, + [AS3722_IRQ_OCCUR_ALARM_SD6] = { + .mask = AS3722_INTERRUPT_MASK4_OCCUR_ALARM_SD6, + .reg_offset = 3, + }, + [AS3722_IRQ_ADC] = { + .mask = AS3722_INTERRUPT_MASK4_ADC, + .reg_offset = 3, + }, +}; + +static const struct regmap_irq_chip as3722_irq_chip = { + .name = "as3722", + .irqs = as3722_irqs, + .num_irqs = ARRAY_SIZE(as3722_irqs), + .num_regs = 4, + .status_base = AS3722_INTERRUPT_STATUS1_REG, + .mask_base = AS3722_INTERRUPT_MASK1_REG, +}; + +static int as3722_check_device_id(struct as3722 *as3722) +{ + u32 val; + int ret; + + /* Check that this is actually a AS3722 */ + ret = as3722_read(as3722, AS3722_ASIC_ID1_REG, &val); + if (ret < 0) { + dev_err(as3722->dev, "ASIC_ID1 read failed: %d\n", ret); + return ret; + } + + if (val != AS3722_DEVICE_ID) { + dev_err(as3722->dev, "Device is not AS3722, ID is 0x%x\n", val); + return -ENODEV; + } + + ret = as3722_read(as3722, AS3722_ASIC_ID2_REG, &val); + if (ret < 0) { + dev_err(as3722->dev, "ASIC_ID2 read failed: %d\n", ret); + return ret; + } + + dev_info(as3722->dev, "AS3722 with revision 0x%x found\n", val); + return 0; +} + +static int as3722_configure_pullups(struct as3722 *as3722) +{ + int ret; + u32 val = 0; + + if (as3722->en_intern_int_pullup) + val |= AS3722_INT_PULL_UP; + if (as3722->en_intern_i2c_pullup) + val |= AS3722_I2C_PULL_UP; + + ret = as3722_update_bits(as3722, AS3722_IOVOLTAGE_REG, + AS3722_INT_PULL_UP | AS3722_I2C_PULL_UP, val); + if (ret < 0) + dev_err(as3722->dev, "IOVOLTAGE_REG update failed: %d\n", ret); + return ret; +} + +static const struct regmap_range as3722_readable_ranges[] = { + regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG), + regmap_reg_range(AS3722_GPIO0_CONTROL_REG, AS3722_LDO7_VOLTAGE_REG), + regmap_reg_range(AS3722_LDO9_VOLTAGE_REG, AS3722_REG_SEQU_MOD3_REG), + regmap_reg_range(AS3722_SD_PHSW_CTRL_REG, AS3722_PWM_CONTROL_H_REG), + regmap_reg_range(AS3722_WATCHDOG_TIMER_REG, AS3722_WATCHDOG_TIMER_REG), + regmap_reg_range(AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG, + AS3722_BATTERY_VOLTAGE_MONITOR2_REG), + regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_PWM_VCONTROL4_REG), + regmap_reg_range(AS3722_BB_CHARGER_REG, AS3722_SRAM_REG), + regmap_reg_range(AS3722_RTC_ACCESS_REG, AS3722_RTC_ACCESS_REG), + regmap_reg_range(AS3722_RTC_STATUS_REG, AS3722_TEMP_STATUS_REG), + regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC_CONFIGURATION_REG), + regmap_reg_range(AS3722_ASIC_ID1_REG, AS3722_ASIC_ID2_REG), + regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG), +}; + +static const struct regmap_access_table as3722_readable_table = { + .yes_ranges = as3722_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(as3722_readable_ranges), +}; + +static const struct regmap_range as3722_writable_ranges[] = { + regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG), + regmap_reg_range(AS3722_GPIO0_CONTROL_REG, AS3722_LDO7_VOLTAGE_REG), + regmap_reg_range(AS3722_LDO9_VOLTAGE_REG, AS3722_GPIO_SIGNAL_OUT_REG), + regmap_reg_range(AS3722_REG_SEQU_MOD1_REG, AS3722_REG_SEQU_MOD3_REG), + regmap_reg_range(AS3722_SD_PHSW_CTRL_REG, AS3722_PWM_CONTROL_H_REG), + regmap_reg_range(AS3722_WATCHDOG_TIMER_REG, AS3722_WATCHDOG_TIMER_REG), + regmap_reg_range(AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG, + AS3722_BATTERY_VOLTAGE_MONITOR2_REG), + regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_PWM_VCONTROL4_REG), + regmap_reg_range(AS3722_BB_CHARGER_REG, AS3722_SRAM_REG), + regmap_reg_range(AS3722_INTERRUPT_MASK1_REG, AS3722_TEMP_STATUS_REG), + regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC1_CONTROL_REG), + regmap_reg_range(AS3722_ADC1_THRESHOLD_HI_MSB_REG, + AS3722_ADC_CONFIGURATION_REG), + regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG), +}; + +static const struct regmap_access_table as3722_writable_table = { + .yes_ranges = as3722_writable_ranges, + .n_yes_ranges = ARRAY_SIZE(as3722_writable_ranges), +}; + +static const struct regmap_range as3722_cacheable_ranges[] = { + regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_LDO11_VOLTAGE_REG), + regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_LDOCONTROL1_REG), +}; + +static const struct regmap_access_table as3722_volatile_table = { + .no_ranges = as3722_cacheable_ranges, + .n_no_ranges = ARRAY_SIZE(as3722_cacheable_ranges), +}; + +const struct regmap_config as3722_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = AS3722_MAX_REGISTER, + .cache_type = REGCACHE_RBTREE, + .rd_table = &as3722_readable_table, + .wr_table = &as3722_writable_table, + .volatile_table = &as3722_volatile_table, +}; + +static int as3722_i2c_of_probe(struct i2c_client *i2c, + struct as3722 *as3722) +{ + struct device_node *np = i2c->dev.of_node; + struct irq_data *irq_data; + + if (!np) { + dev_err(&i2c->dev, "Device Tree not found\n"); + return -EINVAL; + } + + irq_data = irq_get_irq_data(i2c->irq); + if (!irq_data) { + dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq); + return -EINVAL; + } + + as3722->en_intern_int_pullup = of_property_read_bool(np, + "ams,enable-internal-int-pullup"); + as3722->en_intern_i2c_pullup = of_property_read_bool(np, + "ams,enable-internal-i2c-pullup"); + as3722->irq_flags = irqd_get_trigger_type(irq_data); + dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags); + return 0; +} + +static int as3722_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct as3722 *as3722; + unsigned long irq_flags; + int ret; + + as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL); + if (!as3722) + return -ENOMEM; + + as3722->dev = &i2c->dev; + as3722->chip_irq = i2c->irq; + i2c_set_clientdata(i2c, as3722); + + ret = as3722_i2c_of_probe(i2c, as3722); + if (ret < 0) + return ret; + + as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config); + if (IS_ERR(as3722->regmap)) { + ret = PTR_ERR(as3722->regmap); + dev_err(&i2c->dev, "regmap init failed: %d\n", ret); + return ret; + } + + ret = as3722_check_device_id(as3722); + if (ret < 0) + return ret; + + irq_flags = as3722->irq_flags | IRQF_ONESHOT; + ret = regmap_add_irq_chip(as3722->regmap, as3722->chip_irq, + irq_flags, -1, &as3722_irq_chip, + &as3722->irq_data); + if (ret < 0) { + dev_err(as3722->dev, "Failed to add regmap irq: %d\n", ret); + return ret; + } + + ret = as3722_configure_pullups(as3722); + if (ret < 0) + goto scrub; + + ret = mfd_add_devices(&i2c->dev, -1, as3722_devs, + ARRAY_SIZE(as3722_devs), NULL, 0, + regmap_irq_get_domain(as3722->irq_data)); + if (ret) { + dev_err(as3722->dev, "Failed to add MFD devices: %d\n", ret); + goto scrub; + } + + dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n"); + return 0; + +scrub: + regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data); + return ret; +} + +static int as3722_i2c_remove(struct i2c_client *i2c) +{ + struct as3722 *as3722 = i2c_get_clientdata(i2c); + + mfd_remove_devices(as3722->dev); + regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data); + return 0; +} + +static const struct of_device_id as3722_of_match[] = { + { .compatible = "ams,as3722", }, + {}, +}; +MODULE_DEVICE_TABLE(of, as3722_of_match); + +static const struct i2c_device_id as3722_i2c_id[] = { + { "as3722", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, as3722_i2c_id); + +static struct i2c_driver as3722_i2c_driver = { + .driver = { + .name = "as3722", + .owner = THIS_MODULE, + .of_match_table = as3722_of_match, + }, + .probe = as3722_i2c_probe, + .remove = as3722_i2c_remove, + .id_table = as3722_i2c_id, +}; + +module_i2c_driver(as3722_i2c_driver); + +MODULE_DESCRIPTION("I2C support for AS3722 PMICs"); +MODULE_AUTHOR("Florian Lobmaier "); +MODULE_AUTHOR("Laxman Dewangan "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 317b2099938fe6f27e51c4b58e76f4de8212d3e6 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 22 Oct 2013 16:12:39 +0200 Subject: mfd: ti_am335x_tscadc: Avoid possible deadlock of reg_lock Since the addition of continuous sampling mode and shared irq support, the reg_lock lock can be taken with and without interrupts. This patch uses the *_irq* variant which should be used in order to avaoid a deadlock. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e5a40e8a0904..88718abfb9ba 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -56,21 +56,25 @@ EXPORT_SYMBOL_GPL(am335x_tsc_se_update); void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) { - spin_lock(&tsadc->reg_lock); + 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); - spin_unlock(&tsadc->reg_lock); + spin_unlock_irqrestore(&tsadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set); void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) { - spin_lock(&tsadc->reg_lock); + 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); - spin_unlock(&tsadc->reg_lock); + spin_unlock_irqrestore(&tsadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); -- cgit v1.2.3 From 6bfd1e63de34a278d67db32e3644340838308252 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 23 Oct 2013 13:31:00 +0200 Subject: mfd: lpc_sch: Ignore resource conflicts when adding mfd cells Currently probe of lpc_sch fails on Intel Poulsbo because of ACPI resource conflicts. A solution is to set the ignore_resource_conflicts flag in the mfd cells. Tested-by: Andreas Werner Signed-off-by: Johannes Thumshirn Signed-off-by: Lee Jones --- drivers/mfd/lpc_sch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 8cc6aac27cb2..fbfbf0b7f97a 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c @@ -59,18 +59,21 @@ static struct mfd_cell isch_smbus_cell = { .name = "isch_smbus", .num_resources = 1, .resources = &smbus_sch_resource, + .ignore_resource_conflicts = true, }; static struct mfd_cell sch_gpio_cell = { .name = "sch_gpio", .num_resources = 1, .resources = &gpio_sch_resource, + .ignore_resource_conflicts = true, }; static struct mfd_cell wdt_sch_cell = { .name = "ie6xx_wdt", .num_resources = 1, .resources = &wdt_sch_resource, + .ignore_resource_conflicts = true, }; static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = { -- cgit v1.2.3 From 34c5c735a89bc0ad5fab1c29b9f425b77fbb7ae7 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 26 Sep 2012 18:18:04 +0530 Subject: mfd: tps65910: Remove warning during dt node parsing Driver throw the warning message if dt node does not have the info for VMBCH-Threshold and VMBCH2-Threshold. These properties are optional property and hence it is not mandatory to have these on DT node and in this case it should not throw the warning message. It creates noise from driver as follows: [ 0.384605] tps65910 4-002d: VMBCH-Threshold not specified [ 0.384616] tps65910 4-002d: VMBCH2-Threshold not specified Removing the warning message from driver. Signed-off-by: Laxman Dewangan Signed-off-by: Samuel Ortiz --- drivers/mfd/tps65910.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index d79277204835..78ffe6e53eb8 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -410,14 +410,10 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client, ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop); if (!ret) board_info->vmbch_threshold = prop; - else if (*chip_id == TPS65911) - dev_warn(&client->dev, "VMBCH-Threshold not specified"); ret = of_property_read_u32(np, "ti,vmbch2-threshold", &prop); if (!ret) board_info->vmbch2_threshold = prop; - else if (*chip_id == TPS65911) - dev_warn(&client->dev, "VMBCH2-Threshold not specified"); prop = of_property_read_bool(np, "ti,en-ck32k-xtal"); board_info->en_ck32k_xtal = prop; -- cgit v1.2.3 From 501d609abe43894430eecee7f5e498607718b26b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 13 Oct 2013 18:06:12 +0200 Subject: mfd: twl6040: Remove obsolete cleanup for i2c clientdata A few new i2c-drivers came into the kernel which clear the clientdata-pointer on exit or error. This is obsolete meanwhile, the core will do it. Signed-off-by: Wolfram Sang Signed-off-by: Samuel Ortiz --- drivers/mfd/twl6040.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index daf66942071c..9d948af420db 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -565,13 +565,13 @@ static int twl6040_probe(struct i2c_client *client, twl6040->supplies); if (ret != 0) { dev_err(&client->dev, "Failed to get supplies: %d\n", ret); - goto regulator_get_err; + return ret; } ret = regulator_bulk_enable(TWL6040_NUM_SUPPLIES, twl6040->supplies); if (ret != 0) { dev_err(&client->dev, "Failed to enable supplies: %d\n", ret); - goto regulator_get_err; + return ret; } twl6040->dev = &client->dev; @@ -671,9 +671,6 @@ readyirq_err: regmap_del_irq_chip(twl6040->irq, twl6040->irq_data); gpio_err: regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies); -regulator_get_err: - i2c_set_clientdata(client, NULL); - return ret; } @@ -689,7 +686,6 @@ static int twl6040_remove(struct i2c_client *client) regmap_del_irq_chip(twl6040->irq, twl6040->irq_data); mfd_remove_devices(&client->dev); - i2c_set_clientdata(client, NULL); regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies); -- cgit v1.2.3 From 4c78b520ee8f9c4b085912f1db2f1308f7ae5890 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 25 Oct 2013 21:10:00 +0100 Subject: mfd: as3722: Don't export the regmap config It's not used outside this file so can be static. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/as3722.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c index cd8ee593cfa8..f161f2e00df7 100644 --- a/drivers/mfd/as3722.c +++ b/drivers/mfd/as3722.c @@ -314,7 +314,7 @@ static const struct regmap_access_table as3722_volatile_table = { .n_no_ranges = ARRAY_SIZE(as3722_cacheable_ranges), }; -const struct regmap_config as3722_regmap_config = { +static const struct regmap_config as3722_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = AS3722_MAX_REGISTER, -- cgit v1.2.3 From 424aab72933cf1afafdeccf2760a74fe3a2fb7b4 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 10 Oct 2013 10:05:55 +0900 Subject: mfd: max77693: Fix up bug of wrong interrupt number The max77693 MFD device use irq domain method which has hardware interrupt number and virtual interrupt number getting through irq domain mapping. This patch use hardware interrupt number instead of virtual interrupt number to get struct irq_data. Signed-off-by: Chanwoo Choi Signed-off-by: Kyungmin Park Signed-off-by: Samuel Ortiz --- drivers/mfd/max77693-irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c index 1029d018c739..66b58fe77094 100644 --- a/drivers/mfd/max77693-irq.c +++ b/drivers/mfd/max77693-irq.c @@ -128,7 +128,8 @@ static void max77693_irq_sync_unlock(struct irq_data *data) static const inline struct max77693_irq_data * irq_to_max77693_irq(struct max77693_dev *max77693, int irq) { - return &max77693_irqs[irq]; + struct irq_data *data = irq_get_irq_data(irq); + return &max77693_irqs[data->hwirq]; } static void max77693_irq_mask(struct irq_data *data) -- cgit v1.2.3 From 5e90169c5a02da69a1ef721bea7a823e9e48fcb6 Mon Sep 17 00:00:00 2001 From: James Ralston Date: Mon, 4 Nov 2013 09:31:20 -0800 Subject: mfd: lpc_ich: Add Device IDs for Intel Wildcat Point-LP PCH This patch adds the TCO Watchdog Device IDs for the Intel Wildcat Point-LP PCH. Signed-off-by: James Ralston Signed-off-by: Samuel Ortiz --- drivers/mfd/lpc_ich.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 316af07ede3f..da1c6566d93d 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -53,6 +53,7 @@ * document number TBD : Wellsburg * document number TBD : Avoton SoC * document number TBD : Coleto Creek + * document number TBD : Wildcat Point-LP */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -211,6 +212,7 @@ enum lpc_chipsets { LPC_WBG, /* Wellsburg */ LPC_AVN, /* Avoton SoC */ LPC_COLETO, /* Coleto Creek */ + LPC_WPT_LP, /* Wildcat Point-LP */ }; static struct lpc_ich_info lpc_chipset_info[] = { @@ -503,6 +505,10 @@ static struct lpc_ich_info lpc_chipset_info[] = { .name = "Coleto Creek", .iTCO_version = 2, }, + [LPC_WPT_LP] = { + .name = "Lynx Point_LP", + .iTCO_version = 2, + }, }; /* @@ -721,6 +727,13 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, + { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc3), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc5), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, lpc_ich_ids); -- cgit v1.2.3 From 24f76f37aab7cfd97e17976b41182817e887f0e1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Sat, 26 Oct 2013 15:27:04 +0100 Subject: mfd: wm5110: Enable micd clamp functionality Add missing registers and interrupts required for the microphone detection clamping. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index c5c116a7b5ff..bf8b3b5ad1fe 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -243,6 +243,12 @@ int wm5110_patch(struct arizona *arizona) EXPORT_SYMBOL_GPL(wm5110_patch); static const struct regmap_irq wm5110_aod_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_MICD_CLAMP_FALL] = { + .mask = ARIZONA_MICD_CLAMP_FALL_EINT1 + }, + [ARIZONA_IRQ_MICD_CLAMP_RISE] = { + .mask = ARIZONA_MICD_CLAMP_RISE_EINT1 + }, [ARIZONA_IRQ_GP5_FALL] = { .mask = ARIZONA_GP5_FALL_EINT1 }, [ARIZONA_IRQ_GP5_RISE] = { .mask = ARIZONA_GP5_RISE_EINT1 }, [ARIZONA_IRQ_JD_FALL] = { .mask = ARIZONA_JD1_FALL_EINT1 }, @@ -505,6 +511,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */ + { 0x000002A2, 0x0000 }, /* R674 - Micd clamp control */ { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */ @@ -1439,6 +1446,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_ACCESSORY_DETECT_MODE_1: case ARIZONA_HEADPHONE_DETECT_1: case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_MICD_CLAMP_CONTROL: case ARIZONA_MIC_DETECT_1: case ARIZONA_MIC_DETECT_2: case ARIZONA_MIC_DETECT_3: -- cgit v1.2.3 From 03e361b25ee8dfb1fd9b890072c23c4aae01c6c7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Oct 2013 10:03:04 +0100 Subject: mfd: Stop setting refcounting pointers in original mfd_cell arrays Commit 1e29af62f2b285bd18685da93c3ce8c33ca2d1db ("mfd: Add refcounting support to mfd_cells") had to drop the "const" keyword on the "cell" parameter of mfd_add_devices(), as it added the refcounting pointers to the objects of the passed mfd_cell array itself. However, the mfd core code operates on copies of the mfd_cell objects, so there's no need to modify the originally passed objects. Hence, move the setting of the refcounting pointers from mfd_add_devices() to mfd_platform_add_cell(), where the copy of the mfd_cell objects is made. mfd_clone_cell() can just pass (a copy of) the original usage_count pointer. This allows to make the "cell" parameter of mfd_add_devices() "const" again, and avoids future race conditions when registering multiple instances of the same device in parallel. Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index f421586f29fb..8736f4539bc0 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -63,7 +63,8 @@ int mfd_cell_disable(struct platform_device *pdev) EXPORT_SYMBOL(mfd_cell_disable); static int mfd_platform_add_cell(struct platform_device *pdev, - const struct mfd_cell *cell) + const struct mfd_cell *cell, + atomic_t *usage_count) { if (!cell) return 0; @@ -72,11 +73,12 @@ static int mfd_platform_add_cell(struct platform_device *pdev, if (!pdev->mfd_cell) return -ENOMEM; + pdev->mfd_cell->usage_count = usage_count; return 0; } static int mfd_add_device(struct device *parent, int id, - const struct mfd_cell *cell, + const struct mfd_cell *cell, atomic_t *usage_count, struct resource *mem_base, int irq_base, struct irq_domain *domain) { @@ -115,7 +117,7 @@ static int mfd_add_device(struct device *parent, int id, goto fail_res; } - ret = mfd_platform_add_cell(pdev, cell); + ret = mfd_platform_add_cell(pdev, cell, usage_count); if (ret) goto fail_res; @@ -180,7 +182,7 @@ fail_alloc: } int mfd_add_devices(struct device *parent, int id, - struct mfd_cell *cells, int n_devs, + const struct mfd_cell *cells, int n_devs, struct resource *mem_base, int irq_base, struct irq_domain *domain) { @@ -195,8 +197,7 @@ int mfd_add_devices(struct device *parent, int id, for (i = 0; i < n_devs; i++) { atomic_set(&cnts[i], 0); - cells[i].usage_count = &cnts[i]; - ret = mfd_add_device(parent, id, cells + i, mem_base, + ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, irq_base, domain); if (ret) break; @@ -259,8 +260,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, - NULL)) + if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, + cell_entry.usage_count, NULL, 0, NULL)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } -- cgit v1.2.3 From 0b208e41acf34c133a55a57189af30aa7924e0c6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Oct 2013 15:47:22 +0100 Subject: mfd: Fix memory leak in mfd_add_devices() If the first call to mfd_add_device() fails, no child devices have been registered to the parent yet, and thus mfd_remove_devices() won't find anything to remove nor free. Hence the previously allocated array of atomic_t objects will leak. Free the array instead of calling mfd_remove_devices() on failure during the first loop iteration to fix this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 8736f4539bc0..968775da638a 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -187,7 +187,7 @@ int mfd_add_devices(struct device *parent, int id, int irq_base, struct irq_domain *domain) { int i; - int ret = 0; + int ret; atomic_t *cnts; /* initialize reference counting for all cells */ @@ -200,12 +200,16 @@ int mfd_add_devices(struct device *parent, int id, ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, irq_base, domain); if (ret) - break; + goto fail; } - if (ret) - mfd_remove_devices(parent); + return 0; +fail: + if (i) + mfd_remove_devices(parent); + else + kfree(cnts); return ret; } EXPORT_SYMBOL(mfd_add_devices); -- cgit v1.2.3 From d6daef95127e41233ac8e2d8472d8c0cd8687d38 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Nov 2013 11:04:20 +0300 Subject: mfd: pm8921: Potential NULL dereference in pm8921_remove() We assume that "pmic" could be NULL and then dereference it two lines later. I fix this by moving the dereference inside the NULL check. Fixes: c013f0a56c56 ('mfd: Add pm8xxx irq support') Signed-off-by: Dan Carpenter Signed-off-by: Lee Jones --- drivers/mfd/pm8921-core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index a6841f77aa5e..484fe66e6c88 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -171,11 +171,12 @@ static int pm8921_remove(struct platform_device *pdev) drvdata = platform_get_drvdata(pdev); if (drvdata) pmic = drvdata->pm_chip_data; - if (pmic) + if (pmic) { mfd_remove_devices(pmic->dev); - if (pmic->irq_chip) { - pm8xxx_irq_exit(pmic->irq_chip); - pmic->irq_chip = NULL; + if (pmic->irq_chip) { + pm8xxx_irq_exit(pmic->irq_chip); + pmic->irq_chip = NULL; + } } return 0; -- cgit v1.2.3