2010-04-28 05:01:29 +04:00
/ *
* linux/ a r c h / a r m / m a c h - o m a p1 / a m s - d e l t a - f i q - h a n d l e r . S
*
* Based o n l i n u x / a r c h / a r m / l i b / f l o p p y d m a . S
* Renamed a n d m o d i f i e d t o w o r k w i t h 2 . 6 k e r n e l b y M a t t C a l l o w
* Copyright ( C ) 1 9 9 5 , 1 9 9 6 R u s s e l l K i n g
* Copyright ( C ) 2 0 0 4 P e t e T r a p p s
* Copyright ( C ) 2 0 0 6 M a t t C a l l o w
* Copyright ( C ) 2 0 1 0 J a n u s z K r z y s z t o f i k
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify it
* under t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2
* as p u b l i s h e d b y t h e F r e e S o f t w a r e F o u n d a t i o n .
* /
# include < l i n u x / l i n k a g e . h >
# include < p l a t / i o . h >
# include < p l a t / b o a r d - a m s - d e l t a . h >
# include < m a c h / a m s - d e l t a - f i q . h >
/ *
* GPIO r e l a t e d d e f i n i t i o n s , c o p i e d f r o m a r c h / a r m / p l a t - o m a p / g p i o . c .
* Unfortunately, t h o s e w e r e n o t p l a c e d i n a s e p a r a t e h e a d e r f i l e .
* /
# define O M A P 1 5 1 0 _ G P I O _ B A S E 0 x F F F C E 0 0 0
# define O M A P 1 5 1 0 _ G P I O _ D A T A _ I N P U T 0 x00
# define O M A P 1 5 1 0 _ G P I O _ D A T A _ O U T P U T 0 x04
# define O M A P 1 5 1 0 _ G P I O _ D I R _ C O N T R O L 0 x08
# define O M A P 1 5 1 0 _ G P I O _ I N T _ C O N T R O L 0 x0 c
# define O M A P 1 5 1 0 _ G P I O _ I N T _ M A S K 0 x10
# define O M A P 1 5 1 0 _ G P I O _ I N T _ S T A T U S 0 x14
# define O M A P 1 5 1 0 _ G P I O _ P I N _ C O N T R O L 0 x18
/* GPIO register bitmasks */
# define K E Y B R D _ D A T A _ M A S K ( 0 x1 < < A M S _ D E L T A _ G P I O _ P I N _ K E Y B R D _ D A T A )
# define K E Y B R D _ C L K _ M A S K ( 0 x1 < < A M S _ D E L T A _ G P I O _ P I N _ K E Y B R D _ C L K )
# define M O D E M _ I R Q _ M A S K ( 0 x1 < < A M S _ D E L T A _ G P I O _ P I N _ M O D E M _ I R Q )
# define H O O K _ S W I T C H _ M A S K ( 0 x1 < < A M S _ D E L T A _ G P I O _ P I N _ H O O K _ S W I T C H )
# define O T H E R S _ M A S K ( M O D E M _ I R Q _ M A S K | H O O K _ S W I T C H _ M A S K )
/* IRQ handler register bitmasks */
# define D E F E R R E D _ F I Q _ M A S K ( 0 x1 < < ( I N T _ D E F E R R E D _ F I Q % I H 2 _ B A S E ) )
# define G P I O _ B A N K 1 _ M A S K ( 0 x1 < < I N T _ G P I O _ B A N K 1 )
/* Driver buffer byte offsets */
# define B U F _ M A S K ( F I Q _ M A S K * 4 )
# define B U F _ S T A T E ( F I Q _ S T A T E * 4 )
# define B U F _ K E Y S _ C N T ( F I Q _ K E Y S _ C N T * 4 )
# define B U F _ T A I L _ O F F S E T ( F I Q _ T A I L _ O F F S E T * 4 )
# define B U F _ H E A D _ O F F S E T ( F I Q _ H E A D _ O F F S E T * 4 )
# define B U F _ B U F _ L E N ( F I Q _ B U F _ L E N * 4 )
# define B U F _ K E Y ( F I Q _ K E Y * 4 )
# define B U F _ M I S S E D _ K E Y S ( F I Q _ M I S S E D _ K E Y S * 4 )
# define B U F _ B U F F E R _ S T A R T ( F I Q _ B U F F E R _ S T A R T * 4 )
# define B U F _ G P I O _ I N T _ M A S K ( F I Q _ G P I O _ I N T _ M A S K * 4 )
# define B U F _ K E Y S _ H I C N T ( F I Q _ K E Y S _ H I C N T * 4 )
# define B U F _ I R Q _ P E N D ( F I Q _ I R Q _ P E N D * 4 )
# define B U F _ S I R _ C O D E _ L 1 ( F I Q _ S I R _ C O D E _ L 1 * 4 )
# define B U F _ S I R _ C O D E _ L 2 ( I R Q _ S I R _ C O D E _ L 2 * 4 )
# define B U F _ C N T _ I N T _ 0 0 ( F I Q _ C N T _ I N T _ 0 0 * 4 )
# define B U F _ C N T _ I N T _ K E Y ( F I Q _ C N T _ I N T _ K E Y * 4 )
# define B U F _ C N T _ I N T _ M D M ( F I Q _ C N T _ I N T _ M D M * 4 )
# define B U F _ C N T _ I N T _ 0 3 ( F I Q _ C N T _ I N T _ 0 3 * 4 )
# define B U F _ C N T _ I N T _ H S W ( F I Q _ C N T _ I N T _ H S W * 4 )
# define B U F _ C N T _ I N T _ 0 5 ( F I Q _ C N T _ I N T _ 0 5 * 4 )
# define B U F _ C N T _ I N T _ 0 6 ( F I Q _ C N T _ I N T _ 0 6 * 4 )
# define B U F _ C N T _ I N T _ 0 7 ( F I Q _ C N T _ I N T _ 0 7 * 4 )
# define B U F _ C N T _ I N T _ 0 8 ( F I Q _ C N T _ I N T _ 0 8 * 4 )
# define B U F _ C N T _ I N T _ 0 9 ( F I Q _ C N T _ I N T _ 0 9 * 4 )
# define B U F _ C N T _ I N T _ 1 0 ( F I Q _ C N T _ I N T _ 1 0 * 4 )
# define B U F _ C N T _ I N T _ 1 1 ( F I Q _ C N T _ I N T _ 1 1 * 4 )
# define B U F _ C N T _ I N T _ 1 2 ( F I Q _ C N T _ I N T _ 1 2 * 4 )
# define B U F _ C N T _ I N T _ 1 3 ( F I Q _ C N T _ I N T _ 1 3 * 4 )
# define B U F _ C N T _ I N T _ 1 4 ( F I Q _ C N T _ I N T _ 1 4 * 4 )
# define B U F _ C N T _ I N T _ 1 5 ( F I Q _ C N T _ I N T _ 1 5 * 4 )
# define B U F _ C I R C _ B U F F ( F I Q _ C I R C _ B U F F * 4 )
/ *
2011-03-31 05:57:33 +04:00
* Register u s a g e
2010-04-28 05:01:29 +04:00
* r8 - t e m p o r a r y
* r9 - t h e d r i v e r b u f f e r
* r1 0 - t e m p o r a r y
* r1 1 - i n t e r r u p t s m a s k
* r1 2 - b a s e p o i n t e r s
* r1 3 - i n t e r r u p t s s t a t u s
* /
.text
.global qwerty_fiqin_end
ENTRY( q w e r t y _ f i q i n _ s t a r t )
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ FIQ intrrupt handler
ldr r12 , o m a p _ i h1 _ b a s e @ set pointer to level1 handler
ldr r11 , [ r12 , #I R Q _ M I R _ R E G _ O F F S E T ] @ f e t c h i n t e r r u p t s m a s k
ldr r13 , [ r12 , #I R Q _ I T R _ R E G _ O F F S E T ] @ f e t c h i n t e r r u p t s s t a t u s
bics r13 , r13 , r11 @ clear masked - any left?
beq e x i t @ none - spurious FIQ? exit
ldr r10 , [ r12 , #I R Q _ S I R _ F I Q _ R E G _ O F F S E T ] @ g e t r e q u e s t e d i n t e r r u p t n u m b e r
mov r8 , #2 @ reset FIQ agreement
str r8 , [ r12 , #I R Q _ C O N T R O L _ R E G _ O F F S E T ]
cmp r10 , #I N T _ G P I O _ B A N K 1 @ is it GPIO bank interrupt?
beq g p i o @ yes - process it
mov r8 , #1
orr r8 , r11 , r8 , l s l r10 @ mask spurious interrupt
str r8 , [ r12 , #I R Q _ M I R _ R E G _ O F F S E T ]
exit :
subs p c , l r , #4 @ return from FIQ
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@
gpio : @ GPIO bank interrupt handler
ldr r12 , o m a p15 1 0 _ g p i o _ b a s e @ set base pointer to GPIO bank
ldr r11 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ M A S K ] @ fetch GPIO interrupts mask
restart :
ldr r13 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ S T A T U S ] @ fetch status bits
bics r13 , r13 , r11 @ clear masked - any left?
beq e x i t @ no - spurious interrupt? exit
orr r11 , r11 , r13 @ mask all requested interrupts
str r11 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ M A S K ]
ands r10 , r13 , #K E Y B R D _ C L K _ M A S K @ e x t r a c t k e y b o a r d s t a t u s - s e t ?
beq h k s w @ no - try next source
@@@@@@@@@@@@@@@@@@@@@@
@ Keyboard clock FIQ mode interrupt handler
@ r10 now contains KEYBRD_CLK_MASK, use it
str r10 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ S T A T U S ] @ ack the interrupt
bic r11 , r11 , r10 @ unmask it
str r11 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ M A S K ]
@ Process keyboard data
ldr r8 , [ r12 , #O M A P 1510 _ G P I O _ D A T A _ I N P U T ] @ fetch GPIO input
ldr r10 , [ r9 , #B U F _ S T A T E ] @ f e t c h k b d i n t e r f a c e s t a t e
cmp r10 , #0 @ are we expecting start bit?
bne d a t a @ no - go to data processing
ands r8 , r8 , #K E Y B R D _ D A T A _ M A S K @ c h e c k s t a r t b i t - d e t e c t e d ?
beq h k s w @ no - try next source
@ r8 contains KEYBRD_DATA_MASK, use it
str r8 , [ r9 , #B U F _ S T A T E ] @ e n t e r d a t a p r o c e s s i n g s t a t e
@ r10 already contains 0, reuse it
str r10 , [ r9 , #B U F _ K E Y ] @ c l e a r k e y c o d e
mov r10 , #2 @ reset input bit mask
str r10 , [ r9 , #B U F _ M A S K ]
@ Mask other GPIO line interrupts till key done
str r11 , [ r9 , #B U F _ G P I O _ I N T _ M A S K ] @ s a v e m a s k f o r l a t e r r e s t o r e
mvn r11 , #K E Y B R D _ C L K _ M A S K @ p r e p a r e a l l e x c e p t k b d m a s k
str r11 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ M A S K ] @ store into the mask register
b r e s t a r t @ restart
data : ldr r10 , [ r9 , #B U F _ M A S K ] @ f e t c h c u r r e n t i n p u t b i t m a s k
@ r8 still contains GPIO input bits
ands r8 , r8 , #K E Y B R D _ D A T A _ M A S K @ i s k e y b o a r d d a t a l i n e l o w ?
ldreq r8 , [ r9 , #B U F _ K E Y ] @ y e s - f e t c h c o l l e c t e d s o f a r ,
orreq r8 , r8 , r10 @ set 1 at current mask position
streq r8 , [ r9 , #B U F _ K E Y ] @ a n d s a v e b a c k
mov r10 , r10 , l s l #1 @ shift mask left
bics r10 , r10 , #0x800 @ have we got all the bits?
strne r10 , [ r9 , #B U F _ M A S K ] @ n o t y e t - s t o r e t h e m a s k
bne r e s t a r t @ and restart
@ r10 already contains 0, reuse it
str r10 , [ r9 , #B U F _ S T A T E ] @ r e s e t s t a t e t o s t a r t
@ Key done - restore interrupt mask
ldr r10 , [ r9 , #B U F _ G P I O _ I N T _ M A S K ] @ f e t c h s a v e d m a s k
and r11 , r11 , r10 @ unmask all saved as unmasked
str r11 , [ r12 , #O M A P 1510 _ G P I O _ I N T _ M A S K ] @ restore into the mask register
@ Try appending the keycode to the circular buffer
ldr r10 , [ r9 , #B U F _ K E Y S _ C N T ] @ g e t s a v e d k e y s t r o k e s c o u n t
ldr r8 , [ r9 , #B U F _ B U F _ L E N ] @ g e t b u f f e r s i z e
cmp r10 , r8 @ is buffer full?
beq h k s w @ yes - key lost, next source
add r10 , r10 , #1 @ incremet keystrokes counter
str r10 , [ r9 , #B U F _ K E Y S _ C N T ]
ldr r10 , [ r9 , #B U F _ T A I L _ O F F S E T ] @ g e t b u f f e r t a i l o f f s e t
@ r8 already contains buffer size
cmp r10 , r8 @ end of buffer?
moveq r10 , #0 @ yes - rewind to buffer start
ldr r12 , [ r9 , #B U F _ B U F F E R _ S T A R T ] @ g e t b u f f e r s t a r t a d d r e s s
add r12 , r12 , r10 , L S L #2 @ calculate buffer tail address
ldr r8 , [ r9 , #B U F _ K E Y ] @ g e t l a s t k e y c o d e
str r8 , [ r12 ] @ append it to the buffer tail
add r10 , r10 , #1 @ increment buffer tail offset
str r10 , [ r9 , #B U F _ T A I L _ O F F S E T ]
ldr r10 , [ r9 , #B U F _ C N T _ I N T _ K E Y ] @ i n c r e m e n t i n t e r r u p t s c o u n t e r
add r10 , r10 , #1
str r10 , [ r9 , #B U F _ C N T _ I N T _ K E Y ]
@@@@@@@@@@@@@@@@@@@@@@@@
hksw : @Is hook switch interrupt requested?
tst r13 , #H O O K _ S W I T C H _ M A S K @ i s h o o k s w i t c h s t a t u s b i t s e t ?
beq m d m @ no - try next source
@@@@@@@@@@@@@@@@@@@@@@@@
@ Hook switch interrupt FIQ mode simple handler
@ Don't toggle active edge, the switch always bounces
@ Increment hook switch interrupt counter
ldr r10 , [ r9 , #B U F _ C N T _ I N T _ H S W ]
add r10 , r10 , #1
str r10 , [ r9 , #B U F _ C N T _ I N T _ H S W ]
@@@@@@@@@@@@@@@@@@@@@@@@
mdm : @Is it a modem interrupt?
tst r13 , #M O D E M _ I R Q _ M A S K @ i s m o d e m s t a t u s b i t s e t ?
beq i r q @ no - check for next interrupt
@@@@@@@@@@@@@@@@@@@@@@@@
@ Modem FIQ mode interrupt handler stub
@ Increment modem interrupt counter
ldr r10 , [ r9 , #B U F _ C N T _ I N T _ M D M ]
add r10 , r10 , #1
str r10 , [ r9 , #B U F _ C N T _ I N T _ M D M ]
@@@@@@@@@@@@@@@@@@@@@@@@
irq : @ Place deferred_fiq interrupt request
ldr r12 , d e f e r r e d _ f i q _ i h _ b a s e @ set pointer to IRQ handler
mov r10 , #D E F E R R E D _ F I Q _ M A S K @ s e t d e f e r r e d _ f i q b i t
str r10 , [ r12 , #I R Q _ I S R _ R E G _ O F F S E T ] @ p l a c e i t i n t h e I S R r e g i s t e r
ldr r12 , o m a p15 1 0 _ g p i o _ b a s e @ set pointer back to GPIO bank
b r e s t a r t @ check for next GPIO interrupt
@@@@@@@@@@@@@@@@@@@@@@@@@@@
/ *
* Virtual a d d r e s s e s f o r I O
* /
omap_ih1_base :
.word OMAP1 _ I O _ A D D R E S S ( O M A P _ I H 1 _ B A S E )
deferred_fiq_ih_base :
.word OMAP1 _ I O _ A D D R E S S ( D E F E R R E D _ F I Q _ I H _ B A S E )
omap1510_gpio_base :
.word OMAP1 _ I O _ A D D R E S S ( O M A P 1 5 1 0 _ G P I O _ B A S E )
qwerty_fiqin_end :
/ *
* Check t h e s i z e o f t h e F I Q ,
* it c a n n o t g o b e y o n d 0 x f f f f02 0 0 , a n d i s c o p i e d t o 0 x f f f f00 1 c
* /
.if ( qwerty_ f i q i n _ e n d - q w e r t y _ f i q i n _ s t a r t ) > ( 0 x20 0 - 0 x1 c )
.err
.endif