aboutsummaryrefslogblamecommitdiffstats
path: root/arch/arm/boot/compressed/head-clps7500.S
blob: 4a8a689d15e61c7a33719daacf4b994e6b46abb5 (plain) (tree)






















































































                                                                             
/*
 * linux/arch/arm/boot/compressed/head.S
 *
 * Copyright (C) 1999, 2000, 2001 Nexus Electronics Ltd
 */

#include <linux/config.h>

		/* There are three different ways the kernel can be
		   booted on a 7500 system: from Angel (loaded in RAM), from
		   16-bit ROM or from 32-bit Flash.  Luckily, a single kernel
		   image does for them all. */
		/* This branch is taken if the CPU memory width matches the
		   actual device in use.  The default at power on is 16 bits
		   so we must be prepared for a mismatch. */
		.section ".start", "ax"
2:
		b	1f
		.word	0xffff
		.word	0xb632		@ mov r11, #0x03200000
		.word	0xe3a0
		.word	0x0000		@ mov r0, #0
		.word	0xe3a0
		.word	0x0080		@ strb r0, [r11, #0x80]
		.word	0xe5cb
		.word	0xf000		@ mov pc, #0
		.word	0xe3a0
1:
		adr	r1, 2b
		teq	r1, #0
		bne	.Langel
		/* This is a direct-from-ROM boot.  Copy the kernel into 
		   RAM and run it there. */
		mov	r0, #0x30
		mcr	p15, 0, r0, c1, c0, 0
		mov	r0, #0x13
		msr	cpsr_cxsf, r0
		mov	r12, #0x03000000	@ point to LEDs
		orr	r12, r12, #0x00020000
		orr	r12, r12, #0xba00
		mov	r0, #0x5500
		str	r0, [r12]
		mov	r0, #0x10000000
		orr	r0, r0, #0x8000
		mov	r4, r0
		ldr	r2, =_end
2:
		ldr	r3, [r1], #4
		str	r3, [r0], #4
		teq	r0, r2
		bne	2b
		mov	r0, #0xff00
		str	r0, [r12]
1:	
		mov	r12, #0x03000000	@ point to LEDs
		orr	r12, r12, #0x00020000
		orr	r12, r12, #0xba00
		mov	r0, #0xfe00
		str	r0, [r12]

		adr	lr, 1f
		mov	r0, #0
		mov	r1, #14		/* MACH_TYPE_CLPS7500 */
		mov	pc, lr
.Langel:
#ifdef CONFIG_ANGELBOOT
		/* Call Angel to switch into SVC mode. */
		mov	r0, #0x17
		swi	0x123456
#endif
		/* Ensure all interrupts are off and MMU disabled */
		mrs	r0, cpsr
		orr	r0, r0, #0xc0
		msr	cpsr_cxsf, r0

		adr	lr, 1b
		orr	lr, lr, #0x10000000
		mov	r0, #0x30		@ MMU off
		mcr	p15, 0, r0, c1, c0, 0
		mov	r0, r0
	 	mov	pc, lr

		.ltorg

1:
/* And the rest */
#include "head.S"
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204















                                                                       
                         
                       





                              

                           


                     
                    
 
















                                                       
                                      

















                                                                     
                







                               
                       









































                                                             








                                              









                                                
                                          













































                                                                            
                                             

















                                                                        
/* arch/arm/plat-s3c64xx/irq-eint.c
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *      Ben Dooks <ben@simtec.co.uk>
 *      http://armlinux.simtec.co.uk/
 *
 * S3C64XX - Interrupt handling for IRQ_EINT(x)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/sysdev.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>

#include <asm/hardware/vic.h>

#include <plat/regs-irqtype.h>
#include <plat/regs-gpio.h>
#include <plat/gpio-cfg.h>

#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/pm.h>

#define eint_offset(irq)	((irq) - IRQ_EINT(0))
#define eint_irq_to_bit(irq)	(1 << eint_offset(irq))

static inline void s3c_irq_eint_mask(unsigned int irq)
{
	u32 mask;

	mask = __raw_readl(S3C64XX_EINT0MASK);
	mask |= eint_irq_to_bit(irq);
	__raw_writel(mask, S3C64XX_EINT0MASK);
}

static void s3c_irq_eint_unmask(unsigned int irq)
{
	u32 mask;

	mask = __raw_readl(S3C64XX_EINT0MASK);
	mask &= ~eint_irq_to_bit(irq);
	__raw_writel(mask, S3C64XX_EINT0MASK);
}

static inline void s3c_irq_eint_ack(unsigned int irq)
{
	__raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND);
}

static void s3c_irq_eint_maskack(unsigned int irq)
{
	/* compiler should in-line these */
	s3c_irq_eint_mask(irq);
	s3c_irq_eint_ack(irq);
}

