Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea0f8fea authored by Jamie Lenehan's avatar Jamie Lenehan Committed by Paul Mundt
Browse files

sh: sh775x/titan fixes for irq header changes.



The following moves the creation of IPR interupts into setup-7750.c
and updates a few other things to make it all work after the "Drop
CPU subtype IRQ headers" commit. It boots and runs fine on my titan
board.

 - adds an ipr_idx to the ipr_data and uses a function in the subtype
   code to calculate the address of the IPR registers

 - adds a function to enable individual interrupt mode for externals
   in the subtype code and calls that from the titan board code
   instead of doing it directly.

 - I changed the shift in the ipr_data to be the actual # of bits to
   shift, instead of the numnber / 4 - made it easier to match with
   the manual.

Signed-off-by: default avatarJamie Lenehan <lenehan@twibble.org>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent fe9687de
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -375,6 +375,9 @@ config CPU_HAS_MASKREG_IRQ
config CPU_HAS_INTC2_IRQ
	bool

config CPU_HAS_IPR_IRQ
	bool

config CPU_HAS_SR_RB
	bool "CPU has SR.RB"
	depends on CPU_SH3 || CPU_SH4
+15 −12
Original line number Diff line number Diff line
/*
 *	Setup for Titan
 * arch/sh/boards/titan/setup.c - Setup for Titan
 *
 *  Copyright (C) 2006  Jamie Lenehan
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */

#include <linux/init.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/titan.h>
#include <asm/io.h>

extern void __init pcibios_init_platform(void);

static struct ipr_data titan_ipr_map[] = {
	{ TITAN_IRQ_WAN,	IRL0_IPR_ADDR,	IRL0_IPR_POS,	IRL0_PRIORITY },
	{ TITAN_IRQ_LAN,	IRL1_IPR_ADDR,	IRL1_IPR_POS,	IRL1_PRIORITY },
	{ TITAN_IRQ_MPCIA,	IRL2_IPR_ADDR,	IRL2_IPR_POS,	IRL2_PRIORITY },
	{ TITAN_IRQ_USB,	IRL3_IPR_ADDR,	IRL3_IPR_POS,	IRL3_PRIORITY },
	/* IRQ, IPR idx, shift, prio */
	{ TITAN_IRQ_WAN,   3, 12, 8 },	/* eth0 (WAN) */
	{ TITAN_IRQ_LAN,   3,  8, 8 },	/* eth1 (LAN) */
	{ TITAN_IRQ_MPCIA, 3,  4, 8 },	/* mPCI A (top) */
	{ TITAN_IRQ_USB,   3,  0, 8 },	/* mPCI B (bottom), USB */
};

static void __init init_titan_irq(void)
{
	/* enable individual interrupt mode for externals */
	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);

	ipr_irq_enable_irlm();
	/* register ipr irqs */
	make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
}

@@ -47,6 +51,5 @@ struct sh_machine_vector mv_titan __initmv = {
	.mv_ioport_map = titan_ioport_map,

	.mv_init_irq =	init_titan_irq,
	.mv_init_pci =	pcibios_init_platform,
};
ALIAS_MV(titan)
+10 −14
Original line number Diff line number Diff line
@@ -15,25 +15,21 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <linux/io.h>
#include <asm/titan.h>
#include "pci-sh4.h"

static char titan_irq_tab[] __initdata = {
	TITAN_IRQ_WAN,
	TITAN_IRQ_LAN,
	TITAN_IRQ_MPCIA,
	TITAN_IRQ_MPCIB,
	TITAN_IRQ_USB,
};

int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
	int irq = -1;

	switch (slot) {
	case 0: irq = TITAN_IRQ_WAN;   break;	/* eth0 (WAN) */
	case 1: irq = TITAN_IRQ_LAN;   break;	/* eth1 (LAN) */
	case 2: irq = TITAN_IRQ_MPCIA; break;	/* mPCI A */
	case 3: irq = TITAN_IRQ_MPCIB; break;	/* mPCI B */
	case 4: irq = TITAN_IRQ_USB;   break;	/* USB */
	default:
		printk(KERN_INFO "PCI: Bad IRQ mapping "
				 "request for slot %d\n", slot);
		return -1;
	}
	int irq = titan_irq_tab[slot];

	printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
		slot, pin - 1 + 'A', irq);
