162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * cx18 interrupt handling 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 662306a36Sopenharmony_ci * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "cx18-driver.h" 1062306a36Sopenharmony_ci#include "cx18-io.h" 1162306a36Sopenharmony_ci#include "cx18-irq.h" 1262306a36Sopenharmony_ci#include "cx18-mailbox.h" 1362306a36Sopenharmony_ci#include "cx18-scb.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic void xpu_ack(struct cx18 *cx, u32 sw2) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci if (sw2 & IRQ_CPU_TO_EPU_ACK) 1862306a36Sopenharmony_ci wake_up(&cx->mb_cpu_waitq); 1962306a36Sopenharmony_ci if (sw2 & IRQ_APU_TO_EPU_ACK) 2062306a36Sopenharmony_ci wake_up(&cx->mb_apu_waitq); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic void epu_cmd(struct cx18 *cx, u32 sw1) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci if (sw1 & IRQ_CPU_TO_EPU) 2662306a36Sopenharmony_ci cx18_api_epu_cmd_irq(cx, CPU); 2762306a36Sopenharmony_ci if (sw1 & IRQ_APU_TO_EPU) 2862306a36Sopenharmony_ci cx18_api_epu_cmd_irq(cx, APU); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciirqreturn_t cx18_irq_handler(int irq, void *dev_id) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci struct cx18 *cx = dev_id; 3462306a36Sopenharmony_ci u32 sw1, sw2, hw2; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask; 3762306a36Sopenharmony_ci sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask; 3862306a36Sopenharmony_ci hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (sw1) 4162306a36Sopenharmony_ci cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); 4262306a36Sopenharmony_ci if (sw2) 4362306a36Sopenharmony_ci cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); 4462306a36Sopenharmony_ci if (hw2) 4562306a36Sopenharmony_ci cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (sw1 || sw2 || hw2) 4862306a36Sopenharmony_ci CX18_DEBUG_HI_IRQ("received interrupts SW1: %x SW2: %x HW2: %x\n", 4962306a36Sopenharmony_ci sw1, sw2, hw2); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* 5262306a36Sopenharmony_ci * SW1 responses have to happen first. The sending XPU times out the 5362306a36Sopenharmony_ci * incoming mailboxes on us rather rapidly. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci if (sw1) 5662306a36Sopenharmony_ci epu_cmd(cx, sw1); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* To do: interrupt-based I2C handling 5962306a36Sopenharmony_ci if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (sw2) 6462306a36Sopenharmony_ci xpu_ack(cx, sw2); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; 6762306a36Sopenharmony_ci} 68