static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
{
	int offs = eint_offset(irq);
	int pin;
	int shift;
	u32 ctrl, mask;
	u32 newvalue = 0;
	void __iomem *reg;

	if (offs > 27)
		return -EINVAL;

	if (offs <= 15)
		reg = S3C64XX_EINT0CON0;
	else
		reg = S3C64XX_EINT0CON1;

	switch (type) {
	case IRQ_TYPE_NONE:
		printk(KERN_WARNING "No edge setting!\n");
		break;

	case IRQ_TYPE_EDGE_RISING:
		newvalue = S3C2410_EXTINT_RISEEDGE;
		break;

	case IRQ_TYPE_EDGE_FALLING:
		newvalue = S3C2410_EXTINT_FALLEDGE;
		break;

	case IRQ_TYPE_EDGE_BOTH:
		newvalue = S3C2410_EXTINT_BOTHEDGE;
		break;

	case IRQ_TYPE_LEVEL_LOW:
		newvalue = S3C2410_EXTINT_LOWLEV;
		break;

	case IRQ_TYPE_LEVEL_HIGH:
		newvalue = S3C2410_EXTINT_HILEV;
		break;

	default:
		printk(KERN_ERR "No such irq type %d", type);
		return -1;
	}

	shift = (offs / 2) * 4;
	mask = 0x7 << shift;

	ctrl = __raw_readl(reg);
	ctrl &= ~mask;
	ctrl |= newvalue << shift;
	__raw_writel(ctrl, reg);

	/* set the GPIO pin appropriately */

	if (offs < 23)
		pin = S3C64XX_GPN(offs);
	else
		pin = S3C64XX_GPM(offs - 23);

	s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(2));

	return 0;
}

static struct irq_chip s3c_irq_eint = {
	.name		= "s3c-eint",
	.mask		= s3c_irq_eint_mask,
	.unmask		= s3c_irq_eint_unmask,
	.mask_ack	= s3c_irq_eint_maskack,
	.ack		= s3c_irq_eint_ack,
	.set_type	= s3c_irq_eint_set_type,
	.set_wake	= s3c_irqext_wake,
};

/* s3c_irq_demux_eint
 *
 * This function demuxes the IRQ from the group0 external interrupts,
 * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into
 * the specific handlers s3c_irq_demux_eintX_Y.
 */
static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
{
	u32 status = __raw_readl(S3C64XX_EINT0PEND);
	u32 mask = __raw_readl(S3C64XX_EINT0MASK);
	unsigned int irq;

	status &= ~mask;
	status >>= start;
	status &= (1 << (end - start + 1)) - 1;

	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
		if (status & 1)
			generic_handle_irq(irq);

		status >>= 1;
	}
}

static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
{
	s3c_irq_demux_eint(0, 3);
}

static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
{
	s3c_irq_demux_eint(4, 11);
}

static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
{
	s3c_irq_demux_eint(12, 19);
}

static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
{
	s3c_irq_demux_eint(20, 27);
}

static int __init s3c64xx_init_irq_eint(void)
{
	int irq;

	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
		set_irq_chip(irq, &s3c_irq_eint);
		set_irq_handler(irq, handle_level_irq);
		set_irq_flags(irq, IRQF_VALID);
	}

	set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
	set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
	set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
	set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);

	return 0;
}

arch_initcall(s3c64xx_init_irq_eint);