Merge tag 'mfd-3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 16 Nov 2013 00:37:40 +0000 (16:37 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 16 Nov 2013 00:37:40 +0000 (16:37 -0800)
Pull MFD updates from Samuel Ortiz:
 "For the 3.13 merge window we have a couple of new drivers for the AMS
  AS3722 PMIC and for STMicroelectronics STw481x PMIC.

  Although this is a smaller update than usual, we also have:

   - Device tree support for the max77693 driver

   - linux/of.h inclusion for all DT compatible MFD drivers, to avoid
     build breakage in the future

   - Support for Intel Wildcat Point-LP PCH through the lpc_ich driver

   - A small arizona update for new wm5110 DSP registers and a few fixes

   - A small palmas update as well, including an of_device table
     addition and a few minor fixes

   - Two small mfd-core changes, one including a memory leak fix for
     when mfd_add_device() fails

   - Our usual round of minor cleanups and janitorial fixes"

* tag 'mfd-3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (63 commits)
  Documentation: mfd: Update s2mps11.txt
  mfd: pm8921: Potential NULL dereference in pm8921_remove()
  mfd: Fix memory leak in mfd_add_devices()
  mfd: Stop setting refcounting pointers in original mfd_cell arrays
  mfd: wm5110: Enable micd clamp functionality
  mfd: lpc_ich: Add Device IDs for Intel Wildcat Point-LP PCH
  mfd: max77693: Fix up bug of wrong interrupt number
  mfd: as3722: Don't export the regmap config
  mfd: twl6040: Remove obsolete cleanup for i2c clientdata
  mfd: tps65910: Remove warning during dt node parsing
  mfd: lpc_sch: Ignore resource conflicts when adding mfd cells
  mfd: ti_am335x_tscadc: Avoid possible deadlock of reg_lock
  mfd: syscon: Return -ENOSYS if CONFIG_MFD_SYSCON is not enabled
  mfd: Add support for ams AS3722 PMIC
  mfd: max77693: Include linux/of.h header
  mfd: tc3589x: Detect the precise version
  mfd: omap-usb: prepare/unprepare clock while enable/disable
  mfd: max77686: Include linux/of.h header
  mfd: max8907: Include linux/of.h header
  mfd: max8997: Include linux/of.h header
  ...

1  2 
drivers/mfd/arizona-core.c
drivers/mfd/mfd-core.c
include/linux/mfd/core.h
include/linux/mfd/ti_am335x_tscadc.h

@@@ -540,7 -540,7 +540,7 @@@ static int arizona_of_get_core_pdata(st
                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 {
@@@ -569,25 -569,13 +569,25 @@@ static struct mfd_cell early_devs[] = 
        { .name = "arizona-ldo1" },
  };
  
 +static const char *wm5102_supplies[] = {
 +      "DBVDD2",
 +      "DBVDD3",
 +      "CPVDD",
 +      "SPKVDDL",
 +      "SPKVDDR",
 +};
 +
  static struct mfd_cell wm5102_devs[] = {
        { .name = "arizona-micsupp" },
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
        { .name = "arizona-haptics" },
        { .name = "arizona-pwm" },
 -      { .name = "wm5102-codec" },
 +      {
 +              .name = "wm5102-codec",
 +              .parent_supplies = wm5102_supplies,
 +              .num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
 +      },
  };
  
  static struct mfd_cell wm5110_devs[] = {
        { .name = "arizona-gpio" },
        { .name = "arizona-haptics" },
        { .name = "arizona-pwm" },
 -      { .name = "wm5110-codec" },
 +      {
 +              .name = "wm5110-codec",
 +              .parent_supplies = wm5102_supplies,
 +              .num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
 +      },
 +};
 +
 +static const char *wm8997_supplies[] = {
 +      "DBVDD2",
 +      "CPVDD",
 +      "SPKVDD",
  };
  
  static struct mfd_cell wm8997_devs[] = {
        { .name = "arizona-gpio" },
        { .name = "arizona-haptics" },
        { .name = "arizona-pwm" },
 -      { .name = "wm8997-codec" },
 +      {
 +              .name = "wm8997-codec",
 +              .parent_supplies = wm8997_supplies,
 +              .num_parent_supplies = ARRAY_SIZE(wm8997_supplies),
 +      },
  };
  
  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);
  
