summaryrefslogtreecommitdiff
path: root/os/mpc/i2c.c
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
commit78ee7d5717807e6ac779293d0d3c78341de6130a (patch)
treea43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/mpc/i2c.c
parentbdaf46cf45bbb59261da245d548a179d95a42768 (diff)
Move existing boards into subdits split per arch
Diffstat (limited to 'os/mpc/i2c.c')
-rw-r--r--os/mpc/i2c.c439
1 files changed, 0 insertions, 439 deletions
diff --git a/os/mpc/i2c.c b/os/mpc/i2c.c
deleted file mode 100644
index 5218b1c0..00000000
--- a/os/mpc/i2c.c
+++ /dev/null
@@ -1,439 +0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-/*
- * basic read/write interface to mpc8xx I2C bus (master mode)
- */
-
-typedef struct Ctlr Ctlr;
-typedef struct I2C I2C;
-
-struct I2C {
- uchar i2mod;
- uchar rsv12a[3];
- uchar i2add;
- uchar rsv12b[3];
- uchar i2brg;
- uchar rsv12c[3];
- uchar i2com;
- uchar rsv12d[3];
- uchar i2cer;
- uchar rsv12e[3];
- uchar i2cmr;
-};
-
-enum {
- /* i2c-specific BD flags */
- RxeOV= 1<<1, /* overrun */
- TxS= 1<<10, /* transmit start condition */
- TxeNAK= 1<<2, /* last transmitted byte not acknowledged */
- TxeUN= 1<<1, /* underflow */
- TxeCL= 1<<0, /* collision */
- TxERR= (TxeNAK|TxeUN|TxeCL),
-
- /* i2cmod */
- REVD= 1<<5, /* =1, LSB first */
- GCD= 1<<4, /* =1, general call address disabled */
- FLT= 1<<3, /* =0, not filtered; =1, filtered */
- PDIV= 3<<1, /* predivisor field */
- EN= 1<<0, /* enable */
-
- /* i2com */
- STR= 1<<7, /* start transmit */
- I2CM= 1<<0, /* master */
- I2CS= 0<<0, /* slave */
-
- /* i2cer */
- TXE = 1<<4,
- BSY = 1<<2,
- TXB = 1<<1,
- RXB = 1<<0,
-
- /* port B bits */
- I2CSDA = IBIT(27),
- I2CSCL = IBIT(26),
-
- Rbit = 1<<0, /* bit in address byte denoting read */
-
- /* maximum I2C I/O (can change) */
- MaxIO = 128,
- MaxSA = 2, /* longest subaddress */
- Bufsize = (MaxIO+MaxSA+1+4)&~3, /* extra space for subaddress/clock bytes and alignment */
- Freq = 100000,
- I2CTimeout = 250, /* msec */
-
- Chatty = 0,
-};
-
-#define DPRINT if(Chatty)print
-
-/* data cache needn't be flushed if buffers allocated in uncached PHYSIMM */
-#define DCFLUSH(a,n)
-
-/*
- * I2C software structures
- */
-
-struct Ctlr {
- Lock;
- QLock io;
- int init;
- int busywait; /* running before system set up */
- I2C* i2c;
- IOCparam* sp;
-
- BD* rd;
- BD* td;
- int phase;
- Rendez r;
- char* addr;
- char* txbuf;
- char* rxbuf;
-};
-
-static Ctlr i2ctlr[1];
-
-static void interrupt(Ureg*, void*);
-
-static void
-enable(void)
-{
- I2C *i2c;
-
- i2c = i2ctlr->i2c;
- i2c->i2cer = ~0; /* clear events */
- eieio();
- i2c->i2mod |= EN;
- eieio();
- i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */
- eieio();
-}
-
-static void
-disable(void)
-{
- I2C *i2c;
-
- i2c = i2ctlr->i2c;
- i2c->i2cmr = 0; /* mask all interrupts */
- i2c->i2mod &= ~EN;
-}
-
-/*
- * called by the reset routine of any driver using the I2C
- */
-void
-i2csetup(int busywait)
-{
- IMM *io;
- I2C *i2c;
- IOCparam *sp;
- CPMdev *cpm;
- Ctlr *ctlr;
- long f, e, emin;
- int p, d, dmax;
-
- ctlr = i2ctlr;
- ctlr->busywait = busywait;
- if(ctlr->init)
- return;
- print("i2c setup...\n");
- ctlr->init = 1;
- cpm = cpmdev(CPi2c);
- i2c = cpm->regs;
- ctlr->i2c = i2c;
- sp = cpm->param;
- if(sp == nil)
- panic("I2C: can't allocate new parameter memory\n");
- ctlr->sp = sp;
- disable();
-
- if(ctlr->txbuf == nil){
- ctlr->txbuf = cpmalloc(Bufsize, 2);
- ctlr->addr = ctlr->txbuf+MaxIO;
- }
- if(ctlr->rxbuf == nil)
- ctlr->rxbuf = cpmalloc(Bufsize, 2);
- if(ctlr->rd == nil){
- ctlr->rd = bdalloc(1);
- ctlr->rd->addr = PADDR(ctlr->rxbuf);
- ctlr->rd->length = 0;
- ctlr->rd->status = BDWrap;
- }
- if(ctlr->td == nil){
- ctlr->td = bdalloc(2);
- ctlr->td->addr = PADDR(ctlr->txbuf);
- ctlr->td->length = 0;
- ctlr->td->status = BDWrap|BDLast;
- }
-
- /* select port pins */
- io = ioplock();
- io->pbdir |= I2CSDA | I2CSCL;
- io->pbodr |= I2CSDA | I2CSCL;
- io->pbpar |= I2CSDA | I2CSCL;
- iopunlock();
-
- /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
- sp = ctlr->sp;
- sp->rbase = PADDR(ctlr->rd);
- sp->tbase = PADDR(ctlr->td);
- sp->rfcr = 0x18;
- sp->tfcr = 0x18;
- sp->mrblr = Bufsize;
- sp->rstate = 0;
- sp->rptr = 0;
- sp->rbptr = sp->rbase;
- sp->rcnt = 0;
- sp->tstate = 0;
- sp->tbptr = sp->tbase;
- sp->tptr = 0;
- sp->tcnt = 0;
- eieio();
-
- i2c->i2com = I2CM;
- i2c->i2mod = 0; /* normal mode */
- i2c->i2add = 0;
-
- emin = Freq;
- dmax = (m->cpuhz/Freq)/2-3;
- for(d=0; d < dmax; d++){
- for(p=3; p>=0; p--){
- f = (m->cpuhz>>(p+2))/(2*(d+3));
- e = Freq - f;
- if(e < 0)
- e = -e;
- if(e < emin){
- emin = e;
- i2c->i2brg = d;
- i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
- }
- }
- }
- //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
- intrenable(VectorCPIC+cpm->irq, interrupt, i2ctlr, BUSUNKNOWN, "i2c");
-}
-
-enum {
- Idling,
- Done,
- Busy,
- Sending,
- Recving,
-};
-
-static void
-interrupt(Ureg*, void *arg)
-{
- int events;
- Ctlr *ctlr;
- I2C *i2c;
-
- ctlr = arg;
- i2c = ctlr->i2c;
- events = i2c->i2cer;
- eieio();
- i2c->i2cer = events;
- if(events & (BSY|TXE)){
- //print("I2C#%x\n", events);
- if(ctlr->phase != Idling){
- ctlr->phase = Idling;
- wakeup(&ctlr->r);
- }
- }else{
- if(events & TXB){
- //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
- if(ctlr->phase == Sending){
- ctlr->phase = Done;
- wakeup(&ctlr->r);
- }
- }
- if(events & RXB){
- //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
- if(ctlr->phase == Recving){
- ctlr->phase = Done;
- wakeup(&ctlr->r);
- }
- }
- }
-}
-
-static int
-done(void *a)
-{
- return ((Ctlr*)a)->phase < Busy;
-}
-
-static void
-i2cwait(Ctlr *ctlr)
-{
- int i;
-
- if(up == nil || ctlr->busywait){
- for(i=0; i < 5 && !done(ctlr); i++){
- delay(2);
- interrupt(nil, ctlr);
- }
- }else
- tsleep(&ctlr->r, done, ctlr, I2CTimeout);
-}
-
-static int
-i2cerror(char *s)
-{
- if(up)
- error(s);
- /* no current process, don't call error */
- DPRINT("i2c error: %s\n", s);
- return -1;
-}
-
-long
-i2csend(I2Cdev *d, void *buf, long n, ulong offset)
-{
- Ctlr *ctlr;
- int i, p, s;
-
- ctlr = i2ctlr;
- if(up){
- if(n > MaxIO)
- error(Etoobig);
- qlock(&ctlr->io);
- if(waserror()){
- qunlock(&ctlr->io);
- nexterror();
- }
- }
- ctlr->txbuf[0] = d->addr<<1;
- i = 1;
- if(d->salen > 1)
- ctlr->txbuf[i++] = offset>>8;
- if(d->salen)
- ctlr->txbuf[i++] = offset;
- memmove(ctlr->txbuf+i, buf, n);
- if(Chatty){
- print("tx: %8.8lux: ", PADDR(ctlr->txbuf));
- for(s=0; s<n+i; s++)
- print(" %.2ux", ctlr->txbuf[s]&0xFF);
- print("\n");
- }
- DCFLUSH(ctlr->txbuf, Bufsize);
- ilock(ctlr);
- ctlr->phase = Sending;
- ctlr->rd->status = BDEmpty|BDWrap|BDInt;
- ctlr->td->addr = PADDR(ctlr->txbuf);
- ctlr->td->length = n+i;
- ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
- enable();
- ctlr->i2c->i2com = STR|I2CM;
- eieio();
- iunlock(ctlr);
- i2cwait(ctlr);
- disable();
- p = ctlr->phase;
- s = ctlr->td->status;
- if(up){
- poperror();
- qunlock(&ctlr->io);
- }
- if(s & BDReady)
- return i2cerror("timed out");
- if(s & TxERR){
- sprint(up->genbuf, "write error: status %.4ux", s);
- return i2cerror(up->genbuf);
- }
- if(p != Done)
- return i2cerror("phase error");
- return n;
-}
-
-long
-i2crecv(I2Cdev *d, void *buf, long n, ulong offset)
-{
- Ctlr *ctlr;
- int p, s, flag, i;
- BD *td;
- long nr;
-
- ctlr = i2ctlr;
- if(up){
- if(n > MaxIO)
- error(Etoobig);
- qlock(&ctlr->io);
- if(waserror()){
- qunlock(&ctlr->io);
- nexterror();
- }
- }
- ctlr->txbuf[0] = (d->addr<<1)|Rbit;
- if(d->salen){ /* special write to set address */
- ctlr->addr[0] = d->addr<<1;
- i = 1;
- if(d->salen > 1)
- ctlr->addr[i++] = offset >> 8;
- ctlr->addr[i] = offset;
- }
- DCFLUSH(ctlr->txbuf, Bufsize);
- DCFLUSH(ctlr->rxbuf, Bufsize);
- ilock(ctlr);
- ctlr->phase = Recving;
- ctlr->rd->addr = PADDR(ctlr->rxbuf);
- ctlr->rd->status = BDEmpty|BDWrap|BDInt;
- flag = 0;
- td = ctlr->td;
- td[1].status = 0;
- if(d->salen){
- /* special select sequence */
- td->addr = PADDR(ctlr->addr);
- i = d->salen+1;
- if(i > 3)
- i = 3;
- td->length = i;
- /* td->status made BDReady below */
- td++;
- flag = TxS;
- }
- td->addr = PADDR(ctlr->txbuf);
- td->length = n+1;
- td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */
- if(flag)
- ctlr->td->status = BDReady;
- enable();
- ctlr->i2c->i2com = STR|I2CM;
- eieio();
- iunlock(ctlr);
- i2cwait(ctlr);
- disable();
- p = ctlr->phase;
- s = ctlr->td->status;
- if(flag)
- s |= ctlr->td[1].status;
- nr = ctlr->rd->length;
- if(up){
- poperror();
- qunlock(&ctlr->io);
- }
- DPRINT("nr=%ld %4.4ux %8.8lux\n", nr, ctlr->rd->status, ctlr->rd->addr);
- if(nr > n)
- nr = n; /* shouldn't happen */
- if(s & TxERR){
- sprint(up->genbuf, "read: tx status: %.4ux", s);
- return i2cerror(up->genbuf);
- }
- if(s & BDReady || ctlr->rd->status & BDEmpty)
- return i2cerror("timed out");
- if(p != Done)
- return i2cerror("phase error");
- memmove(buf, ctlr->rxbuf, nr);
- if(Chatty){
- for(s=0; s<nr; s++)
- print(" %2.2ux", ctlr->rxbuf[s]&0xFF);
- print("\n");
- }
- return nr;
-}