All of lore.kernel.org
 help / color / mirror / Atom feed
* I2C TWL4030 Keypad
@ 2007-02-16 11:25 Ram
  2007-02-16 14:31 ` G, Manjunath Kondaiah
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Ram @ 2007-02-16 11:25 UTC (permalink / raw)
  To: linux-omap-open-source

Hi,
   Im using omap2430 SDP.
   Im trying to get TWL4030 Keypad to work on 2.6.19. Im using 2.6.14 for
omap2430 as a reference.

   Im using the following files:
        1) i2c-omap.c which exists on 2.6.19
        2) twl4030_core.c
        3) twl4030_gpio.c (taken from 2.6.14)
        4) omap-twl4030keypad.c (taken from 2.6.14)

   made  changes  to support generic interrupts in 2.6.19.

   Im able to read the value of registers using  twl4030_kpread_u8
    TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG, REG_KEY_DEB_REG,
REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1

  However, im not able to recieve interrupts. upon pressing keys in keypad.
i dont observe
  any change in interrupts count. when i do a cat /proc/interrupts.

Im not sure if im missing something.


  I also observe randomly (say 3 out of 10 times), my i2c bus times out and
im unable to read or write TWL4030 registers. i get an return value of
-110.

i2c_omap i2c_omap.2: timeout waiting for bus ready

Please Advice,

Regards,
sriram

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
  2007-02-16 11:25 I2C TWL4030 Keypad Ram
@ 2007-02-16 14:31 ` G, Manjunath Kondaiah
       [not found]   ` <8bf247760702160650s62d2b401lad8746881aedd2aa@mail.gmail.com>
  2007-02-17 13:45 ` Nishanth Menon
  2007-02-26 17:38 ` I2C TWL4030 Keypad Cantu Castillo, Arturo
  2 siblings, 1 reply; 13+ messages in thread
From: G, Manjunath Kondaiah @ 2007-02-16 14:31 UTC (permalink / raw)
  To: Ram, linux-omap-open-source

Make sure the following modules are enabled in the menuconfig:

1. I2C driver
2. TWL4030 Driver
3. TWL4030 keypad driver

Also make sure, triton and its client driver interrupts are mapped in
irqs.h file. If interrupt numbers are mapped properly, check if ARM
interrupt for triton is unmasked or not.

Last thing, check pin muxing for the sys_irq line and configure in
proper mode for triton interrupt to work.

Regards,
Manjunath

-----Original Message-----
From: linux-omap-open-source-bounces+manjugk=ti.com@linux.omap.com
[mailto:linux-omap-open-source-bounces+manjugk=ti.com@linux.omap.com] On
Behalf Of Ram
Sent: Friday, February 16, 2007 4:55 PM
To: linux-omap-open-source@linux.omap.com
Subject: I2C TWL4030 Keypad

Hi,
   Im using omap2430 SDP.
   Im trying to get TWL4030 Keypad to work on 2.6.19. Im using 2.6.14
for
omap2430 as a reference.

   Im using the following files:
        1) i2c-omap.c which exists on 2.6.19
        2) twl4030_core.c
        3) twl4030_gpio.c (taken from 2.6.14)
        4) omap-twl4030keypad.c (taken from 2.6.14)

   made  changes  to support generic interrupts in 2.6.19.

   Im able to read the value of registers using  twl4030_kpread_u8
    TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG,
REG_KEY_DEB_REG,
REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1

  However, im not able to recieve interrupts. upon pressing keys in
keypad.
i dont observe
  any change in interrupts count. when i do a cat /proc/interrupts.

Im not sure if im missing something.


  I also observe randomly (say 3 out of 10 times), my i2c bus times out
and
im unable to read or write TWL4030 registers. i get an return value of
-110.

i2c_omap i2c_omap.2: timeout waiting for bus ready

Please Advice,

Regards,
sriram
_______________________________________________
Linux-omap-open-source mailing list
Linux-omap-open-source@linux.omap.com
http://linux.omap.com/mailman/listinfo/linux-omap-open-source

^ permalink raw reply	[flat|nested] 13+ messages in thread

* I2C TWL4030 Keypad
       [not found]   ` <8bf247760702160650s62d2b401lad8746881aedd2aa@mail.gmail.com>
@ 2007-02-16 15:08     ` Ram
  2007-02-16 15:38       ` Syed Mohammed, Khasim
  0 siblings, 1 reply; 13+ messages in thread
From: Ram @ 2007-02-16 15:08 UTC (permalink / raw)
  To: linux-omap-open-source

>> check if ARM interrupt for triton is unmasked or not.

 Im not sure, where this information is provided?. Could you let me
 know where do i check for this?.

 All are enabled:
 1. I2C driver
 2. TWL4030 Driver
 3. TWL4030 keypad driver

 Im able to read TWL Registers. Although randomly, i do get i2c
bustimeout error.

 Mux settings seem to be okay.


 regards,
 sriram




On 2/16/07, G, Manjunath Kondaiah <manjugk@ti.com> wrote:
> Make sure the following modules are enabled in the menuconfig:
>
> 1. I2C driver
> 2. TWL4030 Driver
> 3. TWL4030 keypad driver
>
> Also make sure, triton and its client driver interrupts are mapped in
> irqs.h file. If interrupt numbers are mapped properly, check if ARM
> interrupt for triton is unmasked or not.
>
> Last thing, check pin muxing for the sys_irq line and configure in
> proper mode for triton interrupt to work.
>
> Regards,
> Manjunath
>
> -----Original Message-----
> From: linux-omap-open-source-bounces+manjugk=ti.com@linux.omap.com
> [mailto:linux-omap-open-source-bounces+manjugk=ti.com@linux.omap.com ] On
> Behalf Of Ram
> Sent: Friday, February 16, 2007 4:55 PM
> To: linux-omap-open-source@linux.omap.com
> Subject: I2C TWL4030 Keypad
>
> Hi,
>    Im using omap2430 SDP.
>    Im trying to get TWL4030 Keypad to work on 2.6.19. Im using 2.6.14
> for
> omap2430 as a reference.
>
>    Im using the following files:
>         1) i2c-omap.c which exists on 2.6.19
>         2) twl4030_core.c
>         3) twl4030_gpio.c (taken from 2.6.14)
>         4) omap-twl4030keypad.c (taken from 2.6.14)
>
>    made  changes  to support generic interrupts in 2.6.19.
>
>    Im able to read the value of registers using  twl4030_kpread_u8
>     TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG,
> REG_KEY_DEB_REG,
> REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1
>
>   However, im not able to recieve interrupts. upon pressing keys in
> keypad.
> i dont observe
>   any change in interrupts count. when i do a cat /proc/interrupts.
>
> Im not sure if im missing something.
>
>
>   I also observe randomly (say 3 out of 10 times), my i2c bus times out
> and
> im unable to read or write TWL4030 registers. i get an return value of
> -110.
>
> i2c_omap i2c_omap.2: timeout waiting for bus ready
>
> Please Advice,
>
> Regards,
> sriram
> _______________________________________________
> Linux-omap-open-source mailing list
> Linux-omap-open-source@linux.omap.com
> http://linux.omap.com/mailman/listinfo/linux-omap-open-source
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
  2007-02-16 15:08     ` Ram
@ 2007-02-16 15:38       ` Syed Mohammed, Khasim
  0 siblings, 0 replies; 13+ messages in thread
From: Syed Mohammed, Khasim @ 2007-02-16 15:38 UTC (permalink / raw)
  To: Ram, linux-omap-open-source

Hi,

Refer to "include/asm-arm/arch-omap/irqs-omap2430.h", there should be
some defines and additions for TWL 

Regards,
Khasim

> -----Original Message-----
> From: linux-omap-open-source-bounces@linux.omap.com
[mailto:linux-omap-
> open-source-bounces@linux.omap.com] On Behalf Of Ram
> Sent: Friday, February 16, 2007 9:09 AM
> To: linux-omap-open-source@linux.omap.com
> Subject: I2C TWL4030 Keypad
> 
> >> check if ARM interrupt for triton is unmasked or not.
> 
>  Im not sure, where this information is provided?. Could you let me
>  know where do i check for this?.
> 
>  All are enabled:
>  1. I2C driver
>  2. TWL4030 Driver
>  3. TWL4030 keypad driver
> 
>  Im able to read TWL Registers. Although randomly, i do get i2c
> bustimeout error.
> 
>  Mux settings seem to be okay.
> 
> 
>  regards,
>  sriram
> 
> 
> 
> 
> On 2/16/07, G, Manjunath Kondaiah <manjugk@ti.com> wrote:
> > Make sure the following modules are enabled in the menuconfig:
> >
> > 1. I2C driver
> > 2. TWL4030 Driver
> > 3. TWL4030 keypad driver
> >
> > Also make sure, triton and its client driver interrupts are mapped
in
> > irqs.h file. If interrupt numbers are mapped properly, check if ARM
> > interrupt for triton is unmasked or not.
> >
> > Last thing, check pin muxing for the sys_irq line and configure in
> > proper mode for triton interrupt to work.
> >
> > Regards,
> > Manjunath
> >
> > -----Original Message-----
> > From: linux-omap-open-source-bounces+manjugk=ti.com@linux.omap.com
> > [mailto:linux-omap-open-source-bounces+manjugk=ti.com@linux.omap.com
]
> On
> > Behalf Of Ram
> > Sent: Friday, February 16, 2007 4:55 PM
> > To: linux-omap-open-source@linux.omap.com
> > Subject: I2C TWL4030 Keypad
> >
> > Hi,
> >    Im using omap2430 SDP.
> >    Im trying to get TWL4030 Keypad to work on 2.6.19. Im using
2.6.14
> > for
> > omap2430 as a reference.
> >
> >    Im using the following files:
> >         1) i2c-omap.c which exists on 2.6.19
> >         2) twl4030_core.c
> >         3) twl4030_gpio.c (taken from 2.6.14)
> >         4) omap-twl4030keypad.c (taken from 2.6.14)
> >
> >    made  changes  to support generic interrupts in 2.6.19.
> >
> >    Im able to read the value of registers using  twl4030_kpread_u8
> >     TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG,
> > REG_KEY_DEB_REG,
> > REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1
> >
> >   However, im not able to recieve interrupts. upon pressing keys in
> > keypad.
> > i dont observe
> >   any change in interrupts count. when i do a cat /proc/interrupts.
> >
> > Im not sure if im missing something.
> >
> >
> >   I also observe randomly (say 3 out of 10 times), my i2c bus times
out
> > and
> > im unable to read or write TWL4030 registers. i get an return value
of
> > -110.
> >
> > i2c_omap i2c_omap.2: timeout waiting for bus ready
> >
> > Please Advice,
> >
> > Regards,
> > sriram
> > _______________________________________________
> > Linux-omap-open-source mailing list
> > Linux-omap-open-source@linux.omap.com
> > http://linux.omap.com/mailman/listinfo/linux-omap-open-source
> >
> _______________________________________________
> Linux-omap-open-source mailing list
> Linux-omap-open-source@linux.omap.com
> http://linux.omap.com/mailman/listinfo/linux-omap-open-source

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: I2C TWL4030 Keypad
  2007-02-16 11:25 I2C TWL4030 Keypad Ram
  2007-02-16 14:31 ` G, Manjunath Kondaiah
@ 2007-02-17 13:45 ` Nishanth Menon
       [not found]   ` <8bf247760702170604h5b2e210cibe4de58d4f898d74@mail.gmail.com>
  2007-02-26 17:38 ` I2C TWL4030 Keypad Cantu Castillo, Arturo
  2 siblings, 1 reply; 13+ messages in thread
From: Nishanth Menon @ 2007-02-17 13:45 UTC (permalink / raw)
  To: Ram; +Cc: linux-omap-open-source

Ram stated on 2/16/2007 5:25 AM:
> I also observe randomly (say 3 out of 10 times), my i2c bus times out and
> im unable to read or write TWL4030 registers. i get an return value of
> -110.
>
> i2c_omap i2c_omap.2: timeout waiting for bus ready
What is ur I2C speed configured? max u should be using is 2.6Mhz, u
could try and bump down to 400khz or so..further, which is the kernel
versions - this is not tested with rt patch..so there might be some
interesting things happening there.. :D
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: I2C TWL4030 Keypad
       [not found]   ` <8bf247760702170604h5b2e210cibe4de58d4f898d74@mail.gmail.com>
@ 2007-02-17 14:08     ` Nishanth Menon
  2007-02-18  8:00       ` Setting the default state (high or low) of a pin zil iram
  0 siblings, 1 reply; 13+ messages in thread
From: Nishanth Menon @ 2007-02-17 14:08 UTC (permalink / raw)
  To: Ram, Linux OMAP List

Ram stated on 2/17/2007 8:04 AM:
> Hi,
> My speed setting are I2C_OMAP243X_BUS1 = 2600 and
> CONFIG_I2C_OMAP243X_BUS0 = 100.
>
> Actually, im confused.
>
> Porting TWL4030 keyboard to 2.6.19. Im using 2.6.14 for omap2430 as a
> reference.
>
ok, try doing this setting up
I2C_OMAP243X_BUS1 = 400

I understand ur not getting interrupts - normally that should not be
happening.. but am guessing here that ur i2c ops are failing due to some
reason...  if ur using the latest kernel with rt enabled, the drivers
have might not have been tested for it and timing issues are popping up..
Regards,
NM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Setting the default state (high or low) of a pin
  2007-02-17 14:08     ` Nishanth Menon
@ 2007-02-18  8:00       ` zil iram
  0 siblings, 0 replies; 13+ messages in thread
From: zil iram @ 2007-02-18  8:00 UTC (permalink / raw)
  To: linux-omap-open-source

Hi,

I have used a pin to be multiplexed as the spi clock for an spi controller. 
It's default state is high but I need it to be low when it is not 
toggling/enabled.

Does anyone know how to set a pin's default state?

Thanks,
Lizette

_________________________________________________________________
Don't just search. Find. Check out the new MSN Search! 
http://search.msn.com/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
  2007-02-16 11:25 I2C TWL4030 Keypad Ram
  2007-02-16 14:31 ` G, Manjunath Kondaiah
  2007-02-17 13:45 ` Nishanth Menon
@ 2007-02-26 17:38 ` Cantu Castillo, Arturo
  2007-02-27  6:20   ` Ram
  2 siblings, 1 reply; 13+ messages in thread
From: Cantu Castillo, Arturo @ 2007-02-26 17:38 UTC (permalink / raw)
  To: Ram, linux-omap-open-source

Hi Ram,
It might be happening that when the driver is initialized the i2c
writing to TWL4030_MODULE_KEYPAD register that is done to enable
interrupts is failing (since you are saying that i2c readings/writings
are failing randomly it is likely), you can try to read this register
and find out if the interrupts are enable.

Also you can check that all the registers that are set in the
initialization routine have the proper value, if i2c writings are
failing randomly, some of them might not be initialized correctly.

Regards,
Arturo
-----Original Message-----
From: linux-omap-open-source-bounces+x0052731=ti.com@linux.omap.com
[mailto:linux-omap-open-source-bounces+x0052731=ti.com@linux.omap.com]
On Behalf Of Ram
Sent: Friday, February 16, 2007 5:25 AM
To: linux-omap-open-source@linux.omap.com
Subject: I2C TWL4030 Keypad

Hi,
   Im using omap2430 SDP.
   Im trying to get TWL4030 Keypad to work on 2.6.19. Im using 2.6.14
for
omap2430 as a reference.

   Im using the following files:
        1) i2c-omap.c which exists on 2.6.19
        2) twl4030_core.c
        3) twl4030_gpio.c (taken from 2.6.14)
        4) omap-twl4030keypad.c (taken from 2.6.14)

   made  changes  to support generic interrupts in 2.6.19.

   Im able to read the value of registers using  twl4030_kpread_u8
    TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG,
REG_KEY_DEB_REG,
REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1

  However, im not able to recieve interrupts. upon pressing keys in
keypad.
i dont observe
  any change in interrupts count. when i do a cat /proc/interrupts.

Im not sure if im missing something.


  I also observe randomly (say 3 out of 10 times), my i2c bus times out
and
im unable to read or write TWL4030 registers. i get an return value of
-110.

i2c_omap i2c_omap.2: timeout waiting for bus ready

Please Advice,

Regards,
sriram
_______________________________________________
Linux-omap-open-source mailing list
Linux-omap-open-source@linux.omap.com
http://linux.omap.com/mailman/listinfo/linux-omap-open-source

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: I2C TWL4030 Keypad
  2007-02-26 17:38 ` I2C TWL4030 Keypad Cantu Castillo, Arturo
@ 2007-02-27  6:20   ` Ram
  2007-02-27 15:09     ` Syed Mohammed, Khasim
  2007-02-28  1:00     ` Syed Mohammed, Khasim
  0 siblings, 2 replies; 13+ messages in thread
From: Ram @ 2007-02-27  6:20 UTC (permalink / raw)
  To: Cantu Castillo, Arturo; +Cc: linux-omap-open-source

Hi,
Keypad driver seems to be okay.
I tried with RTC driver too. I still get the same error.

I feel it is something to do with twl_core driver - the way interrupts
are handled.


i will look into what you have mentioned.

Regards,
sriram





On 2/26/07, Cantu Castillo, Arturo <x0052731@ti.com> wrote:
> Hi Ram,
> It might be happening that when the driver is initialized the i2c
> writing to TWL4030_MODULE_KEYPAD register that is done to enable
> interrupts is failing (since you are saying that i2c readings/writings
> are failing randomly it is likely), you can try to read this register
> and find out if the interrupts are enable.
>
> Also you can check that all the registers that are set in the
> initialization routine have the proper value, if i2c writings are
> failing randomly, some of them might not be initialized correctly.
>
> Regards,
> Arturo
> -----Original Message-----
> From: linux-omap-open-source-bounces+x0052731=ti.com@linux.omap.com
> [mailto:linux-omap-open-source-bounces+x0052731=ti.com@linux.omap.com]
> On Behalf Of Ram
> Sent: Friday, February 16, 2007 5:25 AM
> To: linux-omap-open-source@linux.omap.com
> Subject: I2C TWL4030 Keypad
>
> Hi,
>    Im using omap2430 SDP.
>    Im trying to get TWL4030 Keypad to work on 2.6.19. Im using 2.6.14
> for
> omap2430 as a reference.
>
>    Im using the following files:
>         1) i2c-omap.c which exists on 2.6.19
>         2) twl4030_core.c
>         3) twl4030_gpio.c (taken from 2.6.14)
>         4) omap-twl4030keypad.c (taken from 2.6.14)
>
>    made  changes  to support generic interrupts in 2.6.19.
>
>    Im able to read the value of registers using  twl4030_kpread_u8
>     TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG,
> REG_KEY_DEB_REG,
> REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1
>
>   However, im not able to recieve interrupts. upon pressing keys in
> keypad.
> i dont observe
>   any change in interrupts count. when i do a cat /proc/interrupts.
>
> Im not sure if im missing something.
>
>
>   I also observe randomly (say 3 out of 10 times), my i2c bus times out
> and
> im unable to read or write TWL4030 registers. i get an return value of
> -110.
>
> i2c_omap i2c_omap.2: timeout waiting for bus ready
>
> Please Advice,
>
> Regards,
> sriram
> _______________________________________________
> Linux-omap-open-source mailing list
> Linux-omap-open-source@linux.omap.com
> http://linux.omap.com/mailman/listinfo/linux-omap-open-source
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
  2007-02-27  6:20   ` Ram
@ 2007-02-27 15:09     ` Syed Mohammed, Khasim
  2007-02-28  1:00     ` Syed Mohammed, Khasim
  1 sibling, 0 replies; 13+ messages in thread
From: Syed Mohammed, Khasim @ 2007-02-27 15:09 UTC (permalink / raw)
  To: Ram, Cantu Castillo, Arturo; +Cc: linux-omap-open-source

Ram,

Let me look into this (from today -seriously :)

The first thing we have to address here is I2c for 2430. What is
available in GIT now works for T2 read and write. But this might not be
sufficient to clear/enable T2 registers for an interrupt. 

I will update you my findings later. Sorry for the delay.

Regards,
Khasim

>-----Original Message-----
>From: linux-omap-open-source-bounces@linux.omap.com [mailto:linux-omap-
>open-source-bounces@linux.omap.com] On Behalf Of Ram
>Sent: Tuesday, February 27, 2007 12:20 AM
>To: Cantu Castillo, Arturo
>Cc: linux-omap-open-source@linux.omap.com
>Subject: Re: I2C TWL4030 Keypad
>
>Hi,
>Keypad driver seems to be okay.
>I tried with RTC driver too. I still get the same error.
>
>I feel it is something to do with twl_core driver - the way interrupts
>are handled.
>
>
>i will look into what you have mentioned.
>
>Regards,
>sriram
>
>
>
>
>
>On 2/26/07, Cantu Castillo, Arturo <x0052731@ti.com> wrote:
>> Hi Ram,
>> It might be happening that when the driver is initialized the i2c
>> writing to TWL4030_MODULE_KEYPAD register that is done to enable
>> interrupts is failing (since you are saying that i2c
readings/writings
>> are failing randomly it is likely), you can try to read this register
>> and find out if the interrupts are enable.
>>
>> Also you can check that all the registers that are set in the
>> initialization routine have the proper value, if i2c writings are
>> failing randomly, some of them might not be initialized correctly.
>>
>> Regards,
>> Arturo
>> -----Original Message-----
>> From: linux-omap-open-source-bounces+x0052731=ti.com@linux.omap.com
>>
[mailto:linux-omap-open-source-bounces+x0052731=ti.com@linux.omap.com]
>> On Behalf Of Ram
>> Sent: Friday, February 16, 2007 5:25 AM
>> To: linux-omap-open-source@linux.omap.com
>> Subject: I2C TWL4030 Keypad
>>
>> Hi,
>>    Im using omap2430 SDP.
>>    Im trying to get TWL4030 Keypad to work on 2.6.19. Im using 2.6.14
>> for
>> omap2430 as a reference.
>>
>>    Im using the following files:
>>         1) i2c-omap.c which exists on 2.6.19
>>         2) twl4030_core.c
>>         3) twl4030_gpio.c (taken from 2.6.14)
>>         4) omap-twl4030keypad.c (taken from 2.6.14)
>>
>>    made  changes  to support generic interrupts in 2.6.19.
>>
>>    Im able to read the value of registers using  twl4030_kpread_u8
>>     TWL4030_MODULE_KEYPAD, REG_KEYP_EDR, REG_LK_PTV_REG,
>> REG_KEY_DEB_REG,
>> REG_LONG_KEY_REG1, REG_KEYP_SIH_CTRL, REG_KEYP_IMR1
>>
>>   However, im not able to recieve interrupts. upon pressing keys in
>> keypad.
>> i dont observe
>>   any change in interrupts count. when i do a cat /proc/interrupts.
>>
>> Im not sure if im missing something.
>>
>>
>>   I also observe randomly (say 3 out of 10 times), my i2c bus times
out
>> and
>> im unable to read or write TWL4030 registers. i get an return value
of
>> -110.
>>
>> i2c_omap i2c_omap.2: timeout waiting for bus ready
>>
>> Please Advice,
>>
>> Regards,
>> sriram
>> _______________________________________________
>> Linux-omap-open-source mailing list
>> Linux-omap-open-source@linux.omap.com
>> http://linux.omap.com/mailman/listinfo/linux-omap-open-source
>>
>_______________________________________________
>Linux-omap-open-source mailing list
>Linux-omap-open-source@linux.omap.com
>http://linux.omap.com/mailman/listinfo/linux-omap-open-source

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
  2007-02-27  6:20   ` Ram
  2007-02-27 15:09     ` Syed Mohammed, Khasim
