1/* 2 * tps65912-irq.c -- TI TPS6591x 3 * 4 * Copyright 2011 Texas Instruments Inc. 5 * 6 * Author: Margarita Olaya <magi@slimlogic.co.uk> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * This driver is based on wm8350 implementation. 14 */ 15 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/bug.h> 19#include <linux/device.h> 20#include <linux/interrupt.h> 21#include <linux/irq.h> 22#include <linux/gpio.h> 23#include <linux/mfd/tps65912.h> 24 25static inline int irq_to_tps65912_irq(struct tps65912 *tps65912, 26 int irq) 27{ 28 return irq - tps65912->irq_base; 29} 30 31/* 32 * This is a threaded IRQ handler so can access I2C/SPI. Since the 33 * IRQ handler explicitly clears the IRQ it handles the IRQ line 34 * will be reasserted and the physical IRQ will be handled again if 35 * another interrupt is asserted while we run - in the normal course 36 * of events this is a rare occurrence so we save I2C/SPI reads. We're 37 * also assuming that it's rare to get lots of interrupts firing 38 * simultaneously so try to minimise I/O. 39 */ 40static irqreturn_t tps65912_irq(int irq, void *irq_data) 41{ 42 struct tps65912 *tps65912 = irq_data; 43 u32 irq_sts; 44 u32 irq_mask; 45 u8 reg; 46 int i; 47 48 49 tps65912->read(tps65912, TPS65912_INT_STS, 1, ®); 50 irq_sts = reg; 51 tps65912->read(tps65912, TPS65912_INT_STS2, 1, ®); 52 irq_sts |= reg << 8; 53 tps65912->read(tps65912, TPS65912_INT_STS3, 1, ®); 54 irq_sts |= reg << 16; 55 tps65912->read(tps65912, TPS65912_INT_STS4, 1, ®); 56 irq_sts |= reg << 24; 57 58 tps65912->read(tps65912, TPS65912_INT_MSK, 1, ®); 59 irq_mask = reg; 60 tps65912->read(tps65912, TPS65912_INT_MSK2, 1, ®); 61 irq_mask |= reg << 8; 62 tps65912->read(tps65912, TPS65912_INT_MSK3, 1, ®); 63 irq_mask |= reg << 16; 64 tps65912->read(tps65912, TPS65912_INT_MSK4, 1, ®); 65 irq_mask |= reg << 24; 66 67 irq_sts &= ~irq_mask; 68 if (!irq_sts) 69 return IRQ_NONE; 70 71 for (i = 0; i < tps65912->irq_num; i++) { 72 if (!(irq_sts & (1 << i))) 73 continue; 74 75 handle_nested_irq(tps65912->irq_base + i); 76 } 77 78 /* Write the STS register back to clear IRQs we handled */ 79 reg = irq_sts & 0xFF; 80 irq_sts >>= 8; 81 if (reg) 82 tps65912->write(tps65912, TPS65912_INT_STS, 1, ®); 83 reg = irq_sts & 0xFF; 84 irq_sts >>= 8; 85 if (reg) 86 tps65912->write(tps65912, TPS65912_INT_STS2, 1, ®); 87 reg = irq_sts & 0xFF; 88 irq_sts >>= 8; 89 if (reg) 90 tps65912->write(tps65912, TPS65912_INT_STS3, 1, ®); 91 reg = irq_sts & 0xFF; 92 if (reg) 93 tps65912->write(tps65912, TPS65912_INT_STS4, 1, ®); 94 95 return IRQ_HANDLED; 96} 97 98static void tps65912_irq_lock(struct irq_data *data) 99{ 100 struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); 101 102 mutex_lock(&tps65912->irq_lock); 103} 104 105static void tps65912_irq_sync_unlock(struct irq_data *data) 106{ 107 struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); 108 u32 reg_mask; 109 u8 reg; 110 111 tps65912->read(tps65912, TPS65912_INT_MSK, 1, ®); 112 reg_mask = reg; 113 tps65912->read(tps65912, TPS65912_INT_MSK2, 1, ®); 114 reg_mask |= reg << 8; 115 tps65912->read(tps65912, TPS65912_INT_MSK3, 1, ®); 116 reg_mask |= reg << 16; 117 tps65912->read(tps65912, TPS65912_INT_MSK4, 1, ®); 118 reg_mask |= reg << 24; 119 120 if (tps65912->irq_mask != reg_mask) { 121 reg = tps65912->irq_mask & 0xFF; 122 tps65912->write(tps65912, TPS65912_INT_MSK, 1, ®); 123 reg = tps65912->irq_mask >> 8 & 0xFF; 124 tps65912->write(tps65912, TPS65912_INT_MSK2, 1, ®); 125 reg = tps65912->irq_mask >> 16 & 0xFF; 126 tps65912->write(tps65912, TPS65912_INT_MSK3, 1, ®); 127 reg = tps65912->irq_mask >> 24 & 0xFF; 128 tps65912->write(tps65912, TPS65912_INT_MSK4, 1, ®); 129 } 130 131 mutex_unlock(&tps65912->irq_lock); 132} 133 134static void tps65912_irq_enable(struct irq_data *data) 135{ 136 struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); 137 138 tps65912->irq_mask &= ~(1 << irq_to_tps65912_irq(tps65912, data->irq)); 139} 140 141static void tps65912_irq_disable(struct irq_data *data) 142{ 143 struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); 144 145 tps65912->irq_mask |= (1 << irq_to_tps65912_irq(tps65912, data->irq)); 146} 147 148static struct irq_chip tps65912_irq_chip = { 149 .name = "tps65912", 150 .irq_bus_lock = tps65912_irq_lock, 151 .irq_bus_sync_unlock = tps65912_irq_sync_unlock, 152 .irq_disable = tps65912_irq_disable, 153 .irq_enable = tps65912_irq_enable, 154}; 155 156int tps65912_irq_init(struct tps65912 *tps65912, int irq, 157 struct tps65912_platform_data *pdata) 158{ 159 int ret, cur_irq; 160 int flags = IRQF_ONESHOT; 161 u8 reg; 162 163 if (!irq) { 164 dev_warn(tps65912->dev, "No interrupt support, no core IRQ\n"); 165 return 0; 166 } 167 168 if (!pdata || !pdata->irq_base) { 169 dev_warn(tps65912->dev, "No interrupt support, no IRQ base\n"); 170 return 0; 171 } 172 173 /* Clear unattended interrupts */ 174 tps65912->read(tps65912, TPS65912_INT_STS, 1, ®); 175 tps65912->write(tps65912, TPS65912_INT_STS, 1, ®); 176 tps65912->read(tps65912, TPS65912_INT_STS2, 1, ®); 177 tps65912->write(tps65912, TPS65912_INT_STS2, 1, ®); 178 tps65912->read(tps65912, TPS65912_INT_STS3, 1, ®); 179 tps65912->write(tps65912, TPS65912_INT_STS3, 1, ®); 180 tps65912->read(tps65912, TPS65912_INT_STS4, 1, ®); 181 tps65912->write(tps65912, TPS65912_INT_STS4, 1, ®); 182 183 /* Mask top level interrupts */ 184 tps65912->irq_mask = 0xFFFFFFFF; 185 186 mutex_init(&tps65912->irq_lock); 187 tps65912->chip_irq = irq; 188 tps65912->irq_base = pdata->irq_base; 189 190 tps65912->irq_num = TPS65912_NUM_IRQ; 191 192 /* Register with genirq */ 193 for (cur_irq = tps65912->irq_base; 194 cur_irq < tps65912->irq_num + tps65912->irq_base; 195 cur_irq++) { 196 irq_set_chip_data(cur_irq, tps65912); 197 irq_set_chip_and_handler(cur_irq, &tps65912_irq_chip, 198 handle_edge_irq); 199 irq_set_nested_thread(cur_irq, 1); 200 /* ARM needs us to explicitly flag the IRQ as valid 201 * and will set them noprobe when we do so. */ 202#ifdef CONFIG_ARM 203 set_irq_flags(cur_irq, IRQF_VALID); 204#else 205 irq_set_noprobe(cur_irq); 206#endif 207 } 208 209 ret = request_threaded_irq(irq, NULL, tps65912_irq, flags, 210 "tps65912", tps65912); 211 212 irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); 213 if (ret != 0) 214 dev_err(tps65912->dev, "Failed to request IRQ: %d\n", ret); 215 216 return ret; 217} 218 219int tps65912_irq_exit(struct tps65912 *tps65912) 220{ 221 free_irq(tps65912->chip_irq, tps65912); 222 return 0; 223} 224