root/drivers/mfd/mt6397-irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt6397_irq_lock
  2. mt6397_irq_sync_unlock
  3. mt6397_irq_disable
  4. mt6397_irq_enable
  5. mt6397_irq_set_wake
  6. mt6397_irq_handle_reg
  7. mt6397_irq_thread
  8. mt6397_irq_domain_map
  9. mt6397_irq_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Copyright (c) 2019 MediaTek Inc.
   4 
   5 #include <linux/interrupt.h>
   6 #include <linux/module.h>
   7 #include <linux/of.h>
   8 #include <linux/of_device.h>
   9 #include <linux/of_irq.h>
  10 #include <linux/platform_device.h>
  11 #include <linux/regmap.h>
  12 #include <linux/mfd/mt6323/core.h>
  13 #include <linux/mfd/mt6323/registers.h>
  14 #include <linux/mfd/mt6397/core.h>
  15 #include <linux/mfd/mt6397/registers.h>
  16 
  17 static void mt6397_irq_lock(struct irq_data *data)
  18 {
  19         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  20 
  21         mutex_lock(&mt6397->irqlock);
  22 }
  23 
  24 static void mt6397_irq_sync_unlock(struct irq_data *data)
  25 {
  26         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  27 
  28         regmap_write(mt6397->regmap, mt6397->int_con[0],
  29                      mt6397->irq_masks_cur[0]);
  30         regmap_write(mt6397->regmap, mt6397->int_con[1],
  31                      mt6397->irq_masks_cur[1]);
  32 
  33         mutex_unlock(&mt6397->irqlock);
  34 }
  35 
  36 static void mt6397_irq_disable(struct irq_data *data)
  37 {
  38         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  39         int shift = data->hwirq & 0xf;
  40         int reg = data->hwirq >> 4;
  41 
  42         mt6397->irq_masks_cur[reg] &= ~BIT(shift);
  43 }
  44 
  45 static void mt6397_irq_enable(struct irq_data *data)
  46 {
  47         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  48         int shift = data->hwirq & 0xf;
  49         int reg = data->hwirq >> 4;
  50 
  51         mt6397->irq_masks_cur[reg] |= BIT(shift);
  52 }
  53 
  54 #ifdef CONFIG_PM_SLEEP
  55 static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
  56 {
  57         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
  58         int shift = irq_data->hwirq & 0xf;
  59         int reg = irq_data->hwirq >> 4;
  60 
  61         if (on)
  62                 mt6397->wake_mask[reg] |= BIT(shift);
  63         else
  64                 mt6397->wake_mask[reg] &= ~BIT(shift);
  65 
  66         return 0;
  67 }
  68 #else
  69 #define mt6397_irq_set_wake NULL
  70 #endif
  71 
  72 static struct irq_chip mt6397_irq_chip = {
  73         .name = "mt6397-irq",
  74         .irq_bus_lock = mt6397_irq_lock,
  75         .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
  76         .irq_enable = mt6397_irq_enable,
  77         .irq_disable = mt6397_irq_disable,
  78         .irq_set_wake = mt6397_irq_set_wake,
  79 };
  80 
  81 static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
  82                                   int irqbase)
  83 {
  84         unsigned int status;
  85         int i, irq, ret;
  86 
  87         ret = regmap_read(mt6397->regmap, reg, &status);
  88         if (ret) {
  89                 dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
  90                 return;
  91         }
  92 
  93         for (i = 0; i < 16; i++) {
  94                 if (status & BIT(i)) {
  95                         irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
  96                         if (irq)
  97                                 handle_nested_irq(irq);
  98                 }
  99         }
 100 
 101         regmap_write(mt6397->regmap, reg, status);
 102 }
 103 
 104 static irqreturn_t mt6397_irq_thread(int irq, void *data)
 105 {
 106         struct mt6397_chip *mt6397 = data;
 107 
 108         mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
 109         mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
 110 
 111         return IRQ_HANDLED;
 112 }
 113 
 114 static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
 115                                  irq_hw_number_t hw)
 116 {
 117         struct mt6397_chip *mt6397 = d->host_data;
 118 
 119         irq_set_chip_data(irq, mt6397);
 120         irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
 121         irq_set_nested_thread(irq, 1);
 122         irq_set_noprobe(irq);
 123 
 124         return 0;
 125 }
 126 
 127 static const struct irq_domain_ops mt6397_irq_domain_ops = {
 128         .map = mt6397_irq_domain_map,
 129 };
 130 
 131 int mt6397_irq_init(struct mt6397_chip *chip)
 132 {
 133         int ret;
 134 
 135         mutex_init(&chip->irqlock);
 136 
 137         switch (chip->chip_id) {
 138         case MT6323_CHIP_ID:
 139                 chip->int_con[0] = MT6323_INT_CON0;
 140                 chip->int_con[1] = MT6323_INT_CON1;
 141                 chip->int_status[0] = MT6323_INT_STATUS0;
 142                 chip->int_status[1] = MT6323_INT_STATUS1;
 143                 break;
 144 
 145         case MT6391_CHIP_ID:
 146         case MT6397_CHIP_ID:
 147                 chip->int_con[0] = MT6397_INT_CON0;
 148                 chip->int_con[1] = MT6397_INT_CON1;
 149                 chip->int_status[0] = MT6397_INT_STATUS0;
 150                 chip->int_status[1] = MT6397_INT_STATUS1;
 151                 break;
 152 
 153         default:
 154                 dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
 155                 return -ENODEV;
 156         }
 157 
 158         /* Mask all interrupt sources */
 159         regmap_write(chip->regmap, chip->int_con[0], 0x0);
 160         regmap_write(chip->regmap, chip->int_con[1], 0x0);
 161 
 162         chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
 163                                                  MT6397_IRQ_NR,
 164                                                  &mt6397_irq_domain_ops,
 165                                                  chip);
 166         if (!chip->irq_domain) {
 167                 dev_err(chip->dev, "could not create irq domain\n");
 168                 return -ENOMEM;
 169         }
 170 
 171         ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
 172                                         mt6397_irq_thread, IRQF_ONESHOT,
 173                                         "mt6397-pmic", chip);
 174         if (ret) {
 175                 dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
 176                         chip->irq, ret);
 177                 return ret;
 178         }
 179 
 180         return 0;
 181 }

/* [<][>][^][v][top][bottom][index][help] */