diff options
Diffstat (limited to 'os/ipaq1110/archipaq.c')
| -rw-r--r-- | os/ipaq1110/archipaq.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/os/ipaq1110/archipaq.c b/os/ipaq1110/archipaq.c new file mode 100644 index 00000000..0e3c726b --- /dev/null +++ b/os/ipaq1110/archipaq.c @@ -0,0 +1,376 @@ +/* + * ipaq + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "io.h" +#include "draw.h" +#include <memdraw.h> +#include "screen.h" + +#include "../port/netif.h" +#include "etherif.h" +#include "../port/flashif.h" + +#define EGPIOADDR 0x49000000 /* physical and virtual address of write only register in CS5 space */ + +static ulong egpiocopy; + +static void +egpiosc(ulong set, ulong clr) +{ + int s; + + s = splhi(); + egpiocopy = (egpiocopy & ~clr) | set; + *(ulong*)EGPIOADDR = egpiocopy; + splx(s); +} + +void +archreset(void) +{ + GpioReg *g; + PpcReg *p; + + g = GPIOREG; + g->grer = 0; + g->gfer = 0; + g->gedr = g->gedr; + g->gpcr = ~0; + g->gpdr = GPIO_CLK_SET0_o | GPIO_CLK_SET1_o; // | GPIO_LDD8_15_o; + g->gafr |= GPIO_SYS_CLK_i; // | GPIO_LDD8_15_o; + p = PPCREG; + p->ppdr |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; /* not sure about PPC_TXD4 here */ + p->ppsr &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + + archuartpower(3, 1); /* allow console to work sooner rather than later */ + L3init(); +} + +void +archpowerdown(void) +{ + PmgrReg *p = PMGRREG; + + p->pwer = GPIO_PWR_ON_i; /* only power button for now, not RTC */ + p->pcfr = PCFR_opde; /* stop 3.6MHz oscillator, and drive pcmcia and chip select low */ + p->pgsr = 0; /* drive all outputs to zero in sleep */ + PPCREG->psdr = 0; /* all peripheral pins as outputs during sleep */ +} + +void +archpowerup(void) +{ + GpioReg *g; + int i; + + g = GPIOREG; + g->gpdr |= GPIO_COM_RTS_o; /* just in case it's off */ + g->gpsr = GPIO_COM_RTS_o; + *(ulong*)EGPIOADDR = egpiocopy; + for(i=0; i<50*1000; i++) + ; + while((g->gplr & GPIO_PWR_ON_i) == 0) + ; /* wait for it to come up */ +} + +void +archconfinit(void) +{ + int w; + + conf.topofmem = 0xC0000000+32*MB; + w = PMGRREG->ppcr & 0x1f; + m->cpuhz = CLOCKFREQ*(w*4+16); + + conf.useminicache = 1; + conf.portrait = 1; /* should take from param flash or allow dynamic change */ +} + +void +kbdinit(void) +{ + addclock0link(kbdclock, MS2HZ); +} + +static LCDmode lcd320x240x16tft = +{ +// .x = 320, .y = 240, .depth = 16, .hz = 70, +// .pbs = 2, .dual = 0, .mono = 0, .active = 1, +// .hsync_wid = 4-2, .sol_wait = 12-1, .eol_wait = 17-1, +// .vsync_hgt = 3-1, .soft_wait = 10, .eof_wait = 1, +// .lines_per_int = 0, .palette_delay = 0, .acbias_lines = 0, +// .obits = 16, +// .vsynclow = 1, .hsynclow = 1, + 320, 240, 16, 70, + 2, 0, 0, 1, + 4-2, 12-1, 17-1, + 3-1, 10, 1, + 0, 0, 0, + 16, + 1, 1, +}; + +int +archlcdmode(LCDmode *m) +{ + *m = lcd320x240x16tft; + return 0; +} + +void +archlcdenable(int on) +{ + if(on) + egpiosc(EGPIO_LCD_ON|EGPIO_LCD_PCI|EGPIO_LCD_5V_ON|EGPIO_LVDD_ON, 0); + else + egpiosc(0, EGPIO_LCD_ON|EGPIO_LCD_PCI|EGPIO_LCD_5V_ON|EGPIO_LVDD_ON); +} + +void +archconsole(void) +{ + uartspecial(0, 115200, 'n', &kbdq, &printq, kbdcr2nl); +} + +void +archuartpower(int port, int on) +{ + int s; + + if(port != 3) + return; + s = splhi(); + GPIOREG->gpdr |= GPIO_COM_RTS_o; /* should be done elsewhere */ + GPIOREG->gpsr = GPIO_COM_RTS_o; + splx(s); + if(on) + egpiosc(EGPIO_RS232_ON, 0); + else + egpiosc(0, EGPIO_RS232_ON); +} + +void +archreboot(void) +{ + dcflushall(); + GPIOREG->gedr = 1<<0; + mmuputctl(mmugetctl() & ~CpCaltivec); /* restore bootstrap's vectors */ + RESETREG->rsrr = 1; /* software reset */ + for(;;) + spllo(); +} + +void +archflashwp(Flash*, int wp) +{ + if(wp) + egpiosc(0, EGPIO_VPEN); + else + egpiosc(EGPIO_VPEN, 0); +} + +/* + * for ../port/devflash.c:/^flashreset + * retrieve flash type, virtual base and length and return 0; + * return -1 on error (no flash) + */ +int +archflashreset(int bank, Flash *f) +{ + if(bank != 0) + return -1; + f->type = "cfi16"; + f->addr = KADDR(FLASHMEM); + if((MEMCFGREG->msc0 & (1<<2)) == 0){ + f->interleave = 1; + f->width = 4; + }else + f->width = 2; + return 0; +} + +int +archaudiopower(int on) +{ + int s; + + if(on) + egpiosc(EGPIO_CODEC_RESET | EGPIO_AUD_PWR_ON, 0); + else + egpiosc(0, EGPIO_CODEC_RESET | EGPIO_AUD_ON | EGPIO_AUD_PWR_ON | EGPIO_QMUTE); + s = splhi(); + GPIOREG->gafr |= GPIO_SYS_CLK_i; + GPIOREG->gpdr |= GPIO_CLK_SET0_o | GPIO_CLK_SET1_o; + GPIOREG->gpsr = GPIO_CLK_SET0_o; + GPIOREG->gpcr = GPIO_CLK_SET1_o; + splx(s); + return 0; +} + +void +archcodecreset(void) +{ +// egpiosc(0, EGPIO_CODEC_RESET); +// egpiosc(EGPIO_CODEC_RESET, 0); +} + +void +archaudiomute(int on) +{ + if(on) + egpiosc(EGPIO_QMUTE, 0); + else + egpiosc(0, EGPIO_QMUTE); +} + +void +archaudioamp(int on) +{ + if(on) + egpiosc(EGPIO_AUD_ON, 0); + else + egpiosc(0, EGPIO_AUD_ON); +} + +enum { + Fs512 = 0, + Fs384 = 1, + Fs256 = 2, + + MHz4_096 = GPIO_CLK_SET1_o, + MHz5_6245 = GPIO_CLK_SET1_o|GPIO_CLK_SET0_o, + MHz11_2896 = GPIO_CLK_SET0_o, + MHz12_288 = 0 +}; + +typedef struct Csel Csel; +struct Csel{ + int speed; + int cfs; /* codec system clock multiplier */ + int gclk; /* gpio clock generator setting */ + int div; /* ssp clock divisor */ +}; +static Csel csel[] = { + {8000, Fs512, MHz4_096, 16}, + {11025, Fs512, MHz5_6245, 16}, + {16000, Fs256 , MHz4_096, 8}, + {22050, Fs512, MHz11_2896, 16}, + {32000, Fs384, MHz12_288, 12}, + {44100, Fs256, MHz11_2896, 8}, + {48000, Fs256, MHz12_288, 8}, + {0}, +}; + +int +archaudiospeed(int clock, int set) +{ + GpioReg *g; + SspReg *ssp; + Csel *cs; + int s, div, cr0; + + for(cs = csel; cs->speed > 0; cs++) + if(cs->speed == clock){ + if(!set) + return cs->cfs; + div = cs->div; + if(div == 0) + div = 4; + div = div/2 - 1; + s = splhi(); + g = GPIOREG; + g->gpsr = cs->gclk; + g->gpcr = ~cs->gclk & (GPIO_CLK_SET0_o|GPIO_CLK_SET1_o); + ssp = SSPREG; + cr0 = (div<<8) | 0x1f; /* 16 bits, TI frames, not enabled */ + ssp->sscr0 = cr0; + ssp->sscr1 = 0x0020; /* ext clock */ + ssp->sscr0 = cr0 | 0x80; /* enable */ + splx(s); + return cs->cfs; + } + return -1; +} + +/* + * pcmcia + */ +int +pcmpowered(int slotno) +{ + if(slotno) + return 0; + if(egpiocopy & EGPIO_OPT_PWR_ON) + return 3; + return 0; +} + +void +pcmpower(int slotno, int on) +{ + USED(slotno); /* the pack powers both or none */ + if(on){ + if((egpiocopy & EGPIO_OPT_PWR_ON) == 0){ + egpiosc(EGPIO_OPT_PWR_ON | EGPIO_OPT_ON, 0); + delay(200); + } + }else + egpiosc(0, EGPIO_OPT_PWR_ON | EGPIO_OPT_ON); +} + +void +pcmreset(int slot) +{ + USED(slot); + egpiosc(EGPIO_CARD_RESET, 0); + delay(100); // microdelay(10); + egpiosc(0, EGPIO_CARD_RESET); +} + +int +pcmpin(int slot, int type) +{ + switch(type){ + case PCMready: + return slot==0? 21: 11; + case PCMeject: + return slot==0? 17: 10; + case PCMstschng: + return -1; + } +} + +void +pcmsetvpp(int slot, int vpp) +{ + USED(slot, vpp); +} + +/* + * set ether parameters: the contents should be derived from EEPROM or NVRAM + */ +int +archether(int ctlno, Ether *ether) +{ + static char opt[128]; + + if(ctlno == 1){ + sprint(ether->type, "EC2T"); + return 1; + } + if(ctlno > 0) + return -1; + sprint(ether->type, "wavelan"); + if(0) + strcpy(opt, "mode=0 essid=Limbo station=ipaq1 crypt=off"); /* peertopeer */ + else + strcpy(opt, "mode=managed essid=Vitanuova1 station=ipaq1 crypt=off"); + ether->nopt = tokenize(opt, ether->opt, nelem(ether->opt)); + return 1; +} |
