1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "io.h" 7 #include "../port/error.h" 8 9 /* 10 * basic read/write interface to mpc8xx I2C bus (master mode) 11 */ 12 13 typedef struct Ctlr Ctlr; 14 typedef struct I2C I2C; 15 16 struct I2C { 17 uchar i2mod; 18 uchar rsv12a[3]; 19 uchar i2add; 20 uchar rsv12b[3]; 21 uchar i2brg; 22 uchar rsv12c[3]; 23 uchar i2com; 24 uchar rsv12d[3]; 25 uchar i2cer; 26 uchar rsv12e[3]; 27 uchar i2cmr; 28 }; 29 30 enum { 31 /* i2c-specific BD flags */ 32 RxeOV= 1<<1, /* overrun */ 33 TxS= 1<<10, /* transmit start condition */ 34 TxeNAK= 1<<2, /* last transmitted byte not acknowledged */ 35 TxeUN= 1<<1, /* underflow */ 36 TxeCL= 1<<0, /* collision */ 37 TxERR= (TxeNAK|TxeUN|TxeCL), 38 39 /* i2cmod */ 40 REVD= 1<<5, /* =1, LSB first */ 41 GCD= 1<<4, /* =1, general call address disabled */ 42 FLT= 1<<3, /* =0, not filtered; =1, filtered */ 43 PDIV= 3<<1, /* predivisor field */ 44 EN= 1<<0, /* enable */ 45 46 /* i2com */ 47 STR= 1<<7, /* start transmit */ 48 I2CM= 1<<0, /* master */ 49 I2CS= 0<<0, /* slave */ 50 51 /* i2cer */ 52 TXE = 1<<4, 53 BSY = 1<<2, 54 TXB = 1<<1, 55 RXB = 1<<0, 56 57 /* port B bits */ 58 I2CSDA = IBIT(27), 59 I2CSCL = IBIT(26), 60 61 Rbit = 1<<0, /* bit in address byte denoting read */ 62 63 /* maximum I2C I/O (can change) */ 64 MaxIO = 128, 65 MaxSA = 2, /* longest subaddress */ 66 Bufsize = (MaxIO+MaxSA+1+4)&~3, /* extra space for subaddress/clock bytes and alignment */ 67 Freq = 100000, 68 I2CTimeout = 250, /* msec */ 69 70 Chatty = 0, 71 }; 72 73 #define DPRINT if(Chatty)print 74 75 /* data cache needn't be flushed if buffers allocated in uncached PHYSIMM */ 76 #define DCFLUSH(a,n) 77 78 /* 79 * I2C software structures 80 */ 81 82 struct Ctlr { 83 Lock; 84 QLock io; 85 int init; 86 int busywait; /* running before system set up */ 87 I2C* i2c; 88 IOCparam* sp; 89 90 BD* rd; 91 BD* td; 92 int phase; 93 Rendez r; 94 char* addr; 95 char* txbuf; 96 char* rxbuf; 97 }; 98 99 static Ctlr i2ctlr[1]; 100 101 static void interrupt(Ureg*, void*); 102 103 static void 104 enable(void) 105 { 106 I2C *i2c; 107 108 i2c = i2ctlr->i2c; 109 i2c->i2cer = ~0; /* clear events */ 110 eieio(); 111 i2c->i2mod |= EN; 112 eieio(); 113 i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */ 114 eieio(); 115 } 116 117 static void 118 disable(void) 119 { 120 I2C *i2c; 121 122 i2c = i2ctlr->i2c; 123 i2c->i2cmr = 0; /* mask all interrupts */ 124 i2c->i2mod &= ~EN; 125 } 126 127 /* 128 * called by the reset routine of any driver using the I2C 129 */ 130 void 131 i2csetup(int busywait) 132 { 133 IMM *io; 134 I2C *i2c; 135 IOCparam *sp; 136 CPMdev *cpm; 137 Ctlr *ctlr; 138 long f, e, emin; 139 int p, d, dmax; 140 141 ctlr = i2ctlr; 142 ctlr->busywait = busywait; 143 if(ctlr->init) 144 return; 145 print("i2c setup...\n"); 146 ctlr->init = 1; 147 cpm = cpmdev(CPi2c); 148 i2c = cpm->regs; 149 ctlr->i2c = i2c; 150 sp = cpm->param; 151 if(sp == nil) 152 panic("I2C: can't allocate new parameter memory\n"); 153 ctlr->sp = sp; 154 disable(); 155 156 if(ctlr->txbuf == nil){ 157 ctlr->txbuf = cpmalloc(Bufsize, 2); 158 ctlr->addr = ctlr->txbuf+MaxIO; 159 } 160 if(ctlr->rxbuf == nil) 161 ctlr->rxbuf = cpmalloc(Bufsize, 2); 162 if(ctlr->rd == nil){ 163 ctlr->rd = bdalloc(1); 164 ctlr->rd->addr = PADDR(ctlr->rxbuf); 165 ctlr->rd->length = 0; 166 ctlr->rd->status = BDWrap; 167 } 168 if(ctlr->td == nil){ 169 ctlr->td = bdalloc(2); 170 ctlr->td->addr = PADDR(ctlr->txbuf); 171 ctlr->td->length = 0; 172 ctlr->td->status = BDWrap|BDLast; 173 } 174 175 /* select port pins */ 176 io = ioplock(); 177 io->pbdir |= I2CSDA | I2CSCL; 178 io->pbodr |= I2CSDA | I2CSCL; 179 io->pbpar |= I2CSDA | I2CSCL; 180 iopunlock(); 181 182 /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */ 183 sp = ctlr->sp; 184 sp->rbase = PADDR(ctlr->rd); 185 sp->tbase = PADDR(ctlr->td); 186 sp->rfcr = 0x18; 187 sp->tfcr = 0x18; 188 sp->mrblr = Bufsize; 189 sp->rstate = 0; 190 sp->rptr = 0; 191 sp->rbptr = sp->rbase; 192 sp->rcnt = 0; 193 sp->tstate = 0; 194 sp->tbptr = sp->tbase; 195 sp->tptr = 0; 196 sp->tcnt = 0; 197 eieio(); 198 199 i2c->i2com = I2CM; 200 i2c->i2mod = 0; /* normal mode */ 201 i2c->i2add = 0; 202 203 emin = Freq; 204 dmax = (m->cpuhz/Freq)/2-3; 205 for(d=0; d < dmax; d++){ 206 for(p=3; p>=0; p--){ 207 f = (m->cpuhz>>(p+2))/(2*(d+3)); 208 e = Freq - f; 209 if(e < 0) 210 e = -e; 211 if(e < emin){ 212 emin = e; 213 i2c->i2brg = d; 214 i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */ 215 } 216 } 217 } 218 //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod); 219 intrenable(VectorCPIC+cpm->irq, interrupt, i2ctlr, BUSUNKNOWN, "i2c"); 220 } 221 222 enum { 223 Idling, 224 Done, 225 Busy, 226 Sending, 227 Recving, 228 }; 229 230 static void 231 interrupt(Ureg*, void *arg) 232 { 233 int events; 234 Ctlr *ctlr; 235 I2C *i2c; 236 237 ctlr = arg; 238 i2c = ctlr->i2c; 239 events = i2c->i2cer; 240 eieio(); 241 i2c->i2cer = events; 242 if(events & (BSY|TXE)){ 243 //print("I2C#%x\n", events); 244 if(ctlr->phase != Idling){ 245 ctlr->phase = Idling; 246 wakeup(&ctlr->r); 247 } 248 }else{ 249 if(events & TXB){ 250 //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status); 251 if(ctlr->phase == Sending){ 252 ctlr->phase = Done; 253 wakeup(&ctlr->r); 254 } 255 } 256 if(events & RXB){ 257 //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length); 258 if(ctlr->phase == Recving){ 259 ctlr->phase = Done; 260 wakeup(&ctlr->r); 261 } 262 } 263 } 264 } 265 266 static int 267 done(void *a) 268 { 269 return ((Ctlr*)a)->phase < Busy; 270 } 271 272 static void 273 i2cwait(Ctlr *ctlr) 274 { 275 int i; 276 277 if(up == nil || ctlr->busywait){ 278 for(i=0; i < 5 && !done(ctlr); i++){ 279 delay(2); 280 interrupt(nil, ctlr); 281 } 282 }else 283 tsleep(&ctlr->r, done, ctlr, I2CTimeout); 284 } 285 286 static int 287 i2cerror(char *s) 288 { 289 if(up) 290 error(s); 291 /* no current process, don't call error */ 292 DPRINT("i2c error: %s\n", s); 293 return -1; 294 } 295 296 long 297 i2csend(I2Cdev *d, void *buf, long n, ulong offset) 298 { 299 Ctlr *ctlr; 300 int i, p, s; 301 302 ctlr = i2ctlr; 303 if(up){ 304 if(n > MaxIO) 305 error(Etoobig); 306 qlock(&ctlr->io); 307 if(waserror()){ 308 qunlock(&ctlr->io); 309 nexterror(); 310 } 311 } 312 ctlr->txbuf[0] = d->addr<<1; 313 i = 1; 314 if(d->salen > 1) 315 ctlr->txbuf[i++] = offset>>8; 316 if(d->salen) 317 ctlr->txbuf[i++] = offset; 318 memmove(ctlr->txbuf+i, buf, n); 319 if(Chatty){ 320 print("tx: %8.8lux: ", PADDR(ctlr->txbuf)); 321 for(s=0; s<n+i; s++) 322 print(" %.2ux", ctlr->txbuf[s]&0xFF); 323 print("\n"); 324 } 325 DCFLUSH(ctlr->txbuf, Bufsize); 326 ilock(ctlr); 327 ctlr->phase = Sending; 328 ctlr->rd->status = BDEmpty|BDWrap|BDInt; 329 ctlr->td->addr = PADDR(ctlr->txbuf); 330 ctlr->td->length = n+i; 331 ctlr->td->status = BDReady|BDWrap|BDLast|BDInt; 332 enable(); 333 ctlr->i2c->i2com = STR|I2CM; 334 eieio(); 335 iunlock(ctlr); 336 i2cwait(ctlr); 337 disable(); 338 p = ctlr->phase; 339 s = ctlr->td->status; 340 if(up){ 341 poperror(); 342 qunlock(&ctlr->io); 343 } 344 if(s & BDReady) 345 return i2cerror("timed out"); 346 if(s & TxERR){ 347 sprint(up->genbuf, "write error: status %.4ux", s); 348 return i2cerror(up->genbuf); 349 } 350 if(p != Done) 351 return i2cerror("phase error"); 352 return n; 353 } 354 355 long 356 i2crecv(I2Cdev *d, void *buf, long n, ulong offset) 357 { 358 Ctlr *ctlr; 359 int p, s, flag, i; 360 BD *td; 361 long nr; 362 363 ctlr = i2ctlr; 364 if(up){ 365 if(n > MaxIO) 366 error(Etoobig); 367 qlock(&ctlr->io); 368 if(waserror()){ 369 qunlock(&ctlr->io); 370 nexterror(); 371 } 372 } 373 ctlr->txbuf[0] = (d->addr<<1)|Rbit; 374 if(d->salen){ /* special write to set address */ 375 ctlr->addr[0] = d->addr<<1; 376 i = 1; 377 if(d->salen > 1) 378 ctlr->addr[i++] = offset >> 8; 379 ctlr->addr[i] = offset; 380 } 381 DCFLUSH(ctlr->txbuf, Bufsize); 382 DCFLUSH(ctlr->rxbuf, Bufsize); 383 ilock(ctlr); 384 ctlr->phase = Recving; 385 ctlr->rd->addr = PADDR(ctlr->rxbuf); 386 ctlr->rd->status = BDEmpty|BDWrap|BDInt; 387 flag = 0; 388 td = ctlr->td; 389 td[1].status = 0; 390 if(d->salen){ 391 /* special select sequence */ 392 td->addr = PADDR(ctlr->addr); 393 i = d->salen+1; 394 if(i > 3) 395 i = 3; 396 td->length = i; 397 /* td->status made BDReady below */ 398 td++; 399 flag = TxS; 400 } 401 td->addr = PADDR(ctlr->txbuf); 402 td->length = n+1; 403 td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */ 404 if(flag) 405 ctlr->td->status = BDReady; 406 enable(); 407 ctlr->i2c->i2com = STR|I2CM; 408 eieio(); 409 iunlock(ctlr); 410 i2cwait(ctlr); 411 disable(); 412 p = ctlr->phase; 413 s = ctlr->td->status; 414 if(flag) 415 s |= ctlr->td[1].status; 416 nr = ctlr->rd->length; 417 if(up){ 418 poperror(); 419 qunlock(&ctlr->io); 420 } 421 DPRINT("nr=%ld %4.4ux %8.8lux\n", nr, ctlr->rd->status, ctlr->rd->addr); 422 if(nr > n) 423 nr = n; /* shouldn't happen */ 424 if(s & TxERR){ 425 sprint(up->genbuf, "read: tx status: %.4ux", s); 426 return i2cerror(up->genbuf); 427 } 428 if(s & BDReady || ctlr->rd->status & BDEmpty) 429 return i2cerror("timed out"); 430 if(p != Done) 431 return i2cerror("phase error"); 432 memmove(buf, ctlr->rxbuf, nr); 433 if(Chatty){ 434 for(s=0; s<nr; s++) 435 print(" %2.2ux", ctlr->rxbuf[s]&0xFF); 436 print("\n"); 437 } 438 return nr; 439 } 440