root/drivers/mfd/pcf50633-irq.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcf50633_register_irq
  2. pcf50633_free_irq
  3. __pcf50633_irq_mask_set
  4. pcf50633_irq_mask
  5. pcf50633_irq_unmask
  6. pcf50633_irq_mask_get
  7. pcf50633_irq_call_handler
  8. pcf50633_irq
  9. pcf50633_irq_suspend
  10. pcf50633_irq_resume
  11. pcf50633_irq_init
  12. pcf50633_irq_free

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* NXP PCF50633 Power Management Unit (PMU) driver
   3  *
   4  * (C) 2006-2008 by Openmoko, Inc.
   5  * Author: Harald Welte <laforge@openmoko.org>
   6  *         Balaji Rao <balajirrao@openmoko.org>
   7  * All rights reserved.
   8  */
   9 
  10 #include <linux/interrupt.h>
  11 #include <linux/kernel.h>
  12 #include <linux/mutex.h>
  13 #include <linux/export.h>
  14 #include <linux/slab.h>
  15 
  16 #include <linux/mfd/pcf50633/core.h>
  17 #include <linux/mfd/pcf50633/mbc.h>
  18 
  19 int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
  20                         void (*handler) (int, void *), void *data)
  21 {
  22         if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)
  23                 return -EINVAL;
  24 
  25         if (WARN_ON(pcf->irq_handler[irq].handler))
  26                 return -EBUSY;
  27 
  28         mutex_lock(&pcf->lock);
  29         pcf->irq_handler[irq].handler = handler;
  30         pcf->irq_handler[irq].data = data;
  31         mutex_unlock(&pcf->lock);
  32 
  33         return 0;
  34 }
  35 EXPORT_SYMBOL_GPL(pcf50633_register_irq);
  36 
  37 int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
  38 {
  39         if (irq < 0 || irq >= PCF50633_NUM_IRQ)
  40                 return -EINVAL;
  41 
  42         mutex_lock(&pcf->lock);
  43         pcf->irq_handler[irq].handler = NULL;
  44         mutex_unlock(&pcf->lock);
  45 
  46         return 0;
  47 }
  48 EXPORT_SYMBOL_GPL(pcf50633_free_irq);
  49 
  50 static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
  51 {
  52         u8 reg, bit;
  53         int idx;
  54 
  55         idx = irq >> 3;
  56         reg = PCF50633_REG_INT1M + idx;
  57         bit = 1 << (irq & 0x07);
  58 
  59         pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);
  60 
  61         mutex_lock(&pcf->lock);
  62 
  63         if (mask)
  64                 pcf->mask_regs[idx] |= bit;
  65         else
  66                 pcf->mask_regs[idx] &= ~bit;
  67 
  68         mutex_unlock(&pcf->lock);
  69 
  70         return 0;
  71 }
  72 
  73 int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
  74 {
  75         dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
  76 
  77         return __pcf50633_irq_mask_set(pcf, irq, 1);
  78 }
  79 EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
  80 
  81 int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
  82 {
  83         dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
  84 
  85         return __pcf50633_irq_mask_set(pcf, irq, 0);
  86 }
  87 EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
  88 
  89 int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
  90 {
  91         u8 reg, bits;
  92 
  93         reg =  irq >> 3;
  94         bits = 1 << (irq & 0x07);
  95 
  96         return pcf->mask_regs[reg] & bits;
  97 }
  98 EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
  99 
 100 static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
 101 {
 102         if (pcf->irq_handler[irq].handler)
 103                 pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
 104 }
 105 
 106 /* Maximum amount of time ONKEY is held before emergency action is taken */
 107 #define PCF50633_ONKEY1S_TIMEOUT 8
 108 
 109 static irqreturn_t pcf50633_irq(int irq, void *data)
 110 {
 111         struct pcf50633 *pcf = data;
 112         int ret, i, j;
 113         u8 pcf_int[5], chgstat;
 114 
 115         /* Read the 5 INT regs in one transaction */
 116         ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
 117                                                 ARRAY_SIZE(pcf_int), pcf_int);
 118         if (ret != ARRAY_SIZE(pcf_int)) {
 119                 dev_err(pcf->dev, "Error reading INT registers\n");
 120 
 121                 /*
 122                  * If this doesn't ACK the interrupt to the chip, we'll be
 123                  * called once again as we're level triggered.
 124                  */
 125                 goto out;
 126         }
 127 
 128         /* defeat 8s death from lowsys on A5 */
 129         pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN,  0x04);
 130 
 131         /* We immediately read the usb and adapter status. We thus make sure
 132          * only of USBINS/USBREM IRQ handlers are called */
 133         if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
 134                 chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
 135                 if (chgstat & (0x3 << 4))
 136                         pcf_int[0] &= ~PCF50633_INT1_USBREM;
 137                 else
 138                         pcf_int[0] &= ~PCF50633_INT1_USBINS;
 139         }
 140 
 141         /* Make sure only one of ADPINS or ADPREM is set */
 142         if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
 143                 chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
 144                 if (chgstat & (0x3 << 4))
 145                         pcf_int[0] &= ~PCF50633_INT1_ADPREM;
 146                 else
 147                         pcf_int[0] &= ~PCF50633_INT1_ADPINS;
 148         }
 149 
 150         dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
 151                         "INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
 152                         pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
 153 
 154         /* Some revisions of the chip don't have a 8s standby mode on
 155          * ONKEY1S press. We try to manually do it in such cases. */
 156         if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
 157                 dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
 158                                                         pcf->onkey1s_held);
 159                 if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
 160                         if (pcf->pdata->force_shutdown)
 161                                 pcf->pdata->force_shutdown(pcf);
 162         }
 163 
 164         if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
 165                 dev_info(pcf->dev, "ONKEY1S held\n");
 166                 pcf->onkey1s_held = 1 ;
 167 
 168                 /* Unmask IRQ_SECOND */
 169                 pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
 170                                                 PCF50633_INT1_SECOND);
 171 
 172                 /* Unmask IRQ_ONKEYR */
 173                 pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
 174                                                 PCF50633_INT2_ONKEYR);
 175         }
 176 
 177         if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
 178                 pcf->onkey1s_held = 0;
 179 
 180                 /* Mask SECOND and ONKEYR interrupts */
 181                 if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
 182                         pcf50633_reg_set_bit_mask(pcf,
 183                                         PCF50633_REG_INT1M,
 184                                         PCF50633_INT1_SECOND,
 185                                         PCF50633_INT1_SECOND);
 186 
 187                 if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
 188                         pcf50633_reg_set_bit_mask(pcf,
 189                                         PCF50633_REG_INT2M,
 190                                         PCF50633_INT2_ONKEYR,
 191                                         PCF50633_INT2_ONKEYR);
 192         }
 193 
 194         /* Have we just resumed ? */
 195         if (pcf->is_suspended) {
 196                 pcf->is_suspended = 0;
 197 
 198                 /* Set the resume reason filtering out non resumers */
 199                 for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
 200                         pcf->resume_reason[i] = pcf_int[i] &
 201                                                 pcf->pdata->resumers[i];
 202 
 203                 /* Make sure we don't pass on any ONKEY events to
 204                  * userspace now */
 205                 pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
 206         }
 207 
 208         for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
 209                 /* Unset masked interrupts */
 210                 pcf_int[i] &= ~pcf->mask_regs[i];
 211 
 212                 for (j = 0; j < 8 ; j++)
 213                         if (pcf_int[i] & (1 << j))
 214                                 pcf50633_irq_call_handler(pcf, (i * 8) + j);
 215         }
 216 
 217 out:
 218         return IRQ_HANDLED;
 219 }
 220 
 221 #ifdef CONFIG_PM
 222 
 223 int pcf50633_irq_suspend(struct pcf50633 *pcf)
 224 {
 225         int ret;
 226         int i;
 227         u8 res[5];
 228 
 229 
 230         /* Make sure our interrupt handlers are not called
 231          * henceforth */
 232         disable_irq(pcf->irq);
 233 
 234         /* Save the masks */
 235         ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
 236                                 ARRAY_SIZE(pcf->suspend_irq_masks),
 237                                         pcf->suspend_irq_masks);
 238         if (ret < 0) {
 239                 dev_err(pcf->dev, "error saving irq masks\n");
 240                 goto out;
 241         }
 242 
 243         /* Write wakeup irq masks */
 244         for (i = 0; i < ARRAY_SIZE(res); i++)
 245                 res[i] = ~pcf->pdata->resumers[i];
 246 
 247         ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
 248                                         ARRAY_SIZE(res), &res[0]);
 249         if (ret < 0) {
 250                 dev_err(pcf->dev, "error writing wakeup irq masks\n");
 251                 goto out;
 252         }
 253 
 254         pcf->is_suspended = 1;
 255 
 256 out:
 257         return ret;
 258 }
 259 
 260 int pcf50633_irq_resume(struct pcf50633 *pcf)
 261 {
 262         int ret;
 263 
 264         /* Write the saved mask registers */
 265         ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
 266                                 ARRAY_SIZE(pcf->suspend_irq_masks),
 267                                         pcf->suspend_irq_masks);
 268         if (ret < 0)
 269                 dev_err(pcf->dev, "Error restoring saved suspend masks\n");
 270 
 271         enable_irq(pcf->irq);
 272 
 273         return ret;
 274 }
 275 
 276 #endif
 277 
 278 int pcf50633_irq_init(struct pcf50633 *pcf, int irq)
 279 {
 280         int ret;
 281 
 282         pcf->irq = irq;
 283 
 284         /* Enable all interrupts except RTC SECOND */
 285         pcf->mask_regs[0] = 0x80;
 286         pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
 287         pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
 288         pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
 289         pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
 290         pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
 291 
 292         ret = request_threaded_irq(irq, NULL, pcf50633_irq,
 293                                         IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 294                                         "pcf50633", pcf);
 295 
 296         if (ret)
 297                 dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
 298 
 299         if (enable_irq_wake(irq) < 0)
 300                 dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
 301                         "in this hardware revision", irq);
 302 
 303         return ret;
 304 }
 305 
 306 void pcf50633_irq_free(struct pcf50633 *pcf)
 307 {
 308         free_irq(pcf->irq, pcf);
 309 }

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