コード例 #1
0
ファイル: pmic8901.c プロジェクト: mkannapa/sgh-i727-kernels
static void pm8901_irq_unmask(unsigned int irq)
{
	int	master, irq_bit;
	struct	pm8901_chip *chip = get_irq_data(irq);
	u8	block, config, old_irqs_allowed, old_blocks_allowed;

	irq -= chip->pdata.irq_base;
	block = irq / 8;
	master = block / 8;
	irq_bit = irq % 8;

	old_irqs_allowed = chip->irqs_allowed[block];
	chip->irqs_allowed[block] |= 1 << irq_bit;
	if (!old_irqs_allowed) {
		master = block / 8;

		old_blocks_allowed = chip->blocks_allowed[master];
		chip->blocks_allowed[master] |= 1 << (block % 8);

		if (!old_blocks_allowed)
			chip->masters_allowed |= 1 << master;
	}

	config = PM8901_IRQF_WRITE | chip->config[irq];
	pm8901_config_irq(chip, &block, &config);
}
コード例 #2
0
ファイル: pmic8901.c プロジェクト: mkannapa/sgh-i727-kernels
static void pm8901_irq_ack(unsigned int irq)
{
	struct	pm8901_chip *chip = get_irq_data(irq);
	u8	block, config;

	irq -= chip->pdata.irq_base;
	block = irq / 8;

	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
	pm8901_config_irq(chip, &block, &config);
}
コード例 #3
0
static void pm8901_irq_ack(struct irq_data *d)
{
	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
	u8	block, config;
	unsigned int irq = d->irq;

	irq -= chip->pdata.irq_base;
	block = irq / 8;

	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
	pm8901_config_irq(chip, &block, &config);
}
コード例 #4
0
static int pm8901_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
	int	master, irq_bit;
	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
	u8	block, config;
	unsigned int irq = d->irq;

	irq -= chip->pdata.irq_base;
	if (irq > chip->pm_max_irq) {
		chip->pm_max_irq = irq;
		chip->pm_max_blocks =
			chip->pm_max_irq / 8 + 1;
		chip->pm_max_masters =
			chip->pm_max_blocks / 8 + 1;
	}
	block = irq / 8;
	master = block / 8;
	irq_bit = irq % 8;

	chip->config[irq] = (irq_bit << PM8901_IRQF_BITS_SHIFT) |
			PM8901_IRQF_MASK_RE | PM8901_IRQF_MASK_FE;
	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
		if (flow_type & IRQF_TRIGGER_RISING)
			chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
		if (flow_type & IRQF_TRIGGER_FALLING)
			chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
	} else {
		chip->config[irq] |= PM8901_IRQF_LVL_SEL;

		if (flow_type & IRQF_TRIGGER_HIGH)
			chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
		else
			chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
	}

	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
	return pm8901_config_irq(chip, &block, &config);
}
コード例 #5
0
ファイル: pmic8901.c プロジェクト: mkannapa/sgh-i727-kernels
static void pm8901_irq_mask(unsigned int irq)
{
	int	master, irq_bit;
	struct	pm8901_chip *chip = get_irq_data(irq);
	u8	block, config;

	irq -= chip->pdata.irq_base;
	block = irq / 8;
	master = block / 8;
	irq_bit = irq % 8;

	chip->irqs_allowed[block] &= ~(1 << irq_bit);
	if (!chip->irqs_allowed[block]) {
		chip->blocks_allowed[master] &= ~(1 << (block % 8));

		if (!chip->blocks_allowed[master])
			chip->masters_allowed &= ~(1 << master);
	}

	config = PM8901_IRQF_WRITE | chip->config[irq] |
		PM8901_IRQF_MASK_FE | PM8901_IRQF_MASK_RE;
	pm8901_config_irq(chip, &block, &config);
}
コード例 #6
0
ファイル: pmic8901.c プロジェクト: mkannapa/sgh-i727-kernels
static irqreturn_t pm8901_isr_thread(int irq_requested, void *data)
{
	struct pm8901_chip *chip = data;
	int	i, j, k;
	u8	root, block, config, bits;
	u8	blocks[MAX_PM_MASTERS];
	int	masters = 0, irq, handled = 0, spurious = 0;
	u16     irqs_to_handle[MAX_PM_IRQ];
	unsigned long	irqsave;

	spin_lock_irqsave(&chip->pm_lock, irqsave);

	/* Read root for masters */
	if (pm8901_read_root(chip, &root))
		goto bail_out;

	masters = root >> 1;

	if (!(masters & chip->masters_allowed) ||
	    (masters & ~chip->masters_allowed)) {
		spurious = 1000000;
	}

	/* Read allowed masters for blocks. */
	for (i = 0; i < chip->pm_max_masters; i++) {
		if (masters & (1 << i)) {
			if (pm8901_read_master(chip, i, &blocks[i]))
				goto bail_out;

			if (!blocks[i]) {
				if (pm8901_can_print())
					pr_err("%s: Spurious master: %d "
					       "(blocks=0)", __func__, i);
				spurious += 10000;
			}
		} else
			blocks[i] = 0;
	}

	/* Select block, read status and call isr */
	for (i = 0; i < chip->pm_max_masters; i++) {
		if (!blocks[i])
			continue;

		for (j = 0; j < 8; j++) {
			if (!(blocks[i] & (1 << j)))
				continue;

			block = i * 8 + j;	/* block # */
			if (pm8901_read_block(chip, &block, &bits))
				goto bail_out;

			if (!bits) {
				if (pm8901_can_print())
					pr_err("%s: Spurious block: "
					       "[master, block]=[%d, %d] "
					       "(bits=0)\n", __func__, i, j);
				spurious += 100;
				continue;
			}

			/* Check IRQ bits */
			for (k = 0; k < 8; k++) {
				if (!(bits & (1 << k)))
					continue;

				/* Check spurious interrupts */
				if (((1 << i) & chip->masters_allowed) &&
				    (blocks[i] & chip->blocks_allowed[i]) &&
				    (bits & chip->irqs_allowed[block])) {

					/* Found one */
					irq = block * 8 + k;
					irqs_to_handle[handled] = irq +
						chip->pdata.irq_base;
					handled++;
				} else {
					/* Clear and mask wrong one */
					config = PM8901_IRQF_W_C_M |
						(k < PM8901_IRQF_BITS_SHIFT);

					pm8901_config_irq(chip,
							  &block, &config);

					if (pm8901_can_print())
						pr_err("%s: Spurious IRQ: "
						       "[master, block, bit]="
						       "[%d, %d (%d), %d]\n",
							__func__,
						       i, j, block, k);
					spurious++;
				}
			}
		}

	}

bail_out:

	spin_unlock_irqrestore(&chip->pm_lock, irqsave);

	for (i = 0; i < handled; i++)
		generic_handle_irq(irqs_to_handle[i]);

	if (spurious) {
		if (!pm8901_can_print())
			return IRQ_HANDLED;

		pr_err("%s: spurious = %d (handled = %d)\n",
		       __func__, spurious, handled);
		pr_err("   root = 0x%x (masters_allowed<<1 = 0x%x)\n",
		       root, chip->masters_allowed << 1);
		for (i = 0; i < chip->pm_max_masters; i++) {
			if (masters & (1 << i))
				pr_err("   blocks[%d]=0x%x, "
				       "allowed[%d]=0x%x\n",
				       i, blocks[i],
				       i, chip->blocks_allowed[i]);
		}
	}

	return IRQ_HANDLED;
}