diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/Makefile | 3 | ||||
| -rw-r--r-- | drivers/s3c24x0_i2c.c | 196 | ||||
| -rw-r--r-- | drivers/status_led.c | 131 | 
3 files changed, 237 insertions, 93 deletions
| diff --git a/drivers/Makefile b/drivers/Makefile index 50fc75ae0..8eb9472d0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -38,7 +38,8 @@ OBJS	= 3c589.o 5701rls.o ali512x.o \  	  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 b50176118..eeb6cf6d1 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 @@ void i2c_init (int speed, int slaveadd)      /* 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 @@ int i2c_transfer(unsigned char cmd_type,                   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 @@ int i2c_probe (uchar chip)       * 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 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)      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 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)      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 000000000..ddb6c22e8 --- /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 */ |