]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/i2c/i2c_drv.c
Merge branch 'master' into can-usb1
[lincan.git] / embedded / libs4c / i2c / i2c_drv.c
1 /*******************************************************************
2   Components for embedded applications builded for
3   laboratory and medical instruments firmware  
4  
5   i2c_mx1.c - I2C communication automata for M9328 MX1 microcontroller
6  
7   Copyright holders and project originators
8     (C) 2001-2004 by Pavel Pisa pisa@cmp.felk.cvut.cz
9     (C) 2002-2004 by PiKRON Ltd. http://www.pikron.com
10     (C) 2007-2008 by Petr Smolik
11
12  The COLAMI components can be used and copied under next licenses
13    - MPL - Mozilla Public License
14    - GPL - GNU Public License
15    - LGPL - Lesser GNU Public License
16    - and other licenses added by project originators
17  Code can be modified and re-distributed under any combination
18  of the above listed licenses. If contributor does not agree with
19  some of the licenses, he can delete appropriate line.
20  Warning, if you delete all lines, you are not allowed to
21  distribute code or build project.
22  *******************************************************************/
23
24
25 #include <system_def.h>
26 #include <string.h>
27 #include "i2c_drv_config.h"
28 #include "i2c_drv.h"
29
30 /***************************************************************************/
31 int  
32 i2c_drv_init(i2c_drv_t *drv, int port, int irq, int bitrate,int sladr) 
33 {
34   int r=-1;
35   memset(drv,0,sizeof(i2c_drv_t));
36   drv->magic=I2C_DRV_MAGIC;
37  #ifdef CONFIG_OC_I2C_CHIP_C552
38   r=c552_init_start(drv,port,irq,bitrate,sladr);
39  #endif /* CONFIG_OC_I2C_CHIP_C552 */
40   if (r<0) return r;
41   return 0;
42 }
43
44 /********************************************************************/
45 /* Generic I2C functions */
46
47 void i2c_drv_queue_msg(i2c_msg_head_t **queue, i2c_msg_head_t *msg)
48 {
49   I2C_IRQ_LOCK_FINI
50   i2c_msg_head_t *prev, *next;
51   I2C_IRQ_LOCK;
52   if(msg->on_queue){
53     if(msg->next==msg){
54       if(*msg->on_queue==msg)
55         *msg->on_queue=NULL;
56     }else{
57       msg->next->prev=msg->prev;
58       msg->prev->next=msg->next;
59       if(*msg->on_queue==msg)
60         *msg->on_queue=msg->next;
61     }
62   }
63   if((msg->on_queue=queue)!=NULL){
64     if((next=*queue)!=NULL){
65       msg->prev=prev=next->prev;
66       msg->next=next;
67       next->prev=msg;
68       prev->next=msg;
69     }else{
70       *queue=msg->prev=msg->next=msg;
71     }
72   }
73   I2C_IRQ_UNLOCK;
74   return;
75 }
76
77 int i2c_drv_master_msg_ins(i2c_drv_t *drv, i2c_msg_head_t *msg)
78 {
79   if(!drv) return -1;
80   if(!(drv->flags&I2C_DRV_ON)) return -1;
81   if(!msg->tx_buf) msg->flags&=~I2C_MSG_MS_TX;
82   if(!msg->rx_buf) msg->flags&=~I2C_MSG_MS_RX;
83   i2c_drv_queue_msg(&drv->master_queue,msg);
84   drv->ctrl_fnc(drv,I2C_CTRL_MS_RQ,NULL);
85   return 0;
86 }
87
88 int i2c_drv_master_msg_rem(i2c_drv_t *drv, i2c_msg_head_t *msg)
89 {
90   int act;
91   I2C_IRQ_LOCK_FINI
92   do {
93     i2c_drv_queue_msg(NULL,msg);
94     I2C_IRQ_LOCK;
95     act = (msg==drv->msg_act);
96     if(act) {
97       drv->msg_act=NULL;
98     }
99     I2C_IRQ_UNLOCK;    
100   } while(msg->on_queue || act);
101   return 0;
102 }
103
104 int i2c_drv_flush_all(i2c_drv_t *drv)
105 {
106   I2C_IRQ_LOCK_FINI
107   i2c_msg_head_t *msg, *next;
108   i2c_msg_head_t *queue[3];
109   int quenum;
110
111   I2C_IRQ_LOCK;
112     queue[0]=drv->master_queue;
113     queue[1]=drv->slave_queue;
114     queue[2]=drv->proc_queue;
115     drv->master_queue=NULL;
116     drv->slave_queue=NULL;
117     drv->proc_queue=NULL;
118     drv->msg_act=NULL;
119   I2C_IRQ_UNLOCK;    
120   for(quenum=0;quenum<3;quenum++){
121     msg=queue[quenum];
122     if(!msg) continue;
123     msg->prev->next=NULL;
124     for(;msg;msg=next){
125       next=msg->next;
126       msg->flags|=I2C_MSG_FAIL;
127       msg->on_queue=NULL;
128       if((msg->flags&I2C_MSG_CB_PROC) && (msg->callback))
129         msg->callback(drv,I2C_MSG_CB_PROC,msg);
130     }
131   }
132   return 0;
133 }
134
135 int i2c_drv_master_transfer_callback(struct i2c_drv *drv, int code, struct i2c_msg_head *msg)
136 {
137   if(code!=I2C_MSG_CB_PROC) return 0;
138   set_bit(0,&(msg->private));
139   return 0;
140 }
141
142
143 int i2c_drv_master_transfer(i2c_drv_t *drv, int addr, int tx_rq, int rx_rq,
144                    void *tx_buf, void *rx_buf, int *ptx_len, int *prx_len)
145 {
146   i2c_msg_head_t msg;
147   
148   msg.flags = I2C_MSG_CB_PROC;
149   msg.addr = addr;
150   msg.tx_rq = tx_rq;
151   msg.rx_rq = rx_rq;
152   msg.tx_buf = tx_buf;
153   msg.rx_buf = rx_buf;
154   msg.on_queue = NULL;
155   msg.callback = i2c_drv_master_transfer_callback;
156   msg.private = 0;
157
158   if(msg.tx_buf)
159     msg.flags |= I2C_MSG_MS_TX;
160
161   if(msg.rx_buf && (msg.rx_rq>=1))
162     msg.flags |= I2C_MSG_MS_RX;
163
164   if(!(msg.flags & (I2C_MSG_MS_TX | I2C_MSG_MS_RX)))
165     return 0;
166
167   if(i2c_drv_master_msg_ins(drv, &msg)<0) 
168     return -1;
169
170   /* wait for message process */
171   while(test_bit(0,&(msg.private))==0)
172     drv->poll_fnc(drv);
173
174   if(ptx_len) *ptx_len = msg.tx_len;
175   if(prx_len) *prx_len = msg.rx_len;
176   
177   if(msg.flags & I2C_MSG_FAIL)
178     return -1;
179   
180   return msg.tx_len+msg.rx_len;
181 }
182