1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: #include <sys/machine.h>
15: #ifdef CPU_TMPM367FDFG
16:
17: #include <tk/tkernel.h>
18: #include "../../i2c.h"
19: #include "../../../include/dev_def.h"
20: #if DEV_IIC_ENABLE
21: 22: 23: 24: 25:
26:
27: 28: 29:
30: const LOCAL UW ba[DEV_I2C_UNITNM] = { I2C0_BASE, I2C1_BASE, I2C2_BASE };
31:
32: 33: 34:
35: const LOCAL struct {
36: TMO timout;
37: PRI intpri;
38: UW sck;
39: } ll_devinit[DEV_I2C_UNITNM] = {
40: {
41: .timout = DEVCNF_I2C0_TMO,
42: .intpri = DEVCNF_I2C0_INTPRI,
43: .sck = DEVCNF_I2C0_SCK,
44: },
45: {
46: .timout = DEVCNF_I2C1_TMO,
47: .intpri = DEVCNF_I2C1_INTPRI,
48: .sck = DEVCNF_I2C1_SCK,
49: },
50: {
51: .timout = DEVCNF_I2C2_TMO,
52: .intpri = DEVCNF_I2C2_INTPRI,
53: .sck = DEVCNF_I2C2_SCK,
54: },
55: };
56:
57: 58: 59:
60: typedef struct {
61: ID wait_tskid;
62: UW state;
63: UW sadr;
64: ER ioerr;
65: UW sdat_num;
66: UW rdat_num;
67: UB *sbuf;
68: UB *rbuf;
69: } T_I2C_LLDCB;
70: LOCAL T_I2C_LLDCB ll_devcb[DEV_I2C_UNITNM];
71:
72:
73: 74: 75: 76:
77: LOCAL void i2c_inthdr( UINT intno )
78: {
79: T_I2C_LLDCB *p_cb;
80: UW sbisr;
81: INT unit;
82:
83: for ( unit = 0; unit < DEV_I2C_UNITNM; unit++ ) {
84: if ( INTNO_INTSBI(unit) == intno ) {
85: p_cb = &ll_devcb[unit];
86: break;
87: }
88: }
89: if(unit >= DEV_I2C_UNITNM) return;
90:
91: sbisr = in_w(ba[unit] + I2C_SBIxSR);
92: if ( (sbisr & I2C_SBIxSR_AL) != 0 ) {
93:
94: p_cb->ioerr = E_IO;
95: goto stop;
96: }
97:
98: switch( p_cb->state ) {
99: case I2C_STS_RECV | I2C_STS_TOP:
100: if(p_cb->rdat_num == 1) {
101: out_w(ba[unit] + I2C_SBIxCR1,
102: I2C_SBIxCR1_INIT & ~I2C_SBIxCR1_ACK);
103: }
104: in_w(ba[unit] + I2C_SBIxDBR);
105: p_cb->state = I2C_STS_RECV;
106: break;
107:
108: case I2C_STS_RECV:
109: if(p_cb->rdat_num == 1) {
110: out_w(ba[unit] + I2C_SBIxCR1,
111: I2C_SBIxCR1_INIT & ~I2C_SBIxCR1_ACK);
112: }
113: *(p_cb->rbuf++) = (UB)(in_w(ba[unit] + I2C_SBIxDBR) & 0xff);
114: if(--(p_cb->rdat_num) <= 0) {
115: p_cb->state = I2C_STS_STOP;
116: }
117: break;
118:
119: case I2C_STS_SEND:
120: if ( (sbisr & I2C_SBIxSR_LRB) != 0 ) {
121: p_cb->ioerr = 1;
122: goto stop;
123: }
124:
125: out_w(ba[unit] + I2C_SBIxDBR, *p_cb->sbuf++);
126: if(--(p_cb->sdat_num) <= 0) {
127: if(p_cb->rdat_num == 0) {
128: p_cb->state = I2C_STS_STOP;
129: } else {
130: p_cb->state = I2C_STS_RESTART;
131: }
132: }
133: break;
134:
135: case I2C_STS_RESTART:
136: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_RESTART);
137: if(p_cb->wait_tskid) {
138: tk_wup_tsk(p_cb->wait_tskid);
139: p_cb->wait_tskid = 0;
140: }
141: break;
142:
143: case I2C_STS_STOP:
144: stop:
145: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_STOP);
146: if(p_cb->wait_tskid) {
147: tk_wup_tsk(p_cb->wait_tskid);
148: p_cb->wait_tskid = 0;
149: }
150: break;
151: }
152: }
153:
154: 155: 156:
157: LOCAL void i2c_wait_status( T_I2C_LLDCB *p_cb, INT unit, UW mask, UW value )
158: {
159: _UW t = CLOCK_fc;
160:
161: while ( p_cb->ioerr == E_OK ) {
162: if ( (in_w(ba[unit] + I2C_SBIxSR) & mask) == value ) break;
163: if ( --t == 0 ) p_cb->ioerr = E_TMOUT;
164: }
165: return;
166: }
167:
168: 169: 170:
171: LOCAL ER i2c_trans(INT unit, T_I2C_LLDCB *p_cb)
172: {
173: UINT imask;
174: ER err;
175:
176: p_cb->ioerr = E_OK;
177: p_cb->wait_tskid = 0;
178:
179: while ((err = p_cb->ioerr) == E_OK ) {
180:
181: switch ( p_cb->state ) {
182: case I2C_STS_RESTART:
183: i2c_wait_status(p_cb, unit, I2C_SBIxSR_BB, 0);
184: i2c_wait_status(p_cb, unit, I2C_SBIxSR_LRB, I2C_SBIxSR_LRB);
185: WaitUsec(5);
186:
187:
188: case I2C_STS_START:
189: DI(imask);
190: out_w(ba[unit] + I2C_SBIxCR1, I2C_SBIxCR1_INIT);
191: if(p_cb->sdat_num > 0 ) {
192: out_w(ba[unit] + I2C_SBIxDBR, p_cb->sadr);
193: p_cb->state = I2C_STS_SEND;
194: } else {
195: out_w(ba[unit] + I2C_SBIxDBR, (p_cb->sadr|1));
196: p_cb->state = I2C_STS_RECV | I2C_STS_TOP;
197: }
198: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_START);
199: EI(imask);
200: break;
201:
202: case I2C_STS_STOP:
203: i2c_wait_status(p_cb, unit, I2C_SBIxSR_BB, 0);
204: break;
205: }
206: if ( (err = p_cb->ioerr) != E_OK || p_cb->state == I2C_STS_STOP ) break;
207:
208: p_cb->wait_tskid = tk_get_tid();
209: err = tk_slp_tsk(ll_devinit[unit].timout);
210: if ( err < E_OK ) break;
211: }
212:
213:
214: DI(imask);
215: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_STOP);
216: EI(imask);
217:
218: return err;
219: }
220:
221: 222: 223:
224: Inline void set_com_start(UW unit, UW sadr, UW sdat_num, UW rdat_num, UB *sbuf, UB *rbuf)
225: {
226: ll_devcb[unit].state = I2C_STS_START;
227: ll_devcb[unit].sadr = sadr<<1;
228: ll_devcb[unit].sdat_num = sdat_num;
229: ll_devcb[unit].rdat_num = rdat_num;
230: ll_devcb[unit].sbuf = sbuf;
231: ll_devcb[unit].rbuf = rbuf;
232: }
233:
234:
235: 236: 237:
238: EXPORT W dev_i2c_llctl( UW unit, INT cmd, UW p1, UW p2, UW *pp)
239: {
240: T_I2C_EXEC *p_ex;
241: ER err = E_OK;
242:
243: switch(cmd) {
244: case LLD_I2C_OPEN:
245:
246: out_w(ba[unit] + I2C_SBIxCR0, I2C_SBIxCR0_SBIEN);
247: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_SBIM_I2C | I2C_SBIxCR2_SWRST(2));
248: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_SBIM_I2C | I2C_SBIxCR2_SWRST(1));
249: while ( (in_w(ba[unit] + I2C_SBIxCR1) & I2C_SBIxCR1_SWRMON) == 0 );
250:
251:
252: out_w(ba[unit] + I2C_SBIxCR1, I2C_SBIxCR1_INIT | ll_devinit[unit].sck);
253: out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_STOP);
254: out_w(ba[unit] + I2C_SBIxBR0, 0);
255:
256: EnableInt(INTNO_INTSBI(unit), ll_devinit[unit].intpri);
257: break;
258:
259: case LLD_I2C_CLOSE:
260:
261: DisableInt(INTNO_INTSBI(unit));
262: break;
263:
264: case LLD_I2C_READ:
265: set_com_start( unit, p1, 0, p2, NULL, (UB*)pp);
266: err = i2c_trans(unit, &ll_devcb[unit]);
267: if(err >= E_OK) err = p1 - ll_devcb[unit].sdat_num;
268: break;
269:
270: case LLD_I2C_WRITE:
271: set_com_start( unit, p1, p2, 0, (UB*)pp, NULL);
272: err = i2c_trans(unit, &ll_devcb[unit]);
273: if(err >= E_OK) err = p1 - ll_devcb[unit].sdat_num;
274: break;
275:
276: case LLD_I2C_EXEC:
277: p_ex = (T_I2C_EXEC*)pp;
278: set_com_start( unit, p_ex->sadr, p_ex->snd_size, p_ex->rcv_size, p_ex->snd_data, p_ex->rcv_data);
279: err = i2c_trans(unit, &ll_devcb[unit]);
280: if(err >= E_OK) err = p_ex->snd_size + p_ex->rcv_size;
281: break;
282: }
283:
284: return (W)err;
285: }
286:
287: 288: 289:
290: EXPORT ER dev_i2c_llinit( T_I2C_DCB *p_dcb)
291: {
292: const T_DINT dint = {
293: .intatr = TA_HLNG,
294: .inthdr = i2c_inthdr,
295: };
296: ER err;
297:
298:
299: err = tk_def_int(INTNO_INTSBI(p_dcb->unit), &dint);
300:
301: return err;
302: }
303:
304: #endif
305: #endif