18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Toshiba RBTX4939 interrupt routines
38c2ecf20Sopenharmony_ci * Based on linux/arch/mips/txx9/rbtx4938/irq.c,
48c2ecf20Sopenharmony_ci *	    and RBTX49xx patch from CELF patch archive.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation
78c2ecf20Sopenharmony_ci * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
88c2ecf20Sopenharmony_ci * terms of the GNU General Public License version 2. This program is
98c2ecf20Sopenharmony_ci * licensed "as is" without any warranty of any kind, whether express
108c2ecf20Sopenharmony_ci * or implied.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
148c2ecf20Sopenharmony_ci#include <linux/irq.h>
158c2ecf20Sopenharmony_ci#include <asm/mipsregs.h>
168c2ecf20Sopenharmony_ci#include <asm/txx9/rbtx4939.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/*
198c2ecf20Sopenharmony_ci * RBTX4939 IOC controller definition
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic void rbtx4939_ioc_irq_unmask(struct irq_data *d)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr);
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic void rbtx4939_ioc_irq_mask(struct irq_data *d)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr);
348c2ecf20Sopenharmony_ci	mmiowb();
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic struct irq_chip rbtx4939_ioc_irq_chip = {
388c2ecf20Sopenharmony_ci	.name		= "IOC",
398c2ecf20Sopenharmony_ci	.irq_mask	= rbtx4939_ioc_irq_mask,
408c2ecf20Sopenharmony_ci	.irq_unmask	= rbtx4939_ioc_irq_unmask,
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic inline int rbtx4939_ioc_irqroute(void)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	unsigned char istat = readb(rbtx4939_ifac2_addr);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (unlikely(istat == 0))
498c2ecf20Sopenharmony_ci		return -1;
508c2ecf20Sopenharmony_ci	return RBTX4939_IRQ_IOC + __fls8(istat);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic int rbtx4939_irq_dispatch(int pending)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	int irq;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	if (pending & CAUSEF_IP7)
588c2ecf20Sopenharmony_ci		return MIPS_CPU_IRQ_BASE + 7;
598c2ecf20Sopenharmony_ci	irq = tx4939_irq();
608c2ecf20Sopenharmony_ci	if (likely(irq >= 0)) {
618c2ecf20Sopenharmony_ci		/* redirect IOC interrupts */
628c2ecf20Sopenharmony_ci		switch (irq) {
638c2ecf20Sopenharmony_ci		case RBTX4939_IRQ_IOCINT:
648c2ecf20Sopenharmony_ci			irq = rbtx4939_ioc_irqroute();
658c2ecf20Sopenharmony_ci			break;
668c2ecf20Sopenharmony_ci		}
678c2ecf20Sopenharmony_ci	} else if (pending & CAUSEF_IP0)
688c2ecf20Sopenharmony_ci		irq = MIPS_CPU_IRQ_BASE + 0;
698c2ecf20Sopenharmony_ci	else if (pending & CAUSEF_IP1)
708c2ecf20Sopenharmony_ci		irq = MIPS_CPU_IRQ_BASE + 1;
718c2ecf20Sopenharmony_ci	else
728c2ecf20Sopenharmony_ci		irq = -1;
738c2ecf20Sopenharmony_ci	return irq;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_civoid __init rbtx4939_irq_setup(void)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	int i;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/* mask all IOC interrupts */
818c2ecf20Sopenharmony_ci	writeb(0, rbtx4939_ien_addr);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	/* clear SoftInt interrupts */
848c2ecf20Sopenharmony_ci	writeb(0, rbtx4939_softint_addr);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	txx9_irq_dispatch = rbtx4939_irq_dispatch;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	tx4939_irq_init();
898c2ecf20Sopenharmony_ci	for (i = RBTX4939_IRQ_IOC;
908c2ecf20Sopenharmony_ci	     i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++)
918c2ecf20Sopenharmony_ci		irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
928c2ecf20Sopenharmony_ci					 handle_level_irq);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
958c2ecf20Sopenharmony_ci}
96