11c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil/*
21c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  cx18 interrupt handling
31c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
41c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
56afdeaf865b729287e02aafc61d8d013b89996efAndy Walls *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
61c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
71c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  This program is free software; you can redistribute it and/or modify
81c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  it under the terms of the GNU General Public License as published by
91c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  the Free Software Foundation; either version 2 of the License, or
101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  (at your option) any later version.
111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  This program is distributed in the hope that it will be useful,
131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  but WITHOUT ANY WARRANTY; without even the implied warranty of
141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  GNU General Public License for more details.
161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  You should have received a copy of the GNU General Public License
181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  along with this program; if not, write to the Free Software
191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  02111-1307  USA
211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil */
221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-driver.h"
24b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls#include "cx18-io.h"
251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-irq.h"
261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-mailbox.h"
271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-scb.h"
28465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls
29465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Wallsstatic void xpu_ack(struct cx18 *cx, u32 sw2)
30465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls{
31465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls	if (sw2 & IRQ_CPU_TO_EPU_ACK)
32465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls		wake_up(&cx->mb_cpu_waitq);
33465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls	if (sw2 & IRQ_APU_TO_EPU_ACK)
34465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls		wake_up(&cx->mb_apu_waitq);
351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
37ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Wallsstatic void epu_cmd(struct cx18 *cx, u32 sw1)
38ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls{
39ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	if (sw1 & IRQ_CPU_TO_EPU)
40ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls		cx18_api_epu_cmd_irq(cx, CPU);
41ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	if (sw1 & IRQ_APU_TO_EPU)
42ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls		cx18_api_epu_cmd_irq(cx, APU);
43ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls}
44ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls
451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilirqreturn_t cx18_irq_handler(int irq, void *dev_id)
461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = (struct cx18 *)dev_id;
48d6c7e5f8faad080e75bace5c4f2265e3513e3510Andy Walls	u32 sw1, sw2, hw2;
491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
50d6c7e5f8faad080e75bace5c4f2265e3513e3510Andy Walls	sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;
51d6c7e5f8faad080e75bace5c4f2265e3513e3510Andy Walls	sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask;
52d6c7e5f8faad080e75bace5c4f2265e3513e3510Andy Walls	hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask;
531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
54f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls	if (sw1)
55f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls		cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
56f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls	if (sw2)
57f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls		cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
58f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls	if (hw2)
59f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls		cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (sw1 || sw2 || hw2)
62ac50441720332f22a9d85ac03151d6acb7bc55d6Andy Walls		CX18_DEBUG_HI_IRQ("received interrupts "
63ac50441720332f22a9d85ac03151d6acb7bc55d6Andy Walls				  "SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
65ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	/*
66ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	 * SW1 responses have to happen first.  The sending XPU times out the
67ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	 * incoming mailboxes on us rather rapidly.
68ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	 */
69ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls	if (sw1)
70ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls		epu_cmd(cx, sw1);
71ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060Andy Walls
721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* To do: interrupt-based I2C handling
73465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls	if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	*/
761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
77465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls	if (sw2)
78465f8a805d3796fac2b2fb0c630217f6f76e667cAndy Walls		xpu_ack(cx, sw2);
791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
80f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls	return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
82