@ 2007-02-28  1:00     ` Syed Mohammed, Khasim
  1 sibling, 0 replies; 13+ messages in thread
From: Syed Mohammed, Khasim @ 2007-02-28  1:00 UTC (permalink / raw)
  To: Ram, Cantu Castillo, Arturo; +Cc: linux-omap-open-source

[-- Attachment #1: Type: text/plain, Size: 469 bytes --]

Hi Ram,

As I had communicated before, the issue is due to incomplete I2C driver.
We were not operating at High speed and T2 needs high speed to work
efficiently. Apart from high speed we need FIFO handling + errata fixes
etc.

For now, I have ported high speed I2C driver (from linux.omap.com) to
GIT and Keypad works fine. I will send few patches for your reference.

We have to find an optimal way to get this (I2C) code into tree ...

Regards,
Khasim

[-- Attachment #2: i2c_chips.diff --]
[-- Type: application/octet-stream, Size: 80852 bytes --]

diff -purN linux-omap/drivers/i2c/chips/Kconfig lin_for_twl/drivers/i2c/chips/Kconfig
--- linux-omap/drivers/i2c/chips/Kconfig	2007-01-08 18:56:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/Kconfig	2007-02-26 21:31:32.000000000 -0600
@@ -127,6 +127,10 @@ config TWL4030_CORE
 	help
 	  Say yes here if you have TWL4030 chip on your board
 
+config TWL4030_GPIO
+        bool "TWL4030 GPIO Driver"
+        depends on TWL4030_CORE
+
 config SENSORS_M41T00
 	tristate "ST M41T00 RTC chip"
 	depends on I2C && PPC32
diff -purN linux-omap/drivers/i2c/chips/Makefile lin_for_twl/drivers/i2c/chips/Makefile
--- linux-omap/drivers/i2c/chips/Makefile	2007-01-08 18:56:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/Makefile	2007-02-26 21:32:56.000000000 -0600
@@ -16,6 +16,7 @@ obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv
 obj-$(CONFIG_GPIOEXPANDER_OMAP)	+= gpio_expander_omap.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 obj-$(CONFIG_TWL4030_CORE)      += twl4030_core.o
+obj-$(CONFIG_TWL4030_GPIO)      += twl4030_gpio.o
 obj-$(CONFIG_RTC_X1205_I2C)	+= x1205.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
diff -purN linux-omap/drivers/i2c/chips/twl4030_core.c lin_for_twl/drivers/i2c/chips/twl4030_core.c
--- linux-omap/drivers/i2c/chips/twl4030_core.c	2007-02-16 09:43:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/twl4030_core.c	2007-02-27 18:17:51.000000000 -0600
@@ -1,5 +1,5 @@
 /*
- * twl4030_core.c - driver for TWL4030 PM and audio CODEC device
+ * linux/drivers/i2c/chips/twl4030_core.c
  *
  * Copyright (C) 2005-2006 Texas Instruments, Inc.
  *
@@ -9,9 +9,6 @@
  * Based on tlv320aic23.c:
  * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
  *
- * Code cleanup and modifications to IRQ handler.
- * by syed khasim <x0khasim@ti.com>
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -28,6 +25,7 @@
  *
  */
 
+/*** Includes */
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
@@ -36,100 +34,443 @@
 #include <linux/random.h>
 #include <linux/syscalls.h>
 #include <linux/kthread.h>
-
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/device.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
 
 #include <asm/arch/twl4030.h>
+#include <asm/mach/irq.h>
 #include <asm/arch/gpio.h>
+//#include <asm/arch/platform.h>
 #include <asm/arch/mux.h>
 
+#include <linux/device.h>
+
+#define CONFIG_TWL4030_IRQ_PRIO 26
+
+/* Triton Core internal information (END) */
+
+/* Few power values */
+#define R_CFG_BOOT                      0x05
+#define R_PROTECT_KEY                   0x0E
+
+/* access control */
+#define KEY_UNLOCK1                     0xce
+#define KEY_UNLOCK2                     0xec
+#define KEY_LOCK                        0x00
+
+#define HFCLK_FREQ_19p2_MHZ             (1 << 0)
+#define HFCLK_FREQ_26_MHZ               (2 << 0)
+#define HFCLK_FREQ_38p4_MHZ             (3 << 0)
+#define HIGH_PERF_SQ                    (1 << 3)
+
 /**** Macro Definitions */
-#define TWL_CLIENT_STRING		"TWL4030-ID"
-#define TWL_CLIENT_USED			1
-#define TWL_CLIENT_FREE			0
+#define TWL_CLIENT_STRING                        "TWL4030-ID"
+#define TWL_CLIENT_USED                          1
+#define TWL_CLIENT_FREE                          0
 
 /* IRQ Flags */
-#define FREE				0
-#define USED				1
+#define FREE                                     0
+#define USED                                     1
 
 /** Primary Interrupt Handler on TWL4030 Registers */
 
 /**** Register Definitions */
 
-#define REG_PIH_ISR_P1			(0x1)
-#define REG_PIH_ISR_P2			(0x2)
-#define REG_PIH_SIR			(0x3)
+#define REG_PIH_ISR_P1                           (0x1)
+#define REG_PIH_ISR_P2                           (0x2)
+#define REG_PIH_SIR                              (0x3)
+
+/**** BitField Definitions */
+
+/* PIH_ISR_P1 Fields */
+#define BIT_PIH_ISR_P1_PIH_ISR0                  (0x000)
+#define BIT_PIH_ISR_P1_PIH_ISR0_M                (0x00000001)
+#define BIT_PIH_ISR_P1_PIH_ISR1                  (0x001)
+#define BIT_PIH_ISR_P1_PIH_ISR1_M                (0x00000002)
+#define BIT_PIH_ISR_P1_PIH_ISR2                  (0x002)
+#define BIT_PIH_ISR_P1_PIH_ISR2_M                (0x00000004)
+#define BIT_PIH_ISR_P1_PIH_ISR3                  (0x003)
+#define BIT_PIH_ISR_P1_PIH_ISR3_M                (0x00000008)
+#define BIT_PIH_ISR_P1_PIH_ISR4                  (0x004)
+#define BIT_PIH_ISR_P1_PIH_ISR4_M                (0x00000010)
+#define BIT_PIH_ISR_P1_PIH_ISR5                  (0x005)
+#define BIT_PIH_ISR_P1_PIH_ISR5_M                (0x00000020)
+#define BIT_PIH_ISR_P1_PIH_ISR6                  (0x006)
+#define BIT_PIH_ISR_P1_PIH_ISR6_M                (0x00000040)
+#define BIT_PIH_ISR_P1_PIH_ISR7                  (0x007)
+#define BIT_PIH_ISR_P1_PIH_ISR7_M                (0x00000080)
+/* PIH_ISR_P2 Fields */
+#define BIT_PIH_ISR_P2_PIH_ISR0                  (0x000)
+#define BIT_PIH_ISR_P2_PIH_ISR0_M                (0x00000001)
+#define BIT_PIH_ISR_P2_PIH_ISR1                  (0x001)
+#define BIT_PIH_ISR_P2_PIH_ISR1_M                (0x00000002)
+#define BIT_PIH_ISR_P2_PIH_ISR2                  (0x002)
+#define BIT_PIH_ISR_P2_PIH_ISR2_M                (0x00000004)
+#define BIT_PIH_ISR_P2_PIH_ISR3                  (0x003)
+#define BIT_PIH_ISR_P2_PIH_ISR3_M                (0x00000008)
+#define BIT_PIH_ISR_P2_PIH_ISR4                  (0x004)
+#define BIT_PIH_ISR_P2_PIH_ISR4_M                (0x00000010)
+#define BIT_PIH_ISR_P2_PIH_ISR5                  (0x005)
+#define BIT_PIH_ISR_P2_PIH_ISR5_M                (0x00000020)
+#define BIT_PIH_ISR_P2_PIH_ISR6                  (0x006)
+#define BIT_PIH_ISR_P2_PIH_ISR6_M                (0x00000040)
+#define BIT_PIH_ISR_P2_PIH_ISR7                  (0x007)
+#define BIT_PIH_ISR_P2_PIH_ISR7_M                (0x00000080)
+/* PIH_SIR Fields */
+#define BIT_PIH_SIR_PIH1SIR                      (0x000)
+#define BIT_PIH_SIR_PIH1SIR_M                    (0x00000001)
+#define BIT_PIH_SIR_PIH2SIR                      (0x001)
+#define BIT_PIH_SIR_PIH2SIR_M                    (0x00000002)
+#define BIT_PIH_SIR_PIH3SIR                      (0x002)
+#define BIT_PIH_SIR_PIH3SIR_M                    (0x00000004)
+#define BIT_PIH_SIR_PIH4SIR                      (0x003)
+#define BIT_PIH_SIR_PIH4SIR_M                    (0x00000008)
+#define BIT_PIH_SIR_PIH5SIR                      (0x004)
+#define BIT_PIH_SIR_PIH5SIR_M                    (0x00000010)
+#define BIT_PIH_SIR_PIH6SIR                      (0x005)
+#define BIT_PIH_SIR_PIH6SIR_M                    (0x00000020)
 
 /* Triton Core internal information (BEGIN) */
 
 /* Last - for index max*/
-#define TWL4030_MODULE_LAST		TWL4030_MODULE_SECURED_REG
+#define TWL4030_MODULE_LAST         TWL4030_MODULE_SECURED_REG
 
 /* Slave address */
-#define TWL4030_NUM_SLAVES		0x04
-#define TWL4030_SLAVENUM_NUM0		0x00
-#define TWL4030_SLAVENUM_NUM1		0x01
-#define TWL4030_SLAVENUM_NUM2		0x02
-#define TWL4030_SLAVENUM_NUM3		0x03
-#define TWL4030_SLAVEID_ID0		0x48
-#define TWL4030_SLAVEID_ID1		0x49
-#define TWL4030_SLAVEID_ID2		0x4A
-#define TWL4030_SLAVEID_ID3		0x4B
+#define TWL4030_NUM_SLAVES          0x04
+#define TWL4030_SLAVENUM_NUM0       0x00
+#define TWL4030_SLAVENUM_NUM1       0x01
+#define TWL4030_SLAVENUM_NUM2       0x02
+#define TWL4030_SLAVENUM_NUM3       0x03
+#define TWL4030_SLAVEID_ID0         0x48
+#define TWL4030_SLAVEID_ID1         0x49
+#define TWL4030_SLAVEID_ID2         0x4A
+#define TWL4030_SLAVEID_ID3         0x4B
 
 /* Base Address defns */
 /* USB ID */
-#define TWL4030_BASEADD_USB		0x0000
+#define TWL4030_BASEADD_USB         0x0000
 /* AUD ID */
-#define TWL4030_BASEADD_AUDIO_VOICE	0x0000
-#define TWL4030_BASEADD_GPIO		0x0098
+#define TWL4030_BASEADD_AUDIO_VOICE 0x0000
+
+/* M1 companion board GPIO base address */
+#define TWL4030_BASEADD_GPIO        0x0098
 
-#define TWL4030_BASEADD_INTBR		0x0085
-#define TWL4030_BASEADD_PIH		0x0080
-#define TWL4030_BASEADD_TEST		0x004C
+#define TWL4030_BASEADD_INTBR       0x0085
+#define TWL4030_BASEADD_PIH         0x0080
+#define TWL4030_BASEADD_TEST        0x004C
 /* AUX ID */
-#define TWL4030_BASEADD_INTERRUPTS	0x00B9
-#define TWL4030_BASEADD_LED		0x00EE
-#define TWL4030_BASEADD_MADC		0x0000
-#define TWL4030_BASEADD_MAIN_CHARGE	0x0074
-#define TWL4030_BASEADD_PRECHARGE	0x00AA
-#define TWL4030_BASEADD_PWM0		0x00F8
-#define TWL4030_BASEADD_PWM1		0x00FB
-#define TWL4030_BASEADD_PWMA		0x00EF
-#define TWL4030_BASEADD_PWMB		0x00F1
-#define TWL4030_BASEADD_KEYPAD		0x00D2
+#define TWL4030_BASEADD_INTERRUPTS  0x00B9
+#define TWL4030_BASEADD_LED         0x00EE
+#define TWL4030_BASEADD_MADC        0x0000
+#define TWL4030_BASEADD_MAIN_CHARGE 0x0074
+#define TWL4030_BASEADD_PRECHARGE   0x00AA
+#define TWL4030_BASEADD_PWM0        0x00F8
+#define TWL4030_BASEADD_PWM1        0x00FB
+#define TWL4030_BASEADD_PWMA        0x00EF
+#define TWL4030_BASEADD_PWMB        0x00F1
+#define TWL4030_BASEADD_KEYPAD      0x00D2
 /* POWER ID */
-#define TWL4030_BASEADD_BACKUP		0x0014
-#define TWL4030_BASEADD_INT		0x002E
-#define TWL4030_BASEADD_PM_MASTER	0x0036
-#define TWL4030_BASEADD_PM_RECIEVER	0x005B
-#define TWL4030_BASEADD_RTC		0x001C
-#define TWL4030_BASEADD_SECURED_REG	0x0000
+#define TWL4030_BASEADD_BACKUP      0x0014
+#define TWL4030_BASEADD_INT         0x002E
+#define TWL4030_BASEADD_PM_MASTER   0x0036
+#define TWL4030_BASEADD_PM_RECIEVER 0x005B
+#define TWL4030_BASEADD_RTC         0x001C
+#define TWL4030_BASEADD_SECURED_REG 0x0000
 
 /* Triton Core internal information (END) */
 
-/* Few power values */
-#define R_CFG_BOOT			0x05
-#define R_PROTECT_KEY			0x0E
+/* Pull out the board specific config's defines */
+#define CONFIG_I2C_TWL4030_ID0 1
+#define CONFIG_I2C_TWL4030_ID1 1
+#define CONFIG_I2C_TWL4030_ID2 1
+#define CONFIG_I2C_TWL4030_ID3 1
 
-/* access control */
-#define KEY_UNLOCK1			0xce
-#define KEY_UNLOCK2			0xec
-#define KEY_LOCK			0x00
-
-#define HFCLK_FREQ_19p2_MHZ		(1 << 0)
-#define HFCLK_FREQ_26_MHZ		(2 << 0)
-#define HFCLK_FREQ_38p4_MHZ		(3 << 0)
-#define HIGH_PERF_SQ			(1 << 3)
 
-/* on I2C-1 for 2430SDP */
-#define CONFIG_I2C_TWL4030_ID		1
+/* ----- debug defines ----------------------------------------------- */
+/* Debug - four macros:
+ * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level
+ */
+
+/* Log level standard used here:
+ * Log level 3 all messages
+ * Log level 2 all entry-exit points
+ * Log level 1 major messages
+ * Log level 0 no messages
+ */
+#define TWL4030_LOG_LEVEL 0
+/* detail - 0 - no detail
+ *          1 - function name
+ *          2 - function name, line number
+ * prefix is added to every log message
+ */
+#define TWL4030_DETAIL    0
+
+/* kernel log level*/
+//#define TWL4030_K_LOG_LEVEL KERN_DEBUG
+#define TWL4030_K_LOG_LEVEL
+
+#if ( TWL4030_DETAIL > 0 )
+#define DL1 "%s "
+#define DR1 ,__FUNCTION__
+#else
+#define DL1
+#define DR1
+#endif
+#if ( TWL4030_DETAIL > 1 )
+#define DL2 "[%d] "
+#define DR2 ,__LINE__
+#else
+#define DL2
+#define DR2
+#endif
+
+#define D(format,...)\
+	printk(TWL4030_K_LOG_LEVEL DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)
+
+#if (TWL4030_LOG_LEVEL >= 1)
+#define D1(ARGS...) D(ARGS)
+#else
+#define D1(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 2)
+#define D2(ARGS...) D(ARGS)
+#else
+#define D2(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 3)
+#define D3(ARGS...) D(ARGS)
+#else
+#define D3(ARGS...)
+#endif
+
+#if (TWL4030_LOG_LEVEL >= 2)
+#define FN_IN printk("%s Entry\n",__FUNCTION__);
+#define FN_OUT(ARG) printk("%s[%d]:Exit(%d)\n",__FUNCTION__,__LINE__,ARG);
+#else
+#define FN_IN
+#define FN_OUT(ARG)
+#endif
+
+/* Sys FS Helper functions and macros */
+#ifdef CONFIG_I2C_TWL4030_DBG_SYSFS
+/* Device Information- dummy */
+static struct platform_device twl4030_debug_dev = {
+	.name = TWL_CLIENT_STRING,
+	.id = 0,
+};
+
+/* 255 Max bytes in a field register */
+#define READ_REG_SIZE 255
+/* Sys FS support */
+static ssize_t show_mod(int mod, struct device *dev, char *buf)
+{
+	int j;
+	unsigned char temp_buffer[READ_REG_SIZE + 1];
+	struct timeval stv, stv1, stv2;
+	int timespent1, timespent2;
+	char *sval = buf;
+	/* Read from I2c first 255 bytes (the max we can write in the reg) */
+	do_gettimeofday(&stv);
+	if ((j = twl4030_i2c_read(mod, temp_buffer, 0x0, READ_REG_SIZE)) < 0) {
+		printk(KERN_ERR
+		       "unable to read %d bytes returned %d in module %d\n",
+		       READ_REG_SIZE, j, mod);
+		return j;
+	}
+	do_gettimeofday(&stv1);
+	/* do a read of the last 256th byte */
+	if ((j =
+	     twl4030_i2c_read_u8(mod, temp_buffer + READ_REG_SIZE,
+				 READ_REG_SIZE)) < 0) {
+		printk(KERN_ERR
+		       "unable to read %d reg returned %d in module %d\n",
+		       READ_REG_SIZE, j, mod);
+		return j;
+	}
+	do_gettimeofday(&stv2);
+	sval += sprintf(sval, "  | ");
+	for (j = 0; j < 0x10; j++) {
+		sval += sprintf(sval, "%02X ", j);
+	}
+	sval += sprintf(sval, "\n--+");
+
+	for (j = 0; j < 0x10; j++) {
+		sval += sprintf(sval, " --");
+	}
+
+	sval += sprintf(sval, "\n00| ");
+
+	for (j = 0; j <= READ_REG_SIZE; j++) {
+		sval += sprintf(sval, "%02X", temp_buffer[j]);
+		if (j < READ_REG_SIZE) {
+			sval +=
+			    ((j + 1) % 0x10) ? sprintf(sval,
+						       " ") : sprintf(sval,
+								      "\n%02X| ",
+								      j + 1);
+		}
+	}
+	timespent1 =
+	    (stv1.tv_sec - stv.tv_sec) * 1000000 + (stv1.tv_usec - stv.tv_usec);
+	timespent2 =
+	    (stv2.tv_sec - stv1.tv_sec) * 1000000 + (stv2.tv_usec -
+						     stv1.tv_usec);
+	sval +=
+	    sprintf(sval, "\nTime Taken(uSec): 255bytes=%d 1byte=%d\n", timespent1,
+		    timespent2);
+	sval += 1;
+	*sval = 0;
+	return sval - buf + 1;
+}
+
+/* MSB 8 bits are register address[module reg offset] and LSB 8 bits the value */
+static ssize_t
+set_mod(int mod, struct device *dev, const char *buf, size_t count)
+{
+	u16 val = (u16) simple_strtoul(buf, NULL, 16);
+	printk("Reg=0x%02x, val=0x%02x,mod=%d\n", (val & 0xFF00) >> 8,
+	       (val & 0x00FF), mod);
+	if (twl4030_i2c_write_u8(mod, (val & 0x00FF), (val & 0xFF00) >> 8) < 0) {
+		printk("FAILED\n");
+	} else {
+		printk("SUCCESS\n");
+	}
+	return count;
+}
+
+/* function generator macros */
+#define C_SHOW_MOD(MOD)\
+static ssize_t show_mod##MOD(struct device *dev, struct device_attribute *attr, char *buf)\
+{\
+	return show_mod(MOD, dev, buf);\
+}\
+
+#define C_SET_MOD(MOD)\
+static ssize_t set_mod##MOD(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)\
+{\
+	return set_mod(MOD, dev, buf, count);\
+}\
+
+#define MAK_MOD(MOD) \
+C_SET_MOD(MOD)\
+C_SHOW_MOD(MOD)\
+static DEVICE_ATTR(twl4030_mod##MOD, S_IWUSR | S_IRUGO, &show_mod##MOD, &set_mod##MOD);\
+
+#define TWL4030_SYS_DEV_CREAT(MOD)\
+		device_create_file(&twl4030_debug_dev.dev, &dev_attr_twl4030_mod##MOD);
+		
+#ifdef CONFIG_SOUND_SERVICES_ENABLE
+		
+ssize_t show_sound_services(struct device *dev, struct device_attribute *attr,	char *buf)
+{
+	int res;
+	char *sval = buf;
+	
+	res = twl4030_sndsrv_status();
+	if (res == 0){
+		sval += sprintf (sval, "Status OFF\n");
+	}
+	else if (res == 1){
+		sval += sprintf (sval, "Status ON\n");
+	}
+	else {
+		printk ( KERN_ERR "Sound Services: vibrator status read error !!!  \n");
+		return res;
+	}
+	
+	res = twl4030_sndsrv_get_dtcyl();
+	
+	switch (res){
+		case VIB_DUTY_CYCLE_100:
+			sval += sprintf (sval, "duty cycle = 100%% \n");
+			break;
+	
+		case VIB_DUTY_CYCLE_75:
+			sval += sprintf (sval, "duty cycle = 75%% \n");
+			break;
+		
+		case VIB_DUTY_CYCLE_50:
+			sval += sprintf (sval, "duty cycle = 50%% \n");
+			break;
+	
+		case VIB_DUTY_CYCLE_25:
+			sval += sprintf (sval, "duty cycle = 25%% \n");
+			break;
+	  
+		default:
+			printk ( KERN_ERR "Sound Services: vibrator duty cycle read error !!! \n");
+			return res;
+	}
+	
+	sval+= 1;
+	*sval=0;
+	
+	return sval - buf + 1;
+}
+
+static DEVICE_ATTR(sound_services, S_IRUGO, &show_sound_services, NULL);
+
+#define TWL4030_SYS_DEV_SOUND_SERVICES \
+	device_create_file(&twl4030_debug_dev.dev, &dev_attr_sound_services);\
+
+#else
+
+#define TWL4030_SYS_DEV_SOUND_SERVICES  
+
+#endif
 
+
+
+
+MAK_MOD(0)
+    MAK_MOD(1)
+    MAK_MOD(2)
+    MAK_MOD(3)
+    MAK_MOD(4)
+    MAK_MOD(5)
+    MAK_MOD(6)
+    MAK_MOD(7)
+    MAK_MOD(8)
+    MAK_MOD(9)
+    MAK_MOD(10)
+    MAK_MOD(11)
+    MAK_MOD(12)
+    MAK_MOD(13)
+    MAK_MOD(14)
+    MAK_MOD(15)
+    MAK_MOD(16)
+    MAK_MOD(17)
+    MAK_MOD(18)
+    MAK_MOD(19)
+    MAK_MOD(20)
+    MAK_MOD(21)
+#define TWL_SYS_DEV()\
+	TWL4030_SYS_DEV_CREAT(0)\
+	TWL4030_SYS_DEV_CREAT(1)\
+	TWL4030_SYS_DEV_CREAT(2)\
+	TWL4030_SYS_DEV_CREAT(3)\
+	TWL4030_SYS_DEV_CREAT(4)\
+	TWL4030_SYS_DEV_CREAT(5)\
+	TWL4030_SYS_DEV_CREAT(6)\
+	TWL4030_SYS_DEV_CREAT(7)\
+	TWL4030_SYS_DEV_CREAT(8)\
+	TWL4030_SYS_DEV_CREAT(9)\
+	TWL4030_SYS_DEV_CREAT(10)\
+	TWL4030_SYS_DEV_CREAT(11)\
+	TWL4030_SYS_DEV_CREAT(12)\
+	TWL4030_SYS_DEV_CREAT(13)\
+	TWL4030_SYS_DEV_CREAT(14)\
+	TWL4030_SYS_DEV_CREAT(15)\
+	TWL4030_SYS_DEV_CREAT(16)\
+	TWL4030_SYS_DEV_CREAT(17)\
+	TWL4030_SYS_DEV_CREAT(18)\
+	TWL4030_SYS_DEV_CREAT(19)\
+	TWL4030_SYS_DEV_CREAT(20)\
+	TWL4030_SYS_DEV_CREAT(21)\
+	TWL4030_SYS_DEV_SOUND_SERVICES\
+
+#endif
 /**** Helper functions */
 static int
 twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid);
@@ -150,12 +491,8 @@ struct twl4030_client {
 	const unsigned char address;
 	const char adapter_index;
 	unsigned char inuse;
-
-	/* max numb of i2c_msg required is for read =2 */
-	struct i2c_msg xfer_msg[2];
-
-	/* To lock access to xfer_msg */
-	struct semaphore xfer_lock;
+	struct i2c_msg xfer_msg[2];	/* max numb of i2c_msg required is for read =2 */
+	struct semaphore xfer_lock;	/* To lock access to xfer_msg */
 };
 
 /* Module Mapping */
@@ -166,84 +503,119 @@ struct twl4030mapping {
 
 /* mapping the module id to slave id and base address */
 static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
-	{ TWL4030_SLAVENUM_NUM0, TWL4030_BASEADD_USB },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_AUDIO_VOICE },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_GPIO },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_INTBR },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_PIH },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_TEST },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_KEYPAD },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MADC },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_INTERRUPTS },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_LED },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MAIN_CHARGE },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PRECHARGE },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM0 },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM1 },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMA },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMB },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_BACKUP },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_INT },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_MASTER },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_RECIEVER },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_RTC },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_SECURED_REG },
+	{TWL4030_SLAVENUM_NUM0,
+	 TWL4030_BASEADD_USB /* TWL4030_MODULE_USB        */ },
+
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_AUDIO_VOICE /* TWL4030_MODULE_AUDIO_VOICE */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_GPIO /* TWL4030_MODULE_GPIO       */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_INTBR /* TWL4030_MODULE_INTBR      */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_PIH /* TWL4030_MODULE_PIH        */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_TEST /* TWL4030_MODULE_TEST       */ },
+
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_KEYPAD /* TWL4030_MODULE_KEYPAD     */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_MADC /* TWL4030_MODULE_MADC       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_INTERRUPTS /* TWL4030_MODULE_INTERRUPTS */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_LED /* TWL4030_MODULE_LED        */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_MAIN_CHARGE /* TWL4030_MODULE_MAIN_CHARGE */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PRECHARGE /* TWL4030_MODULE_PRECHARGE  */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWM0 /* TWL4030_MODULE_PWM0       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWM1 /* TWL4030_MODULE_PWM1       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWMA /* TWL4030_MODULE_PWMA       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWMB /* TWL4030_MODULE_PWMB       */ },
+
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_BACKUP /* TWL4030_MODULE_BACKUP     */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_INT /* TWL4030_MODULE_INT        */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_PM_MASTER /* TWL4030_MODULE_PM_MASTER  */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_PM_RECIEVER /* TWL4030_MODULE_PM_RECIEVER */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_RTC /* TWL4030_MODULE_RTC        */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_SECURED_REG /* TWL4030_MODULE_SECURED_REG */ },
 };
 
 static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES] = {
 	{
-		.address	= TWL4030_SLAVEID_ID0,
-		.client_name	= TWL_CLIENT_STRING "0",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID0,
+	 .client_name = TWL_CLIENT_STRING "0",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID0,},
 	{
-		.address	= TWL4030_SLAVEID_ID1,
-		.client_name	= TWL_CLIENT_STRING "1",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID1,
+	 .client_name = TWL_CLIENT_STRING "1",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID1,},
 	{
-		.address	= TWL4030_SLAVEID_ID2,
-		.client_name	= TWL_CLIENT_STRING "2",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID2,
+	 .client_name = TWL_CLIENT_STRING "2",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID2,},
 	{
-		.address	= TWL4030_SLAVEID_ID3,
-		.client_name	= TWL_CLIENT_STRING "3",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID3,
+	 .client_name = TWL_CLIENT_STRING "3",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID3,},
 };
 
 /* One Client Driver , 4 Clients */
 static struct i2c_driver twl4030_driver = {
-	.driver.name	= "TWL4030 I2C",
-	.attach_adapter	= twl4030_attach_adapter,
-	.detach_client	= twl4030_detach_client,
+	.driver.name = "TWL4030 I2C",
+	.attach_adapter = twl4030_attach_adapter,
+	.detach_client = twl4030_detach_client,
 };
 
-/*
- * TWL4030 doesn't have PIH mask, hence dummy function for mask
+/* unique client id */
+static unsigned int twl4030_id;
+
+/* TWL4030 doesn't have PIH mask,
+ * hence dummy function for mask
  * and unmask.
  */
 
-static void twl4030_i2c_ackirq(unsigned int irq) {}
-static void twl4030_i2c_disableint(unsigned int irq) {}
-static void twl4030_i2c_enableint(unsigned int irq) {}
+static void twl4030_i2c_ackirq(unsigned int irq){
+	FN_IN;
+	FN_OUT(0);
+}	
+
+static void twl4030_i2c_disableint(unsigned int irq){
+	FN_IN;
+	FN_OUT(0);
+}
 
+static void twl4030_i2c_enableint(unsigned int irq){
+	FN_IN;
+	FN_OUT(0);
+}	
+	
 /* information for processing in the Work Item */
 static struct irq_chip twl4030_irq_chip = {
-	.ack	= twl4030_i2c_ackirq,
-	.mask	= twl4030_i2c_disableint,
-	.unmask	= twl4030_i2c_enableint,
+	.ack = twl4030_i2c_ackirq,
+	.mask = twl4030_i2c_disableint,
+	.unmask = twl4030_i2c_enableint,
 };
 
-/* Global Functions */
-/*
- * @brief twl4030_i2c_write - Writes a n bit register in TWL4030
+/**** Global Functions */
+/**
+ * @brief twl4030_i2c_write - Writes a n bit register in  TWL4030
  *
  * @param mod_no - module number
  * @param *value - an array of num_bytes+1 containing data to write
  * IMPORTANT - Allocate value num_bytes+1 and valid data starts at
- *		 Offset 1.
+ *             Offset 1.
  * @param reg - register address (just offset will do)
  * @param num_bytes - number of bytes to transfer
  *
@@ -255,9 +627,10 @@ int twl4030_i2c_write(u8 mod_no, u8 * va
 	int sid;
 	struct twl4030_client *client;
 	struct i2c_msg *msg;
-
+	FN_IN;
 	if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 		printk(KERN_ERR "TWL4030: Invalid module Number\n");
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	sid = twl4030_map[mod_no].sid;
@@ -265,33 +638,38 @@ int twl4030_i2c_write(u8 mod_no, u8 * va
 
 	if (unlikely(client->inuse != TWL_CLIENT_USED)) {
 		printk(KERN_ERR
-			"TWL4030: I2C Client[%d] is not initialized[%d]\n",
-			sid, __LINE__);
+		       "TWL4030: I2C Client[%d] is not initialized[%d]\n", sid,
+		       __LINE__);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	down(&(client->xfer_lock));
-	/*
-	 * [MSG1]: fill the register address data
-	 * fill the data Tx buffer
+	/* [MSG1]: fill the register address data 
+	 * fill the data Tx buffer 
 	 */
 	msg = &(client->xfer_msg[0]);
 	msg->addr = client->address;
-	msg->len = num_bytes + 1;
-	msg->flags = 0;
+	if ((client->client.flags & I2C_M_HS) == I2C_M_HS)
+		/* DO HS Mode transfer */
+		msg->flags = I2C_M_WR | I2C_M_HS;	/* write the register value */
+	else
+		msg->flags = I2C_M_WR;	/* write the register value */
+	
+	msg->len = num_bytes + 1;	/* only one value */
 	msg->buf = value;
 	/* over write the first byte of buffer with the register address */
 	*value = twl4030_map[mod_no].base + reg;
-	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 1);
+	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 1);	/* one message */
 	up(&(client->xfer_lock));
-
 	/* i2cTransfer returns num messages.translate it pls.. */
-	if (ret >= 0)
-		ret = 0;
+	if (ret>=0)
+		ret=0;
+	FN_OUT(ret);
 	return ret;
 }
 
 /**
- * @brief twl4030_i2c_read - Reads a n bit register in TWL4030
+ * @brief twl4030_i2c_read - Reads a n bit register in  TWL4030
  *
  * @param mod_no - module number
  * @param *value - an array of num_bytes containing data to be read
@@ -307,8 +685,10 @@ int twl4030_i2c_read(u8 mod_no, u8 * val
 	int sid;
 	struct twl4030_client *client;
 	struct i2c_msg *msg;
+	FN_IN;
 	if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 		printk(KERN_ERR "TWL4030: Invalid module Number\n");
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	sid = twl4030_map[mod_no].sid;
@@ -316,34 +696,43 @@ int twl4030_i2c_read(u8 mod_no, u8 * val
 
 	if (unlikely(client->inuse != TWL_CLIENT_USED)) {
 		printk(KERN_ERR
-			"TWL4030: I2C Client[%d] is not initialized[%d]\n",
-			sid, __LINE__);
+		       "TWL4030: I2C Client[%d] is not initialized[%d]\n", sid,
+		       __LINE__);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	down(&(client->xfer_lock));
 	/* [MSG1] fill the register address data */
 	msg = &(client->xfer_msg[0]);
 	msg->addr = client->address;
-	msg->len = 1;
+	if ((client->client.flags & I2C_M_HS) == I2C_M_HS)
+		msg->flags = I2C_M_WR | I2C_M_HS;	/* Read the register value in HS mode */
+	else
+		msg->flags = I2C_M_WR;	/* Read the register value */
+
+	msg->len = 1;		/* only one value */
 	val = twl4030_map[mod_no].base + reg;
 	msg->buf = &val;
 	/* [MSG2] fill the data rx buffer */
 	msg = &(client->xfer_msg[1]);
 	msg->addr = client->address;
-	msg->flags = I2C_M_RD;	/* Read the register value */
+	if ((client->client.flags & I2C_M_HS) == I2C_M_HS)
+		msg->flags = I2C_M_RD | I2C_M_HS;	/* Read the register value in HS mode */
+	else
+		msg->flags = I2C_M_RD;	/* Read the register value */
 	msg->len = num_bytes;	/* only n bytes */
 	msg->buf = value;
-	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 2);
+	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 2);	/* two messages */
 	up(&(client->xfer_lock));
-
 	/* i2cTransfer returns num messages.translate it pls.. */
-	if (ret >= 0)
-		ret = 0;
+	if (ret>=0)
+		ret=0;
+	FN_OUT(ret);
 	return ret;
 }
 
 /**
- * @brief twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030
+ * @brief twl4030_i2c_write_u8 - Writes a 8 bit register in  TWL4030
  *
  * @param mod_no - module number
  * @param value - the value to be written 8 bit
@@ -355,10 +744,12 @@ int twl4030_i2c_write_u8(u8 mod_no, u8 v
 {
 	int ret;
 	/* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
-	u8 temp_buffer[2] = { 0 };
+	u8 temp_buffer[2]={0};
+	FN_IN;
 	/* offset 1 contains the data */
-	temp_buffer[1] = value;
-	ret = twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
+	temp_buffer[1]=value;
+	ret = twl4030_i2c_write(mod_no,temp_buffer,reg,1) ;
+	FN_OUT(ret);
 	return ret;
 }
 
@@ -373,15 +764,17 @@ int twl4030_i2c_write_u8(u8 mod_no, u8 v
  */
 int twl4030_i2c_read_u8(u8 mod_no, u8 * value, u8 reg)
 {
-	int ret = 0;
-	ret = twl4030_i2c_read(mod_no, value, reg, 1);
+	int ret=0;
+	FN_IN;
+	ret = twl4030_i2c_read(mod_no,value,reg,1);
+	FN_OUT(ret);
 	return ret;
 }
 
 /**** Helper Functions */
 
 /*
- * do_twl4030_module_irq() is the desc->handle method for each of the twl4030
+ * do_twl4030_module_irq() is the desc->handle method for each of the twl4030 
  * module interrupts.  It executes in kernel thread context.
  * On entry, cpu interrupts are disabled.
  */
@@ -390,13 +783,10 @@ static void do_twl4030_module_irq(unsign
 	struct irqaction *action;
 	const unsigned int cpu = smp_processor_id();
 
-	/*
-	 * Earlier this was desc->triggered = 1;
-	 */
-	desc->status = IRQ_INPROGRESS;
+	desc->status |= IRQ_LEVEL;
 
 	/*
-	 * The desc->handle method would normally call the desc->chip->ack
+	 * The desc->handle method would normally call the desc->chip->ack 
 	 * method here, but we won't bother since our ack method is NULL.
 	 */
 
@@ -409,71 +799,87 @@ static void do_twl4030_module_irq(unsign
 			int status = 0;
 			int retval = 0;
 
+			//desc->status |= IRQ_INPROGRESS;
+
 			local_irq_enable();
 
 			do {
-				/* Call the ISR with cpu interrupts enabled */
+				/* Call the ISR with cpu interrupts enabled. */
 				ret = action->handler(irq, action->dev_id);
 				if (ret == IRQ_HANDLED)
 					status |= action->flags;
 				retval |= ret;
 				action = action->next;
 			} while (action);
-
-			if (status & IRQF_SAMPLE_RANDOM)
+		
+			if (status & SA_SAMPLE_RANDOM)
 				add_interrupt_randomness(irq);
-
+	
 			local_irq_disable();
 
-			if (retval != IRQ_HANDLED)
+			if (retval != IRQ_HANDLED) {
 				printk(KERN_ERR "ISR for TWL4030 module"
-					" irq %d can't handle interrupt\n", irq);
+					" irq %d can't handle interrupt\n", 
+					irq);
+			}
 
 			/*
-			 * Here is where we should call the unmask method, but
+			 * Here is where we should call the unmask method, but 
 			 * again we won't bother since it is NULL.
 			 */
-		} else
+		} else {
 			printk(KERN_CRIT "TWL4030 module irq %d has no ISR"
-					" but can't be masked!\n", irq);
-	} else
+				" but can't be masked!\n", irq);
+		}
+		//desc->status &= ~IRQ_INPROGRESS;
+	} else {
 		printk(KERN_CRIT "TWL4030 module irq %d is disabled but can't"
-				" be masked!\n", irq);
+			" be masked!\n", irq);
+	}
 }
 
 /*
- * twl4030_irq_thread() runs as a kernel thread.  It queries the twl4030
- * interrupt controller to see which modules are generating interrupt requests
+ * twl4030_irq_thread() runs as a kernel thread.  It queries the twl4030 
+ * interrupt controller to see which modules are generating interrupt requests 
  * and then calls the desc->handle method for each module requesting service.
  */
 static int twl4030_irq_thread(void *data)
 {
-	int irq = (int)data;
+	struct sched_param param;
+	int irq = (int) data;
 	irq_desc_t *desc = irq_desc + irq;
 	static unsigned i2c_errors;
 	const static unsigned max_i2c_errors = 100;
 
+	daemonize("twl4030-irq");
+
+	current->flags |= PF_NOFREEZE;
+
+	param.sched_priority = CONFIG_TWL4030_IRQ_PRIO;
+	sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
+
 	while (!kthread_should_stop()) {
 		int ret;
 		int module_irq;
 		u8 pih_isr;
 
-		ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
-					  REG_PIH_ISR_P1);
+		ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, 
+			REG_PIH_ISR_P1);
 		if (ret) {
 			printk(KERN_WARNING "I2C error %d while reading TWL4030"
-					" PIH ISR register.\n", ret);
+				" PIH ISR register.\n", ret);
 			if (++i2c_errors >= max_i2c_errors) {
 				printk(KERN_ERR "Maximum I2C error count"
-						" exceeded.  Terminating %s.\n",
-						__FUNCTION__);
+					" exceeded.  Terminating %s.\n", 
+					__FUNCTION__);
 				break;
 			}
 			continue;
 		}
 
-		for (module_irq = IH_TWL4030_BASE; 0 != pih_isr;
-			 pih_isr >>= 1, module_irq++) {
+		for (module_irq = IH_TWL4030_BASE; 0 != pih_isr; 
+			pih_isr >>= 1, module_irq++)
+		{
 			if (pih_isr & 0x1) {
 				irq_desc_t *d = irq_desc + module_irq;
 
@@ -487,6 +893,7 @@ static int twl4030_irq_thread(void *data
 
 		local_irq_disable();
 
+		//desc->status &= ~IRQ_INPROGRESS;
 		set_current_state(TASK_INTERRUPTIBLE);
 		desc->chip->unmask(irq);
 
@@ -501,21 +908,18 @@ static int twl4030_irq_thread(void *data
 /*
  * do_twl4030_irq() is the desc->handle method for the twl4030 interrupt.
  * This is a chained interrupt, so there is no desc->action method for it.
- * Now we need to query the interrupt controller in the twl4030 to determine
- * which module is generating the interrupt request.  However, we can't do i2c
- * transactions in interrupt context, so we must defer that work to a kernel
- * thread.  All we do here is acknowledge and mask the interrupt and wakeup
+ * Now we need to query the interrupt controller in the twl4030 to determine 
+ * which module is generating the interrupt request.  However, we can't do i2c 
+ * transactions in interrupt context, so we must defer that work to a kernel 
+ * thread.  All we do here is acknowledge and mask the interrupt and wakeup 
  * the kernel thread.
  */
 static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc)
 {
 	const unsigned int cpu = smp_processor_id();
-	struct task_struct *thread = (struct task_struct *)desc->chip_data;
+	struct task_struct *thread = get_irq_data(irq);
 
-	/*
-	 * Earlier this was desc->triggered = 1;
-	 */
-	desc->status = IRQ_INPROGRESS;
+	desc->status |= IRQ_LEVEL;	
 
 	/*
 	 * Acknowledge, clear _AND_ disable the interrupt.
@@ -525,6 +929,8 @@ static void do_twl4030_irq(unsigned int 
 	if (!desc->depth) {
 		kstat_cpu(cpu).irqs[irq]++;
 
+		//desc->status |= IRQ_INPROGRESS;
+
 		if (thread && thread->state != TASK_RUNNING)
 			wake_up_process(thread);
 	}
@@ -535,46 +941,54 @@ static int twl4030_detect_client(struct 
 {
 	int err = 0;
 	struct twl4030_client *client;
+
+	FN_IN;
 	if (unlikely(sid >= TWL4030_NUM_SLAVES)) {
 		printk(KERN_ERR "TWL4030: sid[%d] >MOD_LAST[%d]\n", sid,
-				TWL4030_NUM_SLAVES);
+		       TWL4030_NUM_SLAVES);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 
 	/* Check basic functionality */
 	if (!(err = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA |
-						I2C_FUNC_SMBUS_WRITE_BYTE))) {
+					    I2C_FUNC_SMBUS_WRITE_BYTE))) {
 		printk(KERN_WARNING
-			"TWL4030: SlaveID=%d functionality check failed\n", sid);
+		       "TWL4030: SlaveID=%d functionality check failed\n", sid);
+		FN_OUT(err);
 		return err;
 	}
 	client = &(twl4030_modules[sid]);
 	if (unlikely(client->inuse)) {
 		printk(KERN_ERR "TWL4030: Client is already in Use.....\n");
 		printk("%s[ID=0x%x] NOT attached to I2c Adapter %s\n",
-			client->client_name, client->address, adapter->name);
+		       client->client_name, client->address, adapter->name);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 
 	memset(&(client->client), 0, sizeof(struct i2c_client));
 
-	client->client.addr	= client->address;
-	client->client.adapter	= adapter;
-	client->client.driver	= &twl4030_driver;
-
+	client->client.addr = client->address;
+	client->client.adapter = adapter;
+	client->client.driver = &twl4030_driver;
+	if ((adapter->flags & I2C_FUNC_HIGH_SPEED) == I2C_FUNC_HIGH_SPEED) {
+		client->client.flags = I2C_M_HS;	/* We are HS capable */
+	} 
 	memcpy(&(client->client.name), client->client_name,
-			sizeof(TWL_CLIENT_STRING) + 1);
-	printk("TWL4030: TRY attach Slave %s on Adapter %s[%d][%x]\n",
-				client->client_name, adapter->name, err, err);
-	if ((err = i2c_attach_client(&(client->client))))
+	       sizeof(TWL_CLIENT_STRING) + 1);
+//XXX	client->client.data = (void *)client;
+	if ((err = i2c_attach_client(&(client->client)))) {
 		printk(KERN_WARNING
-			"TWL4030: Couldn't attach Slave %s on Adapter "
-			"%s[%d][%x]\n",
-			client->client_name, adapter->name, err, err);
-	else {
+		       "TWL4030: Couldn't attach Slave %s on Adapter %s[%d][%x]\n",
+		       client->client_name, adapter->name, err, err);
+	} else {
+		D1( "TWL4030: %s[ID=0x%x] attached to I2c Adapter %s\n",
+		       client->client_name, client->address, adapter->name);
 		client->inuse = TWL_CLIENT_USED;
 		init_MUTEX(&client->xfer_lock);
 	}
+	FN_OUT(err);
 	return err;
 }
 
@@ -583,40 +997,43 @@ static int twl4030_attach_adapter(struct
 {
 	int i;
 	int ret = 0;
-	static int twl_i2c_adapter = 1;
+	static int twl_i2c_adapter = 0;
+	FN_IN;
 	for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
 		/* Check if I need to hook on to this adapter or not */
 		if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
-			if ((ret = twl4030_detect_client(adapter, i)))
+			if ((ret = twl4030_detect_client(adapter, i))) {
 				goto free_client;
+			}
 		}
 	}
 	twl_i2c_adapter++;
 
-	/*
-	 * Check if the PIH module is initialized, if yes, then init
+	/* Check if the PIH module is initialized, if yes, then init
 	 * the T2 Interrupt subsystem
 	 */
 	if ((twl4030_modules[twl4030_map[TWL4030_MODULE_PIH].sid].inuse ==
-		TWL_CLIENT_USED) && (twl_irq_used != USED)) {
+	     TWL_CLIENT_USED) && (twl_irq_used != USED)) {
 		twl_init_irq();
 		twl_irq_used = USED;
 	}
+	FN_OUT(0);
 	return 0;
-
-free_client:
+      free_client:
 	printk(KERN_ERR
-		"TWL4030: TWL_CLIENT(Idx=%d] REGISTRATION FAILED=%d[0x%x]\n", i,
-			ret, ret);
-
+	       "TWL4030: TWL_CLIENT(Idx=%d] REGISTRATION FAILED=%d[0x%x]\n", i,
+	       ret, ret);
 	/* ignore current slave..it never got registered */
 	i--;
 	while (i >= 0) {
 		/* now remove all those from the current adapter... */
-		if (twl4030_modules[i].adapter_index == twl_i2c_adapter)
-			(void)twl4030_detach_client(&(twl4030_modules[i].client));
+		if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
+			(void)
+			    twl4030_detach_client(&(twl4030_modules[i].client));
+		}
 		i--;
 	}
+	FN_OUT(ret);
 	return ret;
 }
 
@@ -624,71 +1041,83 @@ free_client:
 static int twl4030_detach_client(struct i2c_client *iclient)
 {
 	int err;
+	//XXX struct twl4030_client *client = (struct twl4030_client *)iclient->data;
+	FN_IN;
 	if ((err = i2c_detach_client(iclient))) {
 		printk(KERN_ERR
-				"TWL4030: Client deregistration failed, client not detached.\n");
+		       "TWL4030: Client deregistration failed, client not detached.\n");
+		FN_OUT(err);
 		return err;
 	}
+
+	/* Free 'em up */
+	//XXX client->inuse = TWL_CLIENT_FREE;
+	FN_OUT(0);
+
 	return 0;
 }
 
-struct task_struct *start_twl4030_irq_thread(int irq)
+struct task_struct *
+start_twl4030_irq_thread(int irq)
 {
 	struct task_struct *thread;
 
-	thread = kthread_create(twl4030_irq_thread, (void *)irq,
-				"twl4030 irq %d", irq);
-	if (!thread)
-		printk(KERN_ERR "%s: could not create twl4030 irq %d thread!\n",
+	thread = kthread_create(twl4030_irq_thread, (void *) irq, 
+			"twl4030-irq");
+	if (!thread) {
+		printk(KERN_ERR 
+			"%s: could not create twl4030 irq %d thread!\n", 
 			__FUNCTION__, irq);
+	}
 
 	return thread;
 }
 
 /*
- * These three functions should be part of Voltage frame work
- * added here to complete the functionality for now.
- */
+ *  * These three functions should be part of Voltage frame work
+ *   * added here to complete the functionality for now.
+ *    */
 static int protect_pm_master(void)
 {
-	int e = 0;
-	e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
-			R_PROTECT_KEY);
-	return e;
+        int e = 0;
+        e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
+		                        R_PROTECT_KEY);
+        return e;
 }
 
 static int unprotect_pm_master(void)
 {
-	int e = 0;
-	e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
-			R_PROTECT_KEY);
-	e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
-			R_PROTECT_KEY);
-	return e;
+        int e = 0;
+        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
+			                        R_PROTECT_KEY);
+        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
+			                        R_PROTECT_KEY);
+        return e;
 }
 
 int power_companion_init(void)
 {
-	struct clk *osc;
-	u32 rate, ctrl = HFCLK_FREQ_26_MHZ;
-	int e = 0;
+        struct clk *osc;
+        u32 rate, ctrl = HFCLK_FREQ_26_MHZ;
+        int e = 0;
 
 	osc = clk_get(NULL,"osc_ck");
-	rate = clk_get_rate(osc);
-	clk_put(osc);
+        rate = clk_get_rate(osc);
+        clk_put(osc);
 
 	switch(rate) {
-		case 19200000 : ctrl = HFCLK_FREQ_19p2_MHZ; break;
-		case 26000000 : ctrl = HFCLK_FREQ_26_MHZ; break;
-		case 38400000 : ctrl = HFCLK_FREQ_38p4_MHZ; break;
-	}
+                case 19200000 : ctrl = HFCLK_FREQ_19p2_MHZ; break;
+                case 26000000 : ctrl = HFCLK_FREQ_26_MHZ; break;
+                case 38400000 : ctrl = HFCLK_FREQ_38p4_MHZ; break;
+        }
 
 	ctrl |= HIGH_PERF_SQ;
-	e |= unprotect_pm_master();
-			/* effect->MADC+USB ck en */
-	e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
-	e |= protect_pm_master();
-
+       	e |= unprotect_pm_master();
+       
+	/* effect->MADC+USB ck en */
+        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
+        e |= protect_pm_master();
+	
 	return e;
 }
 
@@ -697,206 +1126,373 @@ static void twl_init_irq(void)
 	int i = 0;
 	int res = 0;
 	int line = 0;
-	/*
-	 * We end up with interrupts from other modules before
+	FN_IN;
+
+	/* We end up with interrupts from other modules before
 	 * they get a chance to handle them...
 	 */
-	/* PWR_ISR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
+	/* HACK ALERT - No Body to handle power ISR yet... */
+	/* POWER HACK (BEGIN) */
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);	/* PWR_ISR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_ISR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);	/* PWR_ISR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_IMR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);
+	/* MASK PWR -we will need this */
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);	/* PWR_IMR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_IMR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);	/* PWR_IMR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
 	/* Clear off any other pending interrupts on power */
-	/* PWR_ISR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);	/* PWR_ISR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_ISR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);	/* PWR_ISR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 	/* POWER HACK (END) */
 	/* Slave address 0x4A */
-
-	/* BCIIMR1_1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);	/* BCIIMR1_1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* BCIIMR1_2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);	/* BCIIMR1_2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* BCIIMR2_1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);	/* BCIIMR2_1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* BCIIMR2_2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);	/* BCIIMR2_2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
 	/* MAD C */
-	/* MADC_IMR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);	/* MADC_IMR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* MADC_IMR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);	/* MADC_IMR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
 	/* key Pad */
-	/* KEYPAD - IMR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x12));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x12));	/* KEYPAD - IMR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-	{
-		u8 clear;
-		/* Clear ISR */
-		twl4030_i2c_read_u8(TWL4030_MODULE_KEYPAD, &clear, 0x11);
-		twl4030_i2c_read_u8(TWL4030_MODULE_KEYPAD, &clear, 0x11);
-	}
-
-	/* KEYPAD - IMR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x14));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x14));	/* KEYPAD - IMR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
 	/* Slave address 0x49 */
-	/* GPIO_IMR1A */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1C));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1C));	/* GPIO_IMR1A */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
-	/* GPIO_IMR2A */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1D));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1D));	/* GPIO_IMR2A */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
-	/* GPIO_IMR3A */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1E));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1E));	/* GPIO_IMR3A */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* GPIO_IMR1B */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x22));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x22));	/* GPIO_IMR1B */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* GPIO_IMR2B */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x23));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x23));	/* GPIO_IMR2B */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* GPIO_IMR3B */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x24));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x24));	/* GPIO_IMR3B */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
 	/* install an irq handler for each of the PIH modules */
-	for (i = IH_TWL4030_BASE; i < IH_TWL4030_END; i++) {
-		set_irq_chip(i, &twl4030_irq_chip);
-		set_irq_handler(i, do_twl4030_module_irq);
-		set_irq_flags(i, IRQF_VALID);
+	for (i = IH_TWL4030_BASE; i <= IH_TWL4030_END; i++) {
+			set_irq_chip(i, &twl4030_irq_chip);
+			set_irq_handler(i, do_twl4030_module_irq);
+			set_irq_flags(i, IRQF_VALID);
 	}
 
 	/* install an irq handler to demultiplex the TWL4030 interrupt */
 	set_irq_data(TWL4030_IRQNUM, start_twl4030_irq_thread(TWL4030_IRQNUM));
-	set_irq_type(TWL4030_IRQNUM, IRQT_FALLING);
 	set_irq_chained_handler(TWL4030_IRQNUM, do_twl4030_irq);
+	
+	power_companion_init();  /* finish power and clock init */
 
-	res = power_companion_init();
-	if (res < 0) {
-		line = __LINE__;
-		goto irq_exit_path;
-	}
-
-irq_exit_path:
-	if (res)
+      irq_exit_path:
+	if (res) {
 		printk(KERN_ERR
-			"TWL4030: Unable to register interrupt "
-			"subsystem[%d][%d]\n", res, line);
+		       "TWL4030: Unable to register interrupt subsystem[%d][%d]\n",
+		       res, line);
+	}
+	FN_OUT(res);
 }
 
 static int __init twl4030_init(void)
 {
 	int res;
-	if ((res = i2c_register_driver(THIS_MODULE, &twl4030_driver))) {
-		printk(KERN_ERR "TWL4030: Driver registration failed \n");
+	FN_IN;
+
+	if ((res = i2c_add_driver(&twl4030_driver))) {
+		printk(KERN_ERR
+		       "TWL4030: Driver registration failed, module not inserted.\n");
+		FN_OUT(res);
 		return res;
 	}
+#if (TWL4030_LOG_LEVEL >= 1)
+	{
+		/* debug dump */
+		int mod = 0;
+		for (mod = 0; mod <= TWL4030_MODULE_LAST; mod++) {
+			u8 sid = twl4030_map[mod].sid;
+			u8 sadd = twl4030_modules[sid].address;
+			printk
+			    ("W8 - mod=%d[0x%x], sid=%d[0x%x] sad=%d[0x%x], modRegBaseAdd=%d[0x%x] \n",
+			     mod, mod, sid, sid, sadd, sadd,
+			     twl4030_map[mod].base, twl4030_map[mod].base);
+		}
+	}
+#endif
+
+#ifdef CONFIG_I2C_TWL4030_DBG_SYSFS
+	{
+		int ret = 0;
+		/* A dummy device */
+		ret = platform_device_register(&twl4030_debug_dev);
+		if (ret != 0) {
+			printk(KERN_ERR "Platform dev_register failed =%d\n", ret);
+			ret = -ENODEV;
+		} else {
+			TWL_SYS_DEV();
+		}
+	}
+#endif
+
+#ifdef CONFIG_SOUND_SERVICES_ENABLE
+
+	twl4030_sndsrv_set_dtcyl(CONFIG_SOUND_SERVICES_DUTY_CYL);
+
+#endif 
+
 	printk(KERN_INFO "TWL4030: Driver registration complete.\n");
+	FN_OUT(res);
 	return res;
 }
 
 static void __exit twl4030_exit(void)
 {
-	if (i2c_del_driver(&twl4030_driver))
+	FN_IN;
+	if (i2c_del_driver(&twl4030_driver)) {
 		printk(KERN_ERR
-			"TWL4030: Driver remove failed, module not removed\n");
+		       "TWL4030: Driver remove failed, module not removed.\n");
+	}
 	twl_irq_used = FREE;
+
+	FN_OUT(0);
+}
+
+#ifdef CONFIG_SOUND_SERVICES_ENABLE
+
+/* Sound Services API's functions*/
+/* this fuction handles the vibrator*/
+
+/*Turns the vibrator ON
+ * returns -EPERM if something fails
+ * or 0 if it succeeds */
+int twl4030_sndsrv_on(void)
+{
+	int res;
+	u8 RdReg;
+
+	/*TURNING ON VIBRATOR*/	
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}	
+	
+	RdReg |= 0x0C;	
+	
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	/*TURNING ON VAUX1*/
+	RdReg = VAUX1_ON;
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VAUX1_REMAP_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VAUX1_REMAP \n");
+		return -EPERM;
+	}
+		
+	return 0;
 }
 
+/*Turns the vibrator OFF 
+ * returns -EPERM if something fails
+ * or 0 if it succeeds */
+int twl4030_sndsrv_off(void)
+{
+	int res;
+	u8 RdReg;
+	
+	/*TURNING OFF VAUX1*/
+	RdReg = VAUX1_OFF;
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VAUX1_REMAP_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VAUX1_REMAP \n");
+		return -EPERM;
+	}
+		
+	/*TURNING OFF VIBRATOR*/	
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}	
+	
+	RdReg &= 0x03;	
+	
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	return 0;	
+}
+
+/*Returns the vibrator status
+ * 0 if vibrator is OFF
+ * 1 if it is ON
+ * or -EPERM if somethings fails*/
+int twl4030_sndsrv_status(void)
+{
+	int res;
+	u8 RdReg;
+	
+	/* VAUX1_DEV_GRP*/
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg , VAUX1_DEV_GRP_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VAUX1_DEV_GRP \n");
+		return -EPERM;
+	}
+	
+	RdReg &= 0x0F;
+	
+	if (RdReg > 0x0E || RdReg < 0x09){
+		return 0;
+	}
+	return 1;
+}
+
+/*Configures the vibrators duty cycle
+ * @param duty_cycle - the duty cycle for the sound services PWM,
+ * 					  interms of: 
+ * 								0x00 - 100 %
+ * 								0x01 - 75%
+ * 								0x02 - 50%
+ * 								0x03 - 25%
+ * 
+ * retunrs 0 if it success
+ * or -EPERM if somethings fails*/
+int twl4030_sndsrv_set_dtcyl(u8 duty_cycle)
+{
+	int res;
+	u8 RdReg;
+	
+	if (duty_cycle & 0xFC){
+		printk(KERN_ERR "SOUND SERVICES: Wrong value for Vibrator Duty cycle \n");
+		return -EPERM;
+	}
+	
+	/*Reading  VIBRATOR_CFG*/
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg , VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	RdReg &= 0xFC;
+	RdReg += duty_cycle;
+	
+	/*writing VIBRATOR_CFG*/	
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VIBRATOR_CFG \n");
+		return -EPERM;
+	}	
+	
+	return 0;
+}
+
+/*Returns the vibrator duty cycle
+ * returns -EPERM if something fails*/
+
+int twl4030_sndsrv_get_dtcyl(void)
+{
+	int res;
+	u8 RdReg;
+	
+	/*Reading  VIBRATOR_CFG*/
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg , VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	return (int)RdReg & 0x03;
+	
+}
+
+EXPORT_SYMBOL(twl4030_sndsrv_on);
+EXPORT_SYMBOL(twl4030_sndsrv_off);
+EXPORT_SYMBOL(twl4030_sndsrv_status);
+EXPORT_SYMBOL(twl4030_sndsrv_set_dtcyl);
+EXPORT_SYMBOL(twl4030_sndsrv_get_dtcyl);
+
+#endif
+ 
 subsys_initcall(twl4030_init);
 module_exit(twl4030_exit);
 
diff -purN linux-omap/drivers/i2c/chips/twl4030_gpio.c lin_for_twl/drivers/i2c/chips/twl4030_gpio.c
--- linux-omap/drivers/i2c/chips/twl4030_gpio.c	1969-12-31 18:00:00.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/twl4030_gpio.c	2007-02-27 11:49:18.000000000 -0600
@@ -0,0 +1,1036 @@
+/*
+ * linux/drivers/i2c/chips/twl4030_gpio.c
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/*** Includes */
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/kthread.h>
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include <asm/arch/twl4030.h>
+#include <asm/arch/irqs.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+
+#include <linux/device.h>
+
+/****************************************
+*  GPIO Block Register definitions
+****************************************/
+
+/**** Register Definitions */
+#define REG_GPIODATAIN1			(0x0)
+#define REG_GPIODATAIN2			(0x1)
+#define REG_GPIODATAIN3			(0x2)
+#define REG_GPIODATADIR1		(0x3)
+#define REG_GPIODATADIR2		(0x4)
+#define REG_GPIODATADIR3		(0x5)
+#define REG_GPIODATAOUT1		(0x6)
+#define REG_GPIODATAOUT2		(0x7)
+#define REG_GPIODATAOUT3		(0x8)
+#define REG_CLEARGPIODATAOUT1		(0x9)
+#define REG_CLEARGPIODATAOUT2		(0xA)
+#define REG_CLEARGPIODATAOUT3		(0xB)
+#define REG_SETGPIODATAOUT1		(0xC)
+#define REG_SETGPIODATAOUT2		(0xD)
+#define REG_SETGPIODATAOUT3		(0xE)
+#define REG_GPIO_DEBEN1			(0xF)
+#define REG_GPIO_DEBEN2			(0x10)
+#define REG_GPIO_DEBEN3			(0x11)
+#define REG_GPIO_CTRL			(0x12)
+#define REG_GPIOPUPDCTR1		(0x13)
+#define REG_GPIOPUPDCTR2		(0x14)
+#define REG_GPIOPUPDCTR3		(0x15)
+#define REG_GPIOPUPDCTR4		(0x16)
+#define REG_GPIOPUPDCTR5		(0x17)
+//#define REG_GPIO_TEST			(0x18)
+#define REG_GPIO_ISR1A			(0x19)
+#define REG_GPIO_ISR2A			(0x1A)
+#define REG_GPIO_ISR3A			(0x1B)
+#define REG_GPIO_IMR1A			(0x1C)
+#define REG_GPIO_IMR2A			(0x1D)
+#define REG_GPIO_IMR3A			(0x1E)
+#define REG_GPIO_ISR1B			(0x1F)
+#define REG_GPIO_ISR2B			(0x20)
+#define REG_GPIO_ISR3B			(0x21)
+#define REG_GPIO_IMR1B			(0x22)
+#define REG_GPIO_IMR2B			(0x23)
+#define REG_GPIO_IMR3B			(0x24)
+//#define REG_GPIO_SIR1			(0x25)
+//#define REG_GPIO_SIR2			(0x26)
+//#define REG_GPIO_SIR3			(0x27)
+#define REG_GPIO_EDR1			(0x28)
+#define REG_GPIO_EDR2			(0x29)
+#define REG_GPIO_EDR3			(0x2A)
+#define REG_GPIO_EDR4			(0x2B)
+#define REG_GPIO_EDR5			(0x2C)
+#define REG_GPIO_SIH_CTRL		(0x2D)
+
+/**** BitField Definitions */
+
+/***** Data banks : 3 banks for 8 gpios each */
+#define DATA_BANK_MAX			8
+#define GET_GPIO_DATA_BANK(x)		((x)/DATA_BANK_MAX)
+#define GET_GPIO_DATA_OFF(x)		((x)%DATA_BANK_MAX)
+
+/* GPIODATADIR Fields each block 0-7 */
+#define BIT_GPIODATADIR_GPIOxDIR(x)		(x)
+#define MASK_GPIODATADIR_GPIOxDIR(x)		(0x01<<(x))
+/* GPIODATAIN Fields each block 0-7 */
+#define BIT_GPIODATAIN_GPIOxIN(x)		(x)
+#define MASK_GPIODATAIN_GPIOxIN(x)		(0x01<<(x))
+/* GPIODATAOUT Fields each block 0-7 */
+#define BIT_GPIODATAOUT_GPIOxOUT(x)		(x)
+#define MASK_GPIODATAOUT_GPIOxOUT(x)		(0x01<<(x))
+/* CLEARGPIODATAOUT Fields */
+#define BIT_CLEARGPIODATAOUT_GPIOxOUT(x)	(x)
+#define MASK_CLEARGPIODATAOUT_GPIOxOUT(x)	(0x01<<(x))
+/* SETGPIODATAOUT Fields */
+#define BIT_SETGPIODATAOUT_GPIOxOUT(x)		(x)
+#define MASK_SETGPIODATAOUT_GPIOxOUT(x)		(0x01<<(x))
+/* GPIO_DEBEN Fields */
+#define BIT_GPIO_DEBEN_GPIOxDEB(x)		(x)
+#define MASK_GPIO_DEBEN_GPIOxDEB(x)		(0x01<<(x))
+/* GPIO_ISR1A Fields */
+#define BIT_GPIO_ISR_GPIOxISR(x)		(x)
+#define MASK_GPIO_ISR_GPIOxISR(x)		(0x01<<(x))
+/* GPIO_IMR1A Fields */
+#define BIT_GPIO_IMR1A_GPIOxIMR(x)		(x)
+#define MASK_GPIO_IMR1A_GPIOxIMR(x)		(0x01<<(x))
+/* GPIO_SIR1 Fields */
+#define BIT_GPIO_SIR1_GPIOxSIR(x)		(x)
+#define MASK_GPIO_SIR1_GPIO0SIR			(0x01<<(x))
+
+/**** Control banks : 5 banks for 4 gpios each */
+#define DATA_CTL_MAX			4
+#define GET_GPIO_CTL_BANK(x)		((x)/DATA_CTL_MAX)
+#define GET_GPIO_CTL_OFF(x)		((x)%DATA_CTL_MAX)
+#define GPIO_BANK_MAX			GET_GPIO_CTL_BANK(TWL4030_GPIO_MAX)
+/* GPIOPUPDCTRx Fields 5 banks of 4 gpios each */
+#define BIT_GPIOPUPDCTR1_GPIOxPD(x)	(2 *(x))
+#define MASK_GPIOPUPDCTR1_GPIOxPD(x)	(0x01<<(2*(x)))
+#define BIT_GPIOPUPDCTR1_GPIOxPU(x)	((x) + 1)
+#define MASK_GPIOPUPDCTR1_GPIOxPU(x)	(0x01<<(((2*(x)) + 1)))
+/* GPIO_EDR1 Fields */
+#define BIT_GPIO_EDR1_GPIOxFALLING(x)	(2 *(x))
+#define MASK_GPIO_EDR1_GPIOxFALLING(x)	(0x01<<(2*(x)))
+#define BIT_GPIO_EDR1_GPIOxRISING(x)	((x) + 1)
+#define MASK_GPIO_EDR1_GPIOxRISING(x)	(0x01<<(((2*(x)) + 1)))
+
+/************ Non equation fields */
+/* GPIO_SIH_CTRL Fields */
+#define BIT_GPIO_SIH_CTRL_EXCLEN	(0x000)
+#define MASK_GPIO_SIH_CTRL_EXCLEN	(0x00000001)
+#define BIT_GPIO_SIH_CTRL_PENDDIS	(0x001)
+#define MASK_GPIO_SIH_CTRL_PENDDIS	(0x00000002)
+#define BIT_GPIO_SIH_CTRL_COR		(0x002)
+#define MASK_GPIO_SIH_CTRL_COR		(0x00000004)
+
+/* GPIO_CTRL Fields */
+#define BIT_GPIO_CTRL_GPIO0CD1		(0x000)
+#define MASK_GPIO_CTRL_GPIO0CD1		(0x00000001)
+#define BIT_GPIO_CTRL_GPIO1CD2		(0x001)
+#define MASK_GPIO_CTRL_GPIO1CD2		(0x00000002)
+#define BIT_GPIO_CTRL_GPIO_ON		(0x002)
+#define MASK_GPIO_CTRL_GPIO_ON		(0x00000004)
+
+/* Mask for GPIO registers when aggregated into a 32-bit integer */
+#define GPIO_32_MASK			0x0003ffff
+
+/***** debug defines */
+/* Debug - four macros:
+ * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level
+ */
+
+/* Log level standard used here:
+ * Log level 3 all messages
+ * Log level 2 all entry-exit points
+ * Log level 1 major messages
+ * Log level 0 no messages
+ */
+#define TWL4030_LOG_LEVEL	0 
+/* detail - 0 - no detail
+ *          1 - function name
+ *          2 - function name, line number
+ * prefix is added to every log message
+ */
+#define TWL4030_DETAIL	2
+
+/* kernel log level*/
+//#define TWL4030_K_LOG_LEVEL KERN_DEBUG
+#define TWL4030_K_LOG_LEVEL
+
+#if ( TWL4030_DETAIL > 0 )
+#define DL1 "%s "
+#define DR1 ,__FUNCTION__
+#else
+#define DL1
+#define DR1
+#endif
+#if ( TWL4030_DETAIL > 1 )
+#define DL2 "[%d] "
+#define DR2 ,__LINE__
+#else
+#define DL2
+#define DR2
+#endif
+
+#define D(format,...)\
+	printk(TWL4030_K_LOG_LEVEL DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)
+
+#if (TWL4030_LOG_LEVEL >= 1)
+#define D1(ARGS...) D(ARGS)
+#else
+#define D1(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 2)
+#define D2(ARGS...) D(ARGS)
+#else
+#define D2(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 3)
+#define D3(ARGS...) D(ARGS)
+#else
+#define D3(ARGS...)
+#endif
+
+#if (TWL4030_LOG_LEVEL >= 2)
+#define FN_IN printk("%s Entry\n",__FUNCTION__);
+#define FN_OUT(ARG) printk("%s[%d]:Exit(%d)\n",__FUNCTION__,__LINE__,ARG);
+#else
+#define FN_IN
+#define FN_OUT(ARG)
+#endif
+
+/**** Data structures */
+/* Global static functions */
+static struct semaphore gpio_sem;
+/* store usage of each GPIO. - each bit represents one GPIO */
+static unsigned int gpio_usage_count;
+/* shadow the imr register */
+static unsigned int gpio_imr_shadow;
+/* bitmask of pending requests to unmask gpio interrupts */
+static unsigned int gpio_pending_unmask;
+/* pointer to gpio unmask thread struct */
+static struct task_struct *gpio_unmask_thread;
+
+static inline int gpio_twl4030_read(u8 address);
+static inline int gpio_twl4030_write(u8 address, u8 data);
+
+/*
+ * Helper functions to read and write the GPIO ISR and IMR registers as
+ * 32-bit integers.
+ * Functions return 0 on success, non-zero otherwise.
+ * The caller must hold a lock on gpio_sem.
+ */
+
+static int gpio_read_isr(unsigned int *isr)
+{
+	int ret;
+
+	*isr = 0;
+	ret = twl4030_i2c_read(TWL4030_MODULE_GPIO, (u8 *) isr,
+			REG_GPIO_ISR1A, 3);
+	le32_to_cpup(isr);
+	*isr &= GPIO_32_MASK;
+
+	return ret;
+}
+
+static int gpio_write_isr(unsigned int isr)
+{
+	int ret;
+
+	isr &= GPIO_32_MASK;
+	/*
+	 * The buffer passed to the twl4030_i2c_write() routine must have an
+	 * extra byte at the beginning reserved for its internal use.
+	 */
+	isr <<= 8;
+	isr = cpu_to_le32(isr);
+	ret = twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &isr,
+			       REG_GPIO_ISR1A, 3);
+	return ret;
+}
+
+static int gpio_write_imr(unsigned int imr)
+{
+	int ret;
+
+	imr &= GPIO_32_MASK;
+	/*
+	 * The buffer passed to the twl4030_i2c_write() routine must have an
+	 * extra byte at the beginning reserved for its internal use.
+	 */
+	imr <<= 8;
+	imr = cpu_to_le32(imr);
+	ret = twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &imr,
+			       REG_GPIO_IMR1A, 3);
+	return ret;
+}
+
+/*
+ * These routines are analagous to the irqchip methods, but they are designed
+ * to be called from thread context with cpu interrupts enabled and with no
+ * locked spinlocks.  We call these routines from our custom IRQ handler
+ * instead of the usual irqchip methods.
+ */
+static void twl4030_gpio_mask_and_ack(unsigned int irq)
+{
+	int gpio = irq - IH_TWL4030_GPIO_BASE;
+
+	down(&gpio_sem);
+	/* mask */
+	gpio_imr_shadow |= (1 << gpio);
+	gpio_write_imr(gpio_imr_shadow);
+	/* ack */
+	gpio_write_isr(1 << gpio);
+	up(&gpio_sem);
+}
+
+static void twl4030_gpio_unmask(unsigned int irq)
+{
+	int gpio = irq - IH_TWL4030_GPIO_BASE;
+
+	down(&gpio_sem);
+	gpio_imr_shadow &= ~(1 << gpio);
+	gpio_write_imr(gpio_imr_shadow);
+	up(&gpio_sem);
+}
+
+/*
+ * These are the irqchip methods for the TWL4030 GPIO interrupts.
+ * Our IRQ handle method doesn't call these, but they will be called by
+ * other routines such as setup_irq() and enable_irq().  They are called
+ * with cpu interrupts disabled and with a lock on the irq_controller_lock
+ * spinlock.  This complicates matters, because accessing the TWL4030 GPIO
+ * interrupt controller requires I2C bus transactions that can't be initiated
+ * in this context.  Our solution is to defer accessing the interrupt
+ * controller to a kernel thread.  We only need to support the unmask method.
+ */
+
+static void twl4030_gpio_mask_and_ack_irqchip(unsigned int irq) {}
+static void twl4030_gpio_mask_irqchip(unsigned int irq) {}
+
+static void twl4030_gpio_unmask_irqchip(unsigned int irq)
+{
+	int gpio = irq - IH_TWL4030_GPIO_BASE;
+
+	gpio_pending_unmask |= (1 << gpio);
+	if (gpio_unmask_thread && gpio_unmask_thread->state != TASK_RUNNING)
+		wake_up_process(gpio_unmask_thread);
+}
+
+static struct irq_chip twl4030_gpio_irq_chip = {
+	.ack	= twl4030_gpio_mask_and_ack_irqchip,
+	.mask	= twl4030_gpio_mask_irqchip,
+	.unmask	= twl4030_gpio_unmask_irqchip,
+};
+
+/*
+ * These are the irqchip methods for the TWL4030 PIH GPIO module interrupt.
+ * The PIH module doesn't have interrupt masking capability, so these
+ * methods are NULL.
+ */
+static void twl4030_gpio_module_ack(unsigned int irq) {}
+static void twl4030_gpio_module_mask(unsigned int irq) {}
+static void twl4030_gpio_module_unmask(unsigned int irq) {}
+static struct irq_chip twl4030_gpio_module_irq_chip = {
+	.ack = twl4030_gpio_module_ack,
+	.mask = twl4030_gpio_module_mask,
+	.unmask = twl4030_gpio_module_unmask,
+};
+
+/**** GLOBAL FUNCTIONS ***/
+
+/**
+ * @brief twl4030_request_gpio
+ *
+ * @param gpio
+ *
+ * @return
+ */
+int twl4030_request_gpio(int gpio)
+{
+	int ret = 0;
+	FN_IN;
+	if (unlikely(gpio >= TWL4030_GPIO_MAX)) {
+		D1(" Invalid GPIO num %d instead of %d\n", gpio,
+		TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	down(&gpio_sem);
+	if (gpio_usage_count & (0x1 << gpio)) {
+		D1("Busy gpio %d requested\n", gpio);
+		ret = -EBUSY;
+	} else {
+		u8 clear_pull[6] = { 0, 0, 0, 0, 0, 0 };
+		/* First time usage? - switch on GPIO module */
+		if (!gpio_usage_count) {
+			ret =
+			gpio_twl4030_write(REG_GPIO_CTRL,
+					MASK_GPIO_CTRL_GPIO_ON);
+			ret = gpio_twl4030_write(REG_GPIO_SIH_CTRL, 0x00);
+		}
+		if (!ret) {
+			gpio_usage_count |= (0x1 << gpio);
+		}
+		ret =
+		twl4030_i2c_write(TWL4030_MODULE_GPIO, clear_pull,
+				REG_GPIOPUPDCTR1, 5);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_free_gpio
+ *
+ * @param gpio
+ *
+ * @return
+ */
+int twl4030_free_gpio(int gpio)
+{
+	int ret = 0;
+	FN_IN;
+	if (unlikely(gpio >= TWL4030_GPIO_MAX)) {
+		D1(" Invalid GPIO num %d instead of %d\n", gpio,
+		TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	down(&gpio_sem);
+	if ((gpio_usage_count & (0x1 << gpio)) == 0) {
+		D1("Attempt to free already free gpio %d\n", gpio);
+		ret = -EPERM;
+	} else {
+		gpio_usage_count &= ~(0x1 << gpio);
+	}
+	/* Last time usage? - switch off GPIO module */
+	if (!gpio_usage_count) {
+		ret = gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_direction
+ *
+ * @param gpio
+ * @param is_input
+ *
+ * @return
+ */
+int twl4030_set_gpio_direction(int gpio, int is_input)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_msk = MASK_GPIODATADIR_GPIOxDIR(GET_GPIO_DATA_OFF(gpio));
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIODATADIR1 + d_bnk;
+
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		if (is_input) {
+			reg = (u8) ((ret) & ~(d_msk));
+		} else {
+			reg = (u8) ((ret) | (d_msk));
+		}
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_dataout
+ *
+ * @param gpio
+ * @param enable
+ *
+ * @return
+ */
+int twl4030_set_gpio_dataout(int gpio, int enable)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_msk = MASK_GPIODATAOUT_GPIOxOUT(GET_GPIO_DATA_OFF(gpio));
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	if (enable) {
+		base = REG_SETGPIODATAOUT1 + d_bnk;
+	} else {
+		base = REG_CLEARGPIODATAOUT1 + d_bnk;
+	}
+	down(&gpio_sem);
+	ret = gpio_twl4030_write(base, d_msk);
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_get_gpio_datain
+ *
+ * @param gpio
+ *
+ * @return
+ */
+int twl4030_get_gpio_datain(int gpio)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_off = BIT_GPIODATAIN_GPIOxIN(GET_GPIO_DATA_OFF(gpio));
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIODATAIN1 + d_bnk;
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	up(&gpio_sem);
+	if (ret > 0) {
+		D2("Actual read val=0x%x\n", ret);
+		ret = (ret >> d_off) & 0x1;
+	}
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_pull
+ *
+ * @param gpio
+ * @param pull_dircn
+ *
+ * @return
+ */
+int twl4030_set_gpio_pull(int gpio, int pull_dircn)
+{
+	u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
+	u8 c_off = GET_GPIO_CTL_OFF(gpio);
+	u8 c_msk = 0;
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIOPUPDCTR1 + c_bnk;
+	if (pull_dircn == TWL4030_GPIO_PULL_DOWN) {
+		c_msk = MASK_GPIOPUPDCTR1_GPIOxPD(c_off);
+	} else if (pull_dircn == TWL4030_GPIO_PULL_UP) {
+		c_msk = MASK_GPIOPUPDCTR1_GPIOxPU(c_off);
+	}
+	D3("GPIIO=%x COFF=%x CBNK=%x, c_msk=%x p_dir=%d", gpio, c_off,
+	c_bnk, c_msk, pull_dircn);
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		/* clear the previous up/down values */
+		reg = (u8) (ret);
+		reg &= ~(MASK_GPIOPUPDCTR1_GPIOxPU(c_off) |
+			MASK_GPIOPUPDCTR1_GPIOxPD(c_off));
+		D3("reg=%x ret=%d c_msk=0x%x", reg, ret, c_msk);
+		reg |= c_msk;
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_edge_ctrl
+ *
+ * @param gpio
+ * @param edge
+ *
+ * @return
+ */
+int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
+{
+	u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
+	u8 c_off = GET_GPIO_CTL_OFF(gpio);
+	u8 c_msk = 0;
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIO_EDR1 + c_bnk;
+	if (edge & TWL4030_GPIO_EDGE_RISING) {
+		c_msk |= MASK_GPIO_EDR1_GPIOxRISING(c_off);
+	}
+	if (edge & TWL4030_GPIO_EDGE_FALLING) {
+		c_msk |= MASK_GPIO_EDR1_GPIOxFALLING(c_off);
+	}
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		/* clear the previous rising/falling values */
+		reg =
+		(u8) (ret &
+			~(MASK_GPIO_EDR1_GPIOxFALLING(c_off) |
+			MASK_GPIO_EDR1_GPIOxRISING(c_off)));
+		reg |= c_msk;
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_debounce
+ *
+ * @param gpio
+ * @param enable
+ *
+ * @return
+ */
+int twl4030_set_gpio_debounce(int gpio, int enable)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_msk = MASK_GPIO_DEBEN_GPIOxDEB(GET_GPIO_DATA_OFF(gpio));
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIO_DEBEN1 + d_bnk;
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		if (enable) {
+			reg = (u8) ((ret) | (d_msk));
+		} else {
+			reg = (u8) ((ret) & ~(d_msk));
+		}
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_card_detect
+ *
+ * @param gpio
+ * @param cd
+ * @param enable
+ *
+ * @return
+ */
+int twl4030_set_gpio_card_detect(int gpio, int enable)
+{
+	u8 reg = 0;
+	u8 msk = (1 << gpio);
+	int ret = 0;
+	FN_IN;
+	/* Only GPIO 0 or 1 can be used for CD feature.. */
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio))
+		|| (gpio >= TWL4030_GPIO_MAX_CD))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted non CD GPIO used \n", gpio,
+		TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(REG_GPIO_CTRL);
+	if (ret >= 0) {
+		if (enable) {
+			reg = (u8) (ret | msk);
+		} else {
+			reg = (u8) (ret & ~msk);
+		}
+		ret = gpio_twl4030_write(REG_GPIO_CTRL, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return (ret);
+}
+
+/**** MODULE FUNCTIONS ***/
+
+/**
+ * @brief gpio_twl4030_write
+ *
+ * @param address
+ * @param data
+ *
+ * @return  0 if successful
+ */
+static inline int gpio_twl4030_write(u8 address, u8 data)
+{
+	int ret = 0;
+	/* DEBUG */
+	D2("GPIO add[0x%02x a.k.a.0x%02X]<=0x%02x", address, address + 0x98,
+	data);
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
+	if (ret >= 0) {
+#if 0
+		/* PARANOIA Check - what if we wrote and it did not Go there?? */
+		u8 data1;
+		ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data1, address);
+		if (ret < 0) {
+			printk(KERN_ERR "re-read failed\n");
+		} else {
+			if (data1 != data) {
+				printk
+				("Write mismatch - wrote %x read %x"
+				" from reg %x\n", data, data1, address);
+			}
+		}
+#endif
+		ret = 0;
+	} else {
+		D2(":Write[0x%x]Error %d\n", address, ret);
+	}
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief gpio_twl4030_read
+ *
+ * @param address
+ *
+ * @return  data if successful else return negative error value
+ */
+static inline int gpio_twl4030_read(u8 address)
+{
+	u8 data;
+	int ret = 0;
+	ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
+	if (ret >= 0) {
+		ret = data;
+	} else {
+		D2("TWL4030:Audio:Read[0x%x] Error %d\n", address, ret);
+	}
+	return ret;
+}
+
+/*
+ * gpio_unmask_thread() runs as a kernel thread.  It is awakened by the unmask
+ * method for the GPIO interrupts.  It unmasks all of the GPIO interrupts
+ * specified in the gpio_pending_unmask bitmask.  We have to do the unmasking
+ * in a kernel thread rather than directly in the unmask method because of the
+ * need to access the TWL4030 via the I2C bus.  Note that we don't need to be
+ * concerned about race conditions where the request to unmask a GPIO interrupt
+ * has already been cancelled before this thread does the unmasking.  If a GPIO
+ * interrupt is improperly unmasked, then the IRQ handler for it will mask it
+ * when an interrupt occurs.
+ */
+static int twl4030_gpio_unmask_thread(void *data)
+{
+	struct sched_param param;
+
+	current->flags |= PF_NOFREEZE;
+
+//	param.sched_priority = 26;
+//	sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
+
+	while (!kthread_should_stop()) {
+		int irq;
+		unsigned int gpio_unmask;
+
+		local_irq_disable();
+		gpio_unmask = gpio_pending_unmask;
+		gpio_pending_unmask = 0;
+		local_irq_enable();
+
+		for (irq = IH_TWL4030_GPIO_BASE; 0 != gpio_unmask;
+			gpio_unmask >>= 1, irq++)
+		{
+			if (gpio_unmask & 0x1)
+				twl4030_gpio_unmask(irq);
+		}
+
+		local_irq_disable();
+		if (!gpio_pending_unmask)
+			set_current_state(TASK_INTERRUPTIBLE);
+		local_irq_enable();
+
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+/*
+ * do_twl4030_gpio_irq() is the desc->handle method for each of the twl4030
+ * gpio interrupts.  It executes in kernel thread context.
+ * On entry, cpu interrupts are enabled.
+ */
+static void do_twl4030_gpio_irq(unsigned int irq, irq_desc_t *desc)
+{
+	struct irqaction *action;
+	const unsigned int cpu = smp_processor_id();
+	
+	desc->status |= IRQ_LEVEL; 
+
+	/*
+	 * Acknowledge, clear _AND_ disable the interrupt.
+	 */
+	twl4030_gpio_mask_and_ack(irq);
+
+	if (!desc->depth) {
+		kstat_cpu(cpu).irqs[irq]++;
+
+		action = desc->action;
+		if (action) {
+			int ret;
+			int status = 0;
+			int retval = 0;
+
+			do {
+				/* Call the ISR with cpu interrupts enabled. */
+				ret = action->handler(irq, action->dev_id);
+
+				if (ret == IRQ_HANDLED)
+					status |= action->flags;
+				retval |= ret;
+				action = action->next;
+			} while (action);
+
+			if (retval != IRQ_HANDLED) {
+				printk(KERN_ERR "ISR for TWL4030 GPIO"
+					" irq %d can't handle interrupt\n",
+					irq);
+			}
+
+			if (!desc->depth)
+				twl4030_gpio_unmask(irq);
+		}
+	}
+}
+
+/*
+ * do_twl4030_gpio_module_irq() is the desc->handle method for the twl4030 gpio
+ * module interrupt.  It executes in kernel thread context.
+ * This is a chained interrupt, so there is no desc->action method for it.
+ * We query the gpio module interrupt controller in the twl4030 to determine
+ * which gpio lines are generating interrupt requests, and then call the
+ * desc->handle method for each gpio that needs service.
+ * On entry, cpu interrupts are disabled.
+ */
+static void do_twl4030_gpio_module_irq(unsigned int irq, irq_desc_t *desc)
+{
+	const unsigned int cpu = smp_processor_id();
+
+	desc->status |= IRQ_LEVEL;
+
+	/*
+	* The desc->handle method would normally call the desc->chip->ack
+	* method here, but we won't bother since our ack method is NULL.
+	*/
+
+	if (!desc->depth) {
+		int gpio_irq;
+		unsigned int gpio_isr;
+
+		kstat_cpu(cpu).irqs[irq]++;
+		local_irq_enable();
+
+		down(&gpio_sem);
+		if (gpio_read_isr(&gpio_isr))
+			gpio_isr = 0;
+		up(&gpio_sem);
+
+		for (gpio_irq = IH_TWL4030_GPIO_BASE; 0 != gpio_isr;
+			gpio_isr >>= 1, gpio_irq++)
+		{
+			if (gpio_isr & 0x1) {
+				irq_desc_t *d = irq_desc + gpio_irq;
+
+				d->handle_irq(gpio_irq, d);
+			}
+		}
+
+		local_irq_disable();
+		/*
+		 * Here is where we should call the unmask method, but again we
+		 * won't bother since it is NULL.
+		 */
+	}
+}
+
+/**
+ * @brief gpio_twl4030_init
+ *
+ * @return
+ */
+static int __init gpio_twl4030_init(void)
+{
+	int ret;
+	int irq = 0;
+
+	FN_IN;
+	/* init the global locking sem */
+	sema_init(&gpio_sem, 1);
+
+	/* All GPIO interrupts are initially masked */
+	gpio_pending_unmask = 0;
+	gpio_imr_shadow = GPIO_32_MASK;
+	ret = gpio_write_imr(gpio_imr_shadow);
+
+	if (!ret) {
+		/*
+		* Create a kernel thread to handle deferred unmasking of gpio
+		* interrupts.
+		*/
+		gpio_unmask_thread = kthread_create(twl4030_gpio_unmask_thread,
+			NULL, "twl4030 gpio");
+		if (!gpio_unmask_thread) {
+			printk(KERN_ERR
+				"%s: could not create twl4030 gpio unmask thread!\n",
+				__FUNCTION__);
+			ret = -ENOMEM;
+		}
+	}
+
+	if (!ret) {
+		/* install an irq handler for each of the gpio interrupts */
+		for (irq = IH_TWL4030_GPIO_BASE; irq < IH_TWL4030_GPIO_END;
+			irq++)
+		{
+			D3("setting for IRQ=%d\n", irq);
+			set_irq_chip(irq, &twl4030_gpio_irq_chip);
+			set_irq_handler(irq, do_twl4030_gpio_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+
+		/*
+		 * Install an irq handler to demultiplex the gpio module
+		 * interrupt.
+		 */
+		set_irq_chip(TWL4030_MODIRQ_GPIO,
+			&twl4030_gpio_module_irq_chip);
+		set_irq_chained_handler(TWL4030_MODIRQ_GPIO,
+			do_twl4030_gpio_module_irq);
+	}
+
+	printk(KERN_INFO "TWL4030 GPIO Demux: IRQ Range %d to %d,"
+		" Initialization %s\n", IH_TWL4030_GPIO_BASE,
+		IH_TWL4030_GPIO_END, (ret) ? "Failed" : "Success");
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief gpio_twl4030_exit
+ *
+ * @return
+ */
+static void __exit gpio_twl4030_exit(void)
+{
+	int irq;
+
+	FN_IN;
+
+	/* uninstall the gpio demultiplexing interrupt handler */
+	set_irq_handler(TWL4030_MODIRQ_GPIO, NULL);
+	set_irq_flags(TWL4030_MODIRQ_GPIO, 0);
+
+	/* uninstall the irq handler for each of the gpio interrupts */
+	for (irq = IH_TWL4030_GPIO_BASE; irq < IH_TWL4030_GPIO_END; irq++)
+	{
+		set_irq_handler(irq, NULL);
+		set_irq_flags(irq, 0);
+	}
+
+	/* stop the gpio unmask kernel thread */
+	if (gpio_unmask_thread) {
+		kthread_stop(gpio_unmask_thread);
+		gpio_unmask_thread = NULL;
+	}
+
+	FN_OUT(0);
+	return;
+}
+
+module_init(gpio_twl4030_init);
+module_exit(gpio_twl4030_exit);
+
+EXPORT_SYMBOL(twl4030_request_gpio);
+EXPORT_SYMBOL(twl4030_free_gpio);
+EXPORT_SYMBOL(twl4030_set_gpio_direction);
+EXPORT_SYMBOL(twl4030_set_gpio_dataout);
+EXPORT_SYMBOL(twl4030_get_gpio_datain);
+EXPORT_SYMBOL(twl4030_set_gpio_pull);
+EXPORT_SYMBOL(twl4030_set_gpio_edge_ctrl);
+EXPORT_SYMBOL(twl4030_set_gpio_debounce);
+EXPORT_SYMBOL(twl4030_set_gpio_card_detect);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPIO interface for TWL4030");
+MODULE_LICENSE("GPL");

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
@ 2007-02-28  1:05 Syed Mohammed, Khasim
  0 siblings, 0 replies; 13+ messages in thread
From: Syed Mohammed, Khasim @ 2007-02-28  1:05 UTC (permalink / raw)
  To: Ram, Cantu Castillo, Arturo; +Cc: linux-omap-open-source

[-- Attachment #1: Type: text/plain, Size: 1202 bytes --]

Few more, with these you should be able to get Keypad working on 2430SDP
with 2.6.20 GIT.

Need some more time to get them on tree :(

Regards,
Khasim

>-----Original Message-----
>From: Syed Mohammed, Khasim
>Sent: Tuesday, February 27, 2007 7:03 PM
>To: 'Ram'; Cantu Castillo, Arturo
>Cc: 'linux-omap-open-source@linux.omap.com'
>Subject: RE: I2C TWL4030 Keypad
>
>This patch is for HS I2C host driver (same as on linux.omap.com)
>
>Regards,
>Khasim
>
>>-----Original Message-----
>>From: Syed Mohammed, Khasim
>>Sent: Tuesday, February 27, 2007 7:01 PM
>>To: 'Ram'; Cantu Castillo, Arturo
>>Cc: linux-omap-open-source@linux.omap.com
>>Subject: RE: I2C TWL4030 Keypad
>>
>>Hi Ram,
>>
>>As I had communicated before, the issue is due to incomplete I2C
driver.
>We
>>were not operating at High speed and T2 needs high speed to work
>>efficiently. Apart from high speed we need FIFO handling + errata
fixes
>>etc.
>>
>>For now, I have ported high speed I2C driver (from linux.omap.com) to
GIT
>>and Keypad works fine. I will send few patches for your reference.
>>
>>We have to find an optimal way to get this (I2C) code into tree ...
>>
>>Regards,
>>Khasim

[-- Attachment #2: include.diff --]
[-- Type: application/octet-stream, Size: 3645 bytes --]

diff -purN linux-omap/include/asm-arm/arch-omap/board-2430sdp.h lin_for_twl/include/asm-arm/arch-omap/board-2430sdp.h
--- linux-omap/include/asm-arm/arch-omap/board-2430sdp.h	2006-12-17 08:56:42.000000000 -0600
+++ lin_for_twl/include/asm-arm/arch-omap/board-2430sdp.h	2007-02-27 10:16:23.000000000 -0600
@@ -39,6 +39,11 @@
 /* TWL4030 Primary Interrupt Handler (PIH) interrupts */
 #define IH_TWL4030_BASE			IH_BOARD_BASE
 #define IH_TWL4030_END			(IH_TWL4030_BASE+8)
-#define NR_IRQS				(IH_TWL4030_END)
+
+/* TWL4030 GPIO Interrupts */
+#define IH_TWL4030_GPIO_BASE		(IH_TWL4030_END)
+#define IH_TWL4030_GPIO_END		(IH_TWL4030_BASE+18)
+
+#define NR_IRQS				(IH_TWL4030_GPIO_END)
 
 #endif /* __ASM_ARCH_OMAP_2430SDP_H */
diff -purN linux-omap/include/asm-arm/arch-omap/twl4030.h lin_for_twl/include/asm-arm/arch-omap/twl4030.h
--- linux-omap/include/asm-arm/arch-omap/twl4030.h	2007-01-08 18:57:20.000000000 -0600
+++ lin_for_twl/include/asm-arm/arch-omap/twl4030.h	2007-02-27 11:12:53.000000000 -0600
@@ -72,6 +72,34 @@
 #define TWL4030_VAUX3_DEV_GRP		0x1F
 #define TWL4030_VAUX3_DEDICATED		0x22
 
+/* TWL4030 GPIO interrupt definitions */
+
+#define TWL4030_GPIO_MIN		0
+#define TWL4030_GPIO_MAX		18
+#define TWL4030_GPIO_MAX_CD		2
+#define TWL4030_GPIO_IRQ_NO(n)		(IH_TWL4030_GPIO_BASE+n)
+#define TWL4030_GPIO_IS_INPUT		1
+#define TWL4030_GPIO_IS_OUTPUT		0
+#define TWL4030_GPIO_IS_ENABLE		1
+#define TWL4030_GPIO_IS_DISABLE		0
+#define TWL4030_GPIO_PULL_UP		0
+#define TWL4030_GPIO_PULL_DOWN		1
+#define TWL4030_GPIO_PULL_NONE		2
+#define TWL4030_GPIO_EDGE_NONE		0
+#define TWL4030_GPIO_EDGE_RISING	1
+#define TWL4030_GPIO_EDGE_FALLING	2
+
+extern int  twl4030_request_gpio(int gpio);
+extern int twl4030_free_gpio(int gpio);
+extern int twl4030_set_gpio_edge_ctrl(int gpio, int edge);
+extern int twl4030_set_gpio_debounce(int gpio, int enable);
+extern int twl4030_set_gpio_card_detect(int gpio, int enable);
+extern int twl4030_gpio_interrupt(int gpio,int enable);
+extern int twl4030_set_gpio_pull(int gpio, int pull_dircn);
+extern int twl4030_set_gpio_dataout(int gpio, int enable);
+extern int  twl4030_get_gpio_datain(int gpio);
+extern int twl4030_set_gpio_direction(int gpio, int is_input);
+
 /* Functions to read and write from TWL4030 */
 
 /*
diff -purN linux-omap/include/linux/i2c.h lin_for_twl/include/linux/i2c.h
--- linux-omap/include/linux/i2c.h	2007-01-08 18:57:30.000000000 -0600
+++ lin_for_twl/include/linux/i2c.h	2007-02-27 15:41:51.000000000 -0600
@@ -210,7 +210,9 @@ struct i2c_adapter {
 	unsigned int class;
 	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
 	void *algo_data;
-
+	
+	unsigned int flags; /* flags specifying div. data FIXME HS-I2C */
+	
 	/* --- administration stuff. */
 	int (*client_register)(struct i2c_client *);
 	int (*client_unregister)(struct i2c_client *);
@@ -356,6 +358,11 @@ struct i2c_msg {
 	__u16 flags;
 #define I2C_M_TEN	0x10	/* we have a ten bit chip address	*/
 #define I2C_M_RD	0x01
+
+#define I2C_M_WR        0x00    /* For readable code! */
+#define I2C_M_HS	0x20
+#define I2C_M_PRI       0x04
+	
 #define I2C_M_NOSTART	0x4000
 #define I2C_M_REV_DIR_ADDR	0x2000
 #define I2C_M_IGNORE_NAK	0x1000
@@ -371,6 +378,7 @@ struct i2c_msg {
 #define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
 #define I2C_FUNC_SMBUS_HWPEC_CALC	0x00000008 /* SMBus 2.0 */
 #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0x00008000 /* SMBus 2.0 */
+#define I2C_FUNC_HIGH_SPEED		0x00000010 /* High Speed Capable */
 #define I2C_FUNC_SMBUS_QUICK		0x00010000
 #define I2C_FUNC_SMBUS_READ_BYTE	0x00020000
 #define I2C_FUNC_SMBUS_WRITE_BYTE	0x00040000

[-- Attachment #3: keypad.diff --]
[-- Type: application/octet-stream, Size: 39173 bytes --]

diff -purN linux-omap/drivers/input/keyboard/Kconfig lin_for_twl/drivers/input/keyboard/Kconfig
--- linux-omap/drivers/input/keyboard/Kconfig	2007-01-08 18:56:34.000000000 -0600
+++ lin_for_twl/drivers/input/keyboard/Kconfig	2007-02-27 13:27:57.000000000 -0600
@@ -203,6 +203,15 @@ config KEYBOARD_OMAP
 	  To compile this driver as a module, choose M here: the
 	  module will be called omap-keypad.
 
+config KEYBOARD_TWL4030
+        tristate "TI TWL4030 keypad support"
+        depends on INPUT_KEYBOARD && TWL4030_CORE && MACH_OMAP_2430SDP
+        help
+          Say Y here if you want to use the OMAP TWL4030 keypad.
+
+          To compile this driver as a module, choose M here: the
+          module will be called omap-twl4030keypad.
+
 config OMAP_PS2
 	tristate "TI OMAP Innovator 1510 PS/2 keyboard & mouse support"
 	depends on ARCH_OMAP15XX && MACH_OMAP_INNOVATOR
diff -purN linux-omap/drivers/input/keyboard/Makefile lin_for_twl/drivers/input/keyboard/Makefile
--- linux-omap/drivers/input/keyboard/Makefile	2007-01-08 18:56:34.000000000 -0600
+++ lin_for_twl/drivers/input/keyboard/Makefile	2007-02-27 13:24:32.000000000 -0600
@@ -19,4 +19,4 @@ obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkb
 obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
 obj-$(CONFIG_OMAP_PS2)			+= innovator_ps2.o
 obj-$(CONFIG_KEYBOARD_AAED2000)         += aaed2000_kbd.o
-
+obj-$(CONFIG_KEYBOARD_TWL4030)          += omap-twl4030keypad.o
diff -purN linux-omap/drivers/input/keyboard/omap-twl4030keypad.c lin_for_twl/drivers/input/keyboard/omap-twl4030keypad.c
--- linux-omap/drivers/input/keyboard/omap-twl4030keypad.c	1969-12-31 18:00:00.000000000 -0600
+++ lin_for_twl/drivers/input/keyboard/omap-twl4030keypad.c	2007-02-27 14:22:11.000000000 -0600
@@ -0,0 +1,727 @@
+/*
+ * linux/drivers/input/omap-twl4030keypad.c
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/suspend.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/twl4030.h>
+#include "twl4030-keypad.h"
+
+/* ----- debug defines ----------------------------------------------- */
+/* Debug - four macros:
+ * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level
+ */
+
+/* Log level standard used here:
+ * Log level 3 all messages
+ * Log level 2 all entry-exit points
+ * Log level 1 major messages
+ * Log level 0 no messages
+ */
+#define OMAP_TWL4030KEYPAD_LOG_LEVEL 1
+/* detail - 0 - no detail
+ *          1 - function name
+ *          2 - function name, line number
+ * prefix is added to every log message
+ */
+#define OMAP_TWL4030KEYPAD_DETAIL    4
+
+/* kernel log level*/
+//#define OMAP_TWL4030KEYPAD_K_LOG_LEVEL KERN_DEBUG
+#define OMAP_TWL4030KEYPAD_K_LOG_LEVEL
+
+#if ( OMAP_TWL4030KEYPAD_DETAIL > 0 )
+#define DL1 "%s "
+#define DR1 ,__FUNCTION__
+#define DEBUG
+#else
+#define DL1
+#define DR1
+#endif
+#if ( OMAP_TWL4030KEYPAD_DETAIL > 1 )
+#define DL2 "[%d] "
+#define DR2 ,__LINE__
+#else
+#define DL2
+#define DR2
+#endif
+
+#define D(format,...)\
+	printk(OMAP_TWL4030KEYPAD_K_LOG_LEVEL DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)
+
+#if (OMAP_TWL4030KEYPAD_LOG_LEVEL >= 1)
+#define D1(ARGS...) D(ARGS)
+#else
+#define D1(ARGS...)
+#endif
+#if (OMAP_TWL4030KEYPAD_LOG_LEVEL >= 2)
+#define D2(ARGS...) D(ARGS)
+#else
+#define D2(ARGS...)
+#endif
+#if (OMAP_TWL4030KEYPAD_LOG_LEVEL >= 3)
+#define D3(ARGS...) D(ARGS)
+#else
+#define D3(ARGS...)
+#endif
+
+#if (OMAP_TWL4030KEYPAD_LOG_LEVEL >= 2)
+#define FN_IN printk("%s Entry\n",__FUNCTION__);
+#define FN_OUT(ARG) printk("%s[%d]:Exit(%d)\n",__FUNCTION__,__LINE__,ARG);
+#else
+#define FN_IN
+#define FN_OUT(ARG)
+#endif
+
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+#define NUM_ROWS 		5
+#define NUM_COLS 		6
+
+#define ROW_MASK 		((1<<NUM_ROWS)-1)
+
+#define SCAN_RATE 		HZ/20
+#define KEYNUM_MASK		0xFF000000
+#define ROWCOL_MASK		0x00FFFFFF
+
+/* Driver Name */
+#define OMAP_TWL4030KEYPAD_NAME "omap_twl4030keypad"
+
+#ifndef CONFIG_TWL4030KEY_AUTORPT
+#define CONFIG_TWL4030KEY_AUTORPT 100
+#endif
+
+#define SCAN_RATE 		HZ/20
+
+/* 
+ * Key mapping for 2430 SDP board
+ */
+
+static int sdp2430_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_A),
+	KEY(0, 3, KEY_B),
+	KEY(0, 4, KEY_C),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_F),
+	KEY(1, 4, KEY_G),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_I),
+	KEY(2, 2, KEY_J),
+	KEY(2, 3, KEY_K),
+	KEY(2, 4, KEY_3),
+	KEY(3, 0, KEY_M),
+	KEY(3, 1, KEY_N),
+	KEY(3, 2, KEY_O),
+	KEY(3, 3, KEY_P),
+	KEY(3, 4, KEY_Q),
+	KEY(4, 0, KEY_R),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_T),
+	KEY(4, 3, KEY_U),
+	KEY(4, 4, KEY_D),
+	KEY(5, 0, KEY_V),
+	KEY(5, 1, KEY_W),
+	KEY(5, 2, KEY_L),
+	KEY(5, 3, KEY_S),
+	KEY(5, 4, KEY_H),
+	0
+};
+
+#if (OMAP_TWL4030KEYPAD_LOG_LEVEL >= 1 )
+
+char *switch_name[NUM_ROWS][NUM_COLS] = {
+	{"S2_L", "S2_D", "S2_S", "S3", "S4", "S23"},
+	{"S2_R", "S2_U", "S5", "S6", "S7", "S24"},
+	{"S8", "S9", "S10", "S11", "S12", "S25"},
+	{"S13", "S14", "S15", "S16", "S17", "S26"},
+	{"S18", "S19", "S20", "S21", "S22", "S27"},
+};
+
+#endif
+
+/* Global variables */
+static int *keymap;
+static unsigned char keypad_state[NUM_ROWS];
+
+/* function templates */
+
+static struct input_dev *omap_twl4030kp;
+struct timer_list kptimer;
+static void omap_kp_timer(unsigned long);
+static void twl4030_keypad_scan(void);	
+struct work_struct timer_work;
+void twl4030_kp_work(void *data);
+void twl4030_timer_work(void *data);
+
+#if CONFIG_DPM
+
+static int omap_kp_probe(struct omap_dev *dev);
+static int omap_kp_suspend(struct omap_dev *dev, u32 state);
+static int omap_kp_resume(struct omap_dev *dev);
+
+/* Driver Information */
+static struct omap_driver omap_twl4030kp_driver = {
+	.devid = OMAP24xx_KP_DEVID,
+	.busid = OMAP_BUS_L4,
+	.probe = omap_kp_probe,
+	.suspend = omap_kp_suspend,
+	.resume = omap_kp_resume,
+	.drv = {
+		.name = OMAP_TWL4030KEYPAD_NAME,
+		},
+};
+
+/* Device Information */
+static struct omap_dev omap_twl4030kp_device = {
+	.name = OMAP_TWL4030KEYPAD_NAME,
+	.devid = OMAP24xx_KP_DEVID,
+	.busid = OMAP_BUS_L4,
+};
+
+#endif
+
+static int twl4030_kpread_u8(u32 module, u8 * data, u32 reg)
+{
+	int ret;
+	FN_IN;
+
+	ret = twl4030_i2c_read_u8(module, data, reg);
+	if (ret < 0) {
+		printk(KERN_WARNING
+		       "Could not read TWL4030 register %X - returned %d[%x]\n",
+		       reg, ret, ret);
+		return ret;
+	}
+
+	FN_OUT(ret);
+
+	return ret;
+}
+
+static int twl4030_kpwrite_u8(u32 module, u8 data, u32 reg)
+{
+	int ret;
+	ret = twl4030_i2c_write_u8(module, data, reg);
+	if (ret < 0) {
+		printk(KERN_WARNING
+		       "Could not write TWL4030 register %X - returned %d[%x]\n",
+		       reg, ret, ret);
+		return ret;
+	}
+	FN_OUT(ret);
+	return ret;
+}
+
+/** 
+* brief omap_kp_find_key
+* 
+* param col 
+* param row 
+* 
+* return 
+*/
+static inline int omap_kp_find_key(int col, int row)
+{
+	int i, key;
+
+	FN_IN;
+	key = KEY(col, row, 0);
+	for (i = 0; keymap[i] != 0; i++) {
+		if ((keymap[i] & KEYNUM_MASK) == key) {
+			return keymap[i] & ROWCOL_MASK;
+		}
+	}
+	FN_OUT(0);
+	return -EINVAL;
+}
+
+static void twl4030_keypad_scan(void){
+	unsigned char new_state[NUM_ROWS], changed, key_down = 0;
+	u8 col, row, spurious = 0;
+	u8 code_reg = REG_FULL_CODE_7_0;
+	int ret;
+
+	/* check for any changes */
+	ret =
+	    twl4030_i2c_read(TWL4030_MODULE_KEYPAD, new_state, code_reg,
+			     NUM_ROWS);
+	if (ret < 0) {
+		printk(KERN_WARNING
+		       "Could not read TWL4030 register %X - returned %d[%x]\n",
+		       code_reg, ret, ret);
+	}
+#if ( OMAP_TWL4030KEYPAD_LOG_LEVEL >= 2)
+	printk("\n ***************Full Code Registers Dump*****************");
+	for (row = 0; row < NUM_ROWS; row++)
+		printk("\n Full Code Register[%d] : %X", row, new_state[row]);
+	printk("\n");
+#endif
+
+	/* check for changes and print those */
+	for (row = 0; row < NUM_ROWS; row++) {
+		changed = new_state[row] ^ keypad_state[row];
+		key_down |= new_state[row];
+
+		D3("new_state[%d] : %d\tkeypad_state[%d]:%d\n", row,
+		   new_state[row], row, keypad_state[row]);
+
+		if (changed == 0)
+			continue;
+
+		for (col = 0; col < NUM_COLS; col++) {
+
+			int key;
+			if (!(changed & (1 << col)))
+				continue;
+
+			D1("key %s %s\n", switch_name[row][col],
+			   (new_state[row] & (1 << col)) ? "press" : "release");
+			key = omap_kp_find_key(col, row);
+			if (key < 0) {
+				printk(KERN_WARNING
+				       "omap-keypad: Spurious key event %d-%d\n",
+				       col, row);
+				/* We scan again after a couple of seconds */
+				spurious = 1;
+				continue;
+			}
+
+			input_report_key(omap_twl4030kp, key,
+					 new_state[row] & (1 << col));
+		}
+	}
+	if (key_down) {
+		/* some key is pressed - keep irq disabled and use timer
+		 * to poll for key release */
+		if (spurious)
+			mod_timer(&kptimer, jiffies + SCAN_RATE * 2);
+		else
+			mod_timer(&kptimer, jiffies + SCAN_RATE);
+	} 
+	memcpy(keypad_state, new_state, sizeof(keypad_state));
+}
+
+void twl4030_timer_work(void *data)
+{
+	FN_IN;
+	twl4030_keypad_scan();
+	FN_OUT(0);
+}
+
+void omap_kp_timer(unsigned long data)
+{
+	schedule_work(&timer_work);
+}
+
+/** 
+* brief do_kp_irq
+* 
+* param irq 
+* param dev_id 
+* param regs 
+*/
+static irqreturn_t do_kp_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u8 reg;
+	int ret;
+
+	FN_IN;
+
+	/* Mask keypad interrupts */
+	reg = KEYP_IMR1_MASK;
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_IMR1);
+	
+	/* Scan keypad for any changes
+	 * in keypad matrix.
+	 */
+	twl4030_keypad_scan();
+
+	/* Clear TWL4030 PIH interrupt */
+	ret = twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_KEYP_ISR1);
+
+	/* Enable interrupts */
+	reg = KEYP_IMR1_UNMASK;
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_IMR1);
+	FN_OUT(0);
+
+	return IRQ_HANDLED;
+}
+
+#if CONFIG_DPM
+/** 
+* brief omap_kp_suspend
+* 
+* param dev 
+* param state 
+* param level 
+* 
+* return 
+*/
+static int omap_kp_suspend(struct omap_dev *odev, u32 state)
+{
+
+	u8 reg;
+	int ret = 0;
+	FN_IN;
+
+	/*Disable timer and tasklet
+	 */
+
+	/* Disable all the interrupts
+	 * of T2 - keypad module
+	 */
+#if	BOARD_WAKE_SOURCE == SDP2430_TRITON_KEY_PRESS
+	reg = KEYP_IMR1_UNMASK;
+#else
+	reg = KEYP_IMR1_MASK;
+#endif
+	ret =
+		twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg,
+				   REG_KEYP_IMR1);
+	del_timer_sync(&kptimer);
+	FN_OUT(ret);
+	return ret;
+}
+
+/** 
+* brief omap_kp_resume
+* 
+* param dev 
+* param level 
+* 
+* return 
+*/
+static int omap_kp_resume(struct omap_dev *odev)
+{
+	u8 reg;
+	int ret = 0;
+	FN_IN;
+
+	/* Enable timer and tasklet, driver is resumes now.
+	 */
+	/* Now it is safe to enable the keypad module interrupts */
+	reg = KEYP_IMR1_UNMASK;
+	ret =
+		twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg,
+				   REG_KEYP_IMR1);
+	FN_OUT(ret);
+	return ret;
+}
+
+/* Registers keypad device with input sub system 
+ * and configures TWL4030 keypad registers 
+ * */
+
+/** 
+* brief omap_kp_probe
+* 
+* param dev 
+* 
+* return 
+*/
+static int omap_kp_probe(struct omap_dev *odev)
+{
+	FN_OUT(0);
+	return 0;
+}
+
+#endif
+
+/** 
+* brief omap_kp_init
+* 
+* return 
+*/
+static int __init omap_kp_init(void)
+{
+	u8 reg, i;
+	u8 code_reg = REG_FULL_CODE_7_0;
+	int ret = 0;
+#ifdef CONFIG_TWL4030KEYPAD_AUTORPT
+	int keyreptime = 0;
+#endif	
+	FN_IN;
+
+	omap_twl4030kp = input_allocate_device();
+		if (omap_twl4030kp == NULL) {
+		return -ENOMEM;
+	}
+
+
+#if CONFIG_DPM
+	if (omap_device_register(&omap_twl4030kp_device)) {
+		printk(KERN_ERR OMAP_TWL4030KEYPAD_NAME
+		       ": device register Failed ...!!!!\n");
+		goto exit_path1;
+	}
+
+	if (omap_driver_register(&omap_twl4030kp_driver)) {
+		printk(KERN_ERR OMAP_TWL4030KEYPAD_NAME
+		       ": driver register Failed ...!!!!\n");
+		goto exit_path2;
+	}
+#endif
+	keymap = sdp2430_keymap;
+
+	/* setup input device */
+	set_bit(EV_KEY, omap_twl4030kp->evbit);
+
+	/*Enable auto repeat feature of Linux input subsystem
+	 */
+
+	set_bit(EV_REP, omap_twl4030kp->evbit);
+	for (i = 0; keymap[i] != 0; i++)
+		set_bit(keymap[i] & 0x00ffffff, omap_twl4030kp->keybit);
+	omap_twl4030kp->name = OMAP_TWL4030KEYPAD_NAME;
+	input_register_device(omap_twl4030kp);
+
+	init_timer(&kptimer);
+	kptimer.function = omap_kp_timer;
+	
+	/* Since keypad driver uses I2C for reading
+	 * twl4030 keypad registers, tasklets cannot
+	 * be used.
+ 	 */ 	
+
+	INIT_WORK(&timer_work, twl4030_timer_work);
+
+#ifdef CONFIG_TWL4030KEYPAD_AUTORPT
+	keyreptime =
+	    (CONFIG_TWL4030KEY_AUTORPT) / (31.25 * 32 * 0.001) - 1;
+
+	/* Reset keypad module */
+	reg = 0;
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_CTRL_REG);
+	if (ret < 0)
+		goto exit_path4;
+
+	/* PARANOIA:
+	 *  mask all events - dont care abt result - should
+	 *  be done by default on a reset of KP module.. still..
+	 */
+	(void)twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, 0xff, REG_KEYP_IMR1);
+
+	/* Set keypad control register to Normal operation, 
+	 * hardware decoding,hardware key auto repeat feature
+	 * and keypad power on*/
+
+	reg = KEYP_CTRL_REG_MASK_AUTORPT;
+#else
+
+	reg = KEYP_CTRL_REG_MASK_NOAUTORPT;
+
+#endif
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_CTRL_REG);
+	if (ret < 0)
+		goto exit_path3;
+
+	/* Set all events to Falling Edge detection */
+
+	reg = KEYP_EDR_MASK;
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_EDR);
+	if (ret < 0)
+		goto exit_path3;
+
+	/* Set Pre Scalar Field PTV to 4
+	 */
+
+	reg = BIT_LK_PTV_REG_PTV_M & (BIT_PTV_REG_PTV4 << BIT_LK_PTV_REG_PTV);
+
+#ifdef CONFIG_TWL4030KEYPAD_AUTORPT
+	/* Set 4 bit MSB auto repeat key value in PTV reg */
+
+	reg |= BIT_LK_PTV_REG_MSB_LK_M & ((keyreptime >> 8)
+					  << BIT_LK_PTV_REG_MSB_LK);
+#endif
+
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_LK_PTV_REG);
+	if (ret < 0)
+		goto exit_path3;
+
+	/* Set key debounce time to 10 ms using equation
+	 * Tint = Tclk * (LOAD_TIM+1) * 2^(PTV+1)
+	 * Where Tclk = 31.25 us ( since kbd_if_clk is 32KHz)
+	 * PTV = 4 for all the operations.
+	 * 
+	 */
+	reg =
+	    BIT_KEY_DEB_REG_KEYP_DEB_M &
+	    (BIT_KEY_DEB9 << BIT_KEY_DEB_REG_KEYP_DEB);
+	reg = 0x3f;
+
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEY_DEB_REG);
+	if (ret < 0)
+		goto exit_path3;
+
+#ifdef CONFIG_TWL4030KEYPAD_AUTORPT
+	reg = 0;
+	/* 
+	 * Set LSB 8 bit timer value for key auto repeat.
+	 * Use the above formula to compute the Timer value
+	 * Ex:
+	 * 100 ms , LOAD_TIM = 63
+	 * 200 ms , LOAD_TIM = c7
+	 * 300 ms , LOAD_TIM = 12B
+	 * 500 ms , LOAD_TIM = 1F3
+	 * 1 sec,   LOAD_TIM = 3E7
+	 * Default is set to 100 ms.
+	 */
+	reg =
+	    BIT_LONG_KEY_REG1_LSB_LK_M &
+	    (keyreptime << BIT_LONG_KEY_REG1_LSB_LK);
+
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_LONG_KEY_REG1);
+	if (ret < 0)
+		goto exit_path3;
+#endif
+
+	/* Set SIH Ctrl register */
+
+	reg = KEYP_SIH_CTRL_MASK;
+	ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_SIH_CTRL);
+	if (ret < 0)
+		goto exit_path3;
+
+	/* Actual Triton2 chip uses 2nd bit 
+	 * PIH register for keypad.
+	 * FPGA uses 1st bit of PIH.
+	 * Update for real hardware later
+	 * Once we have finished config of all regs, enable KP ISR
+	 * before unmasking the interrupt
+	 *
+	 * This ISR will always execute in kernel thread context because of
+	 * the need to access the TWL4030 over the I2C bus.  The SA_NODELAY
+	 * flag is passed to prevent the creation of a harmless but superfluous
+	 * IRQ thread in case the CONFIG_PREEMPT_HARDIRQS kernel configuration
+	 * option is enabled.
+	 */
+	ret = request_irq(TWL4030_MODIRQ_KEYPAD, do_kp_irq,
+		SA_INTERRUPT, "TWL4030 Keypad", omap_twl4030kp);
+	if (ret < 0) {
+		printk(KERN_INFO
+		       "request_irq failed for irq no=%d\n",
+		       TWL4030_MODIRQ_KEYPAD);
+		goto exit_path3;
+	} else {
+		/* Enable keypad module
+		 * interrupts now.
+		 * */
+		reg = KEYP_IMR1_UNMASK;
+		ret =
+		    twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg,
+				       REG_KEYP_IMR1);
+		if (ret < 0) {
+			/* mask all events - dont care abt result */
+			(void)twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, 0xff,
+						 REG_KEYP_IMR1);
+			goto exit_path4;
+		}
+	}
+
+#if (OMAP_TWL4030KEYPAD_LOG_LEVEL >= 1 )
+	printk
+	    ("********TWL4030 keypad module configuration registers dump*********\n");
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_KEYP_CTRL_REG);
+	printk("Register REG_KEYP_CTRL_REG : %X\n", reg);
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_KEYP_EDR);
+	printk("Register REG_KEYP_EDR: %X\n", reg);
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_LK_PTV_REG);
+	printk("Register REG_LK_PTV_REG: %X\n", reg);
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_KEY_DEB_REG);
+	printk("Register REG_KEY_DEB_REG: %X\n", reg);
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_LONG_KEY_REG1);
+	printk("Register REG_LONG_KEY_REG1: %X\n", reg);
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_KEYP_SIH_CTRL);
+	printk("Register REG_KEYP_SIH_CTRL: %X\n", reg);
+	twl4030_kpread_u8(TWL4030_MODULE_KEYPAD, &reg, REG_KEYP_IMR1);
+	printk("Register REG_KEYP_IMR1: %X\n", reg);
+	printk("****************END******************\n");
+#endif
+	/* Read initial state of 
+	 * keypad matrix.
+	 */
+	ret =
+	    twl4030_i2c_read(TWL4030_MODULE_KEYPAD, keypad_state, code_reg,
+			     NUM_ROWS);
+	if (ret < 0) {
+		printk(KERN_WARNING
+		       "Could not read TWL4030 register %X - returned %d[%x]\n",
+		       reg, ret, ret);
+		goto exit_path4;
+	}
+
+	FN_OUT(ret);
+	return (ret);
+      exit_path4:
+	free_irq(TWL4030_MODIRQ_KEYPAD, NULL);
+      exit_path3:
+	input_unregister_device(omap_twl4030kp);
+#if CONFIG_DPM
+      exit_path2:
+	omap_driver_unregister(&omap_twl4030kp_driver);
+      exit_path1:
+	omap_device_unregister(&omap_twl4030kp_device);
+#endif
+	return -ENODEV;
+}
+
+/* On Exit, Un register the device 
+ * and driver with the system
+ */
+
+static void __exit omap_kp_exit(void)
+{
+#if CONFIG_DPM
+	omap_driver_unregister(&omap_twl4030kp_driver);
+	omap_device_register(&omap_twl4030kp_device);
+#endif
+	free_irq(TWL4030_MODIRQ_KEYPAD, NULL);
+	del_timer_sync(&kptimer);
+	/* unregister everything */
+	input_unregister_device(omap_twl4030kp);
+	FN_OUT(0);
+}
+
+module_init(omap_kp_init);
+module_exit(omap_kp_exit);
+MODULE_AUTHOR("TI");
+MODULE_DESCRIPTION("OMAP TWL4030 Keypad Driver");
+MODULE_LICENSE("GPL");
diff -purN linux-omap/drivers/input/keyboard/twl4030-keypad.h lin_for_twl/drivers/input/keyboard/twl4030-keypad.h
--- linux-omap/drivers/input/keyboard/twl4030-keypad.h	1969-12-31 18:00:00.000000000 -0600
+++ lin_for_twl/drivers/input/keyboard/twl4030-keypad.h	2007-02-27 13:26:24.000000000 -0600
@@ -0,0 +1,355 @@
+/*
+ * linux/drivers/input/twl4030-keypad.h - Register defines for TWL4030 keypad module
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __TWL4030_KEYPAD_H__
+#define __TWL4030_KEYPAD_H__
+
+/****************************************
+ *  keypad                           
+ ****************************************/
+
+/**** Register Definitions */
+
+#define REG_KEYP_CTRL_REG                        (0x0)
+#define REG_KEY_DEB_REG                          (0x1)
+#define REG_LONG_KEY_REG1                        (0x2)
+#define REG_LK_PTV_REG                           (0x3)
+#define REG_TIME_OUT_REG1                        (0x4)
+#define REG_TIME_OUT_REG2                        (0x5)
+#define REG_KBC_REG                              (0x6)
+#define REG_KBR_REG                              (0x7)
+#define REG_KEYP_SMS                             (0x8)
+#define REG_FULL_CODE_7_0                        (0x9)
+#define REG_FULL_CODE_15_8                       (0xA)
+#define REG_FULL_CODE_23_16                      (0xB)
+#define REG_FULL_CODE_31_24                      (0xC)
+#define REG_FULL_CODE_39_32                      (0xD)
+#define REG_FULL_CODE_47_40                      (0xE)
+#define REG_FULL_CODE_55_48                      (0xF)
+#define REG_FULL_CODE_63_56                      (0x10)
+#define REG_KEYP_ISR1                            (0x11)
+#define REG_KEYP_IMR1                            (0x12)
+#define REG_KEYP_ISR2                            (0x13)
+#define REG_KEYP_IMR2                            (0x14)
+#define REG_KEYP_SIR                             (0x15)
+#define REG_KEYP_EDR                             (0x16)
+#define REG_KEYP_SIH_CTRL                        (0x17)
+
+/**** BitField Definitions */
+
+/* KEYP_CTRL_REG Fields */
+#define BIT_KEYP_CTRL_REG_SOFT_NRST              (0x000)
+#define BIT_KEYP_CTRL_REG_SOFT_NRST_M            (0x00000001)
+#define BIT_KEYP_CTRL_REG_SOFTMODEN              (0x001)
+#define BIT_KEYP_CTRL_REG_SOFTMODEN_M            (0x00000002)
+#define BIT_KEYP_CTRL_REG_LK_EN                  (0x002)
+#define BIT_KEYP_CTRL_REG_LK_EN_M                (0x00000004)
+#define BIT_KEYP_CTRL_REG_TOE_EN                 (0x003)
+#define BIT_KEYP_CTRL_REG_TOE_EN_M               (0x00000008)
+#define BIT_KEYP_CTRL_REG_TOLE_EN                (0x004)
+#define BIT_KEYP_CTRL_REG_TOLE_EN_M              (0x00000010)
+#define BIT_KEYP_CTRL_REG_RP_EN                  (0x005)
+#define BIT_KEYP_CTRL_REG_RP_EN_M                (0x00000020)
+#define BIT_KEYP_CTRL_REG_KBD_ON                 (0x006)
+#define BIT_KEYP_CTRL_REG_KBD_ON_M               (0x00000040)
+
+#define KEYP_CTRL_REG_MASK_AUTORPT		 BIT_KEYP_CTRL_REG_SOFT_NRST_M | BIT_KEYP_CTRL_REG_RP_EN_M |\
+						 BIT_KEYP_CTRL_REG_SOFTMODEN_M | BIT_KEYP_CTRL_REG_KBD_ON_M
+
+#define KEYP_CTRL_REG_MASK_NOAUTORPT		 BIT_KEYP_CTRL_REG_SOFT_NRST_M | BIT_KEYP_CTRL_REG_SOFTMODEN_M |\
+						 BIT_KEYP_CTRL_REG_KBD_ON_M
+						 
+/* KEY_DEB_REG Fields */
+#define BIT_KEY_DEB_REG_KEYP_DEB                 (0x000)
+#define BIT_KEY_DEB_REG_KEYP_DEB_M               (0x0000003F)
+#define BIT_KEY_DEB9				 (0x9)
+/* LONG_KEY_REG1 Fields */
+#define BIT_LONG_KEY_REG1_LSB_LK                 (0x000)
+#define BIT_LONG_KEY_REG1_LSB_LK_M               (0x000000FF)
+#define BIT_LONG_KEY_100MS			 (0x63)
+/* LK_PTV_REG Fields */
+#define BIT_LK_PTV_REG_MSB_LK                    (0x000)
+#define BIT_LK_PTV_REG_MSB_LK_M                  (0x0000000F)
+#define BIT_LK_PTV_REG_PTV                       (0x005)
+#define BIT_LK_PTV_REG_PTV_M                     (0x000000E0)
+#define BIT_PTV_REG_PTV4			 (0x4)
+/* TIME_OUT_REG1 Fields */
+#define BIT_TIME_OUT_REG1_LSB_TO                 (0x000)
+#define BIT_TIME_OUT_REG1_LSB_TO_M               (0x000000FF)
+/* TIME_OUT_REG2 Fields */
+#define BIT_TIME_OUT_REG2_MSB_TO                 (0x000)
+#define BIT_TIME_OUT_REG2_MSB_TO_M               (0x000000FF)
+/* KBC_REG Fields */
+#define BIT_KBC_REG_KBC0                         (0x000)
+#define BIT_KBC_REG_KBC0_M                       (0x00000001)
+#define BIT_KBC_REG_KBC1                         (0x001)
+#define BIT_KBC_REG_KBC1_M                       (0x00000002)
+#define BIT_KBC_REG_KBC2                         (0x002)
+#define BIT_KBC_REG_KBC2_M                       (0x00000004)
+#define BIT_KBC_REG_KBC3                         (0x003)
+#define BIT_KBC_REG_KBC3_M                       (0x00000008)
+#define BIT_KBC_REG_KBC4                         (0x004)
+#define BIT_KBC_REG_KBC4_M                       (0x00000010)
+#define BIT_KBC_REG_KBC5                         (0x005)
+#define BIT_KBC_REG_KBC5_M                       (0x00000020)
+#define BIT_KBC_REG_KBC6                         (0x006)
+#define BIT_KBC_REG_KBC6_M                       (0x00000040)
+#define BIT_KBC_REG_KBC7                         (0x007)
+#define BIT_KBC_REG_KBC7_M                       (0x00000080)
+/* KBR_REG Fields */
+#define BIT_KBR_REG_KBR0                         (0x000)
+#define BIT_KBR_REG_KBR0_M                       (0x00000001)
+#define BIT_KBR_REG_KBR1                         (0x001)
+#define BIT_KBR_REG_KBR1_M                       (0x00000002)
+#define BIT_KBR_REG_KBR2                         (0x002)
+#define BIT_KBR_REG_KBR2_M                       (0x00000004)
+#define BIT_KBR_REG_KBR3                         (0x003)
+#define BIT_KBR_REG_KBR3_M                       (0x00000008)
+#define BIT_KBR_REG_KBR4                         (0x004)
+#define BIT_KBR_REG_KBR4_M                       (0x00000010)
+#define BIT_KBR_REG_KBR5                         (0x005)
+#define BIT_KBR_REG_KBR5_M                       (0x00000020)
+#define BIT_KBR_REG_KBR6                         (0x006)
+#define BIT_KBR_REG_KBR6_M                       (0x00000040)
+#define BIT_KBR_REG_KBR7                         (0x007)
+#define BIT_KBR_REG_KBR7_M                       (0x00000080)
+/* KEYP_SMS Fields */
+#define BIT_KEYP_SMS_STMSTS                      (0x000)
+#define BIT_KEYP_SMS_STMSTS_M                    (0x0000000F)
+#define BIT_KEYP_SMS_SIR_EN                      (0x004)
+#define BIT_KEYP_SMS_SIR_EN_M                    (0x00000010)
+#define BIT_KEYP_SMS_MISS_EN                     (0x005)
+#define BIT_KEYP_SMS_MISS_EN_M                   (0x00000020)
+/* FULL_CODE_7_0 Fields */
+#define BIT_FULL_CODE_7_0_FULL_CODE_K0           (0x000)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K0_M         (0x00000001)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K1           (0x001)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K1_M         (0x00000002)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K2           (0x002)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K2_M         (0x00000004)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K3           (0x003)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K3_M         (0x00000008)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K4           (0x004)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K4_M         (0x00000010)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K5           (0x005)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K5_M         (0x00000020)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K6           (0x006)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K6_M         (0x00000040)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K7           (0x007)
+#define BIT_FULL_CODE_7_0_FULL_CODE_K7_M         (0x00000080)
+/* FULL_CODE_15_8 Fields */
+#define BIT_FULL_CODE_15_8_FULL_CODE_K8          (0x000)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K8_M        (0x00000001)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K9          (0x001)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K9_M        (0x00000002)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K10         (0x002)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K10_M       (0x00000004)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K11         (0x003)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K11_M       (0x00000008)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K12         (0x004)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K12_M       (0x00000010)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K13         (0x005)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K13_M       (0x00000020)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K14         (0x006)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K14_M       (0x00000040)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K15         (0x007)
+#define BIT_FULL_CODE_15_8_FULL_CODE_K15_M       (0x00000080)
+/* FULL_CODE_23_16 Fields */
+#define BIT_FULL_CODE_23_16_FULL_CODE_K16        (0x000)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K16_M      (0x00000001)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K17        (0x001)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K17_M      (0x00000002)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K18        (0x002)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K18_M      (0x00000004)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K19        (0x003)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K19_M      (0x00000008)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K20        (0x004)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K20_M      (0x00000010)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K21        (0x005)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K21_M      (0x00000020)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K22        (0x006)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K22_M      (0x00000040)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K23        (0x007)
+#define BIT_FULL_CODE_23_16_FULL_CODE_K23_M      (0x00000080)
+/* FULL_CODE_31_24 Fields */
+#define BIT_FULL_CODE_31_24_FULL_CODE_K24        (0x000)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K24_M      (0x00000001)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K25        (0x001)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K25_M      (0x00000002)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K26        (0x002)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K26_M      (0x00000004)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K27        (0x003)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K27_M      (0x00000008)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K28        (0x004)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K28_M      (0x00000010)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K29        (0x005)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K29_M      (0x00000020)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K30        (0x006)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K30_M      (0x00000040)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K31        (0x007)
+#define BIT_FULL_CODE_31_24_FULL_CODE_K31_M      (0x00000080)
+/* FULL_CODE_39_32 Fields */
+#define BIT_FULL_CODE_39_32_FULL_CODE_K32        (0x000)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K32_M      (0x00000001)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K33        (0x001)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K33_M      (0x00000002)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K34        (0x002)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K34_M      (0x00000004)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K35        (0x003)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K35_M      (0x00000008)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K36        (0x004)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K36_M      (0x00000010)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K37        (0x005)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K37_M      (0x00000020)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K38        (0x006)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K38_M      (0x00000040)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K39        (0x007)
+#define BIT_FULL_CODE_39_32_FULL_CODE_K39_M      (0x00000080)
+/* FULL_CODE_47_40 Fields */
+#define BIT_FULL_CODE_47_40_FULL_CODE_K40        (0x000)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K40_M      (0x00000001)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K41        (0x001)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K41_M      (0x00000002)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K42        (0x002)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K42_M      (0x00000004)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K43        (0x003)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K43_M      (0x00000008)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K44        (0x004)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K44_M      (0x00000010)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K45        (0x005)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K45_M      (0x00000020)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K46        (0x006)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K46_M      (0x00000040)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K47        (0x007)
+#define BIT_FULL_CODE_47_40_FULL_CODE_K47_M      (0x00000080)
+/* FULL_CODE_55_48 Fields */
+#define BIT_FULL_CODE_55_48_FULL_CODE_K48        (0x000)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K48_M      (0x00000001)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K49        (0x001)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K49_M      (0x00000002)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K50        (0x002)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K50_M      (0x00000004)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K51        (0x003)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K51_M      (0x00000008)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K52        (0x004)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K52_M      (0x00000010)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K53        (0x005)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K53_M      (0x00000020)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K54        (0x006)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K54_M      (0x00000040)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K55        (0x007)
+#define BIT_FULL_CODE_55_48_FULL_CODE_K55_M      (0x00000080)
+/* FULL_CODE_63_56 Fields */
+#define BIT_FULL_CODE_63_56_FULL_CODE_K56        (0x000)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K56_M      (0x00000001)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K57        (0x001)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K57_M      (0x00000002)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K58        (0x002)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K58_M      (0x00000004)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K59        (0x003)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K59_M      (0x00000008)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K60        (0x004)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K60_M      (0x00000010)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K61        (0x005)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K61_M      (0x00000020)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K62        (0x006)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K62_M      (0x00000040)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K63        (0x007)
+#define BIT_FULL_CODE_63_56_FULL_CODE_K63_M      (0x00000080)
+/* KEYP_ISR1 Fields */
+#define BIT_KEYP_ISR1_ITKPISR1                   (0x000)
+#define BIT_KEYP_ISR1_ITKPISR1_M                 (0x00000001)
+#define BIT_KEYP_ISR1_ITLKISR1                   (0x001)
+#define BIT_KEYP_ISR1_ITLKISR1_M                 (0x00000002)
+#define BIT_KEYP_ISR1_ITTOISR1                   (0x002)
+#define BIT_KEYP_ISR1_ITTOISR1_M                 (0x00000004)
+#define BIT_KEYP_ISR1_ITMISR1                    (0x003)
+#define BIT_KEYP_ISR1_ITMISR1_M                  (0x00000008)
+#define KEYP_ISR1_CLEAR                          (0x0F)						 
+/* KEYP_IMR1 Fields */
+#define BIT_KEYP_IMR1_ITKPIMR1                   (0x000)
+#define BIT_KEYP_IMR1_ITKPIMR1_M                 (0x00000001)
+#define BIT_KEYP_IMR1_ITLKIMR1                   (0x001)
+#define BIT_KEYP_IMR1_ITLKIMR1_M                 (0x00000002)
+#define BIT_KEYP_IMR1_ITTOIMR1                   (0x002)
+#define BIT_KEYP_IMR1_ITTOIMR1_M                 (0x00000004)
+#define BIT_KEYP_IMR1_ITMISIMR1                  (0x003)
+#define BIT_KEYP_IMR1_ITMISIMR1_M                (0x00000008)
+#define KEYP_IMR1_MASK				 (0x0F)
+#define KEYP_IMR1_UNMASK			 (0x00)			 
+/* KEYP_ISR2 Fields */
+#define BIT_KEYP_ISR2_ITKPISR2                   (0x000)
+#define BIT_KEYP_ISR2_ITKPISR2_M                 (0x00000001)
+#define BIT_KEYP_ISR2_ITLKISR2                   (0x001)
+#define BIT_KEYP_ISR2_ITLKISR2_M                 (0x00000002)
+#define BIT_KEYP_ISR2_ITTOISR2                   (0x002)
+#define BIT_KEYP_ISR2_ITTOISR2_M                 (0x00000004)
+#define BIT_KEYP_ISR2_ITMISR2                    (0x003)
+#define BIT_KEYP_ISR2_ITMISR2_M                  (0x00000008)
+/* KEYP_IMR2 Fields */
+#define BIT_KEYP_IMR2_ITKPIMR2                   (0x000)
+#define BIT_KEYP_IMR2_ITKPIMR2_M                 (0x00000001)
+#define BIT_KEYP_IMR2_ITLKIMR2                   (0x001)
+#define BIT_KEYP_IMR2_ITLKIMR2_M                 (0x00000002)
+#define BIT_KEYP_IMR2_ITTOIMR2                   (0x002)
+#define BIT_KEYP_IMR2_ITTOIMR2_M                 (0x00000004)
+#define BIT_KEYP_IMR2_ITMISIMR2                  (0x003)
+#define BIT_KEYP_IMR2_ITMISIMR2_M                (0x00000008)
+/* KEYP_SIR Fields */
+#define BIT_KEYP_SIR_ITKPSIR                     (0x000)
+#define BIT_KEYP_SIR_ITKPSIR_M                   (0x00000001)
+#define BIT_KEYP_SIR_ITLKSIR                     (0x001)
+#define BIT_KEYP_SIR_ITLKSIR_M                   (0x00000002)
+#define BIT_KEYP_SIR_ITTOSIR                     (0x002)
+#define BIT_KEYP_SIR_ITTOSIR_M                   (0x00000004)
+#define BIT_KEYP_SIR_ITMISSIR                    (0x003)
+#define BIT_KEYP_SIR_ITMISSIR_M                  (0x00000008)
+/* KEYP_EDR Fields */
+#define BIT_KEYP_EDR_ITKPFALLING                 (0x000)
+#define BIT_KEYP_EDR_ITKPFALLING_M               (0x00000001)
+#define BIT_KEYP_EDR_ITKPRISING                  (0x001)
+#define BIT_KEYP_EDR_ITKPRISING_M                (0x00000002)
+#define BIT_KEYP_EDR_ITLKFALLING                 (0x002)
+#define BIT_KEYP_EDR_ITLKFALLING_M               (0x00000004)
+#define BIT_KEYP_EDR_ITLKRISING                  (0x003)
+#define BIT_KEYP_EDR_ITLKRISING_M                (0x00000008)
+#define BIT_KEYP_EDR_ITTOFALLING                 (0x004)
+#define BIT_KEYP_EDR_ITTOFALLING_M               (0x00000010)
+#define BIT_KEYP_EDR_ITTORISING                  (0x005)
+#define BIT_KEYP_EDR_ITTORISING_M                (0x00000020)
+#define BIT_KEYP_EDR_ITMISFALLING                (0x006)
+#define BIT_KEYP_EDR_ITMISFALLING_M              (0x00000040)
+#define BIT_KEYP_EDR_ITMISRISING                 (0x007)
+#define BIT_KEYP_EDR_ITMISRISING_M               (0x00000080)
+
+#define KEYP_EDR_MASK				 BIT_KEYP_EDR_ITKPFALLING_M | BIT_KEYP_EDR_ITLKFALLING_M |\
+						 BIT_KEYP_EDR_ITTOFALLING_M | BIT_KEYP_EDR_ITMISFALLING_M
+
+/* KEYP_SIH_CTRL Fields */
+#define BIT_KEYP_SIH_CTRL_EXCLEN                 (0x000)
+#define BIT_KEYP_SIH_CTRL_EXCLEN_M               (0x00000001)
+#define BIT_KEYP_SIH_CTRL_PENDDIS                (0x001)
+#define BIT_KEYP_SIH_CTRL_PENDDIS_M              (0x00000002)
+#define BIT_KEYP_SIH_CTRL_COR                    (0x002)
+#define BIT_KEYP_SIH_CTRL_COR_M                  (0x00000004)
+#define KEYP_SIH_CTRL_MASK                       (0x04);			
+					
+						 
+#endif		/* End of __TWL4030-KEYPAD_H__ */
+

[-- Attachment #4: arch_mach2.diff --]
[-- Type: application/octet-stream, Size: 1038 bytes --]

diff -purN linux-omap/arch/arm/plat-omap/devices.c lin_for_twl/arch/arm/plat-omap/devices.c
--- linux-omap/arch/arm/plat-omap/devices.c     2006-12-17 08:56:39.000000000 -0600
+++ lin_for_twl/arch/arm/plat-omap/devices.c    2007-02-27 16:33:59.000000000 -0600
@@ -509,7 +509,7 @@ static int __init omap_init_devices(void
        omap_init_wdt();
        omap_init_rng();
 #endif
-       omap_init_i2c();
+       //omap_init_i2c();
        return 0;
 }
 arch_initcall(omap_init_devices);
 
diff -purN linux-omap/arch/arm/mach-omap2/devices.c lin_for_twl/arch/arm/mach-omap2/devices.c
--- linux-omap/arch/arm/mach-omap2/devices.c	2006-11-28 09:59:29.000000000 -0600
+++ lin_for_twl/arch/arm/mach-omap2/devices.c	2007-02-27 16:49:14.000000000 -0600
@@ -208,7 +208,7 @@ static int __init omap2_init_devices(voi
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	omap_init_i2c();
+	//omap_init_i2c();
 	omap_init_mbox();
 	omap_init_mcspi();
 	omap_init_sti();

[-- Attachment #5: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: I2C TWL4030 Keypad
@ 2007-02-28  1:02 Syed Mohammed, Khasim
  0 siblings, 0 replies; 13+ messages in thread
From: Syed Mohammed, Khasim @ 2007-02-28  1:02 UTC (permalink / raw)
  To: Ram, Cantu Castillo, Arturo; +Cc: linux-omap-open-source

[-- Attachment #1: Type: text/plain, Size: 792 bytes --]

This patch is for HS I2C host driver (same as on linux.omap.com)

Regards,
Khasim

>-----Original Message-----
>From: Syed Mohammed, Khasim
>Sent: Tuesday, February 27, 2007 7:01 PM
>To: 'Ram'; Cantu Castillo, Arturo
>Cc: linux-omap-open-source@linux.omap.com
>Subject: RE: I2C TWL4030 Keypad
>
>Hi Ram,
>
>As I had communicated before, the issue is due to incomplete I2C
driver. We
>were not operating at High speed and T2 needs high speed to work
>efficiently. Apart from high speed we need FIFO handling + errata fixes
>etc.
>
>For now, I have ported high speed I2C driver (from linux.omap.com) to
GIT
>and Keypad works fine. I will send few patches for your reference.
>
>We have to find an optimal way to get this (I2C) code into tree ...
>
>Regards,
>Khasim

[-- Attachment #2: i2c_bus.diff --]
[-- Type: application/octet-stream, Size: 49346 bytes --]

diff -purN linux-omap/drivers/i2c/busses/Makefile lin_for_twl/drivers/i2c/busses/Makefile
--- linux-omap/drivers/i2c/busses/Makefile	2007-01-08 18:56:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/busses/Makefile	2007-02-27 15:38:53.000000000 -0600
@@ -46,7 +46,7 @@ obj-$(CONFIG_I2C_VIAPRO)	+= i2c-viapro.o
 obj-$(CONFIG_I2C_VOODOO3)	+= i2c-voodoo3.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
-obj-$(CONFIG_I2C_OMAP)          += i2c-omap.o
+obj-$(CONFIG_I2C_OMAP)          += i2c-omap_hs.o
 
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff -purN linux-omap/drivers/i2c/busses/i2c-omap.c lin_for_twl/drivers/i2c/busses/i2c-omap.c
--- linux-omap/drivers/i2c/busses/i2c-omap.c	2007-01-08 18:56:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/busses/i2c-omap.c	2007-02-27 14:34:00.000000000 -0600
@@ -115,7 +115,7 @@
 
 /* REVISIT: Use platform_data instead of module parameters */
 /* Fast Mode = 400 kHz, Standard = 100 kHz */
-static int clock = 100; /* Default: 100 kHz */
+static int clock = 400; /* Default: 100 kHz */
 module_param(clock, int, 0);
 MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
 
diff -purN linux-omap/drivers/i2c/busses/i2c-omap_hs.c lin_for_twl/drivers/i2c/busses/i2c-omap_hs.c
--- linux-omap/drivers/i2c/busses/i2c-omap_hs.c	1969-12-31 18:00:00.000000000 -0600
+++ lin_for_twl/drivers/i2c/busses/i2c-omap_hs.c	2007-02-27 17:48:50.000000000 -0600
@@ -0,0 +1,1487 @@
+/*
+ * linux/drivers/i2c/busses/i2c-omap243x.c
+ *
+ * Unified algorithm/adapter I2C driver for OMAP243x I2C controller.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2005-2006 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * History:
+ * -------
+ * Aug 2005 - Copied from drivers/i2c/i2c-omap24xx.c and ported to 
+ *            243X and added support for HSI2C - Texas Instruments 
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+
+#ifdef CONFIG_PM
+#include <linux/notifier.h>
+#include <linux/device.h>
+#include <asm/arch/bus.h>
+#endif
+#ifdef CONFIG_DPM
+#include <asm/arch/dpm.h>	/* to specify constraints */
+#endif
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+
+#include "i2c-omap_hs.h"
+
+#define INT_I2C1_IRQ	56
+#define INT_I2C2_IRQ	57
+
+int enable_i2c_clock(int i2c_module, int clocksrc);
+void disable_i2c_clock(int i2c_module);
+
+#ifdef CONFIG_PM
+static int dpm_state[2];
+static int prcm_i2c[2] = {PRCM_I2C1, PRCM_I2C2};
+#endif
+
+/* ----- configuration macros ----------------------------------------- */
+
+#define NUM_I2C_ADAP 2		/* number of I2C adapters */
+
+#define I2C_NAME "i2c-omap243x"
+
+/* The default timeout is for the time allowed for each word (2 bytes) of
+ * an I2C transfer to complete.  This value is converted to ticks and
+ * used to initialize the timeout member of the i2c_adapter struct.
+ * For each byte in the trsh, wait for 100Khz (STD speed)
+ */
+#define I2C_DEFAULT_TIMEOUT_MS	  40
+#define I2C_DEFAULT_RETRIES       2
+
+/* The reset timeout is the time allowed for a reset of the I2C controller
+ * to complete.
+ */
+#define I2C_RESET_TIMEOUT_MS 100
+
+/* The bus busy timeout is the maximum time we will wait for the bus to
+ * become idle before initiating a transfer.
+ */
+#define I2C_BUS_BUSY_TIMEOUT_MS 200
+
+/* This driver doesn't support I2C slave mode, so we set our own address
+ * to zero to make sure it won't conflict with any slave devices on the
+ * bus.
+ */
+#define I2C_OWN_ADDRESS 0
+
+/* MCODE For HS transfers */
+#define I2C_MCODE  0
+
+#define CONTROL_PBIAS_LITE_1  IO_ADDRESS(OMAP24XX_CTRL_BASE+0x4A0)
+#define PULL_HS_BUS0          (0x1<<3)
+#define PULL_HS_BUS1          (0x1<<4)
+#ifdef CONFIG_I2C_OMAP243X_SECONDARY_PULL0
+#    ifdef CONFIG_I2C_OMAP243X_SECONDARY_PULL1 
+#        define I2C_SECONDARY_PULL    (PULL_HS_BUS0|PULL_HS_BUS1)
+#    else
+#        define I2C_SECONDARY_PULL    (PULL_HS_BUS0)
+#    endif
+#elif defined (CONFIG_I2C_OMAP243X_SECONDARY_PULL1)
+#    define I2C_SECONDARY_PULL    (PULL_HS_BUS1)
+#endif
+/* ----- debug defines ----------------------------------------------- */
+/* Debug - four macros:
+ * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level
+ */
+
+/* Log level standard used here:
+ * Log level 3 all messages
+ * Log level 2 all entry-exit points
+ * Log level 1 major messages
+ * Log level 0 no messages
+ */
+#define I2C_LOG_LEVEL 0
+/* detail - 0 - no detail
+ *          1 - function name
+ *          2 - function name, line number
+ * prefix is added to every log message
+ */
+#define I2C_DETAIL    2
+
+/* kernel log level*/
+/* #define I2C_K_LOG_LEVEL KERN_DEBUG */
+#define I2C_K_LOG_LEVEL
+
+#if ( I2C_DETAIL > 0 )
+#define DL1 "%s "
+#define DR1 ,__FUNCTION__
+#else
+#define DL1
+#define DR1
+#endif
+#if ( I2C_DETAIL > 1 )
+#define DL2 "[%d] "
+#define DR2 ,__LINE__
+#else
+#define DL2
+#define DR2
+#endif
+
+/* Wanted to reduce printks... at the same time ease development too..
+ * cant do with the format,args version.. does not work with null args :(
+ */
+#define D(format,...)\
+	printk(DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)
+
+#if (I2C_LOG_LEVEL >= 1)
+#define D1(ARGS...) D(ARGS)
+#else
+#define D1(ARGS...)
+#endif
+#if (I2C_LOG_LEVEL >= 2)
+#define D2(ARGS...) D(ARGS)
+#else
+#define D2(ARGS...)
+#endif
+#if (I2C_LOG_LEVEL >= 3)
+#define D3(ARGS...) D(ARGS)
+#else
+#define D3(ARGS...)
+#endif
+
+#if (I2C_LOG_LEVEL >= 2)
+#define FN_IN D("%s Entry",__FUNCTION__);
+#define FN_OUT(ARG) D("%s[%d]:Exit(%d)",__FUNCTION__,__LINE__,ARG);
+#else
+#define FN_IN
+#define FN_OUT(ARG)
+#endif
+
+/* ----- module data structures ---------------------------------------	*/
+
+struct omap24xx_i2c_adapter {
+	struct i2c_adapter adap;
+
+	/* for a given i2c-clock-sclk combination now, only one possible set is possible */
+	unsigned int psc;
+	unsigned int scl_lh;
+
+	unsigned long s_clock;	/* needed for power management */
+#if (I2C_LOG_LEVEL >= 1)
+	unsigned long mmio_base_phys;	/* Just for debug messages */
+#endif
+	unsigned long mmio_base;
+
+	int irq;
+	unsigned short oa;	/* own address */
+	unsigned char mcode;	/* master code */
+	int a_num;	
+	u16 tx_fifo_size;	/* The fifo size of the tx device */
+	u16 rx_fifo_size;	/* The fifo size of the rx device */
+
+	wait_queue_head_t i2c_wait_queue;
+};
+
+static struct omap24xx_i2c_adapter *saved_oadap[NUM_I2C_ADAP];
+
+#ifdef CONFIG_PM
+/* No scaling when we dont do DMA yet */
+#undef I2C_DPM_SCALE
+#ifdef I2C_DPM_SCALE
+static int omap24xx_i2c_scale(struct notifier_block *op, unsigned long level, void * newop);
+static struct notifier_block omap24xxi2c_pre_scale = {
+	         .notifier_call = omap24xx_i2c_scale,
+};
+static struct notifier_block omap24xxi2c_post_scale = {
+	         .notifier_call = omap24xx_i2c_scale,
+};
+#endif
+struct omap24xxi2c_suspend_data {
+	/* Power management suspend lockout stuff */
+	int suspended;
+	wait_queue_head_t suspend_wq;
+};
+static struct omap24xxi2c_suspend_data i2c_suspend_data[NUM_I2C_ADAP];
+/* if suspended, simply return an error */
+#define omap24xx_i2c_suspend_lockout(s,a) \
+	if (((s[a]))->suspended) {\
+		return -EBUSY;\
+	}
+#define omap24xx_i2c_suspend_lockout_queue(s,a) \
+	if (((s[a]))->suspended) {\
+		wait_event((s[a])->suspend_wq,\
+					 (((s[a]))->suspended == 0));\
+	}
+#else
+#define omap24xx_i2c_suspend_lockout(s,a) do {} while(0)
+#define omap24xx_i2c_suspend_lockout_queue(s,a) do {} while(0)
+#endif
+
+/* ----- module params  ---------------------------------------	*/
+
+/* bus 0 clock */
+static int i2c_clock0 = OMAP_I2C_STANDARD;
+static int i2c_clock1 = 2600;
+
+/* ----- Utility functions --------------------------------------------	*/
+
+/*
+ * I2C register I/O routines
+ */
+
+
+/* 16 bit read and writes */
+static __inline__ u16
+omap242x_i2c_readw(const struct omap24xx_i2c_adapter *oadap, u32 offset)
+{
+	unsigned short readv = readw(oadap->mmio_base + offset);
+	D1("R[0x%x]=0x%x\n", (u32) oadap->mmio_base_phys + offset, (u32) readv);
+	return readv;
+}
+
+static __inline__ u16
+omap242x_i2c_writew(const struct omap24xx_i2c_adapter *oadap, u32 offset,
+		    u16 val)
+{
+	writew(val, oadap->mmio_base + offset);
+	D1("W[0x%x]<=0x%x\n", (u32) oadap->mmio_base_phys + offset, (u32) val);
+	return val;
+}
+
+/* 8 bit read and writes */
+static __inline__ u8
+omap242x_i2c_readb(const struct omap24xx_i2c_adapter *oadap, u32 offset)
+{
+	unsigned char readv = readb(oadap->mmio_base + offset);
+	D1("bR[0x%x]=0x%x\n", (u32) (oadap->mmio_base_phys + offset),
+	   (u32) readv);
+	return readv;
+}
+
+static __inline__ u8
+omap242x_i2c_writeb(const struct omap24xx_i2c_adapter *oadap, u32 offset,
+		    u8 val)
+{
+	writeb(val, oadap->mmio_base + offset);
+	D1("bW[0x%x]<=0x%x\n", (u32) oadap->mmio_base_phys + offset, (u32) val);
+	return val;
+}
+
+/** 
+ * @brief i2c_hw_init
+ * Initialize the I2C controller.
+ *
+ * @param oadap 
+ * 
+ * @return intialization status  Returns zero if successful,
+ * non-zero otherwise.
+ */
+static int i2c_hw_init(struct omap24xx_i2c_adapter *oadap)
+{
+	unsigned long timeout;
+	FN_IN;
+
+	/* disable the I2C controller */
+	omap242x_i2c_writew(oadap, I2C_CON, 0);
+
+	/* wait for reset to complete */
+	timeout = jiffies + ((I2C_RESET_TIMEOUT_MS) * HZ) / 1000;
+
+	/* reset the I2C controller */
+	omap242x_i2c_writew(oadap, I2C_SYSC, I2C_SYSC_SRST);
+	/* enable the block to allow reset complete */
+	omap242x_i2c_writew(oadap, I2C_CON, I2C_CON_I2C_EN);
+
+	/* 
+	 * Wait for reset to happen -bit will get set by the h/w once 
+	 * reset is completed 
+	 */
+	while ( 0 == ((omap242x_i2c_readw(oadap, I2C_SYSS) & I2C_SYSS_RDONE))
+	       && time_before(jiffies, timeout)) {
+		if (!in_interrupt()) {
+			if (!signal_pending(current))
+				set_current_state(TASK_INTERRUPTIBLE);
+			else
+				set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		} else
+			udelay(100);
+	}
+	/* if the i2c controller does not report reset completed... */
+	if (0 == ((omap242x_i2c_readw(oadap, I2C_SYSS) & I2C_SYSS_RDONE))) {
+
+		printk
+		    (KERN_ERR "I2C[%d]:Timeout waiting for I2C controller to reset[%d] %d\n",
+		     oadap->a_num,(u32) I2C_RESET_TIMEOUT_MS, (u32) timeout);
+		FN_OUT(ETIMEDOUT);
+		return -ETIMEDOUT;
+	}
+	/* initialize pre-computed prescalar values */
+	omap242x_i2c_writew(oadap, I2C_PSC, oadap->psc);
+
+	/* program tlow and thigh with equal levels */
+	omap242x_i2c_writew(oadap, I2C_SCLL, oadap->scl_lh);	/* tlow */
+	omap242x_i2c_writew(oadap, I2C_SCLH, oadap->scl_lh);	/* thigh */
+	/* set our own slave address */
+	omap242x_i2c_writew(oadap, I2C_OA,
+			    (((oadap->mcode & I2C_OA_MCODE_M) << I2C_OA_MCODE) |
+			     ((oadap->oa & I2C_OA_OA0_M) << I2C_OA_OA0)));
+
+	/* enable the I2C controller */
+	omap242x_i2c_writew(oadap, I2C_CON, I2C_CON_I2C_EN);
+
+	/* wait for reset to complete */
+	timeout = jiffies + ((I2C_RESET_TIMEOUT_MS) * HZ) / 1000;
+	/* Wait for the Functional module to be enabled. */
+	while (!(omap242x_i2c_readw(oadap, I2C_SYSS) & I2C_SYSS_RDONE)
+	       && time_before(jiffies, timeout)) {
+		if (!in_interrupt()) {
+			if (!signal_pending(current))
+				set_current_state(TASK_INTERRUPTIBLE);
+			else
+				set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		} else
+			udelay(100);
+	}
+	if (!(omap242x_i2c_readw(oadap, I2C_SYSS) & I2C_SYSS_RDONE)) {
+		D1("timeout waiting for I2C controller to reset[%d]",
+		   I2C_RESET_TIMEOUT_MS);
+		FN_OUT(ETIMEDOUT);
+		return -ETIMEDOUT;
+	}
+	FN_OUT(0);
+	return 0;
+}
+
+/** 
+ * @brief i2c_hw_release
+ * Disable the i2c controller
+ *
+ * @param oadap 
+ */
+static void i2c_hw_release(struct omap24xx_i2c_adapter *oadap)
+{
+	FN_IN;
+	/* disable the I2C controller */
+	omap242x_i2c_writew(oadap, I2C_CON, 0);
+	FN_OUT(0);
+}
+
+/** 
+ * @brief i2c_wait_while_bb
+ * The I2C bus protocol supports multiple masters.  This driver only supports
+ * using the OMAP I2C bus controller as a master, but we want to try to
+ * accommodate situations where there are other I2C masters sharing the bus.
+ * In order to allow for other bus masters, we have to check if the bus is
+ * busy before initiating a transfer.    
+ *
+ * @param oadap 
+ * 
+ * @return This functions returns 0 if the bus is idle, or 
+ * -ETIMEDOUT if a timeout occurs before the bus becomes idle.
+ */
+static int i2c_wait_while_bb(const struct omap24xx_i2c_adapter *oadap)
+{
+	unsigned long timeout = jiffies + (I2C_BUS_BUSY_TIMEOUT_MS * HZ) / 1000;
+	FN_IN;
+
+	while ((omap242x_i2c_readw(oadap, I2C_STAT) & I2C_STAT_BB)
+	       && time_before(jiffies, timeout)) {
+		if (!in_interrupt()) {
+			if (!signal_pending(current))
+				set_current_state(TASK_INTERRUPTIBLE);
+			else
+				set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		} else
+			udelay(100);
+	}
+	if (omap242x_i2c_readw(oadap, I2C_STAT) & I2C_STAT_BB) {
+		D1("timeout waiting for bus to be idle [%d]", (int)timeout);
+		FN_OUT(ETIMEDOUT);
+		return -ETIMEDOUT;
+	}
+
+	FN_OUT(0);
+	return 0;
+}
+
+/** 
+ * @brief i2c_wait_for_status
+ * Wait for status register update.  
+ * 
+ * @param oadap 
+ * @param poll - do polled wait for status!! max delay 1ms
+ * 
+ * @return  Returns a negative error code or the value of the status 
+ * register.
+ */
+static int i2c_wait_for_status(struct omap24xx_i2c_adapter *oadap, u8 poll,
+			       u32 timeout, int flags)
+{
+	wait_queue_t i2c_wait;
+	u16 status;
+	const u16 ie_mask = I2C_IE_XRDY_IE | I2C_IE_RRDY_IE
+	    | I2C_IE_ARDY_IE | I2C_IE_NACK_IE | I2C_IE_AL_IE | I2C_IE_XDR_IE;
+	const u16 stat_mask = I2C_STAT_XRDY | I2C_STAT_RRDY
+	    | I2C_STAT_ARDY | I2C_STAT_NACK | I2C_STAT_AL | I2C_STAT_XUDF |
+	    I2C_STAT_ROVR | I2C_STAT_XDR | I2C_STAT_RDR;
+	FN_IN;
+
+	status = omap242x_i2c_readw(oadap, I2C_STAT);
+	if ((( flags & I2C_M_PRI) | poll ) && !(status & stat_mask)) {
+		/*  polled mode */
+		typeof(jiffies) new_timeout = jiffies + timeout;
+		while (!(status & stat_mask)
+		       && time_before(jiffies, new_timeout)) {
+			/* Loop as long as we dont timeout-Die CPU Die ;) */
+			status = omap242x_i2c_readw(oadap, I2C_STAT);
+		}
+		if (!(status & stat_mask)) {
+			D1
+			    ("Poll Timedout %s[0x%x] timout=%d\n",
+			     __FUNCTION__, status, (u32) new_timeout);
+			return -ETIMEDOUT;
+		}
+
+	} else if (!(status & stat_mask)) {
+		
+		/* interrupt mode */
+		
+		init_waitqueue_entry(&i2c_wait, current);
+		add_wait_queue(&oadap->i2c_wait_queue, &i2c_wait);
+		
+    
+		/* enable I2C interrupts */
+		omap242x_i2c_writew(oadap, I2C_IE, ie_mask);
+
+		status = omap242x_i2c_readw(oadap, I2C_STAT);
+		if (!(status & stat_mask)) {
+			if (!in_interrupt()){
+				/* no pend signals - wait interruptible/else,
+			 	* wait the required timedelay
+			 	*/
+				if (!signal_pending(current))
+					set_current_state(TASK_INTERRUPTIBLE);
+				else
+					set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(timeout);
+				/* guarenteed to be in running state on exit */
+			}
+			else
+				udelay(100);
+		}             
+		remove_wait_queue(&oadap->i2c_wait_queue, &i2c_wait);
+        
+		status = omap242x_i2c_readw(oadap, I2C_STAT);
+		if (!(status & stat_mask)) {
+			/* still no status update */
+			if (signal_pending(current)) {
+				D1("RestartSYS %s\n", __FUNCTION__);
+				FN_OUT(ERESTARTSYS);
+				return -ERESTARTSYS;
+			} else {
+				D1("Timedout %s[0x%x]\n", __FUNCTION__,
+				       status);
+				FN_OUT(ETIMEDOUT);
+				return -ETIMEDOUT;
+			}
+		}
+	}
+
+	FN_OUT(status);
+	return status;
+}
+
+/** 
+ * @brief omap24xx_i2c_handler
+ * 
+ * @param this_irq 
+ * @param dev_id 
+ * @param regs 
+ */
+static irqreturn_t
+omap24xx_i2c_handler(int this_irq, void *dev_id)
+{
+	struct omap24xx_i2c_adapter *oadap =
+	    (struct omap24xx_i2c_adapter *)dev_id;
+
+	FN_IN;
+	/* disable I2C interrupts */
+	omap242x_i2c_writew(oadap, I2C_IE, 0);
+	wake_up_interruptible(&oadap->i2c_wait_queue);
+	return IRQ_HANDLED;
+}
+
+/** 
+ * @brief omap24xx_i2c_xfer_msg
+ * Read or write a single message.  Returns the number of bytes
+ * successfully read or written.  A start (or restart) condition is always
+ * generated first, followed by msg->len data bytes.  A stop condition is
+ * generated if the stop parameter is non-zero.  Otherwise, the bus is left
+ * busy (clock line pulled low) so that the next transfer can begin with a
+ * restart.
+ * 
+ * @param oadap 
+ * @param msg 
+ * @param stop 
+ * 
+ * @return 0 if successful, else the error condition
+ */
+static int
+omap24xx_i2c_xfer_msg(struct omap24xx_i2c_adapter *oadap,
+		      struct i2c_msg *msg, int stop)
+{
+	struct i2c_adapter *adap = &oadap->adap;
+	u16 data;
+	int status;
+	int retries, stt_reset, stt_status;
+	int count;
+	int ret = 0;
+	u16 fifo_sel = 0;
+	typeof(jiffies) timeout;
+	
+	unsigned int control = (I2C_CON_I2C_EN | I2C_CON_MST | I2C_CON_STT |
+				((msg->flags & I2C_M_TEN) ? I2C_CON_XSA : 0) |
+				((msg->flags & I2C_M_RD) ? 0 : I2C_CON_TRX)); 
+
+	FN_IN;
+
+	D1("%s %d\n", (msg->flags & I2C_M_RD) ? "Rd" : "Wr", msg->len);
+	/* The OMAP controller can't generate a message with zero data bytes, so
+	 * return without doing anything in that case.
+	 */
+	if (!msg->len) {
+		D3("Skipping message with zero-length payload at addr"
+		   " 0x%04x.", msg->addr);
+		FN_OUT(0);
+		return 0;
+	}
+
+	omap24xx_i2c_suspend_lockout_queue(&i2c_suspend_data, oadap->a_num);
+
+	/* Do we do HS transfer or not... simple logic for now 
+	 * We need to extend this logic for DMA usage too
+	 * Combine it with overhead of doing HS Transfers
+	 */
+	if (unlikely
+	    ((msg->flags & I2C_M_HS) && !(adap->flags & I2C_FUNC_HIGH_SPEED))) {
+		printk(KERN_WARNING
+		       "Attempt of HS TX ON FS DEVICE-Auto switching to FS transfer!\n");
+		msg->flags &= ~I2C_M_HS;
+	}
+	if (unlikely
+	    (!(msg->flags & I2C_M_HS) && (adap->flags & I2C_FUNC_HIGH_SPEED))) {
+		D1(KERN_INFO "Unoptimal FS attempt on HS Bus!\n");
+	}
+	control |= ((((msg->flags & I2C_M_HS) ? I2C_CON_OP_MODE_HS :
+		      I2C_CON_OP_MODE_FS) & I2C_CON_OP_MODE_M) <<
+		    I2C_CON_OP_MODE);
+
+	/* Choose the proper Fifo Size */
+	fifo_sel =
+	    ((msg->flags & I2C_M_RD) ? oadap->rx_fifo_size : oadap->
+	     tx_fifo_size);
+
+	D1("timeout=%d, fifo_size=%d,len=%d\n", 
+	   (u32) adap->timeout, fifo_sel, msg->len);
+
+	D3("addr: 0x%04x, len: %d, flags: 0x%x, stop: %d control=0x%x",
+	   msg->addr, msg->len, msg->flags, stop, control);
+
+	for (retries = 0; retries <= adap->retries; retries++) {
+		/* Disable the i2c controller */
+		omap242x_i2c_writew(oadap, I2C_CON, 0);
+		/* Disable DMA, enable RX FIFO CLR, TX FIFO CLR - set the threshholds 
+		 * we do it here to flush the FIFOs
+		 */
+		omap242x_i2c_writew(oadap, I2C_BUF,
+				    ((oadap->
+				      rx_fifo_size & I2C_BUF_RXTRSH_M) <<
+				     I2C_BUF_RXTRSH) | ((oadap->
+							 tx_fifo_size &
+							 I2C_BUF_TXTRSH_M) <<
+							I2C_BUF_TXTRSH) |
+				    I2C_BUF_TXFIFO_CL | I2C_BUF_RXFIFO_CL);
+		status = omap242x_i2c_readw(oadap, I2C_STAT);
+		/* clean out all old status */
+		omap242x_i2c_writew(oadap, I2C_STAT, status);
+		omap242x_i2c_writew(oadap, I2C_SA, msg->addr);
+		omap242x_i2c_writew(oadap, I2C_CNT, msg->len);
+      		omap242x_i2c_writew(oadap, I2C_CON, control);
+		/* Work around for HS I2C bug not allowing to set STT
+		   and STP bit at the same time */
+		stt_reset=0;
+		if(stop) {
+			timeout = jiffies + msecs_to_jiffies(60);
+			while (time_before(jiffies, timeout)) {
+				stt_status = omap242x_i2c_readw(oadap, I2C_CON);
+				if(!(stt_status & I2C_CON_STT )){
+					stt_reset=1;
+					control = ((control & ~(I2C_CON_STT)) | I2C_CON_STP);
+       		     			omap242x_i2c_writew(oadap, I2C_CON, control);
+		     			break;
+				}
+		  	}
+			if(!stt_reset){
+				D1("I2C transfer error: STT bit not reset %x", stt_status);
+				ret = -1;
+				goto xfer_exit;
+			}
+		}
+		count = 0;
+		while (count <= msg->len) {
+			status =
+			    i2c_wait_for_status(oadap, (0 == count), adap->timeout, msg->flags);
+			if (status < 0) {
+				D1("I2C transfer aborted with error %d",
+				   status);
+				ret = status;
+				goto xfer_exit;
+			}
+
+			if (status & I2C_STAT_AL) {
+				D1("Arbitration lost, retrying transfer"
+				   "count=%d[%x]\n", count, status);
+				/* We lost control of the bus to another
+				 * bus master.  Try this transfer again if we get bus back.
+				 */
+				omap242x_i2c_writew(oadap, I2C_STAT, status);
+				if (i2c_wait_while_bb(oadap)) {
+					D1 ("Unable to get the bus back[0x%x]!!\n",
+					     omap242x_i2c_readw(oadap,
+								I2C_STAT));
+					ret = -EREMOTEIO;
+					goto xfer_exit;
+				}
+
+				break;
+			}
+			if (status & I2C_STAT_NACK) {
+				omap242x_i2c_writew(oadap, I2C_STAT,
+						    I2C_STAT_NACK);
+				D1("I2C xfer aborted by NAK");
+				ret = -EREMOTEIO;
+				goto xfer_exit;
+			}
+			D1("count=%d,status=0x%x\n", count, status);
+			if (status & I2C_STAT_ARDY) {
+				omap242x_i2c_writew(oadap, I2C_STAT,
+						    I2C_STAT_ARDY);
+				if (count == msg->len) {
+					/* successful completion of transfer */
+					D3("I2C xfer complete");
+					ret = count;
+					goto xfer_exit;
+				} else {
+					D1 ("I2C transfer ended prematurely[0x%x]\n",
+					     status);
+					ret = -EREMOTEIO;
+					goto xfer_exit;
+				}
+				status &= ~I2C_STAT_ARDY;
+			}
+			if (status & (I2C_STAT_XUDF)) {
+				/* we will be handling it in this loop itself */
+				if (status & (I2C_STAT_XDR | I2C_STAT_XRDY)) {
+					D1("UNDF[%d]\n", count);
+					status &= ~I2C_STAT_XUDF;
+				}
+				omap242x_i2c_writew(oadap,
+						    I2C_STAT, I2C_STAT_XUDF);
+				/* Errata: Try the entire transfer again!! */
+				ret = -EAGAIN;
+				goto xfer_exit;
+
+			}
+			if (status & (I2C_STAT_XRDY | I2C_STAT_XDR)) {
+				u16 num_bytes = 0;
+				u16 clr_status = 0;
+				/* Read the num bytes to copy from buf-stat reg */
+				if (status & I2C_STAT_XRDY) {
+					num_bytes = fifo_sel + 1;
+					clr_status = I2C_STAT_XRDY;
+				} else {	/* XDR */
+					u16 reg = omap242x_i2c_readw(oadap,
+								     I2C_BUFSTAT);
+					num_bytes =
+					    (reg >>
+					     I2C_BUFSTAT_TXLEVEL) &
+					    I2C_BUFSTAT_TXLEVEL_M;
+					D1("++[%x,%d]>", reg, num_bytes);
+					clr_status = I2C_STAT_XDR;
+				}
+
+				D1("***I2C ->XDR %d thrsh %d count %d"
+				   " len %d xrdy = 0x%x xdr 0x%x\n", num_bytes,
+				   fifo_sel + 1, count,
+				   msg->len, status & I2C_STAT_XRDY,
+				   status & I2C_STAT_XDR);
+				if (msg->flags & I2C_M_RD) {
+					D1
+					    ("Unexpected Tx interrupt during I2C Read");
+					ret = -EREMOTEIO;
+					goto xfer_exit;
+				}
+				while (num_bytes) {
+					/* Copy as much as required */
+					if (count < msg->len) {
+						data = msg->buf[count++];
+						omap242x_i2c_writeb(oadap,
+								    I2C_DATA,
+								    (u8) (data &
+									  0xFF));
+						D3("I2C data word tx");
+					} else
+						break;
+					num_bytes--;
+				}
+				omap242x_i2c_writew(oadap,
+						    I2C_STAT, clr_status);
+				status &= ~(I2C_STAT_XDR | I2C_STAT_XRDY);
+			}
+			if (status & (I2C_STAT_ROVR)) {
+				/* we will be handling it in this loop itself */
+				if (status & (I2C_STAT_RDR | I2C_STAT_RRDY)) {
+					status &= ~I2C_STAT_ROVR;
+				}
+				D1("ROVR[%d]\n", count);
+				omap242x_i2c_writew(oadap,
+						    I2C_STAT, I2C_STAT_ROVR);
+			}
+			if (status & (I2C_STAT_RDR | I2C_STAT_RRDY)) {
+				/* Read the num bytes to copy from buf-stat reg */
+				u16 num_bytes = 0;
+				u16 clr_status = 0;
+
+				if (status & I2C_STAT_RRDY) {
+					num_bytes = fifo_sel + 1;
+					clr_status = I2C_STAT_RRDY;
+				} else {	/* RDR */
+					clr_status = I2C_STAT_RDR;
+					num_bytes =
+					    (omap242x_i2c_readw
+					     (oadap,
+					      I2C_BUFSTAT) >>
+					     I2C_BUFSTAT_RXLEVEL) &
+					    I2C_BUFSTAT_RXLEVEL_M;
+				}
+				D1("***I2C ->RDR %d thrsh %d count %d len %d"
+				   " stat-rrdy 0x%x rdr 0x%x\n", num_bytes,
+				   fifo_sel, count,
+				   msg->len, status & I2C_STAT_RRDY,
+				   status & I2C_STAT_RDR);
+				if (!(msg->flags & I2C_M_RD)) {
+					D1("Unexpected Rx interrupt during I2C Write");
+					ret = -EREMOTEIO;
+					goto xfer_exit;
+				}
+				while (num_bytes) {
+					if (count < msg->len) {
+						data =
+						    omap242x_i2c_readb(oadap,
+								       I2C_DATA);
+						msg->buf[count++] = (u8) data;
+					} else {
+						/* we might get transient rrdy/rdr */
+						break;
+					}
+					num_bytes--;
+				}
+				omap242x_i2c_writew(oadap,
+						    I2C_STAT, clr_status);
+				status &= ~(I2C_STAT_RDR | I2C_STAT_RRDY);
+			}
+		}
+	}
+	D1("Retry limit reached--I2C xfer aborted");
+	ret = -EREMOTEIO;
+      xfer_exit:
+	if (ret < 0) {
+		/* Disable the controller */
+		omap242x_i2c_writew(oadap, I2C_CON, 0);
+	}
+	FN_OUT(ret);
+	return ret;
+}
+
+/** 
+ * @brief omap24xx_i2c_xfer
+ * Read or write to an I2C device. 
+ *
+ * @param adap 
+ * @param msgs 
+ * @param num 
+ * 
+ * @return Returns num if all messages are transferred successfully, or a 
+ * negative error code otherwise.  
+ */
+static int omap24xx_i2c_xfer(struct
+			     i2c_adapter
+			     *adap, struct i2c_msg msgs[], int num)
+{
+	struct omap24xx_i2c_adapter
+	*oadap = (struct omap24xx_i2c_adapter *)
+	    adap->algo_data;
+	int retries = 0;
+	struct i2c_msg *pmsg;
+	int i, ret;
+	FN_IN;
+	omap24xx_i2c_suspend_lockout_queue(&i2c_suspend_data, oadap->a_num);
+	if (i2c_wait_while_bb(oadap)) {
+		/* The bus is still busy.  We're going to reset our I2C bus
+		 * controller and then go ahead with our transfer regardless.
+		 */
+		D3("Resetting I2C controller.");
+		i2c_hw_init(oadap);
+	}
+
+	for (i = 0; i < num; i++) {
+		pmsg = &msgs[i];
+		ret = omap24xx_i2c_xfer_msg(oadap, pmsg, (i == (num - 1)));
+		/* If retry required */
+		if (ret == -EAGAIN) {
+			retries++;
+			if (retries >= adap->retries) {
+				return -EREMOTEIO;
+			}
+			i2c_hw_init(oadap);
+			i=0;
+			continue;
+		}
+		if (ret < pmsg->len) {
+			D1("I2C transfer failed.  Resetting I2C controller.-[0x%x]\n", -ret);
+			i2c_hw_init(oadap);
+			FN_OUT((ret < 0) ? ret : -EREMOTEIO);
+			return (ret < 0) ? ret : -EREMOTEIO;
+		}
+	}
+	FN_OUT(num);
+	return num;
+}
+
+/** 
+ * @brief omap24xx_i2c_func
+ *  return the functional capability of the adaptor
+ * @param adap 
+ * 
+ * @return Functional capability in the form of the adap flags
+ */
+static u32 omap24xx_i2c_func(struct
+			     i2c_adapter
+			     *adap)
+{
+	FN_IN;
+	FN_OUT(adap->flags);
+	return (adap->flags);
+}
+
+#ifdef CONFIG_PM
+#ifdef I2C_DPM_SCALE
+/** 
+ * @brief omap24xx_i2c_scale
+ * nothing to do in scale() now--placeholder only - need to look once DMA enabled 
+ * 
+ * @param op 
+ * @param level 
+ * 
+ * @return  0
+ */
+static int omap24xx_i2c_scale(struct notifier_block *op, unsigned long level, void * newop)
+{
+	FN_IN;
+	switch (level) {
+	case SCALE_PRECHANGE:
+		break;
+	case SCALE_POSTCHANGE:
+		break;
+	}
+	FN_OUT(0);
+	return 0;
+}
+#endif
+ /** 
+ * @brief omap24xx_i2c_suspend
+ * Disable the i2c controller and shut down the clocks
+ * Currently using the inbuilt LDM. Need to move to CONFIG_DPM style
+ * 
+ * @param odev 
+ * @param state 
+ * @param level 
+ * 
+ * @return 0
+ */
+static int omap24xx_i2c_suspend(struct
+				omap_dev
+				*odev, u32 state)
+{
+	struct omap24xx_i2c_adapter
+	*oadap = omap_get_drvdata(odev);
+	dpm_state[oadap->a_num] = state;
+	FN_IN;
+
+	switch (state) {
+		case 0:
+			break;
+		case 1:		
+		case 2:
+			prcm_autoidle_ctrl(prcm_i2c[oadap->a_num], ENABLE);
+			break;
+		case 3:
+			D3("suspend%d\n", oadap->a_num);
+			i2c_wait_while_bb(oadap);
+			i2c_suspend_data[oadap->a_num].suspended = 1;
+			/* disable the I2C controller */
+			omap242x_i2c_writew(oadap, I2C_CON, 0);
+			/* Down the clocks */
+			disable_i2c_clock(oadap->a_num);
+			break;
+		default:
+			break;
+	}
+	FN_OUT(0);
+	return 0;
+}
+
+/** 
+ * @brief omap24xx_i2c_resume
+ * 
+ * @param odev 
+ * @param level 
+ * 
+ * @return 0
+ */
+static int omap24xx_i2c_resume(struct
+			       omap_dev
+			       *odev)
+{
+	struct omap24xx_i2c_adapter
+	*oadap = omap_get_drvdata(odev);
+	FN_IN;
+
+	switch (dpm_state[oadap->a_num]) {
+		case 0:
+			break;
+		case 1:		
+		case 2:	
+			prcm_autoidle_ctrl(prcm_i2c[oadap->a_num], DISABLE);
+			break;
+		case 3:
+			enable_i2c_clock(oadap->a_num, oadap->s_clock);
+			i2c_hw_init(oadap);
+			i2c_suspend_data[oadap->a_num].suspended = 0;
+			wake_up(&i2c_suspend_data[oadap->a_num].suspend_wq);
+			D3("resume%d\n", oadap->a_num);
+			break;
+		default:
+			break;
+	}
+	return 0;
+}
+
+/** 
+ * @brief omap24xx_i2c_probe
+ * Dummy entry point.. nothing to do
+ * @param odev 
+ * 
+ * @return 
+ */
+static int omap24xx_i2c_probe(struct
+			      omap_dev
+			      *odev)
+{
+	FN_OUT(0);
+	return 0;
+}
+
+static struct omap_driver i2c_driver_ldm = {
+	.drv = {
+		.name = "i2c-adap-omap24xx",
+		},
+
+	.devid = OMAP24xx_I2C_DEVID,
+	.busid = OMAP_BUS_L4,
+	.clocks = 0,
+	.probe = omap24xx_i2c_probe,
+	.suspend = omap24xx_i2c_suspend,
+	.resume = omap24xx_i2c_resume,
+};
+
+#ifdef CONFIG_DPM
+static struct constraints i2c_omap_constraints1 = {
+	.count = 2,
+	.param = {
+		  {DPM_MD_V, 1050, 1300},
+		  {DPM_MD_PWRST_CORE, 1, 1},	/* 1 = PRCM_ON */
+		  },
+};
+
+static struct constraints i2c_omap_constraints2 = {
+	.count = 2,
+	.param = {
+		  {DPM_MD_V, 1050, 1300},
+		  {DPM_MD_PWRST_CORE, 1, 1},	/* 1 = PRCM_ON */
+		  },
+};
+#endif
+
+
+/* require Dummy release */
+static void dummy_release (struct device * dev)
+{
+	/* nothing to do */
+}
+
+static struct omap_dev i2c_device_ldm[NUM_I2C_ADAP] = {
+	{
+	 .name = "OMAP24xx I2C 0",
+	 .devid = OMAP24xx_I2C_DEVID,
+	 .busid = OMAP_BUS_L4,	/* based on L4 Core */
+	 .dev = {
+		 .release = dummy_release,
+#ifdef CONFIG_DPM
+		 .constraints = &i2c_omap_constraints1,
+#endif
+		 },
+	 }, {
+	     .name = "OMAP24xx I2C 1",
+	     .devid = OMAP24xx_I2C_DEVID,
+	     .busid = OMAP_BUS_L4,	/* based on L4 Core */
+	     .dev = {
+		     .release = dummy_release,
+#ifdef CONFIG_DPM
+		     .constraints = &i2c_omap_constraints2,
+#endif
+		     },
+	     },
+};
+
+#endif				/* DPM */
+
+/* -----exported algorithm data: -------------------------------------	*/
+
+static struct i2c_algorithm omap24xx_i2c_algo = {
+	.master_xfer = omap24xx_i2c_xfer,
+	.functionality = omap24xx_i2c_func,
+};
+
+/** 
+ * @brief omap24xx_i2c_add_bus
+ * registering functions to load algorithms at runtime
+ * 
+ * @param adap 
+ * 
+ * @return  status of i2c_add_adaptor
+ */
+static int omap24xx_i2c_add_bus(struct
+				i2c_adapter
+				*adap)
+{
+	FN_IN;
+	adap->algo = &omap24xx_i2c_algo;
+	adap->timeout = (I2C_DEFAULT_TIMEOUT_MS * HZ) / 1000;
+	if (!adap->timeout) {
+		adap->timeout = 1;
+	}
+	adap->retries = I2C_DEFAULT_RETRIES;
+	FN_OUT(0);
+	return i2c_add_adapter(adap);
+}
+
+/** 
+ * @brief omap24xx_i2c_del_bus
+ * 
+ * @param adap 
+ * 
+ * @return 0
+ */
+static int omap24xx_i2c_del_bus(struct
+				i2c_adapter
+				*adap)
+{
+	FN_IN;
+	FN_OUT(0);
+	return i2c_del_adapter(adap);
+}
+
+/** 
+ * @brief omap24xx_i2c_exit
+ * I2C Module Shutdown
+ */
+void omap24xx_i2c_exit(void)
+{
+	struct omap24xx_i2c_adapter
+	*oadap;
+	struct i2c_adapter *adap;
+	int i;
+	FN_IN;
+	for (i = NUM_I2C_ADAP - 1; i >= 0; i--) {
+		oadap = saved_oadap[i];
+		if (!oadap)
+			continue;
+		adap = &oadap->adap;
+		if (oadap->irq) {
+			free_irq(oadap->irq, oadap);
+			oadap->irq = 0;
+			omap24xx_i2c_del_bus(adap);
+		}
+#ifdef CONFIG_PM
+		if (omap_get_drvdata(&i2c_device_ldm[i]) == oadap) {
+			omap_device_unregister(&i2c_device_ldm[i]);
+		}
+#endif
+		if (oadap->scl_lh) {
+			/* shut down i2c only if we were at the last leg */
+			i2c_hw_release(oadap);
+			disable_i2c_clock(i);
+		}
+		kfree(oadap);
+		saved_oadap[i] = NULL;
+	}
+
+#ifdef  CONFIG_PM
+	omap_driver_unregister(&i2c_driver_ldm);
+#ifdef I2C_DPM_SCALE
+	/* To be enabled on implementing DMA */
+	dpm_unregister_scale(&omap24xxi2c_pre_scale,SCALE_PRECHANGE);
+	dpm_unregister_scale(&omap24xxi2c_post_scale,SCALE_POSTCHANGE);
+#endif
+#endif
+	FN_OUT(0);
+}
+
+/** 
+ * @brief omap24xx_i2c_init
+ * I2C Module Startup
+ * 
+ * @return 0 for success, else return error condition
+ */
+int __init omap24xx_i2c_init(void)
+{
+	struct omap24xx_i2c_adapter
+	*oadap;
+	struct i2c_adapter *adap = NULL;
+	int i;
+#ifdef CONFIG_PM
+	int ret;
+#endif
+	const static unsigned long reg_addr[] =
+	    { I2C1_REG_BASE, I2C2_REG_BASE };
+	const static int i2c_irq[] = { INT_I2C1_IRQ, INT_I2C2_IRQ };
+	const static char *i2c_name[] = { I2C_NAME "-1", I2C_NAME "-2" };
+	int i2c_clock = 0, s_clock = 0, psc = 0, scl_lh = 0, iclk = 0;
+	FN_IN;
+#ifdef CONFIG_PM
+	ret = omap_driver_register(&i2c_driver_ldm);
+	if (ret) {
+		FN_OUT(ret);
+		return ret;
+	}
+#ifdef I2C_DPM_SCALE
+	/* To be enabled on implementing DMA */
+	dpm_register_scale(&omap24xxi2c_pre_scale,SCALE_PRECHANGE);
+	dpm_register_scale(&omap24xxi2c_post_scale,SCALE_POSTCHANGE);
+#endif
+	init_waitqueue_head(&i2c_suspend_data[0].suspend_wq);
+	init_waitqueue_head(&i2c_suspend_data[1].suspend_wq);
+#endif
+#ifdef I2C_SECONDARY_PULL
+	/* Enables the internal secondary pull-up inside the HS
+	 * I2C pad when the I2C is in High-Speed mode and the
+	 * bus line capacitance is exceeding 45 pF.
+	 * Valid only for ES2.0 and above
+	 */
+	if (get_cpu_rev()>=2) {
+		u32 reg = readl(CONTROL_PBIAS_LITE_1);
+		reg &=~(PULL_HS_BUS0|PULL_HS_BUS1);
+		reg |= I2C_SECONDARY_PULL;
+		writel(reg, CONTROL_PBIAS_LITE_1);
+	}
+#endif
+	/* initialize each I2C controller */
+	for (i = 0; i < NUM_I2C_ADAP; i++) {
+		int temp_i2c_clk = i2c_clock;
+		oadap =
+		    kmalloc(sizeof(struct omap24xx_i2c_adapter), GFP_KERNEL);
+		if (!oadap) {
+			printk(KERN_ERR I2C_NAME
+			       ": could not allocate memory\n");
+			goto init_error;
+		}
+		memset(oadap, 0, sizeof(struct omap24xx_i2c_adapter));
+		oadap->a_num = i;
+		saved_oadap[i] = oadap;
+		switch (i) {
+		case 0:
+			i2c_clock = i2c_clock0;
+			break;
+		case 1:
+			i2c_clock = i2c_clock1;
+			break;
+		default:
+			printk(KERN_ERR I2C_NAME ": Unknown bus\n");
+			goto init_error;
+		}
+
+		/* initialize the i2c_adapter struct */
+		adap = &oadap->adap;
+		adap->algo_data = oadap;
+		/* Get the default speed of the device */
+		if (i2c_clock > OMAP_I2C_FAST_MODE) {
+			adap->flags |= I2C_FUNC_HIGH_SPEED;
+		}
+
+		/* We delete I2C_FUNC_SMBUS_QUICK from our list of capabilities
+		 * because that requires the ability to generate messages with
+		 * zero bytes of data.  The OMAP I2C controller is not able to do
+		 * this.  The lack of this feature prevents probing for I2C devices.
+		 */
+		adap->flags |=
+		    (((I2C_FUNC_SMBUS_EMUL) & ~(I2C_FUNC_SMBUS_QUICK))
+		     | I2C_FUNC_10BIT_ADDR);
+		strcpy(adap->name, i2c_name[i]);
+#if (I2C_LOG_LEVEL >= 1)
+		oadap->mmio_base_phys = reg_addr[i];
+#endif
+		/* IMP NOTE: Despite what the TRM says as of now, the confirmation 
+		 * from h/w team is that we are to use only the 96 Meg Fn clock 
+		 * and compute based on that. 
+		 */
+		s_clock = SYSTEM_CLOCK_96;
+		/* clock setting is a single time affair */
+		D2("clock(s,i)[%d] -> (%d,%d)\n", i, s_clock, i2c_clock);
+		if (enable_i2c_clock(i, s_clock)) {
+			printk(KERN_ERR
+			       "%s: Could not set Required system clock \n",
+			       adap->name);
+			goto init_error;
+		}
+		/* PSC selection Logic - look for the highest PSC setting
+		 * that returns a non negative dev value for a given iCLK mode
+		 */
+		psc = I2C_PSC_MAX;
+		while (psc >= I2C_PSC_MIN) {
+			temp_i2c_clk = i2c_clock;
+			iclk = s_clock / (psc + 1);
+			/* In HS mode Ignore the FS settting.. look 
+			 * for Fast Mode settings 
+			 */
+			if (i2c_clock > OMAP_I2C_FAST_MODE) {
+				temp_i2c_clk = OMAP_I2C_FAST_MODE;
+			}
+			scl_lh = (iclk * 10 / (temp_i2c_clk * 2));
+			/* Check for decimal places.. if yes, we ignore it
+			 * Need a perfect match for it to work!!
+			 */
+			if (scl_lh % 10) {
+				scl_lh = -1;
+			} else {
+				scl_lh /= 10;
+				/* Thigh and Tlow use 5 and 7 differences, 
+				 * hence use 6 as the difference computation
+				 */
+				scl_lh -= 6;
+			}
+			/* Values for F/S mode and first phase of HS mode */
+			if (((i2c_clock > OMAP_I2C_STANDARD)
+			     && (scl_lh >= I2C_SCLLH_MIN))
+			    || (((i2c_clock <= OMAP_I2C_STANDARD)
+				 && (scl_lh >= 0)))) {
+				D1("Match! sclk=%d psc=0x%x"
+				   " iclk=%d i2c_clk=%d scl_lh=0x%x\n",
+				   s_clock, psc, iclk, i2c_clock, scl_lh);
+				break;
+			}
+			psc--;
+		}
+		/* Did not find an optimal config */
+		if (psc < I2C_PSC_MIN) {
+			printk(KERN_ERR
+			       "%s: Unable to set Prescalar for i2c_clock=%d sys_clock=%d\n",
+			       adap->name, i2c_clock, s_clock);
+			goto init_error;
+		}
+
+		/* Reset the SCL_LH */
+		scl_lh = 0;
+		/* temp_i2c_clk and iclk already set in for loop */
+		if (i2c_clock > OMAP_I2C_FAST_MODE) {
+			scl_lh =
+			    (((s_clock / ((i2c_clock) * 2)) -
+			      6) & I2C_SCLH_HSSCLL_M);
+			if (scl_lh < I2C_HSSCLLH_MIN) {
+				printk(KERN_ERR
+				       "%s: Unable to set HSSCLH for i2c_clock=%d sys_clock=%d scl_lh=0x%x min =0x%x\n",
+				       adap->name, i2c_clock,
+				       s_clock, scl_lh, I2C_HSSCLLH_MIN);
+				goto init_error;
+			}
+			scl_lh = scl_lh << I2C_SCLL_HSSCLL;
+		}
+		scl_lh |=
+		    (((iclk / (temp_i2c_clk * 2)) -
+		      6) & I2C_SCLL_SCLL_M) << I2C_SCLL_SCLL;
+		D2("Match! sclk=%d psc=0x%x iclk=%d temp_i2c_clk=%d "
+		   "i2c_clk=%d scl_lh=0x%x\n", s_clock, psc, iclk, temp_i2c_clk,
+		   i2c_clock, scl_lh);
+		oadap->psc = psc;
+		oadap->scl_lh = scl_lh;
+		oadap->s_clock = s_clock;
+		oadap->oa = I2C_OWN_ADDRESS;
+		oadap->mcode = I2C_MCODE;	/* needed for HS transfer */
+		/* Dont need to re-map an already remapped address 
+		 * L4Core and wakeup are default mapped 
+		 */
+		oadap->mmio_base = (unsigned long)
+		    IO_ADDRESS(reg_addr[i]);
+		D2("PHY=0x%x,IO=0x%x\n",
+		   (unsigned int)reg_addr[i], (unsigned int)oadap->mmio_base);
+
+		/* Grab the adapter fifo size */
+		oadap->rx_fifo_size =
+		    (omap242x_i2c_readw(oadap, I2C_BUFSTAT) >>
+		     I2C_BUFSTAT_FIFO_DEPTH) & I2C_BUFSTAT_FIFO_DEPTH_M;
+		/* Fifo sizes is 2^(buffstat:fifodepth) * 8 */
+		oadap->rx_fifo_size = (0x1 << oadap->rx_fifo_size) * 8;
+		oadap->tx_fifo_size =
+		    (oadap->rx_fifo_size <
+		     I2C_BUF_TRSH_TX) ? oadap->rx_fifo_size : I2C_BUF_TRSH_TX;
+		oadap->rx_fifo_size -=
+		    (oadap->rx_fifo_size <
+		     I2C_BUF_TRSH_RX) ? oadap->rx_fifo_size : I2C_BUF_TRSH_RX;
+
+		adap->retries = I2C_DEFAULT_RETRIES;
+		D1( "%s: %s I2C bus controller at  PA 0x%08lx, VA 0x%08lx, irq %d\n",
+		       adap->name,
+		       (i2c_clock <= OMAP_I2C_STANDARD) ? "STD" :
+		       (i2c_clock <= OMAP_I2C_FAST_MODE) ? "FM" : "HS",
+		       reg_addr[i], oadap->mmio_base, oadap->irq);
+		init_waitqueue_head(&oadap->i2c_wait_queue);
+
+		if (i2c_hw_init(oadap) < 0) {
+			printk(KERN_ERR
+			       "%s: cannot reset I2C controller\n", adap->name);
+			goto init_error;
+		}
+
+		if (request_irq
+		    (i2c_irq[i],
+		     omap24xx_i2c_handler, 0, adap->name, oadap) < 0) {
+			printk(KERN_ERR
+			       "%s: cannot intall handler for irq"
+			       " %d\n", adap->name, i2c_irq[i]);
+			goto init_error;
+		}
+		oadap->irq = i2c_irq[i];
+		if (omap24xx_i2c_add_bus(adap) < 0) {
+			printk(KERN_ERR
+			       "%s: cannot register I2C adapter\n", adap->name);
+			goto init_error;
+		}
+#ifdef CONFIG_PM
+		if (omap_device_register(&i2c_device_ldm[i])) {
+			printk(KERN_ERR
+			       "%s: cannot register I2C adapter with LDM\n",
+			       adap->name);
+			goto init_error;
+		}
+		/* set driver specific data to use in power mgmt functions */
+		omap_set_drvdata(&i2c_device_ldm[i], oadap);
+#endif
+	}
+	FN_OUT(0);
+	return 0;
+      init_error:
+	/* call our exit routine to cleanup */
+	omap24xx_i2c_exit();
+	for (i = 0; i < NUM_I2C_ADAP; i++) {
+		printk(KERN_ERR
+		       "%s: I2C driver installation failed!\n", i2c_name[i]);
+	}
+	FN_OUT(ENODEV);
+	return -ENODEV;
+}
+
+/* i2c functional clock settings */
+/* FS-Standard mode */
+int enable_i2c_clock(int i2c_module, int clocksrc)
+{
+	struct device *dev = NULL;
+	struct clk *i2ci, *i2cf, *i2chsf;
+	char use_i2cf = 1;
+	char use_hsi2cf = 0;
+	if (i2c_module == 0) {
+		i2ci = clk_get(dev, "i2c1_ick");
+		i2cf = clk_get(dev, "i2c1_fck");
+		i2chsf = clk_get(dev, "i2chs1_fck");
+	} else {
+		i2ci = clk_get(dev, "i2c2_ick");
+		i2cf = clk_get(dev, "i2c2_fck");
+		i2chsf = clk_get(dev, "i2chs2_fck");
+	}
+
+	if (clocksrc == 96000) {
+		use_i2cf = 0;
+		use_hsi2cf = 1;
+	}
+
+	/* down them 
+	clk_unuse(i2ci);
+	clk_unuse(i2cf);
+	clk_unuse(i2chsf);
+	*/
+	
+	/* enable them */
+	if (use_i2cf) {
+		clk_enable(i2cf);
+	}
+	if (use_hsi2cf) {
+		clk_enable(i2chsf);
+	}
+
+	clk_enable(i2ci);
+	return 0;
+}
+
+void disable_i2c_clock(int i2c_module)
+{
+	struct device *dev = NULL;
+	struct clk *i2ci, *i2cf, *i2chsf;
+	if (i2c_module == 0) {
+		i2ci = clk_get(dev, "i2c1_ick");
+		i2cf = clk_get(dev, "i2c1_fck");
+		i2chsf = clk_get(dev, "i2chs1_fck");
+	} else {
+		i2ci = clk_get(dev, "i2c2_ick");
+		i2cf = clk_get(dev, "i2c2_fck");
+		i2chsf = clk_get(dev, "i2chs2_fck");
+	}
+
+	/* down them */
+	clk_disable(i2ci);
+	clk_disable(i2cf);
+	clk_disable(i2chsf);
+}
+
+MODULE_AUTHOR("MontaVista Software, Inc.");
+MODULE_DESCRIPTION("OMAP24xx I2C bus adapter");
+MODULE_LICENSE("GPL");
+
+/* i2c may be needed to bring up other drivers */
+subsys_initcall(omap24xx_i2c_init);
+module_exit(omap24xx_i2c_exit);
diff -purN linux-omap/drivers/i2c/busses/i2c-omap_hs.h lin_for_twl/drivers/i2c/busses/i2c-omap_hs.h
--- linux-omap/drivers/i2c/busses/i2c-omap_hs.h	1969-12-31 18:00:00.000000000 -0600
+++ lin_for_twl/drivers/i2c/busses/i2c-omap_hs.h	2007-02-27 17:43:17.000000000 -0600
@@ -0,0 +1,210 @@
+/*
+ * drivers/i2c/i2c-omap243x.h
+ *
+ * I2C driver for OMAP242x I2C controller.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License 
+ * version 2. This program is licensed "as is" without any warranty of any 
+ * kind, whether express or implied.
+ *
+ * History:
+ * -------
+ * Aug 2005 - Copied from drivers/i2c/i2c-omap24xx.h and ported to 
+ *            243X and added support for HSI2C - Texas Instruments 
+ */
+
+#ifndef OMAP243XI2C_H
+#define OMAP243XI2C_H
+
+/* Grab the base address */
+#include <asm/arch/hardware.h>
+
+/* physical memory map definitions -same for 2420-2430 -HS support in 2430*/
+/* I2C1 module */
+#define I2C1_REG_BASE        (0x48000000 + 0x70000)
+#define I2C1_REG_SIZE        0x00001000 /* unused as of now */
+/* I2C2 module */
+#define I2C2_REG_BASE        (0x48000000 + 0x72000)
+#define I2C2_REG_SIZE        0x00001000 /* unused as of now */
+
+/* define I2C register offsets */
+#define I2C_REV              0x00
+#define I2C_IE               0x04
+#define I2C_STAT             0x08
+#define I2C_WE               0x0C
+#define I2C_SYSS             0x10
+#define I2C_BUF              0x14
+#define I2C_CNT              0x18
+#define I2C_DATA             0x1C
+#define I2C_SYSC             0x20
+#define I2C_CON              0x24
+#define I2C_OA               0x28
+#define I2C_SA               0x2C
+#define I2C_PSC              0x30
+#define I2C_SCLL             0x34
+#define I2C_SCLH             0x38
+#define I2C_SYSTEST          0x3C
+#define I2C_BUFSTAT          0x40
+#define I2C_OA1              0x44
+#define I2C_OA2              0x48
+#define I2C_OA3              0x4C
+#define I2C_ACTOA            0x50
+#define I2C_SBLOCK           0x54
+
+/* Define bit fields within selected registers */
+#define I2C_REV_MAJOR        (15 << 4)
+#define I2C_REV_MAJOR_SHIFT  (4)
+#define I2C_REV_MINOR        (15 << 0)
+#define I2C_REV_MINOR_SHIFT  (0)
+
+#define I2C_IE_XDR_IE        (1 <<  14)
+#define I2C_IE_RDR_IE        (1 <<  13)
+#define I2C_IE_AAS_IE        (1 <<  9)
+#define I2C_IE_BF_IE         (1 <<  8)
+#define I2C_IE_AERR_IE       (1 <<  7)
+#define I2C_IE_STC_IE        (1 <<  6)
+#define I2C_IE_GC_IE         (1 <<  5)
+#define I2C_IE_XRDY_IE       (1 <<  4)
+#define I2C_IE_RRDY_IE       (1 <<  3)
+#define I2C_IE_ARDY_IE       (1 <<  2)
+#define I2C_IE_NACK_IE       (1 <<  1)
+#define I2C_IE_AL_IE         (1 <<  0)
+
+#define I2C_STAT_XDR         (1 << 14)
+#define I2C_STAT_RDR         (1 << 13)
+#define I2C_STAT_BB          (1 << 12)
+#define I2C_STAT_ROVR        (1 << 11)
+#define I2C_STAT_XUDF        (1 << 10)
+#define I2C_STAT_AAS         (1 <<  9)
+#define I2C_STAT_BF          (1 <<  8)
+#define I2C_STAT_AERR        (1 <<  7)
+#define I2C_STAT_STC         (1 <<  6)
+#define I2C_STAT_GC          (1 <<  5)
+#define I2C_STAT_XRDY        (1 <<  4)
+#define I2C_STAT_RRDY        (1 <<  3)
+#define I2C_STAT_ARDY        (1 <<  2)
+#define I2C_STAT_NACK        (1 <<  1)
+#define I2C_STAT_AL          (1 <<  0)
+
+#define I2C_WE_XDR_WE        (1 <<  14)
+#define I2C_WE_RDR_WE        (1 <<  13)
+#define I2C_WE_AAS_WE        (1 <<  9)
+#define I2C_WE_BF_WE         (1 <<  8)
+#define I2C_WE_AERR_WE       (1 <<  7)
+#define I2C_WE_STC_WE        (1 <<  6)
+#define I2C_WE_GC_WE         (1 <<  5)
+#define I2C_WE_XRDY_WE       (1 <<  4)
+#define I2C_WE_RRDY_WE       (1 <<  3)
+#define I2C_WE_ARDY_WE       (1 <<  2)
+#define I2C_WE_NACK_WE       (1 <<  1)
+#define I2C_WE_AL_WE         (1 <<  0)
+
+#define I2C_SYSS_RDONE       (1 <<  0)
+
+#define I2C_BUF_RDMA_EN      (1 << 15)
+#define I2C_BUF_RXFIFO_CL    (1 << 14)
+#define I2C_BUF_RXTRSH       (8)
+#define I2C_BUF_RXTRSH_M     (0x3F)
+#define I2C_BUF_XDMA_EN      (1 <<  7)
+#define I2C_BUF_TXFIFO_CL    (1 <<  6)
+#define I2C_BUF_TXTRSH       (0)
+#define I2C_BUF_TXTRSH_M     (0x3F)
+
+/* FIFO Divisors for threshold -
+ * the Tx fifo should be as low as possible with out causing a undeflow
+ * Rx fifo should be as high as possible without forcing an overflow 
+ * RX Fifo is from FIFO top and tx trsh is from FIFO bottom 
+ */
+#define I2C_BUF_TRSH_TX              1
+#define I2C_BUF_TRSH_RX              5
+
+#define I2C_SYSC_CLKACT      (8)
+#define I2C_SYSC_CLKACT_M    (0x03)
+#define I2C_SYSC_IDLEMODE    (3)
+#define I2C_SYSC_IDLEMODE_M  (0x03)
+#define I2C_SYSC_EN_WK       (1 <<  2)
+#define I2C_SYSC_SRST        (1 <<  1)
+#define I2C_SYSC_AUTO_IDLE   (1 <<  0)
+
+#define I2C_CON_I2C_EN       (1 << 15)
+#define I2C_CON_OP_MODE      (12)
+#define I2C_CON_OP_MODE_M    (0x03)
+/* 00: I2C Fast/Standard mode
+ * 01: I2C High Speed mode
+ * 10: SCCB mode
+ */
+#define I2C_CON_OP_MODE_FS      (0x00)
+#define I2C_CON_OP_MODE_HS      (0x01)
+#define I2C_CON_OP_MODE_SCCB    (0x02) /* not supported as of now */
+#define I2C_CON_STB          (1 << 11)
+#define I2C_CON_MST          (1 << 10)
+#define I2C_CON_TRX          (1 <<  9)
+#define I2C_CON_XSA          (1 <<  8)
+#define I2C_CON_XOA0         (1 <<  7)
+#define I2C_CON_XOA1         (1 <<  6)
+#define I2C_CON_XOA2         (1 <<  5)
+#define I2C_CON_XOA3         (1 <<  4)
+#define I2C_CON_STP          (1 <<  1)
+#define I2C_CON_STT          (1 <<  0)
+
+#define I2C_PSC_MAX          (0x0f)
+#define I2C_PSC_MIN          (0x04)
+
+#define I2C_OA_MCODE         (13)
+#define I2C_OA_MCODE_M       (0x07)
+#define I2C_OA_OA0           (0)
+#define I2C_OA_OA0_M         (0x3FF)
+
+#define I2C_SCLL_SCLL        (0)
+#define I2C_SCLL_SCLL_M      (0xFF)
+#define I2C_SCLL_HSSCLL      (8)
+#define I2C_SCLH_HSSCLL_M    (0xFF)
+#define I2C_SCLH_SCLH        (0)
+#define I2C_SCLH_SCLH_M      (0xFF)
+#define I2C_SCLH_HSSCLH      (8)
+#define I2C_SCLH_HSSCLH_M    (0xFF)
+#define I2C_SCLLH_MIN        (0x12)
+#define I2C_HSSCLLH_MIN      (0x0C)
+
+#define I2C_SYSTEST_ST_EN    (1 << 15)
+#define I2C_SYSTEST_FREE     (1 << 14)
+#define I2C_SYSTEST_TMODE    (3 << 12)
+#define I2C_SYSTEST_TMODE_FUNCTIONAL   (0 << 12)
+#define I2C_SYSTEST_TMODE_CLOCK        (2 << 12)
+#define I2C_SYSTEST_TMODE_LOOPBACK     (3 << 12)
+#define I2C_SYSTEST_SCCB_E_O (1 <<  4)
+#define I2C_SYSTEST_SCL_I    (1 <<  3)
+#define I2C_SYSTEST_SCL_O    (1 <<  2)
+#define I2C_SYSTEST_SDA_I    (1 <<  1)
+#define I2C_SYSTEST_SDA_O    (1 <<  0)
+
+#define I2C_BUFSTAT_FIFO_DEPTH         (14)
+#define I2C_BUFSTAT_FIFO_DEPTH_M       (0x03)
+#define I2C_BUFSTAT_RXLEVEL            (8)
+#define I2C_BUFSTAT_RXLEVEL_M          (0x3F)
+#define I2C_BUFSTAT_TXLEVEL            (0)
+#define I2C_BUFSTAT_TXLEVEL_M          (0x3F)
+
+#define I2C_ACTOA_OA3_ACT     (1 <<  3)
+#define I2C_ACTOA_OA2_ACT     (1 <<  2)
+#define I2C_ACTOA_OA1_ACT     (1 <<  1)
+#define I2C_ACTOA_OA0_ACT     (1 <<  0)
+
+#define I2C_SBLOCK_OA3_EN     (1 <<  3)
+#define I2C_SBLOCK_OA2_EN     (1 <<  2)
+#define I2C_SBLOCK_OA1_EN     (1 <<  1)
+#define I2C_SBLOCK_OA0_EN     (1 <<  0)
+#define OMAP_I2C_STANDARD          100
+#define OMAP_I2C_FAST_MODE         400
+#define OMAP_I2C_HIGH_SPEED        3400
+
+
+#define SYSTEM_CLOCK_12       12000
+#define SYSTEM_CLOCK_96       96000
+
+#endif    /* ifndef OMAP243XI2C_H */

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-02-28  1:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-16 11:25 I2C TWL4030 Keypad Ram
2007-02-16 14:31 ` G, Manjunath Kondaiah
     [not found]   ` <8bf247760702160650s62d2b401lad8746881aedd2aa@mail.gmail.com>
2007-02-16 15:08     ` Ram
2007-02-16 15:38       ` Syed Mohammed, Khasim
2007-02-17 13:45 ` Nishanth Menon
     [not found]   ` <8bf247760702170604h5b2e210cibe4de58d4f898d74@mail.gmail.com>
2007-02-17 14:08     ` Nishanth Menon
2007-02-18  8:00       ` Setting the default state (high or low) of a pin zil iram
2007-02-26 17:38 ` I2C TWL4030 Keypad Cantu Castillo, Arturo
2007-02-27  6:20   ` Ram
2007-02-27 15:09     ` Syed Mohammed, Khasim
2007-02-28  1:00     ` Syed Mohammed, Khasim
2007-02-28  1:02 Syed Mohammed, Khasim
2007-02-28  1:05 Syed Mohammed, Khasim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.