* Patches by David Müller, 12 Jun 2003:
  - rewrite of the S3C24X0 register definitions stuff
  - "driver" for the built-in S3C24X0 RTC

* Patches by Yuli Barcohen, 12 Jun 2003:
  - Add MII support and Ethernet PHY initialization for MPC8260ADS board
  - Fix incorrect SIUMCR initialisation caused by wrong Hard Reset
    configuration word supplied by FPGA on some MPC8260ADS boards

* Patch by Pantelis Antoniou, 10 Jun 2003:
  Unify status LED interface
diff --git a/drivers/Makefile b/drivers/Makefile
index 50fc75a..8eb9472 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -38,7 +38,8 @@
 	  pcnet.o plb2800_eth.o \
 	  s3c24x0_i2c.o sed13806.o serial.o \
 	  smc91111.o smiLynxEM.o              sym53c8xx.o \
-	  ti_pci1410a.o tigon3.o w83c553f.o
+	  ti_pci1410a.o tigon3.o w83c553f.o \
+	  status_led.o
 
 ## Disabled for now:
 ##	  cs8900.o ct69000.o dataflash.o dc2114x.o ds1722.o \
diff --git a/drivers/s3c24x0_i2c.c b/drivers/s3c24x0_i2c.c
index b501761..eeb6cf6 100644
--- a/drivers/s3c24x0_i2c.c
+++ b/drivers/s3c24x0_i2c.c
@@ -39,103 +39,114 @@
 
 #ifdef CONFIG_HARD_I2C
 
-#define	IIC_WRITE	0
-#define IIC_READ	1
+#define	I2C_WRITE	0
+#define I2C_READ	1
 
-#define IIC_OK		0
-#define IIC_NOK		1
-#define IIC_NACK	2
-#define IIC_NOK_LA	3		/* Lost arbitration */
-#define IIC_NOK_TOUT	4		/* time out */
+#define I2C_OK		0
+#define I2C_NOK		1
+#define I2C_NACK	2
+#define I2C_NOK_LA	3		/* Lost arbitration */
+#define I2C_NOK_TOUT	4		/* time out */
 
-#define IICSTAT_BSY	0x20		/* Busy bit */
-#define IICSTAT_NACK	0x01		/* Nack bit */
-#define IICCON_IRPND	0x10		/* Interrupt pending bit */
-#define IIC_MODE_MT	0xC0		/* Master Transmit Mode */
-#define IIC_MODE_MR	0x80		/* Master Receive Mode */
-#define IIC_START_STOP	0x20		/* START / STOP */
-#define IIC_TXRX_ENA	0x10		/* I2C Tx/Rx enable */
+#define I2CSTAT_BSY	0x20		/* Busy bit */
+#define I2CSTAT_NACK	0x01		/* Nack bit */
+#define I2CCON_IRPND	0x10		/* Interrupt pending bit */
+#define I2C_MODE_MT	0xC0		/* Master Transmit Mode */
+#define I2C_MODE_MR	0x80		/* Master Receive Mode */
+#define I2C_START_STOP	0x20		/* START / STOP */
+#define I2C_TXRX_ENA	0x10		/* I2C Tx/Rx enable */
 
-#define IIC_TIMEOUT 1			/* 1 seconde */
+#define I2C_TIMEOUT 1			/* 1 seconde */
 
 
-static int GetIICSDA(void)
+static int GetI2CSDA(void)
 {
-	return (rGPEDAT & 0x8000) >> 15;
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+	return (gpio->GPEDAT & 0x8000) >> 15;
 }
 
 #if 0
-static void SetIICSDA(int x)
+static void SetI2CSDA(int x)
 {
 	rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15;
 }
 #endif
 
