示例#1
0
文件: raminit.c 项目: XVilka/coreboot
/* 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
}
示例#2
0
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;
}
示例#3
0
文件: pcf.c 项目: Gwenio/DragonFlyBSD
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;
}