From 602fc1003b1173c4d4ffc04f819159a3959fd6f7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 22 Nov 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-11-22 --- bitsy/dat.h | 2 +- bitsy/devpcmcia.c | 24 ++++++--- bitsy/devuda1341.c | 122 +++++++++++++++++++++++++++++++-------------- bitsy/fns.h | 1 + bitsy/io.h | 10 ++++ bitsy/main.c | 18 ------- bitsy/power.c | 26 ++++++++++ bitsy/sa1110dma.c | 16 +++++- bitsy/sa1110dma.h | 1 + bitsy/trap.c | 42 ++++++++++++++++ port/portdat.h | 1 + 11 files changed, 198 insertions(+), 65 deletions(-) create mode 100644 bitsy/power.c diff --git a/bitsy/dat.h b/bitsy/dat.h index c4bd21af5660063bcbb53bd8cfcd2298e8985f6d..8968300800ffd53ccb7d2119b3832ecea00f466e 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -316,7 +316,7 @@ struct Cisdat */ struct PCMslot { - Ref; + Ref ref; long memlen; /* memory length */ uchar slotno; /* slot number */ diff --git a/bitsy/devpcmcia.c b/bitsy/devpcmcia.c index 53a3aa39d824b0f7c067e2fecad19ca90fd821c4..5fa38fc60ce636f5527216e0ca05d0c5befcaca1 100644 --- a/bitsy/devpcmcia.c +++ b/bitsy/devpcmcia.c @@ -86,6 +86,9 @@ pcmciareset(void) /* set timing to the default, 300 */ slottiming(0, 300, 300, 300, 0); slottiming(1, 300, 300, 300, 0); + + /* interrupt on card insertion */ + gpiointrenable( } static Chan* @@ -286,7 +289,7 @@ Dev pcmciadevtab = { /* see what's there */ static void -slotinfo(void) +slotinfo(Ureg*, void*) { ulong x = gpioregs->level; @@ -295,8 +298,14 @@ slotinfo(void) slot[0].occupied = 0; slot[1].occupied = 0; } else { - slot[0].occupied = (x & GPIO_CARD_IND0_i) == 0; - slot[1].occupied = (x & GPIO_CARD_IND1_i) == 0; + if(!slot[0].occupied && (x & GPIO_CARD_IND0_i)){ + slot[0].occupied = 1; + slot[0].cisread = 0; + } + if(!slot[1].occupied && (x & GPIO_CARD_IND1_i)){ + slot[1].occupied = 1; + slot[0].cisread = 0; + } } } @@ -304,21 +313,20 @@ slotinfo(void) static void increfp(PCMslot *pp) { + slotinfo(nil, nil); if(incref(&pcmcia) == 1){ egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1); egpiobits(EGPIO_pcmcia_reset, 0); - delay(100); /* time to power up */ + delay(200); /* time to power up */ } - incref(pp); - - slotinfo(); + if(pp->occupied && pp->cisread == 0) + pcmcisread(pp); } static void decrefp(PCMslot *pp) { - slotinfo(); decref(pp); if(decref(&pcmcia) == 0) egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0); diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index c4222333c5848b2ee6b58e70f69b1c2775f3659d..9f6e0fcfb9f20e6fc6060b5e03f3d3c33fd6f089 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -19,7 +19,7 @@ #include "io.h" #include "sa1110dma.h" -static int debug = 2; +static int debug = 0; /* * GPIO based L3 bus support. @@ -382,6 +382,12 @@ L3_read(uchar addr, uchar *data, int len) return bytes; } +void +audiomute(int on) +{ + egpiobits(EGPIO_audio_mute, on); +} + static char Emode[] = "illegal open mode"; static char Evolume[] = "illegal volume specifier"; @@ -390,7 +396,7 @@ bufinit(IOstate *b) { int i; - if (debug) print("#A: bufinit\n"); + if (debug) print("bufinit\n"); for (i = 0; i < Nbuf; i++) { b->buf[i].virt = xalloc(Bufsize); b->buf[i].phys = PADDR(b->buf[i].virt); @@ -403,7 +409,7 @@ setempty(IOstate *b) { int i; - if (debug) print("#A: setempty\n"); + if (debug) print("setempty\n"); for (i = 0; i < Nbuf; i++) { b->buf[i].nbytes = 0; } @@ -470,7 +476,7 @@ enable(void) sspregs->control0 = 0x039f; /* enable */ /* Enable the audio power */ - audiopower(1); + egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 1); /* external clock configured for 44100 samples/sec */ gpioregs->set = GPIO_CLK_SET0_o; @@ -492,15 +498,14 @@ enable(void) L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data0e6, 2 ); if (debug) { - print("uchar status0 = 0x%2.2ux\n", status0); - print("uchar status1 = 0x%2.2ux\n", status1); - print("uchar data02 = 0x%2.2ux\n", data02); - print("ushort data0e2 = 0x%4.4ux\n", data0e2); - print("ushort data0e4 = 0x%4.4ux\n", data0e4); - print("ushort data0e6 = 0x%4.4ux\n", data0e6); - print("#A: audio enabled\n"); - print("\tsspregs->control0 = 0x%lux\n", sspregs->control0); - print("\tsspregs->control1 = 0x%lux\n", sspregs->control1); + print("enable: status0 = 0x%2.2ux\n", status0); + print("enable: status1 = 0x%2.2ux\n", status1); + print("enable: data02 = 0x%2.2ux\n", data02); + print("enable: data0e2 = 0x%4.4ux\n", data0e2); + print("enable: data0e4 = 0x%4.4ux\n", data0e4); + print("enable: data0e6 = 0x%4.4ux\n", data0e6); + print("enable: sspregs->control0 = 0x%lux\n", sspregs->control0); + print("enable: sspregs->control1 = 0x%lux\n", sspregs->control1); } } @@ -521,7 +526,6 @@ static void mxvolume(void) { int *left, *right; - if (debug) print("mxvolume\n"); if(audio.amode & Aread){ left = audio.livol; right = audio.rivol; @@ -540,7 +544,16 @@ mxvolume(void) { L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data0e4, 2 ); L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data0e5, 2 ); } - + if (left[Vinvert]+right[Vinvert] == 0) + status1 &= ~0x04; + else + status1 |= 0x04; + L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1); + if (debug) { + print("mxvolume: status1 = 0x%2.2ux\n", status1); + print("mxvolume: data0e4 = 0x%4.4ux\n", data0e4); + print("mxvolume: data0e5 = 0x%4.4ux\n", data0e5); + } } if(audio.amode & Awrite){ left = audio.lovol; @@ -562,27 +575,26 @@ mxvolume(void) { else data02 |= 0x10; if (left[Vinvert]+right[Vinvert] == 0) - status1 &= ~0x14; + status1 &= ~0x10; else - status1 |= 0x14; + status1 |= 0x10; L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1); L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data00, 1); L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data01, 1); L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data02, 1); if (debug) { - print("uchar status1 = 0x%2.2ux;\n", status1); - print("uchar data00 = 0x%2.2ux; /* audio out */\n", data00); - print("uchar data01 = 0x%2.2ux; /* bass&treb */\n", data01); - print("uchar data02 = 0x%2.2ux; /* mode */\n", data02); + print("mxvolume: status1 = 0x%2.2ux\n", status1); + print("mxvolume: data00 = 0x%2.2ux\n", data00); + print("mxvolume: data01 = 0x%2.2ux\n", data01); + print("mxvolume: data02 = 0x%2.2ux\n", data02); } } - } static void outenable(void) { /* turn on DAC, set output gain switch */ - amplifierpower(1); + egpiobits(EGPIO_audio_power, 1); audiomute(0); status1 |= 0x41; L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1); @@ -590,40 +602,62 @@ outenable(void) { data00 |= 0xf; L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data00, 1); if (debug) { - print("uchar status1 = 0x%2.2ux\n", status1); - print("uchar data00 = 0x%2.2ux\n", data00); + print("outenable: status1 = 0x%2.2ux\n", status1); + print("outenable: data00 = 0x%2.2ux\n", data00); } } static void outdisable(void) { + dmastop(audio.o.dma); /* turn off DAC, clear output gain switch */ audiomute(1); - amplifierpower(0); + egpiobits(EGPIO_audio_power, 0); status1 &= ~0x41; L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1); if (debug) { - print("uchar status1 = 0x%2.2ux\n", status1); + print("outdisable: status1 = 0x%2.2ux\n", status1); } + egpiobits(EGPIO_audio_power, 0); } static void inenable(void) { /* turn on ADC, set input gain switch */ +// egpiobits(EGPIO_audio_power, 1); +// audiomute(0); status1 |= 0x22; L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1); if (debug) { - print("uchar status1 = 0x%2.2ux\n", status1); + print("inenable: status1 = 0x%2.2ux\n", status1); } } static void indisable(void) { + dmastop(audio.i.dma); /* turn off ADC, clear input gain switch */ status1 &= ~0x22; L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1); if (debug) { - print("uchar status1 = 0x%2.2ux\n", status1); + print("indisable: status1 = 0x%2.2ux\n", status1); + } +} + +static void +disable(void) { + egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0); +} + +static void +audiopower(int flag) { + if (flag) { + egpiobits(EGPIO_audio_power, 1); + egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 1); + } else { + /* power off */ + egpiobits(EGPIO_audio_power, 0); + egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0); } } @@ -649,7 +683,12 @@ sendaudio(IOstate *s) { iostats.faildma++; break; } - if (debug > 1) print("#A: dmastart @%p\n", s->next); + if (debug) { + if (debug > 1) + print("dmastart @%p\n", s->next); + else + iprint("+"); + } s->next->nbytes = 0; s->next++; if (s->next == &s->buf[Nbuf]) @@ -680,7 +719,12 @@ recvaudio(IOstate *s) { iostats.faildma++; break; } - if (debug > 1) print("#A: dmastart @%p\n", s->next); + if (debug) { + if (debug > 1) + print("dmastart @%p\n", s->next); + else + iprint("+"); + } s->next++; if (s->next == &s->buf[Nbuf]) s->next = &s->buf[0]; @@ -692,7 +736,12 @@ static void audiointr(void *x, ulong ndma) { IOstate *s = x; - if (debug > 1) iprint("#A: audio interrupt @%p\n", s->current); + if (debug) { + if (debug > 1) + iprint("#A: audio interrupt @%p\n", s->current); + else + iprint("-"); + } /* Only interrupt routine touches s->current */ s->current++; if (s->current == &s->buf[Nbuf]) @@ -762,7 +811,7 @@ audioopen(Chan *c, int mode) setempty(s); s->emptying = &s->buf[Nbuf-1]; s->chan = c; - s->dma = dmaalloc(0, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s); + s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s); } if (omode & Awrite) { outenable(); @@ -777,7 +826,7 @@ audioopen(Chan *c, int mode) resetlevel(); mxvolume(); qunlock(&audio); - if (debug) print("#A: open done\n"); + if (debug) print("open done\n"); break; } c = devopen(c, mode, audiodir, nelem(audiodir), devgen); @@ -829,7 +878,6 @@ audioclose(Chan *c) } dmawait(s->dma); outdisable(); - amplifierpower(0); setempty(s); dmafree(s->dma); qunlock(s); @@ -844,7 +892,6 @@ audioclose(Chan *c) qunlock(s); nexterror(); } - dmawait(s->dma); indisable(); setempty(s); dmafree(s->dma); @@ -853,7 +900,7 @@ audioclose(Chan *c) } if (audio.amode == 0) { /* turn audio off */ - audiopower(0); + egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0); } qunlock(&audio); poperror(); @@ -1127,4 +1174,5 @@ Dev uda1341devtab = { devbwrite, devremove, devwstat, + audiopower, }; diff --git a/bitsy/fns.h b/bitsy/fns.h index 513e4a6750ee2b42fa0cbad0e61983b6aea39504..2bc3e93d85a402642ecbc34fe90e7ba77b0b1374 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -25,6 +25,7 @@ char* getconf(char*); ulong getfar(void); ulong getfsr(void); #define getpgcolor(a) 0 +void gpiointrenable(ulong, int, void (*)(Ureg*, void*), void*, char*) void h3650uartsetup(void); void icacheinvalidate(void); void idle(void); diff --git a/bitsy/io.h b/bitsy/io.h index e1015c8c02c680b907d2eae0f48cbd7c14fab5fd..b17235eb5f0242fc2e8f59002df39ccb1ef8c0e4 100644 --- a/bitsy/io.h +++ b/bitsy/io.h @@ -109,6 +109,16 @@ enum GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */ }; +/* + * edge argument for gpiointrenable + */ +enum +{ + GPIOrising, + GPIOfalling, + GPIOboth, +}; + /* hardware registers */ typedef struct Uartregs Uartregs; struct Uartregs diff --git a/bitsy/main.c b/bitsy/main.c index 9e75a49f5f12d13a2684c9c029638b826197bc94..11572dd4e4835a94a2aeb215b989ae6990bf4339 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -425,24 +425,6 @@ lcdpower(int on) egpiobits(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v, on); } -void -audiopower(int on) -{ - egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, on); -} - -void -amplifierpower(int on) -{ - egpiobits(EGPIO_audio_power, on); -} - -void -audiomute(int on) -{ - egpiobits(EGPIO_audio_mute, on); -} - void flashprogpower(int on) { diff --git a/bitsy/power.c b/bitsy/power.c new file mode 100644 index 0000000000000000000000000000000000000000..32a97d082753647d5c27aa03dbaecb77051bdc03 --- /dev/null +++ b/bitsy/power.c @@ -0,0 +1,26 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "init.h" +#include "pool.h" + +/* Power management for the bitsy */ + +static void +powerintr(Ureg*, void *x) +{ + /* Power button interrupt */ + int i; + + /* debounce, 50 ms*/ + for (i = 0; i < 50; i++) { + delay(1); + if ((gpioregs->level & GPIO_PWR_ON_i) == 0) + return; /* bounced */ + } + rs232power(0); +} diff --git a/bitsy/sa1110dma.c b/bitsy/sa1110dma.c index 49388a33ea7038f891446ae13790da9cfb182a00..74019765f9e12b757dc6daa02899948b29596e24 100644 --- a/bitsy/sa1110dma.c +++ b/bitsy/sa1110dma.c @@ -115,6 +115,11 @@ dmafree(int i) { dma.chan[i].intr = nil; } +void +dmastop(int i) { + dmaregs[i].dcsr_clr = 0xff; +} + ulong dmastart(int chan, ulong addr, int count) { ulong status, n; @@ -194,12 +199,21 @@ dmaintr(Ureg*, void *x) iprint("error, channel %d, status 0x%lux\n", i, dcsr); donebit = 1<<((dcsr&1<dcsr_clr = donebit; + regs->dcsr_clr = 1<dcsr_clr = ERROR; + iprint("DMA error, channel %d, status 0x%lux\n", i, dcsr); + if (dma.chan[i].intr) { + (*dma.chan[i].intr)(dma.chan[i].param, 0); + } + wakeup(&dma.chan[i].r); + return; + } iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr); } diff --git a/bitsy/sa1110dma.h b/bitsy/sa1110dma.h index 2272b57151855919a5f88ae8c20197d8536968dc..b1c5942b730e8d5a7fca82415a016112524bf969 100644 --- a/bitsy/sa1110dma.h +++ b/bitsy/sa1110dma.h @@ -14,4 +14,5 @@ void dmafree(int); ulong dmastart(int, ulong, int); void dmawait(int); +void dmastop(int); int dmaidle(int); diff --git a/bitsy/trap.c b/bitsy/trap.c index 17581135e87fc13ee9f13e5959272cccc0a20148..940bfb845fc37221d5f3c1e420dd1ce4b60529ce 100644 --- a/bitsy/trap.c +++ b/bitsy/trap.c @@ -127,6 +127,44 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name) unlock(&vctllock); } +/* + * enable an interrupt on gpio line. edge is encoded as follows + */ +void +gpiointrenable(ulong bit, int edge, void (*f)(Ureg*, void*), void* a, char *name) +{ + int irq; + + /* figure out which interrupt */ + for(irq = 0; irq < 28; irq++) + if((1<= 28) + panic("gpiointrenable %lux", bit); + if(irq > 11) + irq = 11; + + /* it had better be input */ + if(bit & gpioregs->direction) + panic(""gpiointrenable %lux of output pin", bit); + + /* set edge register */ + switch(edge){ + case GPIOboth: + gpioregs->rising |= bit; + gpioregs->falling |= bit; + break; + case GPIOfalling: + gpioregs->falling |= bit; + break; + case GPIOrising: + gpioregs->rising |= bit; + break; + } + + intrenable(irq, f, a, name); +} + /* * called by trap to handle access faults */ @@ -196,6 +234,10 @@ trap(Ureg *ureg) if(ureg->type == PsrMirq){ found = 0; va = intrregs->icip; + + /* clear any gpio edge interrupt */ + gpioregs->irqbit = va & 0xFFF; + for(v = vctl; v != nil; v = v->next){ if(v->irqbit & va){ v->f(ureg, v->a); diff --git a/port/portdat.h b/port/portdat.h index 2588522808a543bed45cd9d1eabf8a8460460c3b..6e95d788e738788c7bdbec1f026cf48d3e1fff3f 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -193,6 +193,7 @@ struct Dev long (*bwrite)(Chan*, Block*, ulong); void (*remove)(Chan*); void (*wstat)(Chan*, char*); + void (*power)(int); /* power mgt: power(1) → on, power (0) → off */ }; struct Dirtab