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

Commit 68abdbbb authored by Magnus Damm's avatar Magnus Damm Committed by Paul Mundt
Browse files

sh: rework ipr code



This patch reworks the ipr code by grouping the offset array together
with the ipr_data structure in a new data structure called ipr_desc.
This new structure also contains the name of the controller in struct
irq_chip. The idea behind putting struct irq_chip in there is that we
can use offsetof() to locate the base addresses in the irq_chip
callbacks. This strategy has much in common with the recently merged
intc2 code.

One logic change has been made - the original ipr code enabled the
interrupts by default but with this patch they are all disabled by
default.

Signed-off-by: default avatarMagnus Damm <damm@igel.co.jp>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 50f63f25
Loading
Loading
Loading
Loading
+53 −71
Original line number Diff line number Diff line
@@ -15,46 +15,7 @@
#include <asm/io.h>
#include <asm/se.h>

/* 
 * If the problem of make_ipr_irq is solved, 
 * this code will become unnecessary. :-) 
 */
static void se770x_disable_ipr_irq(unsigned int irq)
{
	struct ipr_data *p = get_irq_chip_data(irq);

	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
}

static void se770x_enable_ipr_irq(unsigned int irq)
{
	struct ipr_data *p = get_irq_chip_data(irq);

	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
}

static struct irq_chip se770x_irq_chip = {
	.name           = "MS770xSE-FPGA",
	.mask           = se770x_disable_ipr_irq,
	.unmask         = se770x_enable_ipr_irq,
	.mask_ack       = se770x_disable_ipr_irq,
};

void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
{
	int i;

	for (i = 0; i < nr_irqs; i++) {
		unsigned int irq = table[i].irq;
		disable_irq_nosync(irq);
		set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
			handle_level_irq, "level");
		set_irq_chip_data(irq, &table[i]);
		se770x_enable_ipr_irq(irq);
	}
}

static struct ipr_data se770x_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
	/*
	* Super I/O (Just mimic PC):
	*  1: keyboard
@@ -68,46 +29,67 @@ static struct ipr_data se770x_ipr_map[] = {
	*/
