Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Interrupt driver for RICOH583 power management chip.
0004  *
0005  * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
0006  * Author: Laxman dewangan <ldewangan@nvidia.com>
0007  *
0008  * based on code
0009  *      Copyright (C) 2011 RICOH COMPANY,LTD
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     /* Supporting only trigger level inetrrupt */
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     /* Clear the status */
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     /* Merge gpio interrupts for rising and falling case*/
0299     int_sts[7] |= int_sts[8];
0300 
0301     /* Call interrupt handler if enabled */
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     /* Initailize all int register to 0 */
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     /* Clear all interrupts in case they woke up active. */
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 }