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 50fc75a..8eb9472 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 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 @@ 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 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 */ |