setup.c 5.3 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *  linux/arch/m32r/platforms/usrv/setup.c
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *
 *  Setup routines for MITSUBISHI uServer
 *
 *  Copyright (c) 2001, 2002, 2003  Hiroyuki Kondo, Hirokazu Takata,
 *                                  Hitoshi Yamamoto
 */

#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <asm/m32r.h>
#include <asm/io.h>

#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))

icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];

static void disable_mappi_irq(unsigned int irq)
{
	unsigned long port, data;

	port = irq2port(irq);
	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
	outl(data, port);
}

static void enable_mappi_irq(unsigned int irq)
{
	unsigned long port, data;

	port = irq2port(irq);
	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
	outl(data, port);
}

39
static void mask_mappi(struct irq_data *data)
L
Linus Torvalds 已提交
40
{
41
	disable_mappi_irq(data->irq);
L
Linus Torvalds 已提交
42 43
}

44
static void unmask_mappi(struct irq_data *data)
L
Linus Torvalds 已提交
45
{
46
	enable_mappi_irq(data->irq);
L
Linus Torvalds 已提交
47 48
}

49
static void shutdown_mappi(struct irq_data *data)
L
Linus Torvalds 已提交
50 51 52
{
	unsigned long port;

53
	port = irq2port(data->irq);
L
Linus Torvalds 已提交
54 55 56
	outl(M32R_ICUCR_ILEVEL7, port);
}

57
static struct irq_chip mappi_irq_type =
L
Linus Torvalds 已提交
58
{
59 60 61 62
	.name		= "M32700-IRQ",
	.irq_shutdown	= shutdown_mappi,
	.irq_mask	= mask_mappi,
	.irq_unmask	= unmask_mappi,
L
Linus Torvalds 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
};

/*
 * Interrupt Control Unit of PLD on M32700UT (Level 2)
 */
#define irq2pldirq(x)		((x) - M32700UT_PLD_IRQ_BASE)
#define pldirq2port(x)		(unsigned long)((int)PLD_ICUCR1 + \
				 (((x) - 1) * sizeof(unsigned short)))

typedef struct {
	unsigned short icucr;  /* ICU Control Register */
} pld_icu_data_t;

static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];

static void disable_m32700ut_pld_irq(unsigned int irq)
{
	unsigned long port, data;
	unsigned int pldirq;

	pldirq = irq2pldirq(irq);
	port = pldirq2port(pldirq);
	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
	outw(data, port);
}

static void enable_m32700ut_pld_irq(unsigned int irq)
{
	unsigned long port, data;
	unsigned int pldirq;

	pldirq = irq2pldirq(irq);
	port = pldirq2port(pldirq);
	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
	outw(data, port);
}

100
static void mask_m32700ut_pld(struct irq_data *data)
L
Linus Torvalds 已提交
101
{
102
	disable_m32700ut_pld_irq(data->irq);
L
Linus Torvalds 已提交
103 104
}

105
static void unmask_m32700ut_pld(struct irq_data *data)
L
Linus Torvalds 已提交
106
{
107 108
	enable_m32700ut_pld_irq(data->irq);
	enable_mappi_irq(M32R_IRQ_INT1);
L
Linus Torvalds 已提交
109 110
}

111
static void shutdown_m32700ut_pld(struct irq_data *data)
L
Linus Torvalds 已提交
112 113 114 115
{
	unsigned long port;
	unsigned int pldirq;

116
	pldirq = irq2pldirq(data->irq);
L
Linus Torvalds 已提交
117 118 119 120
	port = pldirq2port(pldirq);
	outw(PLD_ICUCR_ILEVEL7, port);
}

121
static struct irq_chip m32700ut_pld_irq_type =
L
Linus Torvalds 已提交
122
{
123 124 125 126
	.name		= "USRV-PLD-IRQ",
	.irq_shutdown	= shutdown_m32700ut_pld,
	.irq_mask	= mask_m32700ut_pld,
	.irq_unmask	= unmask_m32700ut_pld,
L
Linus Torvalds 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139
};

void __init init_IRQ(void)
{
	static int once = 0;
	int i;

	if (once)
		return;
	else
		once++;

	/* MFT2 : system timer */
T
Thomas Gleixner 已提交
140
	irq_set_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
141
				 handle_level_irq);
L
Linus Torvalds 已提交
142 143 144 145 146
	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
	disable_mappi_irq(M32R_IRQ_MFT2);

#if defined(CONFIG_SERIAL_M32R_SIO)
	/* SIO0_R : uart receive data */
T
Thomas Gleixner 已提交
147
	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
148
				 handle_level_irq);
L
Linus Torvalds 已提交
149 150 151 152
	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
	disable_mappi_irq(M32R_IRQ_SIO0_R);

	/* SIO0_S : uart send data */
T
Thomas Gleixner 已提交
153
	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
154
				 handle_level_irq);
L
Linus Torvalds 已提交
155 156 157 158
	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
	disable_mappi_irq(M32R_IRQ_SIO0_S);

	/* SIO1_R : uart receive data */
T
Thomas Gleixner 已提交
159
	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
160
				 handle_level_irq);
L
Linus Torvalds 已提交
161 162 163 164
	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
	disable_mappi_irq(M32R_IRQ_SIO1_R);

	/* SIO1_S : uart send data */
T
Thomas Gleixner 已提交
165
	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
166
				 handle_level_irq);
L
Linus Torvalds 已提交
167 168 169 170 171
	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
	disable_mappi_irq(M32R_IRQ_SIO1_S);
#endif  /* CONFIG_SERIAL_M32R_SIO */

	/* INT#67-#71: CFC#0 IREQ on PLD */
172
	for (i = 0 ; i < CONFIG_M32R_CFC_NUM ; i++ ) {
T
Thomas Gleixner 已提交
173
		irq_set_chip_and_handler(PLD_IRQ_CF0 + i,
174 175
					 &m32700ut_pld_irq_type,
					 handle_level_irq);
L
Linus Torvalds 已提交
176 177 178 179 180 181 182
		pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
			= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
		disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
	}

#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
	/* INT#76: 16552D#0 IREQ on PLD */
T
Thomas Gleixner 已提交
183
	irq_set_chip_and_handler(PLD_IRQ_UART0, &m32700ut_pld_irq_type,
184
				 handle_level_irq);
L
Linus Torvalds 已提交
185 186 187 188 189
	pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
	disable_m32700ut_pld_irq(PLD_IRQ_UART0);

	/* INT#77: 16552D#1 IREQ on PLD */
T
Thomas Gleixner 已提交
190
	irq_set_chip_and_handler(PLD_IRQ_UART1, &m32700ut_pld_irq_type,
191
				 handle_level_irq);
L
Linus Torvalds 已提交
192 193 194 195 196 197 198
	pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
	disable_m32700ut_pld_irq(PLD_IRQ_UART1);
#endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */

#if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
	/* INT#80: AK4524 IREQ on PLD */
T
Thomas Gleixner 已提交
199
	irq_set_chip_and_handler(PLD_IRQ_SNDINT, &m32700ut_pld_irq_type,
200
				 handle_level_irq);
L
Linus Torvalds 已提交
201 202 203 204 205 206 207 208 209 210 211 212
	pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
		= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
	disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
#endif	/* CONFIG_IDC_AK4524 || CONFIG_IDC_AK4524_MODULE */

	/*
	 * INT1# is used for UART, MMC, CF Controller in FPGA.
	 * We enable it here.
	 */
	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD11;
	enable_mappi_irq(M32R_IRQ_INT1);
}