0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/interrupt.h>
0012 #include <linux/irq.h>
0013 #include <linux/i2c.h>
0014 #include <linux/mfd/rc5t583.h>
0015
0016 enum int_type {
0017 SYS_INT = 0x1,
0018 DCDC_INT = 0x2,
0019 RTC_INT = 0x4,
0020 ADC_INT = 0x8,
0021 GPIO_INT = 0x10,
0022 };
0023
0024 static int gpedge_add[] = {
0025 RC5T583_GPIO_GPEDGE2,
0026 RC5T583_GPIO_GPEDGE2
0027 };
0028
0029 static int irq_en_add[] = {
0030 RC5T583_INT_EN_SYS1,
0031 RC5T583_INT_EN_SYS2,
0032 RC5T583_INT_EN_DCDC,
0033 RC5T583_INT_EN_RTC,
0034 RC5T583_INT_EN_ADC1,
0035 RC5T583_INT_EN_ADC2,
0036 RC5T583_INT_EN_ADC3,
0037 RC5T583_GPIO_EN_INT
0038 };
0039
0040 static int irq_mon_add[] = {
0041 RC5T583_INT_MON_SYS1,
0042 RC5T583_INT_MON_SYS2,
0043 RC5T583_INT_MON_DCDC,
0044 RC5T583_INT_MON_RTC,
0045 RC5T583_INT_IR_ADCL,
0046 RC5T583_INT_IR_ADCH,
0047 RC5T583_INT_IR_ADCEND,
0048 RC5T583_INT_IR_GPIOF,
0049 RC5T583_INT_IR_GPIOR
0050 };
0051
0052 static int irq_clr_add[] = {
0053 RC5T583_INT_IR_SYS1,
0054 RC5T583_INT_IR_SYS2,
0055 RC5T583_INT_IR_DCDC,
0056 RC5T583_INT_IR_RTC,
0057 RC5T583_INT_IR_ADCL,
0058 RC5T583_INT_IR_ADCH,
0059 RC5T583_INT_IR_ADCEND,
0060 RC5T583_INT_IR_GPIOF,
0061 RC5T583_INT_IR_GPIOR
0062 };
0063
0064 static int main_int_type[] = {
0065 SYS_INT,
0066 SYS_INT,
0067 DCDC_INT,
0068 RTC_INT,
0069 ADC_INT,
0070 ADC_INT,
0071 ADC_INT,
0072 GPIO_INT,
0073 GPIO_INT,
0074 };
0075
0076 struct rc5t583_irq_data {
0077 u8 int_type;
0078 u8 master_bit;
0079 u8 int_en_bit;
0080 u8 mask_reg_index;
0081 int grp_index;
0082 };
0083
0084 #define RC5T583_IRQ(_int_type, _master_bit, _grp_index, \
0085 _int_bit, _mask_ind) \
0086 { \
0087 .int_type = _int_type, \
0088 .master_bit = _master_bit, \
0089 .grp_index = _grp_index, \
0090 .int_en_bit = _int_bit, \
0091 .mask_reg_index = _mask_ind, \
0092 }
0093
0094 static const struct rc5t583_irq_data rc5t583_irqs[RC5T583_MAX_IRQS] = {
0095 [RC5T583_IRQ_ONKEY] = RC5T583_IRQ(SYS_INT, 0, 0, 0, 0),
0096 [RC5T583_IRQ_ACOK] = RC5T583_IRQ(SYS_INT, 0, 1, 1, 0),
0097 [RC5T583_IRQ_LIDOPEN] = RC5T583_IRQ(SYS_INT, 0, 2, 2, 0),
0098 [RC5T583_IRQ_PREOT] = RC5T583_IRQ(SYS_INT, 0, 3, 3, 0),
0099 [RC5T583_IRQ_CLKSTP] = RC5T583_IRQ(SYS_INT, 0, 4, 4, 0),
0100 [RC5T583_IRQ_ONKEY_OFF] = RC5T583_IRQ(SYS_INT, 0, 5, 5, 0),
0101 [RC5T583_IRQ_WD] = RC5T583_IRQ(SYS_INT, 0, 7, 7, 0),
0102 [RC5T583_IRQ_EN_PWRREQ1] = RC5T583_IRQ(SYS_INT, 0, 8, 0, 1),
0103 [RC5T583_IRQ_EN_PWRREQ2] = RC5T583_IRQ(SYS_INT, 0, 9, 1, 1),
0104 [RC5T583_IRQ_PRE_VINDET] = RC5T583_IRQ(SYS_INT, 0, 10, 2, 1),
0105
0106 [RC5T583_IRQ_DC0LIM] = RC5T583_IRQ(DCDC_INT, 1, 0, 0, 2),
0107 [RC5T583_IRQ_DC1LIM] = RC5T583_IRQ(DCDC_INT, 1, 1, 1, 2),
0108 [RC5T583_IRQ_DC2LIM] = RC5T583_IRQ(DCDC_INT, 1, 2, 2, 2),
0109 [RC5T583_IRQ_DC3LIM] = RC5T583_IRQ(DCDC_INT, 1, 3, 3, 2),
0110
0111 [RC5T583_IRQ_CTC] = RC5T583_IRQ(RTC_INT, 2, 0, 0, 3),
0112 [RC5T583_IRQ_YALE] = RC5T583_IRQ(RTC_INT, 2, 5, 5, 3),
0113 [RC5T583_IRQ_DALE] = RC5T583_IRQ(RTC_INT, 2, 6, 6, 3),
0114 [RC5T583_IRQ_WALE] = RC5T583_IRQ(RTC_INT, 2, 7, 7, 3),
0115
0116 [RC5T583_IRQ_AIN1L] = RC5T583_IRQ(ADC_INT, 3, 0, 0, 4),
0117 [RC5T583_IRQ_AIN2L] = RC5T583_IRQ(ADC_INT, 3, 1, 1, 4),
0118 [RC5T583_IRQ_AIN3L] = RC5T583_IRQ(ADC_INT, 3, 2, 2, 4),
0119 [RC5T583_IRQ_VBATL] = RC5T583_IRQ(ADC_INT, 3, 3, 3, 4),
0120 [RC5T583_IRQ_VIN3L] = RC5T583_IRQ(ADC_INT, 3, 4, 4, 4),
0121 [RC5T583_IRQ_VIN8L] = RC5T583_IRQ(ADC_INT, 3, 5, 5, 4),
0122 [RC5T583_IRQ_AIN1H] = RC5T583_IRQ(ADC_INT, 3, 6, 0, 5),
0123 [RC5T583_IRQ_AIN2H] = RC5T583_IRQ(ADC_INT, 3, 7, 1, 5),
0124 [RC5T583_IRQ_AIN3H] = RC5T583_IRQ(ADC_INT, 3, 8, 2, 5),
0125 [RC5T583_IRQ_VBATH] = RC5T583_IRQ(ADC_INT, 3, 9, 3, 5),
0126 [RC5T583_IRQ_VIN3H] = RC5T583_IRQ(ADC_INT, 3, 10, 4, 5),
0127 [RC5T583_IRQ_VIN8H] = RC5T583_IRQ(ADC_INT, 3, 11, 5, 5),
0128 [RC5T583_IRQ_ADCEND] = RC5T583_IRQ(ADC_INT, 3, 12, 0, 6),
0129
0130 [RC5T583_IRQ_GPIO0] = RC5T583_IRQ(GPIO_INT, 4, 0, 0, 7),
0131 [RC5T583_IRQ_GPIO1] = RC5T583_IRQ(GPIO_INT, 4, 1, 1, 7),
0132 [RC5T583_IRQ_GPIO2] = RC5T583_IRQ(GPIO_INT, 4, 2, 2, 7),
0133 [RC5T583_IRQ_GPIO3] = RC5T583_IRQ(GPIO_INT, 4, 3, 3, 7),
0134 [RC5T583_IRQ_GPIO4] = RC5T583_IRQ(GPIO_INT, 4, 4, 4, 7),
0135 [RC5T583_IRQ_GPIO5] = RC5T583_IRQ(GPIO_INT, 4, 5, 5, 7),
0136 [RC5T583_IRQ_GPIO6] = RC5T583_IRQ(GPIO_INT, 4, 6, 6, 7),
0137 [RC5T583_IRQ_GPIO7] = RC5T583_IRQ(GPIO_INT, 4, 7, 7, 7),
0138 };
0139
0140 static void rc5t583_irq_lock(struct irq_data *irq_data)
0141 {
0142 struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
0143 mutex_lock(&rc5t583->irq_lock);
0144 }
0145
0146 static void rc5t583_irq_unmask(struct irq_data *irq_data)
0147 {
0148 struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
0149 unsigned int __irq = irq_data->irq - rc5t583->irq_base;
0150 const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
0151
0152 rc5t583->group_irq_en[data->grp_index] |= 1 << data->grp_index;
0153 rc5t583->intc_inten_reg |= 1 << data->master_bit;
0154 rc5t583->irq_en_reg[data->mask_reg_index] |= 1 << data->int_en_bit;
0155 }
0156
0157 static void rc5t583_irq_mask(struct irq_data *irq_data)
0158 {
0159 struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
0160 unsigned int __irq = irq_data->irq - rc5t583->irq_base;
0161 const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
0162
0163 rc5t583->group_irq_en[data->grp_index] &= ~(1 << data->grp_index);
0164 if (!rc5t583->group_irq_en[data->grp_index])
0165 rc5t583->intc_inten_reg &= ~(1 << data->master_bit);
0166
0167 rc5t583->irq_en_reg[data->mask_reg_index] &= ~(1 << data->int_en_bit);
0168 }
0169
0170 static int rc5t583_irq_set_type(struct irq_data *irq_data, unsigned int type)
0171 {
0172 struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
0173 unsigned int __irq = irq_data->irq - rc5t583->irq_base;
0174 const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
0175 int val = 0;
0176 int gpedge_index;
0177 int gpedge_bit_pos;
0178
0179
0180 if ((data->int_type & GPIO_INT) && (type & IRQ_TYPE_EDGE_BOTH)) {
0181 gpedge_index = data->int_en_bit / 4;
0182 gpedge_bit_pos = data->int_en_bit % 4;
0183
0184 if (type & IRQ_TYPE_EDGE_FALLING)
0185 val |= 0x2;
0186
0187 if (type & IRQ_TYPE_EDGE_RISING)
0188 val |= 0x1;
0189
0190 rc5t583->gpedge_reg[gpedge_index] &= ~(3 << gpedge_bit_pos);
0191 rc5t583->gpedge_reg[gpedge_index] |= (val << gpedge_bit_pos);
0192 rc5t583_irq_unmask(irq_data);
0193 return 0;
0194 }
0195 return -EINVAL;
0196 }
0197
0198 static void rc5t583_irq_sync_unlock(struct irq_data *irq_data)
0199 {
0200 struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
0201 int i;
0202 int ret;
0203
0204 for (i = 0; i < ARRAY_SIZE(rc5t583->gpedge_reg); i++) {
0205 ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
0206 rc5t583->gpedge_reg[i]);
0207 if (ret < 0)
0208 dev_warn(rc5t583->dev,
0209 "Error in writing reg 0x%02x error: %d\n",
0210 gpedge_add[i], ret);
0211 }
0212
0213 for (i = 0; i < ARRAY_SIZE(rc5t583->irq_en_reg); i++) {
0214 ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
0215 rc5t583->irq_en_reg[i]);
0216 if (ret < 0)
0217 dev_warn(rc5t583->dev,
0218 "Error in writing reg 0x%02x error: %d\n",
0219 irq_en_add[i], ret);
0220 }
0221
0222 ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN,
0223 rc5t583->intc_inten_reg);
0224 if (ret < 0)
0225 dev_warn(rc5t583->dev,
0226 "Error in writing reg 0x%02x error: %d\n",
0227 RC5T583_INTC_INTEN, ret);
0228
0229 mutex_unlock(&rc5t583->irq_lock);
0230 }
0231 #ifdef CONFIG_PM_SLEEP
0232 static int rc5t583_irq_set_wake(struct irq_data *irq_data, unsigned int on)
0233 {
0234 struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
0235 return irq_set_irq_wake(rc5t583->chip_irq, on);
0236 }
0237 #else
0238 #define rc5t583_irq_set_wake NULL
0239 #endif
0240
0241 static irqreturn_t rc5t583_irq(int irq, void *data)
0242 {
0243 struct rc5t583 *rc5t583 = data;
0244 uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
0245 uint8_t master_int = 0;
0246 int i;
0247 int ret;
0248 unsigned int rtc_int_sts = 0;
0249
0250
0251 for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)
0252 int_sts[i] = 0;
0253
0254 ret = rc5t583_read(rc5t583->dev, RC5T583_INTC_INTMON, &master_int);
0255 if (ret < 0) {
0256 dev_err(rc5t583->dev,
0257 "Error in reading reg 0x%02x error: %d\n",
0258 RC5T583_INTC_INTMON, ret);
0259 return IRQ_HANDLED;
0260 }
0261
0262 for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; ++i) {
0263 if (!(master_int & main_int_type[i]))
0264 continue;
0265
0266 ret = rc5t583_read(rc5t583->dev, irq_mon_add[i], &int_sts[i]);
0267 if (ret < 0) {
0268 dev_warn(rc5t583->dev,
0269 "Error in reading reg 0x%02x error: %d\n",
0270 irq_mon_add[i], ret);
0271 int_sts[i] = 0;
0272 continue;
0273 }
0274
0275 if (main_int_type[i] & RTC_INT) {
0276 rtc_int_sts = 0;
0277 if (int_sts[i] & 0x1)
0278 rtc_int_sts |= BIT(6);
0279 if (int_sts[i] & 0x2)
0280 rtc_int_sts |= BIT(7);
0281 if (int_sts[i] & 0x4)
0282 rtc_int_sts |= BIT(0);
0283 if (int_sts[i] & 0x8)
0284 rtc_int_sts |= BIT(5);
0285 }
0286
0287 ret = rc5t583_write(rc5t583->dev, irq_clr_add[i],
0288 ~int_sts[i]);
0289 if (ret < 0)
0290 dev_warn(rc5t583->dev,
0291 "Error in reading reg 0x%02x error: %d\n",
0292 irq_clr_add[i], ret);
0293
0294 if (main_int_type[i] & RTC_INT)
0295 int_sts[i] = rtc_int_sts;
0296 }
0297
0298
0299 int_sts[7] |= int_sts[8];
0300
0301
0302 for (i = 0; i < RC5T583_MAX_IRQS; ++i) {
0303 const struct rc5t583_irq_data *data = &rc5t583_irqs[i];
0304 if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) &&
0305 (rc5t583->group_irq_en[data->master_bit] &
0306 (1 << data->grp_index)))
0307 handle_nested_irq(rc5t583->irq_base + i);
0308 }
0309
0310 return IRQ_HANDLED;
0311 }
0312
0313 static struct irq_chip rc5t583_irq_chip = {
0314 .name = "rc5t583-irq",
0315 .irq_mask = rc5t583_irq_mask,
0316 .irq_unmask = rc5t583_irq_unmask,
0317 .irq_bus_lock = rc5t583_irq_lock,
0318 .irq_bus_sync_unlock = rc5t583_irq_sync_unlock,
0319 .irq_set_type = rc5t583_irq_set_type,
0320 .irq_set_wake = rc5t583_irq_set_wake,
0321 };
0322
0323 int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base)
0324 {
0325 int i, ret;
0326
0327 if (!irq_base) {
0328 dev_warn(rc5t583->dev, "No interrupt support on IRQ base\n");
0329 return -EINVAL;
0330 }
0331
0332 mutex_init(&rc5t583->irq_lock);
0333
0334
0335 for (i = 0; i < RC5T583_MAX_INTERRUPT_EN_REGS; i++) {
0336 ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
0337 rc5t583->irq_en_reg[i]);
0338 if (ret < 0)
0339 dev_warn(rc5t583->dev,
0340 "Error in writing reg 0x%02x error: %d\n",
0341 irq_en_add[i], ret);
0342 }
0343
0344 for (i = 0; i < RC5T583_MAX_GPEDGE_REG; i++) {
0345 ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
0346 rc5t583->gpedge_reg[i]);
0347 if (ret < 0)
0348 dev_warn(rc5t583->dev,
0349 "Error in writing reg 0x%02x error: %d\n",
0350 gpedge_add[i], ret);
0351 }
0352
0353 ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN, 0x0);
0354 if (ret < 0)
0355 dev_warn(rc5t583->dev,
0356 "Error in writing reg 0x%02x error: %d\n",
0357 RC5T583_INTC_INTEN, ret);
0358
0359
0360 for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++) {
0361 ret = rc5t583_write(rc5t583->dev, irq_clr_add[i], 0);
0362 if (ret < 0)
0363 dev_warn(rc5t583->dev,
0364 "Error in writing reg 0x%02x error: %d\n",
0365 irq_clr_add[i], ret);
0366 }
0367
0368 rc5t583->irq_base = irq_base;
0369 rc5t583->chip_irq = irq;
0370
0371 for (i = 0; i < RC5T583_MAX_IRQS; i++) {
0372 int __irq = i + rc5t583->irq_base;
0373 irq_set_chip_data(__irq, rc5t583);
0374 irq_set_chip_and_handler(__irq, &rc5t583_irq_chip,
0375 handle_simple_irq);
0376 irq_set_nested_thread(__irq, 1);
0377 irq_clear_status_flags(__irq, IRQ_NOREQUEST);
0378 }
0379
0380 ret = devm_request_threaded_irq(rc5t583->dev, irq, NULL, rc5t583_irq,
0381 IRQF_ONESHOT, "rc5t583", rc5t583);
0382 if (ret < 0)
0383 dev_err(rc5t583->dev,
0384 "Error in registering interrupt error: %d\n", ret);
0385 return ret;
0386 }