From patchwork Thu Dec 10 20:04:37 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 66337 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nBAK4bbF016160 for ; Thu, 10 Dec 2009 20:04:37 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750926AbZLJUE3 (ORCPT ); Thu, 10 Dec 2009 15:04:29 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752049AbZLJUE3 (ORCPT ); Thu, 10 Dec 2009 15:04:29 -0500 Received: from d1.icnet.pl ([212.160.220.21]:39761 "EHLO d1.icnet.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750926AbZLJUE1 (ORCPT ); Thu, 10 Dec 2009 15:04:27 -0500 Received: from 87-205-12-81.ip.netia.com.pl ([87.205.12.81] helo=vclass.intranet) by d1.icnet.pl with asmtp (TLS-1.0:DHE_RSA_AES_128_CBC_SHA:16) (Exim 4.34) id 1NIpFZ-0005Yk-AL; Thu, 10 Dec 2009 21:04:33 +0100 From: Janusz Krzysztofik Organization: Tele-Info-System, Poznan, PL To: linux-omap@vger.kernel.org Subject: [RFC][PATCH 1/5] omap1: Amstrad Delta: add FIQ handler for serial keyboard port interrupt processing Date: Thu, 10 Dec 2009 21:04:37 +0100 User-Agent: KMail/1.9.10 Cc: Tony Lindgren , Dmitry Torokhov , linux-input@vger.kernel.org References: <200912102058.43892.jkrzyszt@tis.icnet.pl> In-Reply-To: <200912102058.43892.jkrzyszt@tis.icnet.pl> MIME-Version: 1.0 Content-Disposition: inline Message-Id: <200912102104.39447.jkrzyszt@tis.icnet.pl> X-SA-Exim-Scanned: No (on d1.icnet); SAEximRunCond expanded to false Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org diff -uprN git.orig/arch/arm/mach-omap1/Kconfig git/arch/arm/mach-omap1/Kconfig --- git.orig/arch/arm/mach-omap1/Kconfig 2009-12-02 15:48:37.000000000 +0100 +++ git/arch/arm/mach-omap1/Kconfig 2009-12-10 02:14:37.000000000 +0100 @@ -152,6 +152,14 @@ config MACH_AMS_DELTA Support for the Amstrad E3 (codename Delta) videophone. Say Y here if you have such a device. +config AMS_DELTA_FIQ + bool "Fast Interrupt Request (FIQ) support for the E3" + depends on MACH_AMS_DELTA + select FIQ + help + Provide a FIQ handler for the E3. This redirects the gpio IRQ to FIQ + And is required to use the E3 mailboard + config MACH_OMAP_GENERIC bool "Generic OMAP board" depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) diff -uprN git.orig/arch/arm/mach-omap1/Makefile git/arch/arm/mach-omap1/Makefile --- git.orig/arch/arm/mach-omap1/Makefile 2009-12-10 01:36:56.000000000 +0100 +++ git/arch/arm/mach-omap1/Makefile 2009-12-10 02:14:37.000000000 +0100 @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_OMAP_PALMZ71) += boar obj-$(CONFIG_MACH_OMAP_PALMTT) += board-palmtt.o obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o +obj-$(CONFIG_AMS_DELTA_FIQ) += ams-delta-fiq-handler.o obj-$(CONFIG_MACH_SX1) += board-sx1.o board-sx1-mmc.o obj-$(CONFIG_MACH_HERALD) += board-htcherald.o diff -uprN git.orig/arch/arm/mach-omap1/ams-delta-fiq-handler.S git/arch/arm/mach-omap1/ams-delta-fiq-handler.S --- git.orig/arch/arm/mach-omap1/ams-delta-fiq-handler.S 1970-01-01 01:00:00.000000000 +0100 +++ git/arch/arm/mach-omap1/ams-delta-fiq-handler.S 2009-12-10 03:27:14.000000000 +0100 @@ -0,0 +1,342 @@ +/* + * linux/arch/arm/mach-omap1/ams-delta-fiq-handler.S + * + * Based on linux/arch/arm/lib/floppydma.S + * Renamed and modified to work with 2.6 kernel by Matt Callow + * Copyright (C) 1995, 1996 Russell King + * Copyright (C) 2004 Pete Trapps + * Copyright (C) 2006 Matt Callow + * Copyright (C) 2009 Janusz Krzysztofik + * + * 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 +#include +#include +#include + +#define OMAP1510_TIMER1_BASE 0xfffec500 +#define OMAP1510_TIMER2_BASE 0xfffec600 +#define OMAP1510_TIMER3_BASE 0xfffec700 +#define OMAP1510_WATCHDOG_BASE 0xfffec800 + +#define MAX_INTER_BIT_GAP (6 * 200) /* 6 ticks/uSec => 200uSec */ + +/* MPU Timer Register Offsets */ +#define CNTL_TIMER 0 +#define LOAD_TIM 4 +#define READ_TIM 8 + +#define MPU_L1_INTERRUPT_BASE OMAP1_IO_ADDRESS(0xFFFECB00) +#define MPU_L2_INTERRUPT_BASE OMAP1_IO_ADDRESS(0xFFFE0000) + +#define ITR 0x00 +#define MIR 0x04 +#define SIR_IRQ_CODE 0x10 +#define SIR_FIQ_CODE 0x14 +#define CONTROL_REG 0x18 +#define ILR14 0x54 +#define ILR30 0x94 +#define ISR 0x9C + +#define T_BIT 0x20 +#define F_BIT 0x40 +#define I_BIT 0x80 +#define CC_V_BIT (1 << 28) +#define CC_C_BIT (1 << 29) +#define CC_Z_BIT (1 << 30) +#define CC_N_BIT (1 << 31) +#define PCMASK 0 + +#define GPIO_BASE OMAP1_IO_ADDRESS(0xFFFCE000) +#define GPIO_DATA_INPUT 0x00 +#define GPIO_DATA_OUTPUT 0x04 +#define GPIO_DIRECTION_CONTROL 0x08 +#define GPIO_INTERRUPT_CONTROL 0x0C +#define GPIO_INTERRUPT_MASK 0x10 +#define GPIO_INTERRUPT_STATUS 0x14 +#define GPIO_PIN_CONTROL 0x18 + +/* + * GPIO_DATA_INPUT bit 0 is MBRD_DI_PROC + * GPIO_DATA_INPUT bit 1 is MBRD_CLK + */ +#define MBRD_DI_PROC_MASK 0x01 +#define MBRD_CLK_MASK 0x02 +#define MDM_MASK 0x04 +#define HKSW_MASK 0x10 +#define OTHERS_MASK 0x14 + +#define INT_GPIO0 0 +#define INT_GPIO1 1 +#define INT_GPIO2 2 +#define INT_GPIO3 3 +#define INT_GPIO4 4 +#define INT_GPIO5 5 +#define INT_GPIO6 6 +#define INT_GPIO7 7 +#define INT_GPIO8 8 +#define INT_GPIO9 9 +#define INT_GPIO10 10 +#define INT_GPIO11 11 +#define INT_GPIO12 12 +#define INT_GPIO13 13 +#define INT_GPIO14 14 +#define INT_GPIO15 15 + +#define GPIO6_HDW_IP_SCARD_0_MASK 0x40 + +/* Driver buffer offsets */ +#define FIQ_MASK 0 +#define FIQ_STATE 4 +#define FIQ_CHAR_CNT 8 +#define FIQ_FRNT_OFFSET 12 +#define FIQ_BACK_OFFSET 16 +#define FIQ_BUF_LEN 20 +#define FIQ_CHAR 24 +#define FIQ_MISSED_CHARS 28 +#define FIQ_BUFFER_START 32 +#define FIQ_GPIO_INT_MASK 36 +#define FIQ_CHAR_HICNT 40 +#define FIQ_IRQ_PEND 44 +#define FIQ_SIR_CODE_L1 48 +#define IRQ_SIR_CODE_L2 52 +#define FIQ_CNT_INT_00 56 +#define FIQ_CNT_INT_CHAR 60 +#define FIQ_CNT_INT_MDM 64 +#define FIQ_CNT_INT_FIQ 68 +#define FIQ_CNT_INT_04 72 +#define FIQ_CNT_INT_05 76 +#define FIQ_CNT_INT_KBD 80 +#define FIQ_CNT_INT_07 84 +#define FIQ_CNT_INT_08 88 +#define FIQ_CNT_INT_09 92 +#define FIQ_CNT_INT_10 96 +#define FIQ_CNT_INT_11 100 +#define FIQ_CNT_INT_12 104 +#define FIQ_CNT_INT_13 108 +#define FIQ_CNT_INT_14 112 +#define FIQ_CNT_INT_15 116 +#define FIQ_CIRC_BUFF 120 /*Start of circular buffer */ + +#define TIMER_32k_MASK 0x400000 +#define GPIO_INT_MASK 0x4000 + +/* + * Register useage + * r8 - + * r9 - the driver buffer + * r10 - + * r11 - + * r12 -base pointers + * r13 - + */ + + .text + + .global qwerty_fiqin_end + +ENTRY(qwerty_fiqin_start) + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @setup base pointer = MPU_L1_INTERRUPT_BASE 0xFFFECB00 + ldr r12, mpu_l1_interrupt_base + ldr r11, [r12, #SIR_FIQ_CODE] @read SIR to clear FIQ + + @@@@@@@@@@@@@@@@@@@@@@@@@@@ + @setup base pointer = GPIO_BASE 0xFFFCE000 + ldr r12, gpio_base + +key: @Is it a keyboard interrupt? + ldr r11, [r12,#GPIO_INTERRUPT_STATUS] @ get GPIO interrupt status + and r10, r11, #MBRD_CLK_MASK @ reveal keyboard bit + cmp r10, #MBRD_CLK_MASK @ is keyboard bit low? + bne mdm @ no - spurious - try mdm + mov r10, #MBRD_CLK_MASK + str r10, [r12,#GPIO_INTERRUPT_STATUS] @ Set the bit to clear interrupt + + ldr r10, [r9, #FIQ_CNT_INT_KBD] @ get int count for IRQ handlers + add r10, r10, #1 @ increment it + str r10, [r9, #FIQ_CNT_INT_KBD] @ save status for IRQ handlers + + @@@@@@@@@@@@@@@@@@@@@@ + @ start processing keyboard bitstream +state: + ldr r10, [r9,#FIQ_STATE] + cmp r10, #0 @ are we expecting start bit? + bne data @ no - in data processing state + +start: + ldr r11, [r12, #GPIO_DATA_INPUT] @ get input + and r11, r11, #MBRD_DI_PROC_MASK @ mask out other bits + cmp r11, #MBRD_DI_PROC_MASK @ is kbd data in bit set? + bne exit @ no - exit, wait for next irq + mov r10, #1 @ good start bit, change state + @ to data processing + str r10, [r9,#FIQ_STATE] + mov r10, #0x02 @ set mask to 0x02 + str r10, [r9, #FIQ_MASK] + mov r10, #0 @ clear character byte + str r10, [r9, #FIQ_CHAR] + + @@@@@@@@@ MASK OTHERS TILL KEY DONE @@@@@@@@@@@@@@ + mov r10, #OTHERS_MASK + ldr r11, [r12, #GPIO_INTERRUPT_MASK] @ get mask reg + str r11, [r9, #FIQ_GPIO_INT_MASK] @ save it for later restore + orr r11, r11, r10 @ mask modem int + str r11, [r12, #GPIO_INTERRUPT_MASK] @ write mask reg + @@@@@@@@@@ END @@@@@@@@@@@@@@@@@ + b exit @ exit, wait for first data bit + +data: ldr r11, [r12, #GPIO_DATA_INPUT] @ get input + and r11, r11, #MBRD_DI_PROC_MASK @ mask out other bits + cmp r11, #0 @ is kbd data in clear? + bne shift + ldr r10, [r9, #FIQ_CHAR] + ldr r11, [r9, #FIQ_MASK] + orr r10, r11, r10 @ or mask and character byte + str r10, [r9, #FIQ_CHAR] + +shift: ldr r10, [r9, #FIQ_MASK] + mov r10, r10, lsl #1 @ shift mask left + str r10, [r9, #FIQ_MASK] + cmp r10, #0x800 @ have we got all the bits? + bne exit @ not yet - get more + mov r10, #0 @ yes set state to start + str r10, [r9, #FIQ_STATE] + + @@@@@@@@@ KEY DONE - RESTORE INTERRUPT MASK @@@ + ldr r11, [r9,#FIQ_GPIO_INT_MASK] + str r11, [r12, #GPIO_INTERRUPT_MASK] @ write mask reg + @@@@@@@@@@ END @@@@@@@@@@@@@@@@@ + + @Add char to circular buffer + ldr r10, [r9, #FIQ_CHAR_CNT] @ get char count + ldr r8, [r9, #FIQ_BUF_LEN] @ get buffer size + cmp r10, r8 @ is buffer full? + bne not_full + ldr r10, [r9, #FIQ_MISSED_CHARS] @ get missed char count + add r10, r10, #1 @ inc missed char count + str r10, [r9, #FIQ_MISSED_CHARS] @ save missed char count + b int @ force IRQ + +not_full: + ldr r10, [r9, #FIQ_FRNT_OFFSET] @ get current front offset + ldr r11, [r9, #FIQ_BUF_LEN] @ get buff size + cmp r10, r11 @ offset == buffer size? + bne store @ no - so branch to front + mov r10, #0 @ set front offset = 0 + +store: ldr r12, [r9, #FIQ_BUFFER_START] @ get start addr of circ buffer + add r12, r12, r10, LSL #2 @ add front offset to buff base + ldr r8, [r9, #FIQ_CHAR] @ get latest character + str r8, [r12] @ ####01 store in circ buffer + add r10, r10, #1 @ inc front offset + str r10, [r9, #FIQ_FRNT_OFFSET] @ ####04 store front offset + ldr r8, [r9, #FIQ_CHAR_CNT] @ get char count + add r8, r8, #1 @ inc count of chars in buffer + str r8, [r9, #FIQ_CHAR_CNT] @ ####02 store char count + + ldr r10, [r9, #FIQ_CHAR_HICNT] @ get char count hi watermark + cmp r10, r8 + bgt setstat @ hi count bigger - don't change + str r8, [r9, #FIQ_CHAR_HICNT] @ store char cnt in hi watermark +setstat: + ldr r10, [r9, #FIQ_CNT_INT_CHAR] @ get char cnt for IRQ handlers + add r10, r10, #1 @ increment it + str r10, [r9, #FIQ_CNT_INT_CHAR] @ save status for IRQ handlers + + @@@@@@@@@@@@@@@@@@@@@@@@ + @ Force a INT_OS_32kHz_TIMER interrupt + @setup base pointer = MPU_L2_INTERRUPT_BASE 0xFFFE0000 +int: ldr r12, mpu_l2_interrupt_base + mov r10, #TIMER_32k_MASK @ set 32kHz_TIMER bit + str r10, [r12, #ISR] @ write ISR + + + @@@@@@@@@@@@@@@@@@@@@@@@@@@ + @setup base pointer = GPIO_BASE 0xFFFCE000 + ldr r12, gpio_base + +mdm: @Is it a modem interrupt? + ldr r11, [r12,#GPIO_INTERRUPT_MASK] @ get GPIO interrupt mask + and r10, r11, #MDM_MASK @ reveal modem bit + cmp r10, #MDM_MASK @ is mask bit set? + beq hksw @ yes, next source + + ldr r11, [r12,#GPIO_DATA_INPUT] @ get GPIO data line status + and r10, r11, #MDM_MASK @ reveal modem bit + cmp r10, #MDM_MASK @ is modem bit set? + bne hksw @ no, so skip mdm - next source + + mov r10, #MDM_MASK @ its a mdm interrupt + str r10, [r12,#GPIO_INTERRUPT_STATUS] @ clear the modem interrupt + + ldr r10, [r9, #FIQ_CNT_INT_MDM] @ get modem interrupt count + add r10, r10, #1 @ increment it + str r10, [r9, #FIQ_CNT_INT_MDM] @ save count for IRQ handlers + + @@@@@@@@@@@@@@@@@@@@@@@@ + @ Force a INT_OS_32kHz_TIMER interrupt + @setup base pointer = MPU_L2_INTERRUPT_BASE 0xFFFE0000 + ldr r12, mpu_l2_interrupt_base + mov r10, #TIMER_32k_MASK @ set 32kHz_TIMER bit + str r10, [r12, #ISR] @ write ISR + + @@@@@@@@@@@@@@@@@@@@@@@@@@@ + @setup base pointer = GPIO_BASE 0xFFFCE000 + ldr r12, gpio_base + +hksw: @Is it a hook switch interrupt? + ldr r11, [r12,#GPIO_INTERRUPT_MASK] @ get GPIO interrupt mask + and r10, r11, #HKSW_MASK @ reveal hook switch bit + cmp r10, #HKSW_MASK @ is mask bit set? + beq exit @ yes, exit + + ldr r11, [r12,#GPIO_INTERRUPT_STATUS] @ get GPIO interrupts status + and r10, r11, #HKSW_MASK @ reveal hook switch bit + cmp r10, #HKSW_MASK @ is hook switch bit set? + bne exit @ no, so skip hksw - exit + + mov r10, #HKSW_MASK @ it's a hooksw interrupt + str r10, [r12,#GPIO_INTERRUPT_STATUS] @ clear hook switch interrupt + + ldr r10, [r9, #FIQ_CNT_INT_04] @ get hooksw inerrupt count + add r10, r10, #1 @ increment it + str r10, [r9, #FIQ_CNT_INT_04] @ save count for IRQ handlers + + @@@@@@@@@@@@@@@@@@@@@@@@ + @ Force a INT_OS_32kHz_TIMER interrupt + @setup base pointer = MPU_L2_INTERRUPT_BASE 0xFFFE0000 + ldr r12, mpu_l2_interrupt_base + mov r10, #TIMER_32k_MASK @ set 32kHz_TIMER bit + str r10, [r12, #ISR] @ write ISR + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @setup base pointer = MPU_L1_INTERRUPT_BASE 0xFFFECB00 +exit: ldr r12, mpu_l1_interrupt_base + mov r10, # 0x2 + str r10, [r12, #CONTROL_REG] @ reset FIQ Agreement + + subs pc, lr, #4 @ return from FIQ + +/* + * Virtual addresses for IO + */ +mpu_l1_interrupt_base: + .word MPU_L1_INTERRUPT_BASE +mpu_l2_interrupt_base: + .word MPU_L2_INTERRUPT_BASE +gpio_base: + .word GPIO_BASE +qwerty_fiqin_end: + +/* + * Check the size of the FIQ, + * it cannot go beyond 0xffff0200, and is copied to 0xffff001c + */ +.if (qwerty_fiqin_end - qwerty_fiqin_start) > (0x200 - 0x1c) + .err +.endif diff -uprN git.orig/arch/arm/plat-omap/include/plat/irqs.h git/arch/arm/plat-omap/include/plat/irqs.h --- git.orig/arch/arm/plat-omap/include/plat/irqs.h 2009-12-02 15:48:51.000000000 +0100 +++ git/arch/arm/plat-omap/include/plat/irqs.h 2009-12-10 03:38:02.000000000 +0100 @@ -489,4 +489,8 @@ void omap_intc_restore_context(void); #include +#ifdef CONFIG_FIQ +#define FIQ_START 1024 +#endif + #endif