-static void SetIICSCL(int x)
+static void SetI2CSCL(int x)
 {
-	rGPEDAT = (rGPEDAT & ~0x4000) | (x&1) << 14;
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+	gpio->GPEDAT = (gpio->GPEDAT & ~0x4000) | (x&1) << 14;
 }
 
 
 static int WaitForXfer(void)
 {
+    S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
     int i, status;
 
-    i = IIC_TIMEOUT * 1000;
-    status = rIICCON;
-    while ((i > 0) && !(status & IICCON_IRPND)) {
+    i = I2C_TIMEOUT * 1000;
+    status = i2c->IICCON;
+    while ((i > 0) && !(status & I2CCON_IRPND)) {
     	udelay(1000);
-	status = rIICCON;
+	status = i2c->IICCON;
 	i--;
     }
 
-    return(status & IICCON_IRPND) ? IIC_OK : IIC_NOK_TOUT;
+    return(status & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
 }
 
 static int IsACK(void)
 {
-    return(!(rIICSTAT & IICSTAT_NACK));
+    S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
+
+    return(!(i2c->IICSTAT & I2CSTAT_NACK));
 }
 
 static void ReadWriteByte(void)
 {
-    rIICCON &= ~IICCON_IRPND;
+    S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
+
+    i2c->IICCON &= ~I2CCON_IRPND;
 }
 
 void i2c_init (int speed, int slaveadd)
 {
+    S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
+    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
     ulong freq, pres = 16, div;
     int i, status;
 
     /* wait for some time to give previous transfer a chance to finish */
 
-    i = IIC_TIMEOUT * 1000;
-    status = rIICSTAT;
-    while ((i > 0) && (status & IICSTAT_BSY)) {
+    i = I2C_TIMEOUT * 1000;
+    status = i2c->IICSTAT;
+    while ((i > 0) && (status & I2CSTAT_BSY)) {
 	udelay(1000);
-	status = rIICSTAT;
+	status = i2c->IICSTAT;
 	i--;
     }
 
-    if ((status & IICSTAT_BSY) || GetIICSDA() == 0) {
-	ulong old_gpecon = rGPECON;
+    if ((status & I2CSTAT_BSY) || GetI2CSDA() == 0) {
+	ulong old_gpecon = gpio->GPECON;
 	/* bus still busy probably by (most) previously interrupted transfer */
 
-	/* set IICSDA and IICSCL (GPE15, GPE14) to GPIO */
-	rGPECON = (rGPECON & ~0xF0000000) | 0x10000000;
+	/* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
+	gpio->GPECON = (gpio->GPECON & ~0xF0000000) | 0x10000000;
 
-	/* toggle IICSCL until bus idle */
-	SetIICSCL(0); udelay(1000);
+	/* toggle I2CSCL until bus idle */
+	SetI2CSCL(0); udelay(1000);
 	i = 10;
-	while ((i > 0) && (GetIICSDA() != 1)) {
-		SetIICSCL(1); udelay(1000);
-		SetIICSCL(0); udelay(1000);
+	while ((i > 0) && (GetI2CSDA() != 1)) {
+		SetI2CSCL(1); udelay(1000);
+		SetI2CSCL(0); udelay(1000);
 		i--;
 	}
-	SetIICSCL(1); udelay(1000);
+	SetI2CSCL(1); udelay(1000);
 
 	/* restore pin functions */
-	rGPECON = old_gpecon;
+	gpio->GPECON = old_gpecon;
     }
 
     /* calculate prescaler and divisor values */
@@ -150,13 +161,13 @@
 
     /* set prescaler, divisor according to freq, also set
        ACKGEN, IRQ */
-    rIICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0);
+    i2c->IICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0);
 
     /* init to SLAVE REVEIVE and set slaveaddr */
-    rIICSTAT = 0;
-    rIICADD = slaveadd;
+    i2c->IICSTAT = 0;
+    i2c->IICADD = slaveadd;
     /* program Master Transmit (and implicit STOP) */
-    rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA;
+    i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA;
 
 }
 
@@ -176,142 +187,143 @@
                  unsigned char data[],
 		 unsigned short data_len)
 {
+    S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
     int i, status, result;
 
     if (data == 0 || data_len == 0) {
 	/*Don't support data transfer of no length or to address 0*/
 	printf( "i2c_transfer: bad call\n" );
-	return IIC_NOK;
+	return I2C_NOK;
     }
 
     //CheckDelay();
 
     /* Check I2C bus idle */
-    i = IIC_TIMEOUT * 1000;
-    status = rIICSTAT;
-    while ((i > 0) && (status & IICSTAT_BSY)) {
+    i = I2C_TIMEOUT * 1000;
+    status = i2c->IICSTAT;
+    while ((i > 0) && (status & I2CSTAT_BSY)) {
 	udelay(1000);
-	status = rIICSTAT;
+	status = i2c->IICSTAT;
 	i--;
     }
 
 
-    if (status & IICSTAT_BSY) {
-	result = IIC_NOK_TOUT;
+    if (status & I2CSTAT_BSY) {
+	result = I2C_NOK_TOUT;
         return(result);
     }
 
-    rIICCON |= 0x80;
+    i2c->IICCON |= 0x80;
 
-    result = IIC_OK;
+    result = I2C_OK;
 
     switch (cmd_type) {
-	case IIC_WRITE:
+	case I2C_WRITE:
 	    if (addr && addr_len) {
-		rIICDS = chip;
+		i2c->IICDS = chip;
 		/* send START */
-		rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA | IIC_START_STOP;
+		i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP;
 		i = 0;
-		while ((i < addr_len) && (result == IIC_OK)) {
+		while ((i < addr_len) && (result == I2C_OK)) {
 		    result = WaitForXfer();
-		    rIICDS = addr[i];
+		    i2c->IICDS = addr[i];
 		    ReadWriteByte();
 		    i++;
 		}
 		i = 0;
-		while ((i < data_len) && (result == IIC_OK)) {
+		while ((i < data_len) && (result == I2C_OK)) {
 		    result = WaitForXfer();
-		    rIICDS = data[i];
+		    i2c->IICDS = data[i];
 		    ReadWriteByte();
 		    i++;
 		}
 	    } else {
-		rIICDS = chip;
+		i2c->IICDS = chip;
 		/* send START */
-		rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA | IIC_START_STOP;
+		i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP;
 		i = 0;
-		while ((i < data_len) && (result = IIC_OK)) {
+		while ((i < data_len) && (result = I2C_OK)) {
 		    result = WaitForXfer();
-		    rIICDS = data[i];
+		    i2c->IICDS = data[i];
 		    ReadWriteByte();
 		    i++;
 		}
 	    }
 
-	    if (result == IIC_OK)
+	    if (result == I2C_OK)
 	        result = WaitForXfer();
 
 	    /* send STOP */
-	    rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA;
+	    i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA;
 	    ReadWriteByte();
 	    break;
 
-	case IIC_READ:
+	case I2C_READ:
 	    if (addr && addr_len) {
-		rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA;
-		rIICDS = chip;
+		i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA;
+		i2c->IICDS = chip;
 		/* send START */
-		rIICSTAT |= IIC_START_STOP;
+		i2c->IICSTAT |= I2C_START_STOP;
 		result = WaitForXfer();
 		if (IsACK()) {
 		    i = 0;
-		    while ((i < addr_len) && (result == IIC_OK)) {
-			rIICDS = addr[i];
+		    while ((i < addr_len) && (result == I2C_OK)) {
+			i2c->IICDS = addr[i];
 			ReadWriteByte();
 			result = WaitForXfer();
 			i++;
 		    }
 
-		    rIICDS = chip;
+		    i2c->IICDS = chip;
 		    /* resend START */
-		    rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA | IIC_START_STOP;
+		    i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP;
 		    ReadWriteByte();
 		    result = WaitForXfer();
 		    i = 0;
-		    while ((i < data_len) && (result == IIC_OK)) {
+		    while ((i < data_len) && (result == I2C_OK)) {
 			/* disable ACK for final READ */
 			if (i == data_len - 1)
-			    rIICCON &= ~0x80;
+			    i2c->IICCON &= ~0x80;
 			ReadWriteByte();
 			result = WaitForXfer();
-			data[i] = rIICDS;
+			data[i] = i2c->IICDS;
 			i++;
 		    }
 		} else {
-		    result = IIC_NACK;
+		    result = I2C_NACK;
 		}
 
 	    } else {
-		rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA;
-		rIICDS = chip;
+		i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA;
+		i2c->IICDS = chip;
 		/* send START */
-		rIICSTAT |= IIC_START_STOP;
+		i2c->IICSTAT |= I2C_START_STOP;
 		result = WaitForXfer();
 
 		if (IsACK()) {
 		    i = 0;
-		    while ((i < data_len) && (result == IIC_OK)) {
+		    while ((i < data_len) && (result == I2C_OK)) {
 			/* disable ACK for final READ */
 			if (i == data_len - 1)
-			    rIICCON &= ~0x80;
+			    i2c->IICCON &= ~0x80;
 		        ReadWriteByte();
 			result = WaitForXfer();
-			data[i] = rIICDS;
+			data[i] = i2c->IICDS;
 			i++;
 		    }
 		} else {
-		    result = IIC_NACK;
+		    result = I2C_NACK;
 		}
 	    }
 
 	    /* send STOP */
-	    rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA;
+	    i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA;
 	    ReadWriteByte();
 	    break;
 
 	default:
 	    printf( "i2c_transfer: bad call\n" );
-    	    result = IIC_NOK;
+    	    result = I2C_NOK;
 	    break;
     }
 
@@ -329,7 +341,7 @@
      * address was <ACK>ed (i.e. there was a chip at that address which
      * drove the data line low).
      */
-    return(i2c_transfer (IIC_READ, chip << 1, 0, 0, buf, 1) != IIC_OK);
+    return(i2c_transfer (I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK);
 }
 
 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
@@ -365,7 +377,7 @@
     if( alen > 0 )
 	chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-    if( (ret = i2c_transfer(IIC_READ, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
+    if( (ret = i2c_transfer(I2C_READ, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
         printf( "I2c read: failed %d\n", ret);
         return 1;
     }
@@ -403,7 +415,7 @@
     if( alen > 0 )
         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-    return (i2c_transfer(IIC_WRITE, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
+    return (i2c_transfer(I2C_WRITE, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
 }
 
 #endif	/* CONFIG_HARD_I2C */
diff --git a/drivers/status_led.c b/drivers/status_led.c
new file mode 100644
index 0000000..ddb6c22
--- /dev/null
+++ b/drivers/status_led.c
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <status_led.h>
+
+/*
+ * The purpose of this code is to signal the operational status of a
+ * target which usually boots over the network; while running in
+ * U-Boot, a status LED is blinking. As soon as a valid BOOTP reply
+ * message has been received, the LED is turned off. The Linux
+ * kernel, once it is running, will start blinking the LED again,
+ * with another frequency.
+ */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_STATUS_LED
+
+typedef struct {
+	led_id_t mask;
+	int state;
+	int period;
+	int cnt;
+} led_dev_t;
+
+led_dev_t led_dev[] = {
+    {	STATUS_LED_BIT,
+	STATUS_LED_STATE,
+	STATUS_LED_PERIOD,
+	0,
+    },
+#if defined(STATUS_LED_BIT1)
+    {	STATUS_LED_BIT1,
+	STATUS_LED_STATE1,
+	STATUS_LED_PERIOD1,
+	0,
+    },
+#endif
+#if defined(STATUS_LED_BIT2)
+    {	STATUS_LED_BIT2,
+	STATUS_LED_STATE2,
+	STATUS_LED_PERIOD2,
+	0,
+    },
+#endif
+#if defined(STATUS_LED_BIT3)
+    {	STATUS_LED_BIT3,
+	STATUS_LED_STATE3,
+	STATUS_LED_PERIOD3,
+	0,
+    },
+#endif
+};
+
+#define MAX_LED_DEV	(sizeof(led_dev)/sizeof(led_dev_t))
+
+static int status_led_init_done = 0;
+
+static void status_led_init (void)
+{
+	led_dev_t *ld;
+	int i;
+
+	for (i = 0, ld = led_dev; i < MAX_LED_DEV; i++, ld++)
+		__led_init (ld->mask, ld->state);
+	status_led_init_done = 1;
+}
+
+void status_led_tick (ulong timestamp)
+{
+	led_dev_t *ld;
+	int i;
+
+	if (!status_led_init_done)
+		status_led_init ();
+
+	for (i = 0, ld = led_dev; i < MAX_LED_DEV; i++, ld++) {
+
+		if (ld->state != STATUS_LED_BLINKING)
+			continue;
+
+		if (++ld->cnt >= ld->period) {
+			__led_toggle (ld->mask);
+			ld->cnt -= ld->period;
+		}
+
+	}
+}
+
+void status_led_set (int led, int state)
+{
+	led_dev_t *ld;
+
+	if (led < 0 || led >= MAX_LED_DEV)
+		return;
+
+	if (!status_led_init_done)
+		status_led_init ();
+
+	ld = &led_dev[led];
+
+	ld->state = state;
+	if (state == STATUS_LED_BLINKING) {
+		ld->cnt = 0;		/* always start with full period    */
+		state = STATUS_LED_ON;	/* always start with LED _ON_       */
+	}
+	__led_set (ld->mask, state);
+}
+
+#endif	/* CONFIG_STATUS_LED */