linux/drivers/media/pci/cx18/cx18-irq.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  cx18 interrupt handling
   4 *
   5 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
   6 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
   7 */
   8
   9#include "cx18-driver.h"
  10#include "cx18-io.h"
  11#include "cx18-irq.h"
  12#include "cx18-mailbox.h"
  13#include "cx18-scb.h"
  14
  15static void xpu_ack(struct cx18 *cx, u32 sw2)
  16{
  17        if (sw2 & IRQ_CPU_TO_EPU_ACK)
  18                wake_up(&cx->mb_cpu_waitq);
  19        if (sw2 & IRQ_APU_TO_EPU_ACK)
  20                wake_up(&cx->mb_apu_waitq);
  21}
  22
  23static void epu_cmd(struct cx18 *cx, u32 sw1)
  24{
  25        if (sw1 & IRQ_CPU_TO_EPU)
  26                cx18_api_epu_cmd_irq(cx, CPU);
  27        if (sw1 & IRQ_APU_TO_EPU)
  28                cx18_api_epu_cmd_irq(cx, APU);
  29}
  30
  31irqreturn_t cx18_irq_handler(int irq, void *dev_id)
  32{
  33        struct cx18 *cx = (struct cx18 *)dev_id;
  34        u32 sw1, sw2, hw2;
  35
  36        sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;
  37        sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask;
  38        hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask;
  39
  40        if (sw1)
  41                cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
  42        if (sw2)
  43                cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
  44        if (hw2)
  45                cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
  46
  47        if (sw1 || sw2 || hw2)
  48                CX18_DEBUG_HI_IRQ("received interrupts SW1: %x  SW2: %x  HW2: %x\n",
  49                                  sw1, sw2, hw2);
  50
  51        /*
  52         * SW1 responses have to happen first.  The sending XPU times out the
  53         * incoming mailboxes on us rather rapidly.
  54         */
  55        if (sw1)
  56                epu_cmd(cx, sw1);
  57
  58        /* To do: interrupt-based I2C handling
  59        if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
  60        }
  61        */
  62
  63        if (sw2)
  64                xpu_ack(cx, sw2);
  65
  66        return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
  67}
  68