/* cache is assumed to be disabled */ int sizemem(void) { int rows,banks, cols, i, bank; unsigned char al; volatile unsigned long *lp = (volatile unsigned long *) CACHELINESZ; unsigned long l; /* initialize dram controller registers */ /* disable write buffer/read-ahead buffer */ *dbctl = 0; /* no ecc interrupts of any kind. */ *eccctl = 0; /* Set SDRAM timing for slowest speed. */ *drcmctl = 0x1e; /* setup dram register for all banks * with max cols and max banks * this is the oldest trick in the book. You are going to set up for max rows * and cols, then do a write, then see if the data is wrapped to low memory. * you can actually tell by which data gets to which low memory, * exactly how many rows and cols you have. */ *drccfg=0xbbbb; /* setup loop to do 4 external banks starting with bank 3 */ *drcbendadr=0x0ff000000; /* for now, set it up for one loop of bank 0. Just to get it to go at all. */ *drcbendadr=0x0ff; /* issue a NOP to all DRAMs */ /* Setup DRAM control register with Disable refresh, * disable write buffer Test Mode and NOP command select */ *drcctl=0x01; /* dummy write for NOP to take effect */ dummy_write(); print_err("NOP\n"); /* 100? 200? */ udelay(100); print_err("after udelay\n"); /* issue all banks precharge */ *drcctl=0x02; print_err("set *drcctl to 2 \n"); dummy_write(); print_err("PRE\n"); /* issue 2 auto refreshes to all banks */ *drcctl=0x04; dummy_write(); print_err("AUTO1\n"); dummy_write(); print_err("AUTO2\n"); /* issue LOAD MODE REGISTER command */ *drcctl=0x03; dummy_write(); print_err("LOAD MODE REG\n"); *drcctl=0x04; for (i=0; i<8; i++) /* refresh 8 times */{ dummy_write(); print_err("dummy write\n"); } print_err("8 dummy writes\n"); /* set control register to NORMAL mode */ *drcctl=0x00; print_err("normal\n"); print_err("HI done normal\n"); print_err("sizemem\n"); for(bank = 3; bank >= 0; bank--) { print_err("Try to assign to l\n"); *lp = 0xdeadbeef; print_err("assigned l ... \n"); if (*lp != 0xdeadbeef) { print_err(" no memory at bank "); // print_err_hex8(bank); // print_err(" value "); print_err_hex32(*lp); print_err("\n"); // continue; } *drcctl = 2; dummy_write(); *drccfg = *drccfg >> 4; l = *drcbendadr; l >>= 8; *drcbendadr = l; print_err("loop around\n"); *drcctl = 0; dummy_write(); } #if 0 /* enable last bank and setup ending address * register for max ram in last bank */ *drcbendadr=0x0ff000000; // dumpram(); /* issue a NOP to all DRAMs */ /* Setup DRAM control register with Disable refresh, * disable write buffer Test Mode and NOP command select */ *drcctl=0x01; /* dummy write for NOP to take effect */ dummy_write(); print_err("NOP\n"); /* 100? 200? */ //udelay(100); print_err("after udelay\n"); /* issue all banks precharge */ *drcctl=0x02; print_err("set *drcctl to 2 \n"); dummy_write(); print_err("PRE\n"); /* issue 2 auto refreshes to all banks */ *drcctl=0x04; dummy_write(); print_err("AUTO1\n"); dummy_write(); print_err("AUTO2\n"); /* issue LOAD MODE REGISTER command */ *drcctl=0x03; dummy_write(); print_err("LOAD MODE REG\n"); *drcctl=0x04; for (i=0; i<8; i++) /* refresh 8 times */{ dummy_write(); print_err("dummy write\n"); } print_err("8 dummy writes\n"); /* set control register to NORMAL mode */ *drcctl=0x00; print_err("normal\n"); print_err("HI done normal\n"); bank = 3; /* this is really ugly, it is right from assembly code. * we need to clean it up later */ start: /* write col 11 wrap adr */ COL11_ADR=COL11_DATA; if(COL11_ADR!=COL11_DATA) goto bad_ram; print_err("11\n"); /* write col 10 wrap adr */ COL10_ADR=COL10_DATA; if(COL10_ADR!=COL10_DATA) goto bad_ram; print_err("10\n"); /* write col 9 wrap adr */ COL09_ADR=COL09_DATA; if(COL09_ADR!=COL09_DATA) goto bad_ram; print_err("9\n"); /* write col 8 wrap adr */ COL08_ADR=COL08_DATA; if(COL08_ADR!=COL08_DATA) goto bad_ram; print_err("8\n"); /* write row 14 wrap adr */ ROW14_ADR=ROW14_DATA; if(ROW14_ADR!=ROW14_DATA) goto bad_ram; print_err("14\n"); /* write row 13 wrap adr */ ROW13_ADR=ROW13_DATA; if(ROW13_ADR!=ROW13_DATA) goto bad_ram; print_err("13\n"); /* write row 12 wrap adr */ ROW12_ADR=ROW12_DATA; if(ROW12_ADR!=ROW12_DATA) goto bad_ram; print_err("12\n"); /* write row 11 wrap adr */ ROW11_ADR=ROW11_DATA; if(ROW11_ADR!=ROW11_DATA) goto bad_ram; print_err("11\n"); /* write row 10 wrap adr */ ROW10_ADR=ROW10_DATA; if(ROW10_ADR!=ROW10_DATA) goto bad_ram; print_err("10\n"); /* * read data @ row 12 wrap adr to determine # banks, * and read data @ row 14 wrap adr to determine # rows. * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM. * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4 * if data @ row 12 wrap == 11 or 12, we have 4 banks */ banks=2; if (ROW12_ADR != ROW10_DATA) { banks=4; print_err("4b\n"); if(ROW12_ADR != ROW11_DATA) { if(ROW12_ADR != ROW12_DATA) goto bad_ram; } } /* validate row mask */ rows=ROW14_ADR; if (rows<ROW11_DATA) goto bad_ram; if (rows>ROW14_DATA) goto bad_ram; /* verify all 4 bytes of dword same */ /* if(rows&0xffff!=(rows>>16)&0xffff) goto bad_ram; if(rows&0xff!=(rows>>8)&0xff) goto bad_ram; */ /* now just get one of them */ rows &= 0xff; print_err("rows"); print_err_hex32(rows); print_err("\n"); /* validate column data */ cols=COL11_ADR; if(cols<COL08_DATA) goto bad_ram; if (cols>COL11_DATA) goto bad_ram; /* verify all 4 bytes of dword same */ /* if(cols&0xffff!=(cols>>16)&0xffff) goto bad_ram; if(cols&0xff!=(cols>>8)&0xff) goto bad_ram; */ print_err("cols"); print_err_hex32(cols); print_err("\n"); cols -= COL08_DATA; /* cols now is in the range of 0 1 2 3 ... */ i = cols&3; // i = cols + rows; /* wacky end addr calculation */ /* al = 3; al -= (i & 0xff);k */ /* what a fookin' mess this is */ if(banks==4) i+=8; /* <-- i holds merged value */ /* i now has the col width in bits 0-1 and the bank count (2 or 4) * in bit 3. * this is the format for the drccfg register */ /* fix ending addr mask*/ /*FIXME*/ /* let's just go with this to start ... see if we can get ANYWHERE */ /* need to get end addr. Need to do it with the bank in mind. */ /* al = 3; al -= i&3; *drcbendaddr = rows >> al; print_err("computed ending_adr = "); print_err_hex8(ending_adr); print_err("\n"); */ bad_reinit: /* issue all banks recharge */ *drcctl=0x02; dummy_write(); /* update ending address register */ // *drcbendadr = ending_adr; /* update config register */ *drccfg &= ~(0xff << bank*4); if (ending_adr) *drccfg = ((banks == 4 ? 8 : 0) | cols & 3)<< (bank*4); // dumpram(); /* skip the rest for now */ // bank = 0; // *drccfg=*drccfg&YYY|ZZZZ; if(bank!=0) { bank--; // drcbendaddr--; *drcbendaddr = 0xff000000; //*(&*drcbendadr+XXYYXX)=0xff; goto start; } /* set control register to NORMAL mode */ *drcctl=0x18; dummy_write(); return bank; bad_ram: print_info("bad ram!\n"); /* you are here because the read-after-write failed, * in most cases because: no ram in that bank! * set badbank to 1 and go to reinit */ ending_adr = 0; goto bad_reinit; while(1) print_err("DONE NEXTBANK\n"); #endif }
void pcf_intr(void *arg) { struct pcf_softc *sc = arg; char data, status, addr; char error = 0; PCF_LOCK(sc); status = pcf_get_S1(sc); if (status & PIN) { printf("pcf: spurious interrupt, status=0x%x\n", status & 0xff); goto error; } if (status & LAB) printf("pcf: bus arbitration lost!\n"); if (status & BER) { error = IIC_EBUSERR; iicbus_intr(sc->iicbus, INTR_ERROR, &error); goto error; } do { status = pcf_get_S1(sc); switch(sc->pcf_slave_mode) { case SLAVE_TRANSMITTER: if (status & LRB) { /* ack interrupt line */ dummy_write(sc); /* no ack, don't send anymore */ sc->pcf_slave_mode = SLAVE_RECEIVER; iicbus_intr(sc->iicbus, INTR_NOACK, NULL); break; } /* get data from upper code */ iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data); pcf_set_S0(sc, data); break; case SLAVE_RECEIVER: if (status & AAS) { addr = pcf_get_S0(sc); if (status & AD0) iicbus_intr(sc->iicbus, INTR_GENERAL, &addr); else iicbus_intr(sc->iicbus, INTR_START, &addr); if (addr & LSB) { sc->pcf_slave_mode = SLAVE_TRANSMITTER; /* get the first char from upper code */ iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data); /* send first data byte */ pcf_set_S0(sc, data); } break; } /* stop condition received? */ if (status & STS) { /* ack interrupt line */ dummy_read(sc); /* emulate intr stop condition */ iicbus_intr(sc->iicbus, INTR_STOP, NULL); } else { /* get data, ack interrupt line */ data = pcf_get_S0(sc); /* deliver the character */ iicbus_intr(sc->iicbus, INTR_RECEIVE, &data); } break; default: panic("%s: unknown slave mode (%d)!", __func__, sc->pcf_slave_mode); } } while ((pcf_get_S1(sc) & PIN) == 0); PCF_UNLOCK(sc); return; error: /* unknown event on bus...reset PCF */ pcf_set_S1(sc, PIN|ESO|ENI|ACK); sc->pcf_slave_mode = SLAVE_RECEIVER; PCF_UNLOCK(sc); return; }
static void pcfintr(void *arg) { device_t pcfdev = (device_t)arg; struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); char data, status, addr; char error = 0; status = PCF_GET_S1(pcf); if (status & PIN) { device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff); goto error; } if (status & LAB) device_printf(pcfdev, "bus arbitration lost!\n"); if (status & BER) { error = IIC_EBUSERR; iicbus_intr(pcf->iicbus, INTR_ERROR, &error); goto error; } do { status = PCF_GET_S1(pcf); switch(pcf->pcf_slave_mode) { case SLAVE_TRANSMITTER: if (status & LRB) { /* ack interrupt line */ dummy_write(pcf); /* no ack, don't send anymore */ pcf->pcf_slave_mode = SLAVE_RECEIVER; iicbus_intr(pcf->iicbus, INTR_NOACK, NULL); break; } /* get data from upper code */ iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data); PCF_SET_S0(pcf, data); break; case SLAVE_RECEIVER: if (status & AAS) { addr = PCF_GET_S0(pcf); if (status & AD0) iicbus_intr(pcf->iicbus, INTR_GENERAL, &addr); else iicbus_intr(pcf->iicbus, INTR_START, &addr); if (addr & LSB) { pcf->pcf_slave_mode = SLAVE_TRANSMITTER; /* get the first char from upper code */ iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data); /* send first data byte */ PCF_SET_S0(pcf, data); } break; } /* stop condition received? */ if (status & STS) { /* ack interrupt line */ dummy_read(pcf); /* emulate intr stop condition */ iicbus_intr(pcf->iicbus, INTR_STOP, NULL); } else { /* get data, ack interrupt line */ data = PCF_GET_S0(pcf); /* deliver the character */ iicbus_intr(pcf->iicbus, INTR_RECEIVE, &data); } break; default: panic("%s: unknown slave mode (%d)!", __func__, pcf->pcf_slave_mode); } } while ((PCF_GET_S1(pcf) & PIN) == 0); return; error: /* unknown event on bus...reset PCF */ PCF_SET_S1(pcf, PIN|ES0|ENI|ACK); pcf->pcf_slave_mode = SLAVE_RECEIVER; return; }