i2c-adap-pxa.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  i2c_adap_pxa.c
  3.  *
  4.  *  I2C adapter for the PXA I2C bus access.
  5.  *
  6.  *  Copyright (C) 2002 Intrinsyc Software Inc.
  7.  * 
  8.  *  This program is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License version 2 as
  10.  *  published by the Free Software Foundation.
  11.  *
  12.  *  History:
  13.  *    Apr 2002: Initial version [CS]
  14.  *    Jun 2002: Properly seperated algo/adap [FB]
  15.  */
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/i2c.h>
  19. #include <linux/i2c-id.h>
  20. #include <linux/init.h>
  21. #include <linux/time.h>
  22. #include <linux/sched.h>
  23. #include <linux/delay.h>
  24. #include <asm/hardware.h>
  25. #include <asm/irq.h>
  26. #include <asm/arch/irqs.h>              /* for IRQ_I2C */
  27. #include "i2c-pxa.h"
  28. /*
  29.  * Set this to zero to remove all the debug statements via dead code elimination.
  30.  */
  31. //#define DEBUG       1
  32. #if DEBUG
  33. static unsigned int i2c_debug = DEBUG;
  34. #else
  35. #define i2c_debug 0
  36. #endif
  37. static int irq = 0;
  38. static int i2c_pending = 0;             /* interrupt pending when 1 */
  39. static volatile int bus_error = 0;
  40. static volatile int tx_finished = 0;
  41. static volatile int rx_finished = 0;
  42. static wait_queue_head_t i2c_wait;
  43. /* place a byte in the transmit register */
  44. static void i2c_pxa_write_byte(u8 value) 
  45. {
  46.         IDBR = value;
  47. }
  48. /* read byte in the receive register */
  49. static u8 i2c_pxa_read_byte(void) 
  50. {
  51.         return (u8) (0xff & IDBR);
  52. }
  53. static void i2c_pxa_start(void)
  54. {
  55. ICR |= ICR_START;
  56. ICR &= ~(ICR_STOP | ICR_ALDIE | ICR_ACKNAK);
  57. bus_error=0;            /* clear any bus_error from previous txfers */
  58. tx_finished=0;          /* clear rx and tx interrupts from previous txfers */
  59. rx_finished=0;
  60. }
  61. static void i2c_pxa_repeat_start(void)
  62. {
  63. ICR |= ICR_START;
  64. ICR &= ~(ICR_STOP | ICR_ALDIE);
  65. bus_error=0;            /* clear any bus_error from previous txfers */
  66. tx_finished=0;          /* clear rx and tx interrupts from previous txfers */
  67. rx_finished=0;
  68. }
  69. static void i2c_pxa_stop(void)
  70. {
  71. ICR |= ICR_STOP;
  72. ICR &= ~(ICR_START);
  73. }
  74. static void i2c_pxa_midbyte(void)
  75. {
  76. ICR &= ~(ICR_START | ICR_STOP);
  77. }
  78. static void i2c_pxa_abort(void)
  79. {
  80. ICR |= ICR_MA;
  81. }
  82. static int i2c_pxa_wait_bus_not_busy( void)
  83. {
  84.         int timeout = DEF_TIMEOUT;
  85.         while (timeout-- && (ISR & ISR_IBB)) {
  86.                 udelay(100); /* wait for 100 us */
  87.         }
  88.         return (timeout<=0);
  89. }
  90. static void i2c_pxa_wait_for_ite(void){
  91. unsigned long flags;
  92. if (irq > 0) {
  93. save_flags_cli(flags);
  94. if (i2c_pending == 0) {
  95. interruptible_sleep_on_timeout(&i2c_wait, I2C_SLEEP_TIMEOUT );
  96. }
  97. i2c_pending = 0;
  98. restore_flags(flags);
  99. } else {
  100. udelay(100);
  101. }
  102. }
  103. static int i2c_pxa_wait_for_int( int wait_type)
  104. {
  105.         int timeout = DEF_TIMEOUT;
  106. #ifdef DEBUG
  107. if (bus_error)
  108. printk(KERN_INFO"i2c_pxa_wait_for_int: Bus error on entern");
  109. if (rx_finished)
  110. printk(KERN_INFO"i2c_pxa_wait_for_int: Receive interrupt on entern");
  111. if (tx_finished)
  112. printk(KERN_INFO"i2c_pxa_wait_for_int: Transmit interrupt on entern");
  113. #endif
  114.         if (wait_type == I2C_RECEIVE){         /* wait on receive */
  115.                 while (timeout-- && !(rx_finished)){
  116.                         i2c_pxa_wait_for_ite();
  117.                 }
  118. #ifdef DEBUG
  119.                 if (timeout<0){
  120.                         if (tx_finished)
  121.                                 printk("Error: i2c-algo-pxa.o: received a tx"
  122.                                         " interrupt while waiting on a rx in wait_for_int");
  123.                 }
  124. #endif
  125.         } else {                  /* wait on transmit */
  126.         
  127.                 while (timeout-- && !(tx_finished)){
  128.                         i2c_pxa_wait_for_ite();
  129.                 }
  130. #ifdef DEBUG
  131.                 if (timeout<0){
  132.                         if (rx_finished)
  133.                                 printk("Error: i2c-algo-pxa.o: received a rx"
  134.                                         " interrupt while waiting on a tx in wait_for_int");
  135.                 }
  136. #endif
  137.         }       
  138.         udelay(ACK_DELAY);      /* this is needed for the bus error */
  139.         tx_finished=0;
  140.         rx_finished=0;
  141.         if (bus_error){
  142.                 bus_error=0;
  143.                 if( i2c_debug > 2)printk("wait_for_int: error - no ack.n");
  144.                 return BUS_ERROR;
  145.         }
  146.         if (timeout <= 0)
  147.                 return(-1);
  148.         else
  149.                 return(0);
  150. }
  151. static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte)
  152. {
  153. if( lastbyte)
  154. {
  155. if( receive==I2C_RECEIVE) ICR |= ICR_ACKNAK; 
  156. i2c_pxa_stop();
  157. }
  158. else if( midbyte)
  159. {
  160. i2c_pxa_midbyte();
  161. }
  162. ICR |= ICR_TB;
  163. }
  164. static void i2c_pxa_reset( void)
  165. {
  166. #ifdef DEBUG
  167. printk("Resetting I2C Controller Unitn");
  168. printk("Status Register  %#xn",ISR);
  169. printk("Control Register %#xn",ICR);
  170. printk("Data Buffer      %#xn",IDBR);
  171. printk("Bus Monitor Reg  %#xn",IBMR);
  172. #endif
  173.         /* disable unit */
  174. ICR &= ~ICR_IUE;
  175.         /* reset the unit */
  176. ICR |= ICR_UR;
  177.         udelay(100);
  178.         /* disable unit */
  179. ICR &= ~ICR_IUE;
  180.         
  181.         /* set the global I2C clock on */
  182.         CKEN |= CKEN14_I2C;
  183.         /* set our slave address */
  184. ISAR = I2C_PXA_SLAVE_ADDR;
  185.         /* set control register values */
  186. ICR = I2C_ICR_INIT;
  187.         /* set clear interrupt bits */
  188. ISR = I2C_ISR_INIT;
  189.         /* enable unit */
  190. ICR |= ICR_IUE;
  191.         udelay(100);
  192. }
  193. static void i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs) 
  194. {
  195.         int status;
  196.         status = (ISR);
  197.         if (status & ISR_BED){
  198.                 (ISR) |= ISR_BED;
  199.                 bus_error=ISR_BED;
  200.         }
  201.         if (status & ISR_ITE){
  202.                 (ISR) |= ISR_ITE;
  203.                 tx_finished=ISR_ITE;
  204.         }
  205.         if (status & ISR_IRF){
  206.                 (ISR) |= ISR_IRF;
  207.                 rx_finished=ISR_IRF;
  208.         }
  209.         i2c_pending = 1;
  210.         wake_up_interruptible(&i2c_wait);
  211. }
  212. static int i2c_pxa_resource_init( void)
  213. {
  214.         init_waitqueue_head(&i2c_wait);
  215.         if (request_irq(IRQ_I2C, &i2c_pxa_handler, SA_INTERRUPT, "I2C_PXA", 0) < 0) {
  216.                 irq = 0;
  217.                 if( i2c_debug)
  218. printk(KERN_INFO "I2C: Failed to register I2C irq %in", IRQ_I2C);
  219.                 return -ENODEV;
  220.         }else{
  221.                 irq = IRQ_I2C;
  222.                 enable_irq(irq);
  223.         }
  224.         return 0;
  225. }
  226. static void i2c_pxa_resource_release( void)
  227. {
  228.         if( irq > 0)
  229.         {
  230.                 disable_irq(irq);
  231.                 free_irq(irq,0);
  232.                 irq=0;
  233.         }
  234. }
  235. static void i2c_pxa_inc_use(struct i2c_adapter *adap)
  236. {
  237. #ifdef MODULE
  238.         MOD_INC_USE_COUNT;
  239. #endif
  240. }
  241. static void i2c_pxa_dec_use(struct i2c_adapter *adap)
  242. {
  243. #ifdef MODULE
  244.         MOD_DEC_USE_COUNT;
  245. #endif
  246. }
  247. static int i2c_pxa_client_register(struct i2c_client *client)
  248. {
  249.         return 0;
  250. }
  251. static int i2c_pxa_client_unregister(struct i2c_client *client)
  252. {
  253.         return 0;
  254. }
  255. static struct i2c_algo_pxa_data i2c_pxa_data = {
  256.         write_byte: i2c_pxa_write_byte,
  257.         read_byte: i2c_pxa_read_byte,
  258.         start: i2c_pxa_start,
  259.         repeat_start: i2c_pxa_repeat_start,
  260.         stop: i2c_pxa_stop,
  261.         abort: i2c_pxa_abort,
  262.         wait_bus_not_busy: i2c_pxa_wait_bus_not_busy,
  263.         wait_for_interrupt: i2c_pxa_wait_for_int,
  264.         transfer: i2c_pxa_transfer,
  265.         reset: i2c_pxa_reset,
  266. udelay: 10,
  267. timeout: DEF_TIMEOUT,
  268. };
  269. static struct i2c_adapter i2c_pxa_ops = {
  270.         name:                   "PXA-I2C-Adapter",
  271.         id:                     I2C_ALGO_PXA,
  272.         algo_data:              &i2c_pxa_data,
  273.         inc_use:                i2c_pxa_inc_use,
  274.         dec_use:                i2c_pxa_dec_use,
  275.         client_register:        i2c_pxa_client_register,
  276.         client_unregister:      i2c_pxa_client_unregister,
  277.         retries:                2,
  278. };
  279. extern int i2c_pxa_add_bus(struct i2c_adapter *);
  280. extern int i2c_pxa_del_bus(struct i2c_adapter *);
  281. static int __init i2c_adap_pxa_init(void)
  282. {
  283.         if( i2c_pxa_resource_init() == 0) {
  284.                 if (i2c_pxa_add_bus(&i2c_pxa_ops) < 0) {
  285.                         i2c_pxa_resource_release();
  286.                         printk(KERN_INFO "I2C: Failed to add busn");
  287.                         return -ENODEV;
  288.                 }
  289.         } else {
  290.                 return -ENODEV;
  291.         }
  292.         printk(KERN_INFO "I2C: Successfully added busn");
  293.         return 0;
  294. }
  295. static void i2c_adap_pxa_exit(void)
  296. {
  297.         i2c_pxa_del_bus( &i2c_pxa_ops);
  298.         i2c_pxa_resource_release();
  299.         printk(KERN_INFO "I2C: Successfully removed busn");
  300. }
  301. module_init(i2c_adap_pxa_init);
  302. module_exit(i2c_adap_pxa_exit);