pcf50633-irq.c (7573B)
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 19int 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} 35EXPORT_SYMBOL_GPL(pcf50633_register_irq); 36 37int 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} 48EXPORT_SYMBOL_GPL(pcf50633_free_irq); 49 50static 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 73int 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} 79EXPORT_SYMBOL_GPL(pcf50633_irq_mask); 80 81int 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} 87EXPORT_SYMBOL_GPL(pcf50633_irq_unmask); 88 89int 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} 98EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get); 99 100static 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 109static 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 217out: 218 return IRQ_HANDLED; 219} 220 221#ifdef CONFIG_PM 222 223int 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 256out: 257 return ret; 258} 259 260int 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 278int 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 306void pcf50633_irq_free(struct pcf50633 *pcf) 307{ 308 free_irq(pcf->irq, pcf); 309}