diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/ds1621.c | 253 | ||||
-rw-r--r-- | drivers/mmc/bfin_sdh.c | 25 | ||||
-rw-r--r-- | drivers/mtd/spi/spansion.c | 16 | ||||
-rw-r--r-- | drivers/mtd/spi/winbond.c | 9 | ||||
-rw-r--r-- | drivers/net/bfin_mac.c | 68 | ||||
-rw-r--r-- | drivers/spi/bfin_spi.c | 155 | ||||
-rw-r--r-- | drivers/video/atmel_lcdfb.c | 3 |
7 files changed, 328 insertions, 201 deletions
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index d15a082df5..5a2ea62899 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -22,7 +22,7 @@ */ /* - * Dallas Semiconductor's DS1621 Digital Thermometer and Thermostat. + * Dallas Semiconductor's DS1621/1631 Digital Thermometer and Thermostat. */ #include <common.h> @@ -32,7 +32,7 @@ /* * Device code */ -#define DTT_I2C_DEV_CODE 0x48 /* Dallas Semi's DS1621 */ +#define DTT_I2C_DEV_CODE 0x48 /* Dallas Semi's DS1621 */ #define DTT_READ_TEMP 0xAA #define DTT_READ_COUNTER 0xA8 #define DTT_READ_SLOPE 0xA9 @@ -42,148 +42,147 @@ #define DTT_TEMP_LOW 0xA2 #define DTT_CONFIG 0xAC +/* + * Config register bits + */ +#define DTT_CONFIG_1SHOT 0x01 +#define DTT_CONFIG_POLARITY 0x02 +#define DTT_CONFIG_R0 0x04 /* ds1631 only */ +#define DTT_CONFIG_R1 0x08 /* ds1631 only */ +#define DTT_CONFIG_NVB 0x10 +#define DTT_CONFIG_TLF 0x20 +#define DTT_CONFIG_THF 0x40 +#define DTT_CONFIG_DONE 0x80 + + int dtt_read(int sensor, int reg) { - int dlen; - uchar data[2]; - - /* - * Calculate sensor address and command. - * - */ - sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* Calculate addr of ds1621*/ - - /* - * Prepare to handle 2 byte result. - */ - if ((reg == DTT_READ_TEMP) || - (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW)) - dlen = 2; - else - dlen = 1; - - /* - * Now try to read the register. - */ - if (i2c_read(sensor, reg, 1, data, dlen) != 0) - return 1; - - /* - * Handle 2 byte result. - */ - if (dlen == 2) - return ((int)((short)data[1] + (((short)data[0]) << 8))); - - return (int)data[0]; -} /* dtt_read() */ + int dlen; + uchar data[2]; + + /* Calculate sensor address and command */ + sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* Calculate addr of ds1621*/ + + /* Prepare to handle 2 byte result */ + switch(reg) { + case DTT_READ_TEMP: + case DTT_TEMP_HIGH: + case DTT_TEMP_LOW: + dlen = 2; + break; + default: + dlen = 1; + } + + /* Now try to read the register */ + if (i2c_read(sensor, reg, 1, data, dlen) != 0) + return 1; + + /* Handle 2 byte result */ + if (dlen == 2) + return (short)((data[0] << 8) | data[1]); + + return (int)data[0]; +} int dtt_write(int sensor, int reg, int val) { - int dlen; - uchar data[2]; - - /* - * Calculate sensor address and register. - * - */ - sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); - - /* - * Handle various data sizes. - */ - if ((reg == DTT_READ_TEMP) || - (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW)) { - dlen = 2; - data[0] = (char)((val >> 8) & 0xff); /* MSB first */ - data[1] = (char)(val & 0xff); - } - else if ((reg == DTT_WRITE_START_CONV) || (reg == DTT_WRITE_STOP_CONV)) { - dlen = 0; - data[0] = (char)0; - data[1] = (char)0; - } - else { - dlen = 1; - data[0] = (char)(val & 0xff); - } - - /* - * Write value to device. - */ - if (i2c_write(sensor, reg, 1, data, dlen) != 0) - return 1; - - return 0; -} /* dtt_write() */ + int dlen; + uchar data[2]; + + /* Calculate sensor address and register */ + sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); + + /* Handle various data sizes. */ + switch(reg) { + case DTT_READ_TEMP: + case DTT_TEMP_HIGH: + case DTT_TEMP_LOW: + dlen = 2; + data[0] = (char)((val >> 8) & 0xff); /* MSB first */ + data[1] = (char)(val & 0xff); + break; + case DTT_WRITE_START_CONV: + case DTT_WRITE_STOP_CONV: + dlen = 0; + data[0] = (char)0; + data[1] = (char)0; + break; + default: + dlen = 1; + data[0] = (char)(val & 0xff); + } + + /* Write value to device */ + if (i2c_write(sensor, reg, 1, data, dlen) != 0) + return 1; + + /* Poll NV memory busy bit in case write was to register stored in EEPROM */ + while(i2c_reg_read(sensor, DTT_CONFIG) & DTT_CONFIG_NVB) + ; + + return 0; +} static int _dtt_init(int sensor) { - int val; - - /* - * Setup High Temp. - */ - val = ((CONFIG_SYS_DTT_MAX_TEMP * 2) << 7) & 0xff80; - if (dtt_write(sensor, DTT_TEMP_HIGH, val) != 0) - return 1; - udelay(50000); /* Max 50ms */ - - /* - * Setup Low Temp - hysteresis. - */ - val = (((CONFIG_SYS_DTT_MAX_TEMP - CONFIG_SYS_DTT_HYSTERESIS) * 2) << 7) & 0xff80; - if (dtt_write(sensor, DTT_TEMP_LOW, val) != 0) - return 1; - udelay(50000); /* Max 50ms */ - - /* - * Setup configuraton register - * - * Clear THF & TLF, Reserved = 1, Polarity = Active Low, One Shot = YES - * - * We run in polled mode, since there isn't any way to know if this - * lousy device is ready to provide temperature readings on power up. - */ - val = 0x9; - if (dtt_write(sensor, DTT_CONFIG, val) != 0) - return 1; - udelay(50000); /* Max 50ms */ - - return 0; -} /* _dtt_init() */ + int val; + + /* Setup High Temp */ + val = ((CONFIG_SYS_DTT_MAX_TEMP * 2) << 7) & 0xff80; + if (dtt_write(sensor, DTT_TEMP_HIGH, val) != 0) + return 1; + + /* Setup Low Temp - hysteresis */ + val = (((CONFIG_SYS_DTT_MAX_TEMP - CONFIG_SYS_DTT_HYSTERESIS) * 2) << 7) & 0xff80; + if (dtt_write(sensor, DTT_TEMP_LOW, val) != 0) + return 1; + + /* + * Setup configuraton register + * + * Clear THF & TLF, Reserved = 1, Polarity = Active Low, One Shot = YES + * + * We run in polled mode, since there isn't any way to know if this + * lousy device is ready to provide temperature readings on power up. + */ + val = 0x9; + if (dtt_write(sensor, DTT_CONFIG, val) != 0) + return 1; + + return 0; +} int dtt_init (void) { - int i; - unsigned char sensors[] = CONFIG_DTT_SENSORS; + int i; + unsigned char sensors[] = CONFIG_DTT_SENSORS; - for (i = 0; i < sizeof(sensors); i++) { - if (_dtt_init(sensors[i]) != 0) - printf("DTT%d: FAILED\n", i+1); - else - printf("DTT%d: %i C\n", i+1, dtt_get_temp(sensors[i])); - } + for (i = 0; i < sizeof(sensors); i++) { + if (_dtt_init(sensors[i]) != 0) + printf("DTT%d: FAILED\n", i + 1); + else + printf("DTT%d: %i C\n", i + 1, dtt_get_temp(sensors[i])); + } - return (0); -} /* dtt_init() */ + return (0); +} int dtt_get_temp(int sensor) { - int i; - - /* - * Start a conversion, may take up to 1 second. - */ - dtt_write(sensor, DTT_WRITE_START_CONV, 0); - for (i = 0; i <= 10; i++) { - udelay(100000); - if (dtt_read(sensor, DTT_CONFIG) & 0x80) - break; - } - - return (dtt_read(sensor, DTT_READ_TEMP) / 256); -} /* dtt_get_temp() */ + int i; + + /* Start a conversion, may take up to 1 second. */ + dtt_write(sensor, DTT_WRITE_START_CONV, 0); + for (i = 0; i <= 10; i++) { + udelay(100000); + if (dtt_read(sensor, DTT_CONFIG) & DTT_CONFIG_DONE) + break; + } + + return (dtt_read(sensor, DTT_READ_TEMP) / 256); +} diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index 4a77779f5b..27d9bf6cbf 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -58,27 +58,29 @@ static int sdh_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) { - unsigned int sdh_cmd; - unsigned int status; + unsigned int status, timeout; int cmd = mmc_cmd->cmdidx; int flags = mmc_cmd->resp_type; int arg = mmc_cmd->cmdarg; - int ret = 0; - sdh_cmd = 0; - - sdh_cmd |= cmd; + int ret; + u16 sdh_cmd; + sdh_cmd = cmd | CMD_E; if (flags & MMC_RSP_PRESENT) sdh_cmd |= CMD_RSP; - if (flags & MMC_RSP_136) sdh_cmd |= CMD_L_RSP; bfin_write_SDH_ARGUMENT(arg); - bfin_write_SDH_COMMAND(sdh_cmd | CMD_E); + bfin_write_SDH_COMMAND(sdh_cmd); /* wait for a while */ + timeout = 0; do { + if (++timeout > 1000000) { + status = CMD_TIME_OUT; + break; + } udelay(1); status = bfin_read_SDH_STATUS(); } while (!(status & (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | @@ -94,12 +96,15 @@ sdh_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) } if (status & CMD_TIME_OUT) - ret |= TIMEOUT; + ret = TIMEOUT; else if (status & CMD_CRC_FAIL && flags & MMC_RSP_CRC) - ret |= COMM_ERR; + ret = COMM_ERR; + else + ret = 0; bfin_write_SDH_STATUS_CLR(CMD_SENT_STAT | CMD_RESP_END_STAT | CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT); + return ret; } diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index d6c1a5f9d3..c0900f978f 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -52,6 +52,7 @@ #define SPSN_ID_S25FL128P 0x2018 #define SPSN_EXT_ID_S25FL128P_256KB 0x0300 #define SPSN_EXT_ID_S25FL128P_64KB 0x0301 +#define SPSN_EXT_ID_S25FL032P 0x4d00 #define SPANSION_SR_WIP (1 << 0) /* Write-in-Progress */ @@ -124,6 +125,14 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { .nr_sectors = 64, .name = "S25FL128P_256K", }, + { + .idcode1 = SPSN_ID_S25FL032A, + .idcode2 = SPSN_EXT_ID_S25FL032P, + .page_size = 256, + .pages_per_sector = 256, + .nr_sectors = 64, + .name = "S25FL032P", + }, }; static int spansion_wait_ready(struct spi_flash *flash, unsigned long timeout) @@ -262,7 +271,6 @@ int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) return -1; } - len /= sector_size; cmd[0] = CMD_S25FLXX_SE; cmd[2] = 0x00; cmd[3] = 0x00; @@ -274,8 +282,8 @@ int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) } ret = 0; - for (actual = 0; actual < len; actual++) { - cmd[1] = (offset / sector_size) + actual; + for (actual = 0; actual < len; actual += sector_size) { + cmd[1] = (offset + actual) >> 16; ret = spi_flash_cmd(flash->spi, CMD_S25FLXX_WREN, NULL, 0); if (ret < 0) { @@ -298,7 +306,7 @@ int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) } debug("SF: SPANSION: Successfully erased %u bytes @ 0x%x\n", - len * sector_size, offset); + len, offset); spi_release_bus(flash->spi); return ret; diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index ff1df25a1d..de3aeb810a 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -27,6 +27,7 @@ #define WINBOND_ID_W25X16 0x3015 #define WINBOND_ID_W25X32 0x3016 #define WINBOND_ID_W25X64 0x3017 +#define WINBOND_ID_W25Q64 0x4017 #define WINBOND_SR_WIP (1 << 0) /* Write-in-Progress */ @@ -77,6 +78,14 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { .nr_blocks = 128, .name = "W25X64", }, + { + .id = WINBOND_ID_W25Q64, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "W25Q64", + }, }; static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout) diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 36d4046ec1..dcc781a46a 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -131,12 +131,12 @@ static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, goto out; } - if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) { + if (bfin_read_DMA2_IRQ_STATUS() & DMA_ERR) { printf("Ethernet: tx DMA error\n"); goto out; } - for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) { + for (i = 0; (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN); ++i) { if (i > TOUT_LOOP) { puts("Ethernet: tx time out\n"); goto out; @@ -145,9 +145,9 @@ static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, txbuf[txIdx]->FrmData->NoBytes = length; memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length); txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData; - *pDMA2_NEXT_DESC_PTR = txbuf[txIdx]->Dma; - *pDMA2_CONFIG = txdmacfg.data; - *pEMAC_OPMODE |= TE; + bfin_write_DMA2_NEXT_DESC_PTR(txbuf[txIdx]->Dma); + bfin_write_DMA2_CONFIG(txdmacfg.data); + bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) { if (i > TOUT_LOOP) { @@ -194,7 +194,7 @@ static int bfin_EMAC_recv(struct eth_device *dev) NetRxPackets[rxIdx] = (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest); NetReceive(NetRxPackets[rxIdx], length - 4); - *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR; + bfin_write_DMA1_IRQ_STATUS(DMA_DONE | DMA_ERR); rxbuf[rxIdx]->StatusWord = 0x00000000; if ((rxIdx + 1) >= PKTBUFSRX) rxIdx = 0; @@ -229,7 +229,7 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode) size_t count; /* Enable PHY output */ - *pVR_CTL |= CLKBUFOE; + bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); /* Set all the pins to peripheral mode */ peripheral_request_list(pins, "bfin_mac"); @@ -265,30 +265,32 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode) bfin_write_EMAC_MMC_CTL(RSTC | CROLL); /* Initialize the TX DMA channel registers */ - *pDMA2_X_COUNT = 0; - *pDMA2_X_MODIFY = 4; - *pDMA2_Y_COUNT = 0; - *pDMA2_Y_MODIFY = 0; + bfin_write_DMA2_X_COUNT(0); + bfin_write_DMA2_X_MODIFY(4); + bfin_write_DMA2_Y_COUNT(0); + bfin_write_DMA2_Y_MODIFY(0); /* Initialize the RX DMA channel registers */ - *pDMA1_X_COUNT = 0; - *pDMA1_X_MODIFY = 4; - *pDMA1_Y_COUNT = 0; - *pDMA1_Y_MODIFY = 0; + bfin_write_DMA1_X_COUNT(0); + bfin_write_DMA1_X_MODIFY(4); + bfin_write_DMA1_Y_COUNT(0); + bfin_write_DMA1_Y_MODIFY(0); return 0; } static int bfin_EMAC_setup_addr(struct eth_device *dev) { - *pEMAC_ADDRLO = + bfin_write_EMAC_ADDRLO( dev->enetaddr[0] | dev->enetaddr[1] << 8 | dev->enetaddr[2] << 16 | - dev->enetaddr[3] << 24; - *pEMAC_ADDRHI = + dev->enetaddr[3] << 24 + ); + bfin_write_EMAC_ADDRHI( dev->enetaddr[4] | - dev->enetaddr[5] << 8; + dev->enetaddr[5] << 8 + ); return 0; } @@ -328,8 +330,8 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd) } /* Set RX DMA */ - *pDMA1_NEXT_DESC_PTR = rxbuf[0]->Dma; - *pDMA1_CONFIG = rxbuf[0]->Dma[0].CONFIG_DATA; + bfin_write_DMA1_NEXT_DESC_PTR(rxbuf[0]->Dma); + bfin_write_DMA1_CONFIG(rxbuf[0]->Dma[0].CONFIG_DATA); /* Wait MII done */ bfin_miiphy_wait(); @@ -350,7 +352,7 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd) opmode |= TE | RMII; #endif /* Turn on the EMAC */ - *pEMAC_OPMODE = opmode; + bfin_write_EMAC_OPMODE(opmode); return 0; } @@ -358,11 +360,10 @@ static void bfin_EMAC_halt(struct eth_device *dev) { debug("Eth_halt: ......\n"); /* Turn off the EMAC */ - *pEMAC_OPMODE = 0x00000000; + bfin_write_EMAC_OPMODE(0); /* Turn off the EMAC RX DMA */ - *pDMA1_CONFIG = 0x0000; - *pDMA2_CONFIG = 0x0000; - + bfin_write_DMA1_CONFIG(0); + bfin_write_DMA2_CONFIG(0); } ADI_ETHER_BUFFER *SetupRxBuffer(int no) @@ -443,16 +444,19 @@ int ether_post_test(int flags) uchar buf[64]; int i, value = 0; int length; + uint addr; printf("\n--------"); bfin_EMAC_init(NULL, NULL); /* construct the package */ - buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF); - buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8); - buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16); - buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24); - buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF); - buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8); + addr = bfin_read_EMAC_ADDRLO(); + buf[0] = buf[6] = addr; + buf[1] = buf[7] = addr >> 8; + buf[2] = buf[8] = addr >> 16; + buf[3] = buf[9] = addr >> 24; + addr = bfin_read_EMAC_ADDRHI(); + buf[4] = buf[10] = addr; + buf[5] = buf[11] = addr >> 8; buf[12] = 0x08; /* Type: ARP */ buf[13] = 0x06; buf[14] = 0x00; /* Hardware type: Ethernet */ diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index 556b97a64d..d7e14749dd 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -1,7 +1,7 @@ /* * Driver for Blackfin On-Chip SPI device * - * Copyright (c) 2005-2008 Analog Devices Inc. + * Copyright (c) 2005-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -13,6 +13,7 @@ #include <spi.h> #include <asm/blackfin.h> +#include <asm/dma.h> #include <asm/gpio.h> #include <asm/portmux.h> #include <asm/mach-common/bits/spi.h> @@ -237,10 +238,131 @@ void spi_release_bus(struct spi_slave *slave) SSYNC(); } +#ifdef __ADSPBF54x__ +# define SPI_DMA_BASE DMA4_NEXT_DESC_PTR +#elif defined(__ADSPBF533__) || defined(__ADSPBF532__) || defined(__ADSPBF531__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) +# define SPI_DMA_BASE DMA5_NEXT_DESC_PTR +#elif defined(__ADSPBF561__) +# define SPI_DMA_BASE DMA2_4_NEXT_DESC_PTR +#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) || \ + defined(__ADSPBF52x__) || defined(__ADSPBF51x__) +# define SPI_DMA_BASE DMA7_NEXT_DESC_PTR +#else +# error "Please provide SPI DMA channel defines" +#endif +static volatile struct dma_register *dma = (void *)SPI_DMA_BASE; + #ifndef CONFIG_BFIN_SPI_IDLE_VAL # define CONFIG_BFIN_SPI_IDLE_VAL 0xff #endif +#ifdef CONFIG_BFIN_SPI_NO_DMA +# define SPI_DMA 0 +#else +# define SPI_DMA 1 +#endif + +static int spi_dma_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx, + uint bytes) +{ + int ret = -1; + u16 ndsize, spi_config, dma_config; + struct dmasg dmasg[2]; + const u8 *buf; + + if (tx) { + debug("%s: doing half duplex TX\n", __func__); + buf = tx; + spi_config = TDBR_DMA; + dma_config = 0; + } else { + debug("%s: doing half duplex RX\n", __func__); + buf = rx; + spi_config = RDBR_DMA; + dma_config = WNR; + } + + dmasg[0].start_addr = (unsigned long)buf; + dmasg[0].x_modify = 1; + dma_config |= WDSIZE_8 | DMAEN; + if (bytes <= 65536) { + blackfin_dcache_flush_invalidate_range(buf, buf + bytes); + ndsize = NDSIZE_5; + dmasg[0].cfg = NDSIZE_0 | dma_config | FLOW_STOP | DI_EN; + dmasg[0].x_count = bytes; + } else { + blackfin_dcache_flush_invalidate_range(buf, buf + 65536 - 1); + ndsize = NDSIZE_7; + dmasg[0].cfg = NDSIZE_5 | dma_config | FLOW_ARRAY | DMA2D; + dmasg[0].x_count = 0; /* 2^16 */ + dmasg[0].y_count = bytes >> 16; /* count / 2^16 */ + dmasg[0].y_modify = 1; + dmasg[1].start_addr = (unsigned long)(buf + (bytes & ~0xFFFF)); + dmasg[1].cfg = NDSIZE_0 | dma_config | FLOW_STOP | DI_EN; + dmasg[1].x_count = bytes & 0xFFFF; /* count % 2^16 */ + dmasg[1].x_modify = 1; + } + + dma->cfg = 0; + dma->irq_status = DMA_DONE | DMA_ERR; + dma->curr_desc_ptr = dmasg; + write_SPI_CTL(bss, (bss->ctl & ~TDBR_CORE)); + write_SPI_STAT(bss, -1); + SSYNC(); + + write_SPI_TDBR(bss, CONFIG_BFIN_SPI_IDLE_VAL); + dma->cfg = ndsize | FLOW_ARRAY | DMAEN; + write_SPI_CTL(bss, (bss->ctl & ~TDBR_CORE) | spi_config); + SSYNC(); + + /* + * We already invalidated the first 64k, + * now while we just wait invalidate the remaining part. + * Its not likely that the DMA is going to overtake + */ + if (bytes > 65536) + blackfin_dcache_flush_invalidate_range(buf + 65536, buf + bytes); + + while (!(dma->irq_status & DMA_DONE)) + if (ctrlc()) + goto done; + + dma->cfg = 0; + + ret = 0; + done: + write_SPI_CTL(bss, bss->ctl); + return ret; +} + +static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx, + uint bytes) +{ + /* todo: take advantage of hardware fifos */ + while (bytes--) { + u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL); + debug("%s: tx:%x ", __func__, value); + write_SPI_TDBR(bss, value); + SSYNC(); + while ((read_SPI_STAT(bss) & TXS)) + if (ctrlc()) + return -1; + while (!(read_SPI_STAT(bss) & SPIF)) + if (ctrlc()) + return -1; + while (!(read_SPI_STAT(bss) & RXS)) + if (ctrlc()) + return -1; + value = read_SPI_RDBR(bss); + if (rx) + *rx++ = value; + debug("rx:%x\n", value); + } + + return 0; +} + int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { @@ -265,32 +387,11 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, if (flags & SPI_XFER_BEGIN) spi_cs_activate(slave); - /* todo: take advantage of hardware fifos and setup RX dma */ - while (bytes--) { - u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL); - debug("%s: tx:%x ", __func__, value); - write_SPI_TDBR(bss, value); - SSYNC(); - while ((read_SPI_STAT(bss) & TXS)) - if (ctrlc()) { - ret = -1; - goto done; - } - while (!(read_SPI_STAT(bss) & SPIF)) - if (ctrlc()) { - ret = -1; - goto done; - } - while (!(read_SPI_STAT(bss) & RXS)) - if (ctrlc()) { - ret = -1; - goto done; - } - value = read_SPI_RDBR(bss); - if (rx) - *rx++ = value; - debug("rx:%x\n", value); - } + /* TX DMA doesn't work quite right */ + if (SPI_DMA && bytes > 6 && (!tx /*|| !rx*/)) + ret = spi_dma_xfer(bss, tx, rx, bytes); + else + ret = spi_pio_xfer(bss, tx, rx, bytes); done: if (flags & SPI_XFER_END) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index db867638f6..c02ffd8036 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -143,8 +143,9 @@ void lcd_ctrl_init(void *lcdbase) /* Set contrast */ value = ATMEL_LCDC_PS_DIV8 | - ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; + if (!panel_info.vl_cont_pol_low) + value |= ATMEL_LCDC_POL_POSITIVE; lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_CTR, value); lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); |