diff --combined drivers/mfd/mfd-core.c
@@@ -20,7 -20,6 +20,7 @@@
  #include <linux/module.h>
  #include <linux/irqdomain.h>
  #include <linux/of.h>
 +#include <linux/regulator/consumer.h>
  
  static struct device_type mfd_dev_type = {
        .name   = "mfd_device",
@@@ -64,7 -63,8 +64,8 @@@ int mfd_cell_disable(struct platform_de
  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;
        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)
  {
        pdev->dev.dma_mask = parent->dma_mask;
        pdev->dev.dma_parms = parent->dma_parms;
  
 +      ret = devm_regulator_bulk_register_supply_alias(
 +                      &pdev->dev, cell->parent_supplies,
 +                      parent, cell->parent_supplies,
 +                      cell->num_parent_supplies);
 +      if (ret < 0)
 +              goto fail_res;
 +
        if (parent->of_node && cell->of_compatible) {
                for_each_child_of_node(parent->of_node, np) {
                        if (of_device_is_compatible(np, cell->of_compatible)) {
                ret = platform_device_add_data(pdev,
                                        cell->platform_data, cell->pdata_size);
                if (ret)
 -                      goto fail_res;
 +                      goto fail_alias;
        }
  
-       ret = mfd_platform_add_cell(pdev, cell);
+       ret = mfd_platform_add_cell(pdev, cell, usage_count);
        if (ret)
 -              goto fail_res;
 +              goto fail_alias;
  
        for (r = 0; r < cell->num_resources; r++) {
                res[r].name = cell->resources[r].name;
                if (!cell->ignore_resource_conflicts) {
                        ret = acpi_check_resource_conflict(&res[r]);
                        if (ret)
 -                              goto fail_res;
 +                              goto fail_alias;
                }
        }
  
        ret = platform_device_add_resources(pdev, res, cell->num_resources);
        if (ret)
 -              goto fail_res;
 +              goto fail_alias;
  
        ret = platform_device_add(pdev);
        if (ret)
 -              goto fail_res;
 +              goto fail_alias;
  
        if (cell->pm_runtime_no_callbacks)
                pm_runtime_no_callbacks(&pdev->dev);
  
        return 0;
  
 +fail_alias:
 +      devm_regulator_bulk_unregister_supply_alias(&pdev->dev,
 +                                                  cell->parent_supplies,
 +                                                  cell->num_parent_supplies);
  fail_res:
        kfree(res);
  fail_device:
@@@ -192,12 -182,12 +194,12 @@@ 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)
  {
        int i;
-       int ret = 0;
+       int ret;
        atomic_t *cnts;
  
        /* initialize reference counting for all cells */
  
        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;
+                       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);
@@@ -271,8 -264,8 +276,8 @@@ int mfd_clone_cell(const char *cell, co
        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]);
        }
diff --combined include/linux/mfd/core.h
@@@ -59,12 -59,6 +59,12 @@@ struct mfd_cell 
         * pm_runtime_no_callbacks().
         */
        bool                    pm_runtime_no_callbacks;
 +
 +      /* A list of regulator supplies that should be mapped to the MFD
 +       * device rather than the child device when requested
 +       */
 +      const char              **parent_supplies;
 +      int                     num_parent_supplies;
  };
  
  /*
@@@ -104,7 -98,7 +104,7 @@@ static inline const struct mfd_cell *mf
  }
  
  extern 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 *irq_domain);
  
  /* Step Enable */
  #define STEPENB_MASK          (0x1FFFF << 0)
  #define STEPENB(val)          ((val) << 0)
 +#define ENB(val)                      (1 << (val))
 +#define STPENB_STEPENB                STEPENB(0x1FFFF)
 +#define STPENB_STEPENB_TC     STEPENB(0x1FFF)
  
  /* IRQ enable */
  #define IRQENB_HW_PEN         BIT(0)
  #define IRQENB_FIFO0THRES     BIT(2)
 +#define IRQENB_FIFO0OVRRUN    BIT(3)
 +#define IRQENB_FIFO0UNDRFLW   BIT(4)
  #define IRQENB_FIFO1THRES     BIT(5)
 +#define IRQENB_FIFO1OVRRUN    BIT(6)
 +#define IRQENB_FIFO1UNDRFLW   BIT(7)
  #define IRQENB_PENUP          BIT(9)
  
  /* Step Configuration */
  #define STEPCONFIG_MODE_MASK  (3 << 0)
  #define STEPCONFIG_MODE(val)  ((val) << 0)
 +#define STEPCONFIG_MODE_SWCNT STEPCONFIG_MODE(1)
  #define STEPCONFIG_MODE_HWSYNC        STEPCONFIG_MODE(2)
  #define STEPCONFIG_AVG_MASK   (7 << 2)
  #define STEPCONFIG_AVG(val)   ((val) << 2)
  #define ADC_CLK                       3000000
  #define TOTAL_STEPS           16
  #define TOTAL_CHANNELS                8
 +#define FIFO1_THRESHOLD               19
  
  /*
- * ADC runs at 3MHz, and it takes
- * 15 cycles to latch one data output.
- * Hence the idle time for ADC to
- * process one sample data would be
- * around 5 micro seconds.
- */
- #define IDLE_TIMEOUT 5 /* microsec */
+  * time in us for processing a single channel, calculated as follows:
+  *
+  * num cycles = open delay + (sample delay + conv time) * averaging
+  *
+  * num cycles: 152 + (1 + 13) * 16 = 376
+  *
+  * clock frequency: 26MHz / 8 = 3.25MHz
+  * clock period: 1 / 3.25MHz = 308ns
+  *
+  * processing time: 376 * 308ns = 116us
+  */
+ #define IDLE_TIMEOUT 116 /* microsec */
  
  #define TSCADC_CELLS          2
  
@@@ -155,6 -151,7 +160,7 @@@ struct ti_tscadc_dev 
        struct mfd_cell cells[TSCADC_CELLS];
        u32 reg_se_cache;
        spinlock_t reg_lock;
+       unsigned int clk_div;
  
        /* tsc device */
        struct titsc *tsc;