Merge tag 'mfd-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
[cascardo/linux.git] / drivers / mfd / max77620.c
index f32fbb8..258757e 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max77620.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
-static struct resource gpio_resources[] = {
+static const struct resource gpio_resources[] = {
        DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
 };
 
-static struct resource power_resources[] = {
+static const struct resource power_resources[] = {
        DEFINE_RES_IRQ(MAX77620_IRQ_LBT_MBATLOW),
 };
 
-static struct resource rtc_resources[] = {
+static const struct resource rtc_resources[] = {
        DEFINE_RES_IRQ(MAX77620_IRQ_TOP_RTC),
 };
 
-static struct resource thermal_resources[] = {
+static const struct resource thermal_resources[] = {
        DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM1),
        DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2),
 };
@@ -111,15 +111,6 @@ static const struct mfd_cell max20024_children[] = {
        },
 };
 
-static struct regmap_irq_chip max77620_top_irq_chip = {
-       .name = "max77620-top",
-       .irqs = max77620_top_irqs,
-       .num_irqs = ARRAY_SIZE(max77620_top_irqs),
-       .num_regs = 2,
-       .status_base = MAX77620_REG_IRQTOP,
-       .mask_base = MAX77620_REG_IRQTOPM,
-};
-
 static const struct regmap_range max77620_readable_ranges[] = {
        regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
 };
@@ -180,6 +171,51 @@ static const struct regmap_config max20024_regmap_config = {
        .volatile_table = &max77620_volatile_table,
 };
 
+/*
+ * MAX77620 and MAX20024 has the following steps of the interrupt handling
+ * for TOP interrupts:
+ * 1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting GLBLM.
+ * 2. Read IRQTOP and service the interrupt.
+ * 3. Once all interrupts has been checked and serviced, the interrupt service
+ *    routine un-masks the hardware interrupt line by clearing GLBLM.
+ */
+static int max77620_irq_global_mask(void *irq_drv_data)
+{
+       struct max77620_chip *chip = irq_drv_data;
+       int ret;
+
+       ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT,
+                                MAX77620_GLBLM_MASK, MAX77620_GLBLM_MASK);
+       if (ret < 0)
+               dev_err(chip->dev, "Failed to set GLBLM: %d\n", ret);
+
+       return ret;
+}
+
+static int max77620_irq_global_unmask(void *irq_drv_data)
+{
+       struct max77620_chip *chip = irq_drv_data;
+       int ret;
+
+       ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT,
+                                MAX77620_GLBLM_MASK, 0);
+       if (ret < 0)
+               dev_err(chip->dev, "Failed to reset GLBLM: %d\n", ret);
+
+       return ret;
+}
+
+static struct regmap_irq_chip max77620_top_irq_chip = {
+       .name = "max77620-top",
+       .irqs = max77620_top_irqs,
+       .num_irqs = ARRAY_SIZE(max77620_top_irqs),
+       .num_regs = 2,
+       .status_base = MAX77620_REG_IRQTOP,
+       .mask_base = MAX77620_REG_IRQTOPM,
+       .handle_pre_irq = max77620_irq_global_mask,
+       .handle_post_irq = max77620_irq_global_unmask,
+};
+
 /* max77620_get_fps_period_reg_value:  Get FPS bit field value from
  *                                    requested periods.
  * MAX77620 supports the FPS period of 40, 80, 160, 320, 540, 1280, 2560
@@ -433,6 +469,7 @@ static int max77620_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
+       max77620_top_irq_chip.irq_drv_data = chip;
        ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
                                       IRQF_ONESHOT | IRQF_SHARED,
                                       chip->irq_base, &max77620_top_irq_chip,
@@ -568,7 +605,6 @@ static const struct i2c_device_id max77620_id[] = {
        {"max20024", MAX20024},
        {},
 };
-MODULE_DEVICE_TABLE(i2c, max77620_id);
 
 static const struct dev_pm_ops max77620_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(max77620_i2c_suspend, max77620_i2c_resume)
@@ -582,11 +618,4 @@ static struct i2c_driver max77620_driver = {
        .probe = max77620_probe,
        .id_table = max77620_id,
 };
-
-module_i2c_driver(max77620_driver);
-
-MODULE_DESCRIPTION("MAX77620/MAX20024 Multi Function Device Core Driver");
-MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
-MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
-MODULE_LICENSE("GPL v2");
+builtin_i2c_driver(max77620_driver);