#if defined(CONFIG_CPU_SUBTYPE_SH7705)
	/* This is default value */
	{ 13, 0, 8,  0x0f-13 ,BCR_ILCRA},
	{ 5 , 0, 4,  0x0f- 5 ,BCR_ILCRA},
	{ 10, 0, 0,  0x0f-10, BCR_ILCRB},
	{ 7 , 0, 4,  0x0f- 7, BCR_ILCRC},
	{ 3 , 0, 0,  0x0f- 3, BCR_ILCRC},
	{ 1 , 0, 12, 0x0f- 1, BCR_ILCRD},
	{ 12, 0, 4,  0x0f-12, BCR_ILCRD}, /* LAN */
	{ 2 , 0, 8,  0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */
	{ 6 , 0, 4,  0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */
	{ 14, 0, 0,  0x0f-14, BCR_ILCRE}, /* PCIRQ0 */
	{ 0 , 0, 12, 0x0f   , BCR_ILCRF}, 
	{ 4 , 0, 4,  0x0f- 4, BCR_ILCRF},
	{ 8 , 0, 12, 0x0f- 8, BCR_ILCRG},
	{ 9 , 0, 8,  0x0f- 9, BCR_ILCRG},
	{ 11, 0, 4,  0x0f-11, BCR_ILCRG},
	{ 13, 0, 8,  0x0f-13, },
	{ 5 , 0, 4,  0x0f- 5, },
	{ 10, 1, 0,  0x0f-10, },
	{ 7 , 2, 4,  0x0f- 7, },
	{ 3 , 2, 0,  0x0f- 3, },
	{ 1 , 3, 12, 0x0f- 1, },
	{ 12, 3, 4,  0x0f-12, }, /* LAN */
	{ 2 , 4, 8,  0x0f- 2, }, /* PCIRQ2 */
	{ 6 , 4, 4,  0x0f- 6, }, /* PCIRQ1 */
	{ 14, 4, 0,  0x0f-14, }, /* PCIRQ0 */
	{ 0 , 5, 12, 0x0f   , }, 
	{ 4 , 5, 4,  0x0f- 4, },
	{ 8 , 6, 12, 0x0f- 8, },
	{ 9 , 6, 8,  0x0f- 9, },
	{ 11, 6, 4,  0x0f-11, },
#else
	{ 14, 0,  8, 0x0f-14 ,BCR_ILCRA},
	{ 12, 0,  4, 0x0f-12 ,BCR_ILCRA},
	{  8, 0,  4, 0x0f- 8 ,BCR_ILCRB},
	{  6, 0, 12, 0x0f- 6 ,BCR_ILCRC},
	{  5, 0,  8, 0x0f- 5 ,BCR_ILCRC},
	{  4, 0,  4, 0x0f- 4 ,BCR_ILCRC},
	{  3, 0,  0, 0x0f- 3 ,BCR_ILCRC},
	{  1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
	{ 14, 0,  8, 0x0f-14, },
	{ 12, 0,  4, 0x0f-12, },
	{  8, 1,  4, 0x0f- 8, },
	{  6, 2, 12, 0x0f- 6, },
	{  5, 2,  8, 0x0f- 5, },
	{  4, 2,  4, 0x0f- 4, },
	{  3, 2,  0, 0x0f- 3, },
	{  1, 3, 12, 0x0f- 1, },
#if defined(CONFIG_STNIC)
	/* ST NIC */
	{ 10, 0,  4, 0x0f-10 ,BCR_ILCRD}, 	/* LAN */
	{ 10, 3,  4, 0x0f-10, }, 	/* LAN */
#endif
	/* MRSHPC IRQs setting */
	{  0, 0, 12, 0x0f- 0 ,BCR_ILCRE},	/* PCIRQ3 */
	{ 11, 0,  8, 0x0f-11 ,BCR_ILCRE}, 	/* PCIRQ2 */
	{  9, 0,  4, 0x0f- 9 ,BCR_ILCRE}, 	/* PCIRQ1 */
	{  7, 0,  0, 0x0f- 7 ,BCR_ILCRE}, 	/* PCIRQ0 */
	{  0, 4, 12, 0x0f- 0, },	/* PCIRQ3 */
	{ 11, 4,  8, 0x0f-11, }, 	/* PCIRQ2 */
	{  9, 4,  4, 0x0f- 9, }, 	/* PCIRQ1 */
	{  7, 4,  0, 0x0f- 7, }, 	/* PCIRQ0 */
	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
	/* NOTE: #2 and #13 are not used on PC */
	{ 13, 0,  4, 0x0f-13 ,BCR_ILCRG}, 	/* SLOTIRQ2 */
	{  2, 0,  0, 0x0f- 2 ,BCR_ILCRG}, 	/* SLOTIRQ1 */
	{ 13, 6,  4, 0x0f-13, }, 	/* SLOTIRQ2 */
	{  2, 6,  0, 0x0f- 2, }, 	/* SLOTIRQ1 */
#endif
};

static unsigned long ipr_offsets[] = {
	BCR_ILCRA,
	BCR_ILCRB,
	BCR_ILCRC,
	BCR_ILCRD,
	BCR_ILCRE,
	BCR_ILCRF,
	BCR_ILCRG,
};

static struct ipr_desc ipr_irq_desc = {
	.ipr_offsets	= ipr_offsets,
	.nr_offsets	= ARRAY_SIZE(ipr_offsets),

	.ipr_data	= ipr_irq_table,
	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
	.chip = {
		.name	= "IPR-se770x",
	},
};

/*
 * Initialize IRQ setting
 */
@@ -122,5 +104,5 @@ void __init init_se_IRQ(void)
	ctrl_outw(0, BCR_ILCRF);
	ctrl_outw(0, BCR_ILCRG);

	make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
	register_ipr_controller(&ipr_irq_desc);
}
+12 −3
Original line number Diff line number Diff line
@@ -19,15 +19,24 @@
#define INTC_INTMSK0             0xFFD00044
#define INTC_INTMSKCLR0          0xFFD00064

struct se7722_data {
	unsigned char irq;
	unsigned char ipr_idx;
	unsigned char shift;
	unsigned short priority;
	unsigned long addr;
};


static void disable_se7722_irq(unsigned int irq)
{
	struct ipr_data *p = get_irq_chip_data(irq);
	struct se7722_data *p = get_irq_chip_data(irq);
	ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
}

static void enable_se7722_irq(unsigned int irq)
{
	struct ipr_data *p = get_irq_chip_data(irq);
	struct se7722_data *p = get_irq_chip_data(irq);
	ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
}

@@ -38,7 +47,7 @@ static struct irq_chip se7722_irq_chip __read_mostly = {
	.mask_ack       = disable_se7722_irq,
};

static struct ipr_data ipr_irq_table[] = {
static struct se7722_data ipr_irq_table[] = {
	/* irq        ,idx,sft, priority     , addr   */
	{ MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
	{ MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
+23 −36
Original line number Diff line number Diff line
@@ -14,44 +14,31 @@
#include <asm/irq.h>
#include <asm/se7751.h>

static struct ipr_data se7751_ipr_map[] = {
  /* Leave old Solution Engine code in for reference. */
#if defined(CONFIG_SH_SOLUTION_ENGINE)
	/*
	 * Super I/O (Just mimic PC):
	 *  1: keyboard
	 *  3: serial 0
	 *  4: serial 1
	 *  5: printer
	 *  6: floppy
	 *  8: rtc
	 * 12: mouse
	 * 14: ide0
	 */
	{ 14, BCR_ILCRA, 2, 0x0f-14 },
	{ 12, BCR_ILCRA, 1, 0x0f-12 },
	{  8, BCR_ILCRB, 1, 0x0f- 8 },
	{  6, BCR_ILCRC, 3, 0x0f- 6 },
	{  5, BCR_ILCRC, 2, 0x0f- 5 },
	{  4, BCR_ILCRC, 1, 0x0f- 4 },
	{  3, BCR_ILCRC, 0, 0x0f- 3 },
	{  1, BCR_ILCRD, 3, 0x0f- 1 },
static struct ipr_data ipr_irq_table[] = {
	{ 13, 3, 3, 2 },
	/* Add additional entries here as drivers are added and tested. */
};

	{ 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */
static unsigned long ipr_offsets[] = {
	BCR_ILCRA,
	BCR_ILCRB,
	BCR_ILCRC,
	BCR_ILCRD,
	BCR_ILCRE,
	BCR_ILCRF,
	BCR_ILCRG,
};

	{  0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */
	{ 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */
	{  9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */
	{  7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
static struct ipr_desc ipr_irq_desc = {
	.ipr_offsets	= ipr_offsets,
	.nr_offsets	= ARRAY_SIZE(ipr_offsets),

	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
	/* NOTE: #2 and #13 are not used on PC */
	{ 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */
	{  2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */
#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
	{ 13, BCR_ILCRD, 3, 2 },
	/* Add additional entries here as drivers are added and tested. */
#endif
	.ipr_data	= ipr_irq_table,
	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),

	.chip = {
		.name	= "IPR-se7751",
	},
};

/*
@@ -59,5 +46,5 @@ static struct ipr_data se7751_ipr_map[] = {
 */
void __init init_7751se_IRQ(void)
{
	make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map));
	register_ipr_controller(&ipr_irq_desc);
}
+22 −6
Original line number Diff line number Diff line
@@ -15,17 +15,33 @@
#include <asm/sh03/sh03.h>
#include <asm/addrspace.h>

static struct ipr_data sh03_ipr_map[] = {
	{ IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY },
	{ IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY },
	{ IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY },
	{ IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY },
static struct ipr_data ipr_irq_table[] = {
	{ IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
	{ IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
	{ IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
	{ IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
};

static unsigned long ipr_offsets[] = {
	INTC_IPRD,
};

static struct ipr_desc ipr_irq_desc = {
	.ipr_offsets	= ipr_offsets,
	.nr_offsets	= ARRAY_SIZE(ipr_offsets),

	.ipr_data	= ipr_irq_table,
	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),

	.chip = {
		.name	= "IPR-sh03",
	},
};

static void __init init_sh03_IRQ(void)
{
	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
	make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map));
	register_ipr_controller(&ipr_irq_desc);
}

extern void *cf_io_base;
+23 −7
Original line number Diff line number Diff line
@@ -6,28 +6,44 @@
 * SHMIN Support.
 */
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/machvec.h>
#include <asm/shmin.h>
#include <asm/clock.h>
#include <asm/irq.h>
#include <asm/io.h>

#define PFC_PHCR	0xa400010eUL
#define INTC_ICR1	0xa4000010UL
#define INTC_IPRC	0xa4000016UL

static struct ipr_data shmin_ipr_map[] = {
	{ .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 },
	{ .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 },
	{ .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 },
	{ .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 },
static struct ipr_data ipr_irq_table[] = {
	{ 32, 0, 0, 0 },
	{ 33, 0, 4, 0 },
	{ 34, 0, 8, 8 },
	{ 35, 0, 12, 0 },
};

static unsigned long ipr_offsets[] = {
	INTC_IPRC,
};

static struct ipr_desc ipr_irq_desc = {
	.ipr_offsets	= ipr_offsets,
	.nr_offsets	= ARRAY_SIZE(ipr_offsets),

	.ipr_data	= ipr_irq_table,
	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),

	.chip = {
		.name	= "IPR-shmin",
	},
};

static void __init init_shmin_irq(void)
{
	ctrl_outw(0x2a00, PFC_PHCR);	// IRQ0-3=IRQ
	ctrl_outw(0x0aaa, INTC_ICR1);	// IRQ0-3=IRQ-mode,Low-active.
	make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map));
	register_ipr_controller(&ipr_irq_desc);
}

static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
Loading