1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14:
15: 16: 17: 18:
19:
20: #include "clkdrv.h"
21: #include <tk/util.h>
22: #include <device/em1d512_iic.h>
23:
24: #ifdef DEBUG
25: #define DP(x) printf x
26: #else
27: #define DP(x)
28: #endif
29:
30: #define IICMAX 2
31: LOCAL FastLock IICLock[IICMAX];
32: LOCAL ID IICTskID[IICMAX];
33: LOCAL const UW IICBase[IICMAX] = {0x50040000, 0x50030000};
34: LOCAL const UW IICVec[IICMAX] = {IV_IRQ(33), IV_IRQ(39)};
35:
36: #define IIC_IIC(x) (IICBase[x] + 0x0000)
37: #define IIC_IICC(x) (IICBase[x] + 0x0008)
38: #define IIC_SVA(x) (IICBase[x] + 0x000c)
39: #define IIC_IICCL(x) (IICBase[x] + 0x0010)
40: #define IIC_IICSE(x) (IICBase[x] + 0x001c)
41: #define IIC_IICF(x) (IICBase[x] + 0x0028)
42:
43: #define IICC_IICE (1 << 7)
44: #define IICC_LREL (1 << 6)
45: #define IICC_WREL (1 << 5)
46: #define IICC_SPIE (1 << 4)
47: #define IICC_WTIM (1 << 3)
48: #define IICC_ACKE (1 << 2)
49: #define IICC_STT (1 << 1)
50: #define IICC_SPT (1 << 0)
51:
52: #define IICCL_CLD (1 << 5)
53: #define IICCL_DAD (1 << 4)
54: #define IICCL_SMC (1 << 3)
55: #define IICCL_DFC (1 << 2)
56:
57: #define IICSE_MSTS (1 << 15)
58: #define IICSE_ALD (1 << 14)
59: #define IICSE_EXC (1 << 13)
60: #define IICSE_COI (1 << 12)
61: #define IICSE_TRC (1 << 11)
62: #define IICSE_ACKD (1 << 10)
63: #define IICSE_STD (1 << 9)
64: #define IICSE_SPD (1 << 8)
65:
66: #define IICF_STCF (1 << 7)
67: #define IICF_IICBSY (1 << 6)
68: #define IICF_STCEN (1 << 1)
69: #define IICF_IICRSV (1 << 0)
70:
71: #define TIMEOUT 1000000
72:
73:
74: LOCAL ER wait_state(UW addr, UW mask, UW value)
75: {
76: W i;
77:
78: for (i = TIMEOUT; i > 0; i--) {
79: WaitUsec(1);
80: if ((in_w(addr) & mask) == value) break;
81: }
82:
83: return i ? E_OK : E_TMOUT;
84: }
85:
86:
87: LOCAL void iic_inthdr(INTVEC vec)
88: {
89: W i;
90:
91: for (i = 0; i < IICMAX; i++) {
92: if (vec == IICVec[i]) {
93: tk_wup_tsk(IICTskID[i]);
94: break;
95: }
96: }
97:
98: ClearInt(vec);
99: return;
100: }
101:
102:
103: LOCAL ER wait_int(void)
104: {
105: return tk_slp_tsk(TIMEOUT / 1000);
106: }
107:
108:
109: LOCAL ER send_start(W ch, UH addr)
110: {
111: ER er;
112: UW sts;
113:
114:
115: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) & ~IICC_ACKE);
116: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) | IICC_STT);
117:
118:
119: er = wait_state(IIC_IICSE(ch), IICSE_MSTS, IICSE_MSTS);
120: if (er < E_OK) {
121: DP(("send_start: wait_state %d\n", er));
122: goto fin0;
123: }
124:
125:
126: out_w(IIC_IIC(ch), addr & 0xff);
127: er = wait_int();
128: if (er < E_OK) {
129: DP(("send_start: wait_int %d\n", er));
130: goto fin0;
131: }
132:
133:
134: sts = in_w(IIC_IICSE(ch));
135: if ((sts & IICSE_ALD) || !(sts & IICSE_ACKD)) {
136: DP(("send_start: IICSE %#x\n", sts));
137: er = E_IO;
138: goto fin0;
139: }
140:
141: er = E_OK;
142: fin0:
143: return er;
144: }
145:
146:
147: LOCAL ER send_stop(W ch)
148: {
149: ER er;
150:
151:
152: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) | IICC_SPT);
153:
154:
155: er = wait_state(IIC_IICSE(ch), IICSE_SPD, IICSE_SPD);
156: if (er < E_OK) {
157: DP(("send_stop: wait_state %d\n", er));
158: }
159:
160: return er;
161: }
162:
163:
164: LOCAL ER send_data(W ch, UH data)
165: {
166: ER er;
167: UW sts;
168:
169:
170: out_w(IIC_IIC(ch), data & 0xff);
171: er = wait_int();
172: if (er < E_OK) {
173: DP(("send_data: wait_int %d\n", er));
174: goto fin0;
175: }
176:
177:
178: sts = in_w(IIC_IICSE(ch));
179: if (!(sts & IICSE_ACKD)) {
180: DP(("send_data: IICSE %#x\n", sts));
181: er = E_IO;
182: goto fin0;
183: }
184:
185: er = E_OK;
186: fin0:
187: return er;
188: }
189:
190:
191: LOCAL ER recv_data(W ch, UH *cmddata)
192: {
193: ER er;
194: W cmd = *cmddata;
195:
196:
197: if (cmd & IIC_TOPDATA) {
198: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) & ~IICC_WTIM);
199: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) | IICC_ACKE);
200: }
201:
202:
203: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) | IICC_WREL);
204: er = wait_int();
205: if (er < E_OK) {
206: DP(("recv_data: wait_int %d\n", er));
207: goto fin0;
208: }
209:
210:
211: *cmddata = (cmd & 0xff00) | (in_w(IIC_IIC(ch)) & 0xff);
212: er = E_OK;
213: fin0:
214:
215: if ((cmd & IIC_LASTDATA) || er < E_OK) {
216: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) | IICC_WTIM);
217: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) & ~IICC_ACKE);
218: out_w(IIC_IICC(ch), in_w(IIC_IICC(ch)) | IICC_WREL);
219: wait_int();
220: }
221:
222: return er;
223: }
224:
225:
226: EXPORT ER IICXfer(W ch, UH *cmddata, W words)
227: {
228: ER er;
229:
230:
231: if (ch < 0 || ch > 1) {
232: er = E_PAR;
233: goto fin0;
234: }
235:
236: Lock(&IICLock[ch]);
237: IICTskID[ch] = tk_get_tid();
238:
239:
240: out_w(IIC_IICC(ch), 0);
241: out_w(IIC_IICCL(ch), IICCL_SMC | IICCL_DFC);
242: out_w(IIC_IICF(ch), IICF_STCEN | IICF_IICRSV);
243: out_w(IIC_IICC(ch), IICC_IICE | IICC_WTIM);
244: tk_can_wup(TSK_SELF);
245:
246:
247: wait_state(IIC_IICF(ch), IICF_IICBSY, 0);
248:
249:
250: for (; words > 0; words--) {
251: if (*cmddata & IIC_START) {
252: er = send_start(ch, *cmddata);
253:
254: } else if (*cmddata & IIC_STOP) {
255: er = send_stop(ch);
256:
257: } else if (*cmddata & IIC_SEND) {
258: er = send_data(ch, *cmddata);
259:
260: } else if (*cmddata & IIC_RECV) {
261: er = recv_data(ch, cmddata);
262:
263: } else {
264: er = E_OK;
265:
266: }
267:
268:
269: if (er < E_OK) {
270: send_stop(ch);
271: goto fin1;
272: }
273:
274: cmddata++;
275: }
276:
277: er = E_OK;
278: fin1:
279: out_w(IIC_IICC(ch), 0);
280: Unlock(&IICLock[ch]);
281: fin0:
282: return er;
283: }
284:
285:
286: EXPORT ER IICup(W ch, BOOL start)
287: {
288: #define IICTag "IIC_"
289:
290: ER er;
291: T_DINT dint;
292:
293:
294: if (ch < 0 || ch > 1) {
295: er = E_PAR;
296: goto fin0;
297: }
298:
299:
300: if (!start) {
301: er = E_OK;
302: goto fin2;
303: }
304:
305:
306: er = CreateLock(&IICLock[ch], IICTag);
307: if (er < E_OK) {
308: DP(("IICup: CreateLock %d\n", er));
309: goto fin0;
310: }
311:
312:
313: dint.intatr = TA_HLNG;
314: dint.inthdr = iic_inthdr;
315: er = tk_def_int(IICVec[ch], &dint);
316: if (er < E_OK) {
317: DP(("IICup: tk_def_int %d\n", er));
318: goto fin1;
319: }
320:
321:
322: SetIntMode(IICVec[ch], IM_ENA);
323: ClearInt(IICVec[ch]);
324: EnableInt(IICVec[ch]);
325:
326: er = E_OK;
327: goto fin0;
328:
329: fin2:
330: DisableInt(IICVec[ch]);
331: ClearInt(IICVec[ch]);
332: SetIntMode(IICVec[ch], IM_DIS);
333: tk_def_int(IICVec[ch], NULL);
334: fin1:
335: DeleteLock(&IICLock[ch]);
336: fin0:
337: return er;
338: }