ref: 254b07675e1a5348f2a8723f55e6b5b1b18a4721
dir: /os/ipaq1110/archipaq.c/
/*
* 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;
default:
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;
}