+2 −1
Original line number Diff line number Diff line
#
# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
#
obj-y	+= ipr.o imask.o
obj-y	+= imask.o

obj-$(CONFIG_CPU_HAS_IPR_IRQ)		+= ipr.o
obj-$(CONFIG_CPU_HAS_PINT_IRQ)		+= pint.o
obj-$(CONFIG_CPU_HAS_MASKREG_IRQ)	+= maskreg.o
obj-$(CONFIG_CPU_HAS_INTC2_IRQ)		+= intc2.o
+6 −97
Original line number Diff line number Diff line
@@ -25,17 +25,15 @@
static void disable_ipr_irq(unsigned int irq)
{
	struct ipr_data *p = get_irq_chip_data(irq);
	int shift = p->shift*4;
	/* Set the priority in IPR to 0 */
	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr);
	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
}

static void enable_ipr_irq(unsigned int irq)
{
	struct ipr_data *p = get_irq_chip_data(irq);
	int shift = p->shift*4;
	/* Set priority in IPR back to original value */
	ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr);
	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
}

static struct irq_chip ipr_irq_chip = {
@@ -51,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)

	for (i = 0; i < nr_irqs; i++) {
		unsigned int irq = table[i].irq;
		table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
		/* could the IPR index be mapped, if not we ignore this */
		if (table[i].addr == 0)
			continue;
		disable_irq_nosync(irq);
		set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
				      handle_level_irq, "level");
@@ -60,99 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
}
EXPORT_SYMBOL(make_ipr_irq);

/*
 * XXX: Move this garbage in to the drivers, and kill off the ridiculous CPU
 * subtype checks.
 */
static struct ipr_data sys_ipr_map[] = {
#ifndef CONFIG_CPU_SUBTYPE_SH7780
	{ TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY },
	{ TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY },
#ifdef RTC_IRQ
	{ RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY },
#endif
#ifdef SCI_ERI_IRQ
	{ SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
	{ SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
	{ SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
#endif
#ifdef SCIF1_ERI_IRQ
	{ SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
	{ SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
	{ SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
	{ SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
#endif
#ifdef SCIF2_ERI_IRQ
	{ SCIF2_ERI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
	{ SCIF2_RXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
	{ SCIF2_BRI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
	{ SCIF2_TXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
#endif
#ifdef SCIF3_ERI_IRQ
	{ SCIF3_ERI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
	{ SCIF3_RXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
	{ SCIF3_BRI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
	{ SCIF3_TXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
	{ SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY },
	{ DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
	{ DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
	{ VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
#endif
#ifdef SCIF_ERI_IRQ
	{ SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
	{ SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
	{ SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
	{ SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
#endif
#ifdef IRDA_ERI_IRQ
	{ IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
	{ IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
	{ IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
	{ IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
	/*
	 * Initialize the Interrupt Controller (INTC)
	 * registers to their power on values
	 */

	/*
	 * Enable external irq (INTC IRQ mode).
	 * You should set corresponding bits of PFC to "00"
	 * to enable these interrupts.
	 */
	{ IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY },
	{ IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY },
	{ IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY },
	{ IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY },
	{ IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY },
	{ IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY },
#endif
#endif
};

void __init init_IRQ(void)
{
	make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map));

#ifdef CONFIG_CPU_HAS_PINT_IRQ
	init_IRQ_pint();
#endif

#ifdef CONFIG_CPU_HAS_INTC2_IRQ
	init_IRQ_intc2();
#endif
	/* Perform the machine specific initialisation */
	if (sh_mv.mv_init_irq != NULL)
		sh_mv.mv_init_irq();

	irq_ctx_init(smp_processor_id());
}

#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
int ipr_irq_demux(int irq)
{
Loading