2008-04-29 03:24:33 +04:00
/*
* cx18 interrupt handling
*
* Copyright ( C ) 2007 Hans Verkuil < hverkuil @ xs4all . nl >
2008-11-22 07:37:34 +03:00
* Copyright ( C ) 2008 Andy Walls < awalls @ radix . net >
2008-04-29 03:24:33 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA
* 02111 - 1307 USA
*/
# include "cx18-driver.h"
2008-08-30 23:03:44 +04:00
# include "cx18-io.h"
2008-04-29 03:24:33 +04:00
# include "cx18-irq.h"
# include "cx18-mailbox.h"
# include "cx18-scb.h"
2008-11-05 04:02:23 +03:00
static void xpu_ack ( struct cx18 * cx , u32 sw2 )
{
if ( sw2 & IRQ_CPU_TO_EPU_ACK )
wake_up ( & cx - > mb_cpu_waitq ) ;
if ( sw2 & IRQ_APU_TO_EPU_ACK )
wake_up ( & cx - > mb_apu_waitq ) ;
2008-04-29 03:24:33 +04:00
}
2008-11-16 07:38:19 +03:00
static void epu_cmd ( struct cx18 * cx , u32 sw1 )
{
if ( sw1 & IRQ_CPU_TO_EPU )
cx18_api_epu_cmd_irq ( cx , CPU ) ;
if ( sw1 & IRQ_APU_TO_EPU )
cx18_api_epu_cmd_irq ( cx , APU ) ;
}
2008-04-29 03:24:33 +04:00
irqreturn_t cx18_irq_handler ( int irq , void * dev_id )
{
struct cx18 * cx = ( struct cx18 * ) dev_id ;
2008-11-18 04:48:46 +03:00
u32 sw1 , sw2 , hw2 ;
2008-04-29 03:24:33 +04:00
2008-11-18 04:48:46 +03:00
sw1 = cx18_read_reg ( cx , SW1_INT_STATUS ) & cx - > sw1_irq_mask ;
sw2 = cx18_read_reg ( cx , SW2_INT_STATUS ) & cx - > sw2_irq_mask ;
hw2 = cx18_read_reg ( cx , HW2_INT_CLR_STATUS ) & cx - > hw2_irq_mask ;
2008-04-29 03:24:33 +04:00
2008-11-01 02:49:12 +03:00
if ( sw1 )
cx18_write_reg_expect ( cx , sw1 , SW1_INT_STATUS , ~ sw1 , sw1 ) ;
if ( sw2 )
cx18_write_reg_expect ( cx , sw2 , SW2_INT_STATUS , ~ sw2 , sw2 ) ;
if ( hw2 )
cx18_write_reg_expect ( cx , hw2 , HW2_INT_CLR_STATUS , ~ hw2 , hw2 ) ;
2008-04-29 03:24:33 +04:00
if ( sw1 | | sw2 | | hw2 )
2008-11-08 05:57:46 +03:00
CX18_DEBUG_HI_IRQ ( " received interrupts "
" SW1: %x SW2: %x HW2: %x \n " , sw1 , sw2 , hw2 ) ;
2008-04-29 03:24:33 +04:00
2008-11-16 07:38:19 +03:00
/*
* SW1 responses have to happen first . The sending XPU times out the
* incoming mailboxes on us rather rapidly .
*/
if ( sw1 )
epu_cmd ( cx , sw1 ) ;
2008-04-29 03:24:33 +04:00
/* To do: interrupt-based I2C handling
2008-11-05 04:02:23 +03:00
if ( hw2 & ( HW2_I2C1_INT | HW2_I2C2_INT ) ) {
2008-04-29 03:24:33 +04:00
}
*/
2008-11-05 04:02:23 +03:00
if ( sw2 )
xpu_ack ( cx , sw2 ) ;
2008-04-29 03:24:33 +04:00
2008-11-01 02:49:12 +03:00
return ( sw1 | | sw2 | | hw2 ) ? IRQ_HANDLED : IRQ_NONE ;
2008-04-29 03:24:33 +04:00
}