max8998-irq.c (6345B)
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// Interrupt controller support for MAX8998 4// 5// Copyright (C) 2010 Samsung Electronics Co.Ltd 6// Author: Joonyoung Shim <jy0922.shim@samsung.com> 7 8#include <linux/device.h> 9#include <linux/interrupt.h> 10#include <linux/irq.h> 11#include <linux/irqdomain.h> 12#include <linux/mfd/max8998-private.h> 13 14struct max8998_irq_data { 15 int reg; 16 int mask; 17}; 18 19static struct max8998_irq_data max8998_irqs[] = { 20 [MAX8998_IRQ_DCINF] = { 21 .reg = 1, 22 .mask = MAX8998_IRQ_DCINF_MASK, 23 }, 24 [MAX8998_IRQ_DCINR] = { 25 .reg = 1, 26 .mask = MAX8998_IRQ_DCINR_MASK, 27 }, 28 [MAX8998_IRQ_JIGF] = { 29 .reg = 1, 30 .mask = MAX8998_IRQ_JIGF_MASK, 31 }, 32 [MAX8998_IRQ_JIGR] = { 33 .reg = 1, 34 .mask = MAX8998_IRQ_JIGR_MASK, 35 }, 36 [MAX8998_IRQ_PWRONF] = { 37 .reg = 1, 38 .mask = MAX8998_IRQ_PWRONF_MASK, 39 }, 40 [MAX8998_IRQ_PWRONR] = { 41 .reg = 1, 42 .mask = MAX8998_IRQ_PWRONR_MASK, 43 }, 44 [MAX8998_IRQ_WTSREVNT] = { 45 .reg = 2, 46 .mask = MAX8998_IRQ_WTSREVNT_MASK, 47 }, 48 [MAX8998_IRQ_SMPLEVNT] = { 49 .reg = 2, 50 .mask = MAX8998_IRQ_SMPLEVNT_MASK, 51 }, 52 [MAX8998_IRQ_ALARM1] = { 53 .reg = 2, 54 .mask = MAX8998_IRQ_ALARM1_MASK, 55 }, 56 [MAX8998_IRQ_ALARM0] = { 57 .reg = 2, 58 .mask = MAX8998_IRQ_ALARM0_MASK, 59 }, 60 [MAX8998_IRQ_ONKEY1S] = { 61 .reg = 3, 62 .mask = MAX8998_IRQ_ONKEY1S_MASK, 63 }, 64 [MAX8998_IRQ_TOPOFFR] = { 65 .reg = 3, 66 .mask = MAX8998_IRQ_TOPOFFR_MASK, 67 }, 68 [MAX8998_IRQ_DCINOVPR] = { 69 .reg = 3, 70 .mask = MAX8998_IRQ_DCINOVPR_MASK, 71 }, 72 [MAX8998_IRQ_CHGRSTF] = { 73 .reg = 3, 74 .mask = MAX8998_IRQ_CHGRSTF_MASK, 75 }, 76 [MAX8998_IRQ_DONER] = { 77 .reg = 3, 78 .mask = MAX8998_IRQ_DONER_MASK, 79 }, 80 [MAX8998_IRQ_CHGFAULT] = { 81 .reg = 3, 82 .mask = MAX8998_IRQ_CHGFAULT_MASK, 83 }, 84 [MAX8998_IRQ_LOBAT1] = { 85 .reg = 4, 86 .mask = MAX8998_IRQ_LOBAT1_MASK, 87 }, 88 [MAX8998_IRQ_LOBAT2] = { 89 .reg = 4, 90 .mask = MAX8998_IRQ_LOBAT2_MASK, 91 }, 92}; 93 94static inline struct max8998_irq_data * 95irq_to_max8998_irq(struct max8998_dev *max8998, struct irq_data *data) 96{ 97 return &max8998_irqs[data->hwirq]; 98} 99 100static void max8998_irq_lock(struct irq_data *data) 101{ 102 struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data); 103 104 mutex_lock(&max8998->irqlock); 105} 106 107static void max8998_irq_sync_unlock(struct irq_data *data) 108{ 109 struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data); 110 int i; 111 112 for (i = 0; i < ARRAY_SIZE(max8998->irq_masks_cur); i++) { 113 /* 114 * If there's been a change in the mask write it back 115 * to the hardware. 116 */ 117 if (max8998->irq_masks_cur[i] != max8998->irq_masks_cache[i]) { 118 max8998->irq_masks_cache[i] = max8998->irq_masks_cur[i]; 119 max8998_write_reg(max8998->i2c, MAX8998_REG_IRQM1 + i, 120 max8998->irq_masks_cur[i]); 121 } 122 } 123 124 mutex_unlock(&max8998->irqlock); 125} 126 127static void max8998_irq_unmask(struct irq_data *data) 128{ 129 struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data); 130 struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, data); 131 132 max8998->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; 133} 134 135static void max8998_irq_mask(struct irq_data *data) 136{ 137 struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data); 138 struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, data); 139 140 max8998->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; 141} 142 143static struct irq_chip max8998_irq_chip = { 144 .name = "max8998", 145 .irq_bus_lock = max8998_irq_lock, 146 .irq_bus_sync_unlock = max8998_irq_sync_unlock, 147 .irq_mask = max8998_irq_mask, 148 .irq_unmask = max8998_irq_unmask, 149}; 150 151static irqreturn_t max8998_irq_thread(int irq, void *data) 152{ 153 struct max8998_dev *max8998 = data; 154 u8 irq_reg[MAX8998_NUM_IRQ_REGS]; 155 int ret; 156 int i; 157 158 ret = max8998_bulk_read(max8998->i2c, MAX8998_REG_IRQ1, 159 MAX8998_NUM_IRQ_REGS, irq_reg); 160 if (ret < 0) { 161 dev_err(max8998->dev, "Failed to read interrupt register: %d\n", 162 ret); 163 return IRQ_NONE; 164 } 165 166 /* Apply masking */ 167 for (i = 0; i < MAX8998_NUM_IRQ_REGS; i++) 168 irq_reg[i] &= ~max8998->irq_masks_cur[i]; 169 170 /* Report */ 171 for (i = 0; i < MAX8998_IRQ_NR; i++) { 172 if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) { 173 irq = irq_find_mapping(max8998->irq_domain, i); 174 if (WARN_ON(!irq)) { 175 disable_irq_nosync(max8998->irq); 176 return IRQ_NONE; 177 } 178 handle_nested_irq(irq); 179 } 180 } 181 182 return IRQ_HANDLED; 183} 184 185int max8998_irq_resume(struct max8998_dev *max8998) 186{ 187 if (max8998->irq && max8998->irq_domain) 188 max8998_irq_thread(max8998->irq, max8998); 189 return 0; 190} 191 192static int max8998_irq_domain_map(struct irq_domain *d, unsigned int irq, 193 irq_hw_number_t hw) 194{ 195 struct max8997_dev *max8998 = d->host_data; 196 197 irq_set_chip_data(irq, max8998); 198 irq_set_chip_and_handler(irq, &max8998_irq_chip, handle_edge_irq); 199 irq_set_nested_thread(irq, 1); 200 irq_set_noprobe(irq); 201 202 return 0; 203} 204 205static const struct irq_domain_ops max8998_irq_domain_ops = { 206 .map = max8998_irq_domain_map, 207}; 208 209int max8998_irq_init(struct max8998_dev *max8998) 210{ 211 int i; 212 int ret; 213 struct irq_domain *domain; 214 215 if (!max8998->irq) { 216 dev_warn(max8998->dev, 217 "No interrupt specified, no interrupts\n"); 218 return 0; 219 } 220 221 mutex_init(&max8998->irqlock); 222 223 /* Mask the individual interrupt sources */ 224 for (i = 0; i < MAX8998_NUM_IRQ_REGS; i++) { 225 max8998->irq_masks_cur[i] = 0xff; 226 max8998->irq_masks_cache[i] = 0xff; 227 max8998_write_reg(max8998->i2c, MAX8998_REG_IRQM1 + i, 0xff); 228 } 229 230 max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff); 231 max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff); 232 233 domain = irq_domain_add_simple(NULL, MAX8998_IRQ_NR, 234 max8998->irq_base, &max8998_irq_domain_ops, max8998); 235 if (!domain) { 236 dev_err(max8998->dev, "could not create irq domain\n"); 237 return -ENODEV; 238 } 239 max8998->irq_domain = domain; 240 241 ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread, 242 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 243 "max8998-irq", max8998); 244 if (ret) { 245 dev_err(max8998->dev, "Failed to request IRQ %d: %d\n", 246 max8998->irq, ret); 247 return ret; 248 } 249 250 if (!max8998->ono) 251 return 0; 252 253 ret = request_threaded_irq(max8998->ono, NULL, max8998_irq_thread, 254 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | 255 IRQF_ONESHOT, "max8998-ono", max8998); 256 if (ret) 257 dev_err(max8998->dev, "Failed to request IRQ %d: %d\n", 258 max8998->ono, ret); 259 260 return 0; 261} 262 263void max8998_irq_exit(struct max8998_dev *max8998) 264{ 265 if (max8998->ono) 266 free_irq(max8998->ono, max8998); 267 268 if (max8998->irq) 269 free_irq(max8998->irq, max8998); 270}