1 /* 2 * cx18 interrupt handling 3 * 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20 * 02111-1307 USA 21 */ 22 23 #include "cx18-driver.h" 24 #include "cx18-io.h" 25 #include "cx18-irq.h" 26 #include "cx18-mailbox.h" 27 #include "cx18-scb.h" 28 29 static void xpu_ack(struct cx18 *cx, u32 sw2) 30 { 31 if (sw2 & IRQ_CPU_TO_EPU_ACK) 32 wake_up(&cx->mb_cpu_waitq); 33 if (sw2 & IRQ_APU_TO_EPU_ACK) 34 wake_up(&cx->mb_apu_waitq); 35 } 36 37 static void epu_cmd(struct cx18 *cx, u32 sw1) 38 { 39 if (sw1 & IRQ_CPU_TO_EPU) 40 cx18_api_epu_cmd_irq(cx, CPU); 41 if (sw1 & IRQ_APU_TO_EPU) 42 cx18_api_epu_cmd_irq(cx, APU); 43 } 44 45 irqreturn_t cx18_irq_handler(int irq, void *dev_id) 46 { 47 struct cx18 *cx = (struct cx18 *)dev_id; 48 u32 sw1, sw2, hw2; 49 50 sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask; 51 sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask; 52 hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask; 53 54 if (sw1) 55 cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); 56 if (sw2) 57 cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); 58 if (hw2) 59 cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); 60 61 if (sw1 || sw2 || hw2) 62 CX18_DEBUG_HI_IRQ("received interrupts " 63 "SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); 64 65 /* 66 * SW1 responses have to happen first. The sending XPU times out the 67 * incoming mailboxes on us rather rapidly. 68 */ 69 if (sw1) 70 epu_cmd(cx, sw1); 71 72 /* To do: interrupt-based I2C handling 73 if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { 74 } 75 */ 76 77 if (sw2) 78 xpu_ack(cx, sw2); 79 80 return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; 81 } 82