⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callout_interrupt_pxa250.s

📁 Centrality Atlas II development software
💻 S
字号:
## Copyright 2007, 2008, QNX Software Systems. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not reproduce, modify or distribute this software except in # compliance with the License. You may obtain a copy of the License # at: http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTIES OF ANY KIND, either express or implied.## This file may contain contributions from others, either as # contributors under the License or as licensors under other terms.  # Please review this entire file for other proprietary rights or license # notices, as well as the QNX Development Suite License Guide at # http://licensing.qnx.com/license-guide/ for other information.#/* * PXA250 specific interrupt callouts. * * This should be usable by any board that uses a PXA250. * * interrupt_id_* and interrupt_eoi_* are copied and intermixed with other * kernel code during initialisation. * * They do not follow normal calling conventions, and must fall through * to the end, rather than attempting to perform a return instruction. * * The INTR_GENFLAG_* bits in the intrinfo_entry defines which of the * following values can be loaded on entry to these code fragments: * *	r5 - holds the syspageptr				(INTR_GENFLAG_SYSPAGE  set) *	r6 - holds the intrinfo_entry pointer	(INTR_GENFLAG_INTRINFO set) *	r7 - holds the interrupt mask count		(INTR_GENFLAG_INTRMASK set) *	r8 - holds INTRLEVEL pointer * * The interrupt_id_* routine returns the (controller-relative) level in r4 * * FIXME: WARNING - GPIO_2-GPIO_80 are NEVER DISABLED by the id and mask *		  callouts. They can only be disabled by clearing the edge detects, *		  which means we can lose interrupts if the device interrupts before *		  the eoi/unmask callout is called, since the edge transition occurs *		  before the edge detect is reenabled. This means that interrupt *		  handlers for devices using these interrupts must cope with the *	      potential re-entrancy: *			1) pulse/event handlers should mutex the event handler to *			   serialise the interrupts (the pulses will be queued). *			2) handler functions need to be made re-entrant. * *		  The real fix would require us to keep a "soft" disable mask *		  which is used in the id callout. When a "disabled" interrupt *		  is detected, it is marked as "pending", and the edge detect *		  is disabled by the id callout. The eoi and unmask callouts *		  need to check the "pending" status and invoke interrupt *		  handling. This requires some way of invoking the interrupt *		  dispatch code in the kernel. */#include "callout.ah"/* * Data in RW storage */rw_intr:	.word	32#define	OFF_INTR		0		// interrupt controller base#define	OFF_GPIO		4		// GPIO register base#define	OFF_GRER0		8		// pxa250_grer0#define	OFF_GRER1		12		// pxa250_grer1#define	OFF_GRER2		16		// pxa250_grer2#define	OFF_GFER0		20		// pxa250_gfer0#define	OFF_GFER1		24		// pxa250_gfer1#define	OFF_GFER2		28		// pxa250_gfer2Lintr_base:	.word	PXA250_INTR_BASELgpio_base:	.word	PXA250_GPIO_BASE/* * ----------------------------------------------------------------------- * Callout patch routines * *	r0 - physical address of syspage *	r1 - virtual  address of syspage *	r2 - offset from start of syspage to start of the callout routine *	r3 - offset from start of syspage to read/write data used by callout * ----------------------------------------------------------------------- *//* * Patch the id callout, and set up the RW storage */patch_id:	stmdb	sp!,{r4,lr}	add		r2, r0, r2			// address of callout routine	add		r4, r0, r3			// address of rw data	/*	 * Patch the callout with the rw offset	 */	and		ip, r3, #0xff	ldr		r1, [r2]	bic		r1, r1, #0xff	orr		r1, r1, ip	str		r1, [r2], #4	mov		ip, r3, lsr #8	and		ip, ip, #0xff	ldr		r1, [r2]	bic		r1, r1, #0xff	orr		r1, r1, ip	str		r1, [r2]	/*	 * Map PXA250_INTR_BASE and store in RW data	 */	mov		r0, #PXA250_INTR_SIZE	ldr		r1, Lintr_base	bl		callout_io_map	str		r0, [r4, #OFF_INTR]	/*	 * MAP PXA250_GPIO_BASE and store in RW data	 */	mov		r0, #PXA250_GPIO_SIZE	ldr		r1, Lgpio_base	bl		callout_io_map	str		r0, [r4, #OFF_GPIO]	/*	 * Store the grer/gfer values	 */	ldr		r0, =pxa250_grer0	ldr		r0, [r0]	str		r0, [r4, #OFF_GRER0]	ldr		r0, =pxa250_grer1	ldr		r0, [r0]	str		r0, [r4, #OFF_GRER1]	ldr		r0, =pxa250_grer2	ldr		r0, [r0]	str		r0, [r4, #OFF_GRER2]	ldr		r0, =pxa250_gfer0	ldr		r0, [r0]	str		r0, [r4, #OFF_GFER0]	ldr		r0, =pxa250_gfer1	ldr		r0, [r0]	str		r0, [r4, #OFF_GFER1]	ldr		r0, =pxa250_gfer2	ldr		r0, [r0]	str		r0, [r4, #OFF_GFER2]	ldmia	sp!,{r4,pc}/* * Patch other callouts */patch_other:	stmdb	sp!,{r4,lr}	add		r4, r0, r2			// address of callout routine	/*	 * Patch callout with rw offset	 */	and		ip, r3, #0xff	ldr		r1, [r4]	bic		r1, r1, #0xff	orr		r1, r1, ip	str		r1, [r4], #4	mov		ip, r3, lsr #8	ldr		r1, [r4]	bic		r1, r1, #0xff	orr		r1, r1, ip	str		r1, [r4]	ldmia	sp!,{r4,pc}/* * ----------------------------------------------------------------------- * PXA250 interrupt controller callouts * ----------------------------------------------------------------------- */CALLOUT_START(interrupt_id_pxa250, rw_intr, patch_id)	mov		ip,     #0x000000ff		// RW offset (patched)	orr		ip, ip, #0x0000ff00	add		ip, r5, ip				// INTR_GENFLAG_LOAD_SYSPAGE specified	ldr		r0, [ip, #OFF_INTR]	/*	 * Read pending IRQ interrupts and scan for first set bit	 */	ldr		r1, [r0, #PXA250_ICIP]	mov		r4, #32	mov		r2, #10:	sub		r4, r4, #1	teq		r4, #7							// interrupts 0-7 are reserved	subeq	r4, r4, #8	beq		1f	tst		r1, r2, lsl r4	beq		0b	/*	 * Mask the interrupt source	 */	ldr		r1, [r0, #PXA250_ICMR]	mov		r2, r2, lsl r4	bic		r1, r1, r2	str		r1, [r0, #PXA250_ICMR]	/*	 * Clear GEDR0 for GPIO_0/GPIO_1 interrupts	 */	ldr		r0, [ip, #OFF_GPIO]	sub		r1, r4, #7	teq		r1, #1	teqne	r1, #2	streq	r1, [r0, #PXA250_GEDR0]1:CALLOUT_END(interrupt_id_pxa250)CALLOUT_START(interrupt_eoi_pxa250, rw_intr, patch_other)	mov		ip,     #0x000000ff		// RW data offset (patched)	orr		ip, ip, #0x0000ff00	add		ip, r5, ip				// INTR_GENFLAG_LOAD_SYSPAGE specified	/*	 * Only unmask interrupt if mask count is zero	 */	teq		r7, #0	bne		0f	ldr		r0, [ip, #OFF_INTR]	/*	 * Enable interrupt source.	 */	mov		r2, #1	ldr		r1, [r0, #PXA250_ICMR]	orr		r1, r1, r2, lsl r4	str		r1, [r0, #PXA250_ICMR]0:CALLOUT_END(interrupt_eoi_pxa250)/* * error = interrupt_mask_pxa250(syspage_ptr, vector) */CALLOUT_START(interrupt_mask_pxa250, rw_intr, patch_other)	mov		ip,     #0x000000ff		// RW data offset (patched)	orr		ip, ip, #0x0000ff00	add		ip, r0, ip	ldr		r0, [ip, #OFF_INTR]	/*	 * Clear ICMR bit (1 << interrupt_number)	 */	ldr		r2, [r0, #PXA250_ICMR]	mov		r3, #1	bic		r2, r2, r3, lsl r1	str		r2, [r0, #PXA250_ICMR]	mov		r0, #0	mov		pc, lrCALLOUT_END(interrupt_mask_pxa250)/* * error = interrupt_unmask_pxa250(syspage_ptr, vector) */CALLOUT_START(interrupt_unmask_pxa250, rw_intr, patch_other)	mov		ip,     #0x000000ff		// RW data offset (patched)	orr		ip, ip, #0x0000ff00	add		ip, r0, ip	ldr		r0, [ip, #OFF_INTR]	/*	 * Convert vector to bit mask	 */	mov		r2, #1	mov		r2, r2, lsl r1	/*	 * Enable interrupt source	 */	ldr		r3, [r0, #PXA250_ICMR]	orr		r3, r3, r2	str		r3, [r0, #PXA250_ICMR]	/*	 * Enable edge detect for GPIO_0/GPIO_1	 */	sub		r1, r1, #7	teq		r1, #1	teqne	r1, #2	bne		0f	ldr		r2, [ip, #OFF_GRER0]	ldr		r3, [ip, #OFF_GFER0]	ldr		r0, [ip, #OFF_GPIO]	ands	r2, r2, r1	ldrne	r2, [r0, #PXA250_GRER0]	orrne	r2, r2, r1	strne	r2, [r0, #PXA250_GRER0]	ands	r3, r3, r1	ldrne	r2, [r0, #PXA250_GFER0]	orrne	r2, r2, r1	strne	r2, [r0, #PXA250_GFER0]0:	mov		r0, #0	mov		pc, lrCALLOUT_END(interrupt_unmask_pxa250)/* * ----------------------------------------------------------------------- * PXA250 GPIO interrupt callouts * ----------------------------------------------------------------------- */CALLOUT_START(interrupt_id_pxa250_gpio, rw_intr, patch_other)	mov		ip,     #0x000000ff		// RW offset (patched)	orr		ip, ip, #0x0000ff00	add		ip, r5, ip				// INTR_GENFLAG_LOAD_SYSPAGE specified	ldr		r0, [ip, #OFF_GPIO]	/*	 * Read GEDR2	 */	ldr		r1, [r0, #PXA250_GEDR2]	mov		r4, #17	mov		r2, #10:	subs	r4, r4, #1	blt		1f	tst		r1, r2, lsl r4	beq		0b	mov		r2, r2, lsl r4	str		r2, [r0, #PXA250_GEDR2]		// clear edge detect	add		r4, r4, #64	b		3f1:	/*	 * Read GEDR1	 */	ldr		r1, [r0, #PXA250_GEDR1]	mov		r4, #32	mov		r2, #10:	subs	r4, r4, #1	blt		2f	tst		r1, r2, lsl r4	beq		0b	mov		r2, r2, lsl r4	str		r2, [r0, #PXA250_GEDR1]		// clear edge detect	add		r4, r4, #32	b		3f2:	/*	 * Read GEDR0	 */	ldr		r1, [r0, #PXA250_GEDR0]	mov		r4, #32	mov		r2, #10:	sub		r4, r4, #1	cmp		r4, #1						// don't do GPIO_1/0	beq		3f	tst		r1, r2, lsl r4	beq		0b	mov		r2, r2, lsl r4	str		r2, [r0, #PXA250_GEDR0]		// clear edge detect	/*	 * Adjust r4, since vector base starts at GPIO_2	 *	 * FIXME: we don't disable the interrupt here, since we can only do that	 *		  by disabling the edge detects. This would mean we can lose an	 *		  interrupt if it occurs whilst the edge detects are disabled.	 */3:	sub		r4, r4, #2CALLOUT_END(interrupt_id_pxa250_gpio)CALLOUT_START(interrupt_eoi_pxa250_gpio, 0, 0)	/*	 * FIXME: since we don't mask the interrupt in interrupt_id_pxa250_gpio	 *		  there is nothing to do in this callout.	 */CALLOUT_END(interrupt_eoi_pxa250_gpio)/* * error = interrupt_mask_pxa250_gpio(syspage_ptr, vector) */CALLOUT_START(interrupt_mask_pxa250_gpio, 0, 0)	/*	 * FIXME: since we can't reliably mask the interrupt we do nothing	 */	mov		r0, #0	mov		pc, lrCALLOUT_END(interrupt_mask_pxa250_gpio)/* * error = interrupt_unmask_pxa250_gpio(syspage_ptr, vector) */CALLOUT_START(interrupt_unmask_pxa250_gpio, rw_intr, patch_other)	mov		ip,     #0x000000ff		// RW data offset (patched)	orr		ip, ip, #0x0000ff00	add		ip, r0, ip	ldr		r0, [ip, #OFF_GPIO]	add		r1, r1, #2	/*	 * Calculate which register to hit and the bitmask	 */	cmp		r1, #64	addge	r0, r0, #4	addge	ip, ip, #4	cmplt	r1, #32	addge	r0, r0, #4	addge	ip, ip, #4	and		r1, r1, #31	mov		r2, #1	mov		r1, r2, lsl r1	/*	 * Enable edge detects	 */	ldr		r2, [ip, #OFF_GRER0]	ldr		r3, [ip, #OFF_GFER0]	ands	r2, r2, r1	ldrne	r2, [r0, #PXA250_GRER0]	orrne	r2, r2, r1	strne	r2, [r0, #PXA250_GRER0]	ands	r3, r3, r1	ldrne	r2, [r0, #PXA250_GFER0]	orrne	r2, r2, r1	strne	r2, [r0, #PXA250_GFER0]	mov		r0, #0	mov		pc, lrCALLOUT_END(interrupt_unmask_pxa250_gpio)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -