Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.11 319 lines 9.0 kB view raw
1/* 2 * max77686-irq.c - Interrupt controller support for MAX77686 3 * 4 * Copyright (C) 2012 Samsung Electronics Co.Ltd 5 * Chiwoong Byun <woong.byun@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * This driver is based on max8997-irq.c 22 */ 23 24#include <linux/err.h> 25#include <linux/irq.h> 26#include <linux/interrupt.h> 27#include <linux/gpio.h> 28#include <linux/mfd/max77686.h> 29#include <linux/mfd/max77686-private.h> 30#include <linux/irqdomain.h> 31#include <linux/regmap.h> 32 33enum { 34 MAX77686_DEBUG_IRQ_INFO = 1 << 0, 35 MAX77686_DEBUG_IRQ_MASK = 1 << 1, 36 MAX77686_DEBUG_IRQ_INT = 1 << 2, 37}; 38 39static int debug_mask = 0; 40module_param(debug_mask, int, 0); 41MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)"); 42 43static const u8 max77686_mask_reg[] = { 44 [PMIC_INT1] = MAX77686_REG_INT1MSK, 45 [PMIC_INT2] = MAX77686_REG_INT2MSK, 46 [RTC_INT] = MAX77686_RTC_INTM, 47}; 48 49static struct regmap *max77686_get_regmap(struct max77686_dev *max77686, 50 enum max77686_irq_source src) 51{ 52 switch (src) { 53 case PMIC_INT1 ... PMIC_INT2: 54 return max77686->regmap; 55 case RTC_INT: 56 return max77686->rtc_regmap; 57 default: 58 return ERR_PTR(-EINVAL); 59 } 60} 61 62struct max77686_irq_data { 63 int mask; 64 enum max77686_irq_source group; 65}; 66 67#define DECLARE_IRQ(idx, _group, _mask) \ 68 [(idx)] = { .group = (_group), .mask = (_mask) } 69static const struct max77686_irq_data max77686_irqs[] = { 70 DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0), 71 DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1), 72 DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2), 73 DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3), 74 DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4), 75 DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5), 76 DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6), 77 DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7), 78 DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0), 79 DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1), 80 DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0), 81 DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1), 82 DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2), 83 DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3), 84 DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4), 85 DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5), 86}; 87 88static void max77686_irq_lock(struct irq_data *data) 89{ 90 struct max77686_dev *max77686 = irq_get_chip_data(data->irq); 91 92 if (debug_mask & MAX77686_DEBUG_IRQ_MASK) 93 pr_info("%s\n", __func__); 94 95 mutex_lock(&max77686->irqlock); 96} 97 98static void max77686_irq_sync_unlock(struct irq_data *data) 99{ 100 struct max77686_dev *max77686 = irq_get_chip_data(data->irq); 101 int i; 102 103 for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) { 104 u8 mask_reg = max77686_mask_reg[i]; 105 struct regmap *map = max77686_get_regmap(max77686, i); 106 107 if (debug_mask & MAX77686_DEBUG_IRQ_MASK) 108 pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n", 109 __func__, i, mask_reg, max77686->irq_masks_cur[i]); 110 111 if (mask_reg == MAX77686_REG_INVALID || 112 IS_ERR_OR_NULL(map)) 113 continue; 114 115 max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i]; 116 117 regmap_write(map, max77686_mask_reg[i], 118 max77686->irq_masks_cur[i]); 119 } 120 121 mutex_unlock(&max77686->irqlock); 122} 123 124static const inline struct max77686_irq_data *to_max77686_irq(int irq) 125{ 126 struct irq_data *data = irq_get_irq_data(irq); 127 return &max77686_irqs[data->hwirq]; 128} 129 130static void max77686_irq_mask(struct irq_data *data) 131{ 132 struct max77686_dev *max77686 = irq_get_chip_data(data->irq); 133 const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq); 134 135 max77686->irq_masks_cur[irq_data->group] |= irq_data->mask; 136 137 if (debug_mask & MAX77686_DEBUG_IRQ_MASK) 138 pr_info("%s: group=%d, cur=0x%x\n", 139 __func__, irq_data->group, 140 max77686->irq_masks_cur[irq_data->group]); 141} 142 143static void max77686_irq_unmask(struct irq_data *data) 144{ 145 struct max77686_dev *max77686 = irq_get_chip_data(data->irq); 146 const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq); 147 148 max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask; 149 150 if (debug_mask & MAX77686_DEBUG_IRQ_MASK) 151 pr_info("%s: group=%d, cur=0x%x\n", 152 __func__, irq_data->group, 153 max77686->irq_masks_cur[irq_data->group]); 154} 155 156static struct irq_chip max77686_irq_chip = { 157 .name = "max77686", 158 .irq_bus_lock = max77686_irq_lock, 159 .irq_bus_sync_unlock = max77686_irq_sync_unlock, 160 .irq_mask = max77686_irq_mask, 161 .irq_unmask = max77686_irq_unmask, 162}; 163 164static irqreturn_t max77686_irq_thread(int irq, void *data) 165{ 166 struct max77686_dev *max77686 = data; 167 unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {}; 168 unsigned int irq_src; 169 int ret; 170 int i, cur_irq; 171 172 ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src); 173 if (ret < 0) { 174 dev_err(max77686->dev, "Failed to read interrupt source: %d\n", 175 ret); 176 return IRQ_NONE; 177 } 178 179 if (debug_mask & MAX77686_DEBUG_IRQ_INT) 180 pr_info("%s: irq_src=0x%x\n", __func__, irq_src); 181 182 if (irq_src == MAX77686_IRQSRC_PMIC) { 183 ret = regmap_bulk_read(max77686->regmap, 184 MAX77686_REG_INT1, irq_reg, 2); 185 if (ret < 0) { 186 dev_err(max77686->dev, "Failed to read interrupt source: %d\n", 187 ret); 188 return IRQ_NONE; 189 } 190 191 if (debug_mask & MAX77686_DEBUG_IRQ_INT) 192 pr_info("%s: int1=0x%x, int2=0x%x\n", __func__, 193 irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]); 194 } 195 196 if (irq_src & MAX77686_IRQSRC_RTC) { 197 ret = regmap_read(max77686->rtc_regmap, 198 MAX77686_RTC_INT, &irq_reg[RTC_INT]); 199 if (ret < 0) { 200 dev_err(max77686->dev, "Failed to read interrupt source: %d\n", 201 ret); 202 return IRQ_NONE; 203 } 204 205 if (debug_mask & MAX77686_DEBUG_IRQ_INT) 206 pr_info("%s: rtc int=0x%x\n", __func__, 207 irq_reg[RTC_INT]); 208 209 } 210 211 for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) 212 irq_reg[i] &= ~max77686->irq_masks_cur[i]; 213 214 for (i = 0; i < MAX77686_IRQ_NR; i++) { 215 if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) { 216 cur_irq = irq_find_mapping(max77686->irq_domain, i); 217 if (cur_irq) 218 handle_nested_irq(cur_irq); 219 } 220 } 221 222 return IRQ_HANDLED; 223} 224 225static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq, 226 irq_hw_number_t hw) 227{ 228 struct max77686_dev *max77686 = d->host_data; 229 230 irq_set_chip_data(irq, max77686); 231 irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq); 232 irq_set_nested_thread(irq, 1); 233#ifdef CONFIG_ARM 234 set_irq_flags(irq, IRQF_VALID); 235#else 236 irq_set_noprobe(irq); 237#endif 238 return 0; 239} 240 241static struct irq_domain_ops max77686_irq_domain_ops = { 242 .map = max77686_irq_domain_map, 243}; 244 245int max77686_irq_init(struct max77686_dev *max77686) 246{ 247 struct irq_domain *domain; 248 int i; 249 int ret; 250 int val; 251 struct regmap *map; 252 253 mutex_init(&max77686->irqlock); 254 255 if (max77686->irq_gpio && !max77686->irq) { 256 max77686->irq = gpio_to_irq(max77686->irq_gpio); 257 258 if (debug_mask & MAX77686_DEBUG_IRQ_INT) { 259 ret = gpio_request(max77686->irq_gpio, "pmic_irq"); 260 if (ret < 0) { 261 dev_err(max77686->dev, 262 "Failed to request gpio %d with ret:" 263 "%d\n", max77686->irq_gpio, ret); 264 return IRQ_NONE; 265 } 266 267 gpio_direction_input(max77686->irq_gpio); 268 val = gpio_get_value(max77686->irq_gpio); 269 gpio_free(max77686->irq_gpio); 270 pr_info("%s: gpio_irq=%x\n", __func__, val); 271 } 272 } 273 274 if (!max77686->irq) { 275 dev_err(max77686->dev, "irq is not specified\n"); 276 return -ENODEV; 277 } 278 279 /* Mask individual interrupt sources */ 280 for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) { 281 max77686->irq_masks_cur[i] = 0xff; 282 max77686->irq_masks_cache[i] = 0xff; 283 map = max77686_get_regmap(max77686, i); 284 285 if (IS_ERR_OR_NULL(map)) 286 continue; 287 if (max77686_mask_reg[i] == MAX77686_REG_INVALID) 288 continue; 289 290 regmap_write(map, max77686_mask_reg[i], 0xff); 291 } 292 domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR, 293 &max77686_irq_domain_ops, max77686); 294 if (!domain) { 295 dev_err(max77686->dev, "could not create irq domain\n"); 296 return -ENODEV; 297 } 298 max77686->irq_domain = domain; 299 300 ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread, 301 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 302 "max77686-irq", max77686); 303 304 if (ret) 305 dev_err(max77686->dev, "Failed to request IRQ %d: %d\n", 306 max77686->irq, ret); 307 308 309 if (debug_mask & MAX77686_DEBUG_IRQ_INFO) 310 pr_info("%s-\n", __func__); 311 312 return 0; 313} 314 315void max77686_irq_exit(struct max77686_dev *max77686) 316{ 317 if (max77686->irq) 318 free_irq(max77686->irq, max77686); 319}