18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * cx18 interrupt handling 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 68c2ecf20Sopenharmony_ci * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "cx18-driver.h" 108c2ecf20Sopenharmony_ci#include "cx18-io.h" 118c2ecf20Sopenharmony_ci#include "cx18-irq.h" 128c2ecf20Sopenharmony_ci#include "cx18-mailbox.h" 138c2ecf20Sopenharmony_ci#include "cx18-scb.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic void xpu_ack(struct cx18 *cx, u32 sw2) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci if (sw2 & IRQ_CPU_TO_EPU_ACK) 188c2ecf20Sopenharmony_ci wake_up(&cx->mb_cpu_waitq); 198c2ecf20Sopenharmony_ci if (sw2 & IRQ_APU_TO_EPU_ACK) 208c2ecf20Sopenharmony_ci wake_up(&cx->mb_apu_waitq); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic void epu_cmd(struct cx18 *cx, u32 sw1) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci if (sw1 & IRQ_CPU_TO_EPU) 268c2ecf20Sopenharmony_ci cx18_api_epu_cmd_irq(cx, CPU); 278c2ecf20Sopenharmony_ci if (sw1 & IRQ_APU_TO_EPU) 288c2ecf20Sopenharmony_ci cx18_api_epu_cmd_irq(cx, APU); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciirqreturn_t cx18_irq_handler(int irq, void *dev_id) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct cx18 *cx = (struct cx18 *)dev_id; 348c2ecf20Sopenharmony_ci u32 sw1, sw2, hw2; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask; 378c2ecf20Sopenharmony_ci sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask; 388c2ecf20Sopenharmony_ci hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (sw1) 418c2ecf20Sopenharmony_ci cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); 428c2ecf20Sopenharmony_ci if (sw2) 438c2ecf20Sopenharmony_ci cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); 448c2ecf20Sopenharmony_ci if (hw2) 458c2ecf20Sopenharmony_ci cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (sw1 || sw2 || hw2) 488c2ecf20Sopenharmony_ci CX18_DEBUG_HI_IRQ("received interrupts SW1: %x SW2: %x HW2: %x\n", 498c2ecf20Sopenharmony_ci sw1, sw2, hw2); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* 528c2ecf20Sopenharmony_ci * SW1 responses have to happen first. The sending XPU times out the 538c2ecf20Sopenharmony_ci * incoming mailboxes on us rather rapidly. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci if (sw1) 568c2ecf20Sopenharmony_ci epu_cmd(cx, sw1); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* To do: interrupt-based I2C handling 598c2ecf20Sopenharmony_ci if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (sw2) 648c2ecf20Sopenharmony_ci xpu_ack(cx, sw2); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; 678c2ecf20Sopenharmony_ci} 68