162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Toshiba RBTX4927 specific interrupt handlers
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Author: MontaVista Software, Inc.
562306a36Sopenharmony_ci *	   source@mvista.com
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright 2001-2002 MontaVista Software Inc.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  This program is free software; you can redistribute it and/or modify it
1062306a36Sopenharmony_ci *  under the terms of the GNU General Public License as published by the
1162306a36Sopenharmony_ci *  Free Software Foundation; either version 2 of the License, or (at your
1262306a36Sopenharmony_ci *  option) any later version.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1562306a36Sopenharmony_ci *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1662306a36Sopenharmony_ci *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1762306a36Sopenharmony_ci *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1862306a36Sopenharmony_ci *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1962306a36Sopenharmony_ci *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2062306a36Sopenharmony_ci *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2162306a36Sopenharmony_ci *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
2262306a36Sopenharmony_ci *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2362306a36Sopenharmony_ci *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci *  You should have received a copy of the GNU General Public License along
2662306a36Sopenharmony_ci *  with this program; if not, write to the Free Software Foundation, Inc.,
2762306a36Sopenharmony_ci *  675 Mass Ave, Cambridge, MA 02139, USA.
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * I8259A_IRQ_BASE+00
3162306a36Sopenharmony_ci * I8259A_IRQ_BASE+01 PS2/Keyboard
3262306a36Sopenharmony_ci * I8259A_IRQ_BASE+02 Cascade RBTX4927-ISA (irqs 8-15)
3362306a36Sopenharmony_ci * I8259A_IRQ_BASE+03
3462306a36Sopenharmony_ci * I8259A_IRQ_BASE+04
3562306a36Sopenharmony_ci * I8259A_IRQ_BASE+05
3662306a36Sopenharmony_ci * I8259A_IRQ_BASE+06
3762306a36Sopenharmony_ci * I8259A_IRQ_BASE+07
3862306a36Sopenharmony_ci * I8259A_IRQ_BASE+08
3962306a36Sopenharmony_ci * I8259A_IRQ_BASE+09
4062306a36Sopenharmony_ci * I8259A_IRQ_BASE+10
4162306a36Sopenharmony_ci * I8259A_IRQ_BASE+11
4262306a36Sopenharmony_ci * I8259A_IRQ_BASE+12 PS2/Mouse (not supported at this time)
4362306a36Sopenharmony_ci * I8259A_IRQ_BASE+13
4462306a36Sopenharmony_ci * I8259A_IRQ_BASE+14 IDE
4562306a36Sopenharmony_ci * I8259A_IRQ_BASE+15
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+00 Software 0
4862306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+01 Software 1
4962306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+02 Cascade TX4927-CP0
5062306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+03 Multiplexed -- do not use
5162306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+04 Multiplexed -- do not use
5262306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+05 Multiplexed -- do not use
5362306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+06 Multiplexed -- do not use
5462306a36Sopenharmony_ci * MIPS_CPU_IRQ_BASE+07 CPU TIMER
5562306a36Sopenharmony_ci *
5662306a36Sopenharmony_ci * TXX9_IRQ_BASE+00
5762306a36Sopenharmony_ci * TXX9_IRQ_BASE+01
5862306a36Sopenharmony_ci * TXX9_IRQ_BASE+02
5962306a36Sopenharmony_ci * TXX9_IRQ_BASE+03 Cascade RBTX4927-IOC
6062306a36Sopenharmony_ci * TXX9_IRQ_BASE+04
6162306a36Sopenharmony_ci * TXX9_IRQ_BASE+05 RBTX4927 RTL-8019AS ethernet
6262306a36Sopenharmony_ci * TXX9_IRQ_BASE+06
6362306a36Sopenharmony_ci * TXX9_IRQ_BASE+07
6462306a36Sopenharmony_ci * TXX9_IRQ_BASE+08 TX4927 SerialIO Channel 0
6562306a36Sopenharmony_ci * TXX9_IRQ_BASE+09 TX4927 SerialIO Channel 1
6662306a36Sopenharmony_ci * TXX9_IRQ_BASE+10
6762306a36Sopenharmony_ci * TXX9_IRQ_BASE+11
6862306a36Sopenharmony_ci * TXX9_IRQ_BASE+12
6962306a36Sopenharmony_ci * TXX9_IRQ_BASE+13
7062306a36Sopenharmony_ci * TXX9_IRQ_BASE+14
7162306a36Sopenharmony_ci * TXX9_IRQ_BASE+15
7262306a36Sopenharmony_ci * TXX9_IRQ_BASE+16 TX4927 PCI PCI-C
7362306a36Sopenharmony_ci * TXX9_IRQ_BASE+17
7462306a36Sopenharmony_ci * TXX9_IRQ_BASE+18
7562306a36Sopenharmony_ci * TXX9_IRQ_BASE+19
7662306a36Sopenharmony_ci * TXX9_IRQ_BASE+20
7762306a36Sopenharmony_ci * TXX9_IRQ_BASE+21
7862306a36Sopenharmony_ci * TXX9_IRQ_BASE+22 TX4927 PCI PCI-ERR
7962306a36Sopenharmony_ci * TXX9_IRQ_BASE+23 TX4927 PCI PCI-PMA (not used)
8062306a36Sopenharmony_ci * TXX9_IRQ_BASE+24
8162306a36Sopenharmony_ci * TXX9_IRQ_BASE+25
8262306a36Sopenharmony_ci * TXX9_IRQ_BASE+26
8362306a36Sopenharmony_ci * TXX9_IRQ_BASE+27
8462306a36Sopenharmony_ci * TXX9_IRQ_BASE+28
8562306a36Sopenharmony_ci * TXX9_IRQ_BASE+29
8662306a36Sopenharmony_ci * TXX9_IRQ_BASE+30
8762306a36Sopenharmony_ci * TXX9_IRQ_BASE+31
8862306a36Sopenharmony_ci *
8962306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+00 FPCIB0 PCI-D (SouthBridge)
9062306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+01 FPCIB0 PCI-C (SouthBridge)
9162306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+02 FPCIB0 PCI-B (SouthBridge/IDE/pin=1,INTR)
9262306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+03 FPCIB0 PCI-A (SouthBridge/USB/pin=4)
9362306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+04
9462306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+05
9562306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+06
9662306a36Sopenharmony_ci * RBTX4927_IRQ_IOC+07
9762306a36Sopenharmony_ci *
9862306a36Sopenharmony_ci * NOTES:
9962306a36Sopenharmony_ci * SouthBridge/INTR is mapped to SouthBridge/A=PCI-B/#58
10062306a36Sopenharmony_ci * SouthBridge/ISA/pin=0 no pci irq used by this device
10162306a36Sopenharmony_ci * SouthBridge/IDE/pin=1 no pci irq used by this device, using INTR
10262306a36Sopenharmony_ci * via ISA IRQ14
10362306a36Sopenharmony_ci * SouthBridge/USB/pin=4 using pci irq SouthBridge/D=PCI-A=#59
10462306a36Sopenharmony_ci * SouthBridge/PMC/pin=0 no pci irq used by this device
10562306a36Sopenharmony_ci * SuperIO/PS2/Keyboard, using INTR via ISA IRQ1
10662306a36Sopenharmony_ci * SuperIO/PS2/Mouse, using INTR via ISA IRQ12 (mouse not currently supported)
10762306a36Sopenharmony_ci * JP7 is not bus master -- do NOT use -- only 4 pci bus master's
10862306a36Sopenharmony_ci * allowed -- SouthBridge, JP4, JP5, JP6
10962306a36Sopenharmony_ci */
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci#include <linux/init.h>
11262306a36Sopenharmony_ci#include <linux/types.h>
11362306a36Sopenharmony_ci#include <linux/interrupt.h>
11462306a36Sopenharmony_ci#include <linux/irq.h>
11562306a36Sopenharmony_ci#include <asm/io.h>
11662306a36Sopenharmony_ci#include <asm/mipsregs.h>
11762306a36Sopenharmony_ci#include <asm/txx9/generic.h>
11862306a36Sopenharmony_ci#include <asm/txx9/rbtx4927.h>
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic int toshiba_rbtx4927_irq_nested(int sw_irq)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	u8 level3;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	level3 = readb(rbtx4927_imstat_addr) & 0x1f;
12562306a36Sopenharmony_ci	if (unlikely(!level3))
12662306a36Sopenharmony_ci		return -1;
12762306a36Sopenharmony_ci	return RBTX4927_IRQ_IOC + __fls8(level3);
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic void toshiba_rbtx4927_irq_ioc_enable(struct irq_data *d)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	unsigned char v;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	v = readb(rbtx4927_imask_addr);
13562306a36Sopenharmony_ci	v |= (1 << (d->irq - RBTX4927_IRQ_IOC));
13662306a36Sopenharmony_ci	writeb(v, rbtx4927_imask_addr);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic void toshiba_rbtx4927_irq_ioc_disable(struct irq_data *d)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	unsigned char v;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	v = readb(rbtx4927_imask_addr);
14462306a36Sopenharmony_ci	v &= ~(1 << (d->irq - RBTX4927_IRQ_IOC));
14562306a36Sopenharmony_ci	writeb(v, rbtx4927_imask_addr);
14662306a36Sopenharmony_ci	mmiowb();
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
15062306a36Sopenharmony_cistatic struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
15162306a36Sopenharmony_ci	.name = TOSHIBA_RBTX4927_IOC_NAME,
15262306a36Sopenharmony_ci	.irq_mask = toshiba_rbtx4927_irq_ioc_disable,
15362306a36Sopenharmony_ci	.irq_unmask = toshiba_rbtx4927_irq_ioc_enable,
15462306a36Sopenharmony_ci};
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic void __init toshiba_rbtx4927_irq_ioc_init(void)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	int i;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	/* mask all IOC interrupts */
16162306a36Sopenharmony_ci	writeb(0, rbtx4927_imask_addr);
16262306a36Sopenharmony_ci	/* clear SoftInt interrupts */
16362306a36Sopenharmony_ci	writeb(0, rbtx4927_softint_addr);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	for (i = RBTX4927_IRQ_IOC;
16662306a36Sopenharmony_ci	     i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++)
16762306a36Sopenharmony_ci		irq_set_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
16862306a36Sopenharmony_ci					 handle_level_irq);
16962306a36Sopenharmony_ci	irq_set_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic int rbtx4927_irq_dispatch(int pending)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	int irq;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (pending & STATUSF_IP7)			/* cpu timer */
17762306a36Sopenharmony_ci		irq = MIPS_CPU_IRQ_BASE + 7;
17862306a36Sopenharmony_ci	else if (pending & STATUSF_IP2) {		/* tx4927 pic */
17962306a36Sopenharmony_ci		irq = txx9_irq();
18062306a36Sopenharmony_ci		if (irq == RBTX4927_IRQ_IOCINT)
18162306a36Sopenharmony_ci			irq = toshiba_rbtx4927_irq_nested(irq);
18262306a36Sopenharmony_ci	} else if (pending & STATUSF_IP0)		/* user line 0 */
18362306a36Sopenharmony_ci		irq = MIPS_CPU_IRQ_BASE + 0;
18462306a36Sopenharmony_ci	else if (pending & STATUSF_IP1)			/* user line 1 */
18562306a36Sopenharmony_ci		irq = MIPS_CPU_IRQ_BASE + 1;
18662306a36Sopenharmony_ci	else
18762306a36Sopenharmony_ci		irq = -1;
18862306a36Sopenharmony_ci	return irq;
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_civoid __init rbtx4927_irq_setup(void)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	txx9_irq_dispatch = rbtx4927_irq_dispatch;
19462306a36Sopenharmony_ci	tx4927_irq_init();
19562306a36Sopenharmony_ci	toshiba_rbtx4927_irq_ioc_init();
19662306a36Sopenharmony_ci	/* Onboard 10M Ether: High Active */
19762306a36Sopenharmony_ci	irq_set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH);
19862306a36Sopenharmony_ci}
199