cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcf50633-irq.c (7573B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* NXP PCF50633 Power Management Unit (PMU) driver
      3 *
      4 * (C) 2006-2008 by Openmoko, Inc.
      5 * Author: Harald Welte <laforge@openmoko.org>
      6 * 	   Balaji Rao <balajirrao@openmoko.org>
      7 * All rights reserved.
      8 */
      9
     10#include <linux/interrupt.h>
     11#include <linux/kernel.h>
     12#include <linux/mutex.h>
     13#include <linux/export.h>
     14#include <linux/slab.h>
     15
     16#include <linux/mfd/pcf50633/core.h>
     17#include <linux/mfd/pcf50633/mbc.h>
     18
     19int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
     20			void (*handler) (int, void *), void *data)
     21{
     22	if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)
     23		return -EINVAL;
     24
     25	if (WARN_ON(pcf->irq_handler[irq].handler))
     26		return -EBUSY;
     27
     28	mutex_lock(&pcf->lock);
     29	pcf->irq_handler[irq].handler = handler;
     30	pcf->irq_handler[irq].data = data;
     31	mutex_unlock(&pcf->lock);
     32
     33	return 0;
     34}
     35EXPORT_SYMBOL_GPL(pcf50633_register_irq);
     36
     37int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
     38{
     39	if (irq < 0 || irq >= PCF50633_NUM_IRQ)
     40		return -EINVAL;
     41
     42	mutex_lock(&pcf->lock);
     43	pcf->irq_handler[irq].handler = NULL;
     44	mutex_unlock(&pcf->lock);
     45
     46	return 0;
     47}
     48EXPORT_SYMBOL_GPL(pcf50633_free_irq);
     49
     50static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
     51{
     52	u8 reg, bit;
     53	int idx;
     54
     55	idx = irq >> 3;
     56	reg = PCF50633_REG_INT1M + idx;
     57	bit = 1 << (irq & 0x07);
     58
     59	pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);
     60
     61	mutex_lock(&pcf->lock);
     62
     63	if (mask)
     64		pcf->mask_regs[idx] |= bit;
     65	else
     66		pcf->mask_regs[idx] &= ~bit;
     67
     68	mutex_unlock(&pcf->lock);
     69
     70	return 0;
     71}
     72
     73int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
     74{
     75	dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
     76
     77	return __pcf50633_irq_mask_set(pcf, irq, 1);
     78}
     79EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
     80
     81int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
     82{
     83	dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
     84
     85	return __pcf50633_irq_mask_set(pcf, irq, 0);
     86}
     87EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
     88
     89int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
     90{
     91	u8 reg, bits;
     92
     93	reg =  irq >> 3;
     94	bits = 1 << (irq & 0x07);
     95
     96	return pcf->mask_regs[reg] & bits;
     97}
     98EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
     99
    100static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
    101{
    102	if (pcf->irq_handler[irq].handler)
    103		pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
    104}
    105
    106/* Maximum amount of time ONKEY is held before emergency action is taken */
    107#define PCF50633_ONKEY1S_TIMEOUT 8
    108
    109static irqreturn_t pcf50633_irq(int irq, void *data)
    110{
    111	struct pcf50633 *pcf = data;
    112	int ret, i, j;
    113	u8 pcf_int[5], chgstat;
    114
    115	/* Read the 5 INT regs in one transaction */
    116	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
    117						ARRAY_SIZE(pcf_int), pcf_int);
    118	if (ret != ARRAY_SIZE(pcf_int)) {
    119		dev_err(pcf->dev, "Error reading INT registers\n");
    120
    121		/*
    122		 * If this doesn't ACK the interrupt to the chip, we'll be
    123		 * called once again as we're level triggered.
    124		 */
    125		goto out;
    126	}
    127
    128	/* defeat 8s death from lowsys on A5 */
    129	pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN,  0x04);
    130
    131	/* We immediately read the usb and adapter status. We thus make sure
    132	 * only of USBINS/USBREM IRQ handlers are called */
    133	if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
    134		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
    135		if (chgstat & (0x3 << 4))
    136			pcf_int[0] &= ~PCF50633_INT1_USBREM;
    137		else
    138			pcf_int[0] &= ~PCF50633_INT1_USBINS;
    139	}
    140
    141	/* Make sure only one of ADPINS or ADPREM is set */
    142	if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
    143		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
    144		if (chgstat & (0x3 << 4))
    145			pcf_int[0] &= ~PCF50633_INT1_ADPREM;
    146		else
    147			pcf_int[0] &= ~PCF50633_INT1_ADPINS;
    148	}
    149
    150	dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
    151			"INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
    152			pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
    153
    154	/* Some revisions of the chip don't have a 8s standby mode on
    155	 * ONKEY1S press. We try to manually do it in such cases. */
    156	if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
    157		dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
    158							pcf->onkey1s_held);
    159		if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
    160			if (pcf->pdata->force_shutdown)
    161				pcf->pdata->force_shutdown(pcf);
    162	}
    163
    164	if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
    165		dev_info(pcf->dev, "ONKEY1S held\n");
    166		pcf->onkey1s_held = 1 ;
    167
    168		/* Unmask IRQ_SECOND */
    169		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
    170						PCF50633_INT1_SECOND);
    171
    172		/* Unmask IRQ_ONKEYR */
    173		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
    174						PCF50633_INT2_ONKEYR);
    175	}
    176
    177	if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
    178		pcf->onkey1s_held = 0;
    179
    180		/* Mask SECOND and ONKEYR interrupts */
    181		if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
    182			pcf50633_reg_set_bit_mask(pcf,
    183					PCF50633_REG_INT1M,
    184					PCF50633_INT1_SECOND,
    185					PCF50633_INT1_SECOND);
    186
    187		if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
    188			pcf50633_reg_set_bit_mask(pcf,
    189					PCF50633_REG_INT2M,
    190					PCF50633_INT2_ONKEYR,
    191					PCF50633_INT2_ONKEYR);
    192	}
    193
    194	/* Have we just resumed ? */
    195	if (pcf->is_suspended) {
    196		pcf->is_suspended = 0;
    197
    198		/* Set the resume reason filtering out non resumers */
    199		for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
    200			pcf->resume_reason[i] = pcf_int[i] &
    201						pcf->pdata->resumers[i];
    202
    203		/* Make sure we don't pass on any ONKEY events to
    204		 * userspace now */
    205		pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
    206	}
    207
    208	for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
    209		/* Unset masked interrupts */
    210		pcf_int[i] &= ~pcf->mask_regs[i];
    211
    212		for (j = 0; j < 8 ; j++)
    213			if (pcf_int[i] & (1 << j))
    214				pcf50633_irq_call_handler(pcf, (i * 8) + j);
    215	}
    216
    217out:
    218	return IRQ_HANDLED;
    219}
    220
    221#ifdef CONFIG_PM
    222
    223int pcf50633_irq_suspend(struct pcf50633 *pcf)
    224{
    225	int ret;
    226	int i;
    227	u8 res[5];
    228
    229
    230	/* Make sure our interrupt handlers are not called
    231	 * henceforth */
    232	disable_irq(pcf->irq);
    233
    234	/* Save the masks */
    235	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
    236				ARRAY_SIZE(pcf->suspend_irq_masks),
    237					pcf->suspend_irq_masks);
    238	if (ret < 0) {
    239		dev_err(pcf->dev, "error saving irq masks\n");
    240		goto out;
    241	}
    242
    243	/* Write wakeup irq masks */
    244	for (i = 0; i < ARRAY_SIZE(res); i++)
    245		res[i] = ~pcf->pdata->resumers[i];
    246
    247	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
    248					ARRAY_SIZE(res), &res[0]);
    249	if (ret < 0) {
    250		dev_err(pcf->dev, "error writing wakeup irq masks\n");
    251		goto out;
    252	}
    253
    254	pcf->is_suspended = 1;
    255
    256out:
    257	return ret;
    258}
    259
    260int pcf50633_irq_resume(struct pcf50633 *pcf)
    261{
    262	int ret;
    263
    264	/* Write the saved mask registers */
    265	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
    266				ARRAY_SIZE(pcf->suspend_irq_masks),
    267					pcf->suspend_irq_masks);
    268	if (ret < 0)
    269		dev_err(pcf->dev, "Error restoring saved suspend masks\n");
    270
    271	enable_irq(pcf->irq);
    272
    273	return ret;
    274}
    275
    276#endif
    277
    278int pcf50633_irq_init(struct pcf50633 *pcf, int irq)
    279{
    280	int ret;
    281
    282	pcf->irq = irq;
    283
    284	/* Enable all interrupts except RTC SECOND */
    285	pcf->mask_regs[0] = 0x80;
    286	pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
    287	pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
    288	pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
    289	pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
    290	pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
    291
    292	ret = request_threaded_irq(irq, NULL, pcf50633_irq,
    293					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
    294					"pcf50633", pcf);
    295
    296	if (ret)
    297		dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
    298
    299	if (enable_irq_wake(irq) < 0)
    300		dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
    301			"in this hardware revision", irq);
    302
    303	return ret;
    304}
    305
    306void pcf50633_irq_free(struct pcf50633 *pcf)
    307{
    308	free_irq(pcf->irq, pcf);
    309}