2 * kirkwood two-wire serial interface (TWSI) and
3 * inter-integrated circuit (I²C) driver
6 #include "../port/lib.h"
10 #include "../port/error.h"
18 typedef struct Kwtwsi Kwtwsi;
19 typedef struct Twsi Twsi;
21 struct Kwtwsi { /* device registers */
26 ulong status; /* ro */
27 ulong rate; /* wo: baud rate */
31 uchar _pad0[0x1c-0x14];
33 uchar _pad1[0x98-0x20];
42 Twsiack = 1<<2, /* recv'd data; clear to ack */
43 Twsiint = 1<<3, /* interrupt conditions true */
47 Twsiinten = 1<<7, /* interrupts enabled */
62 /* remainder is state needed to track the operation in progress */
66 uchar *bp; /* current ptr into buf */
69 ulong addr; /* device address */
75 static Dirtab twsidir[] = {
76 ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
77 "twsi", {Qtwsi}, 0, 0660,
80 static char Eabsts[] = "abnormal status";
85 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
95 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
99 krp->data = twsi.addr << 1 | Twsidoread;
105 if(twsi.bp < twsi.end) {
106 *twsi.bp++ = krp->data;
109 krp->ctl &= ~Twsiack;
124 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
128 krp->data = twsi.addr << 1 | Twsidowrite;
132 if(twsi.bp < twsi.end)
133 krp->data = *twsi.bp++;
151 twsixfer(uchar *buf, ulong len, ulong offset, void (*op)(void))
155 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
159 twsi.end = buf + len;
162 twsi.done = twsi.intr = 0;
165 krp->ctl = (krp->ctl & ~Twsiint) | Twsistart;
168 sleep(&twsi.nextbyte, twsigotintr, 0);
171 /* signal to start new op & extinguish intr source */
172 krp->ctl &= ~Twsiint;
174 krp->ctl |= Twsiinten;
180 twsi.bp = nil; /* prevent accidents */
189 interrupt(Ureg *, void *)
191 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
194 wakeup(&twsi.nextbyte);
196 krp->ctl &= ~Twsiinten; /* stop further interrupts */
198 intrclear(Irqlo, IRQ0twsi);
204 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
206 intrenable(Irqlo, IRQ0twsi, interrupt, nil, "twsi");
207 krp->ctl &= ~Twsiint;
208 krp->ctl |= Twsiinten;
215 Kwtwsi *krp = (Kwtwsi *)soc.twsi;
217 krp->ctl &= ~Twsiinten;
219 intrdisable(Irqlo, IRQ0twsi, interrupt, nil, "twsi");
223 twsiattach(char *param)
225 return devattach(L'²', param);
229 twsiwalk(Chan *c, Chan *nc, char **name, int nname)
231 return devwalk(c, nc, name, nname, twsidir, nelem(twsidir), devgen);
235 twsistat(Chan *c, uchar *db, int n)
237 return devstat(c, db, n, twsidir, nelem(twsidir), devgen);
241 twsiopen(Chan *c, int omode)
243 switch((ulong)c->qid.path){
250 c = devopen(c, omode, twsidir, nelem(twsidir), devgen);
251 c->mode = openmode(omode);
263 twsiread(Chan *c, void *v, long n, vlong off)
265 switch((ulong)c->qid.path){
269 return devdirread(c, v, n, twsidir, nelem(twsidir), devgen);
271 return twsixfer(v, n, off, twsidoread);
276 twsiwrite(Chan *c, void *v, long n, vlong off)
278 switch((ulong)c->qid.path){
282 return twsixfer(v, n, off, twsidowrite);