diff options
author | Minkyu Kang <mk7.kang@samsung.com> | 2010-04-19 10:26:18 +0900 |
---|---|---|
committer | Minkyu Kang <mk7.kang@samsung.com> | 2010-04-19 10:26:18 +0900 |
commit | 83653121d7382fccfe329cb732f77f116341ef1d (patch) | |
tree | 0b1ce6764252af15dfb2614372de98a44a7ec61f /drivers | |
parent | 0f1f21a345e02a68ec16f7ab9e7dc687f9276089 (diff) | |
parent | 07739bcef5da07cc4a4edef8b91014ccc332eda3 (diff) | |
download | u-boot-imx-83653121d7382fccfe329cb732f77f116341ef1d.zip u-boot-imx-83653121d7382fccfe329cb732f77f116341ef1d.tar.gz u-boot-imx-83653121d7382fccfe329cb732f77f116341ef1d.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot-arm
Conflicts:
cpu/arm1176/cpu.c
cpu/arm1176/start.S
cpu/arm_cortexa8/s5pc1xx/Makefile
cpu/arm_cortexa8/s5pc1xx/clock.c
drivers/serial/serial_s5p.c
include/asm-arm/arch-s5pc1xx/clk.h
include/asm-arm/arch-s5pc1xx/gpio.h
include/asm-arm/arch-s5pc1xx/uart.h
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
Diffstat (limited to 'drivers')
31 files changed, 1619 insertions, 213 deletions
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index 5f9bd10..dbb5e8c 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -173,7 +173,7 @@ Maps a pointer to the BIOS image on the graphics card on the PCI bus. ****************************************************************************/ void *PCI_mapBIOSImage(pci_dev_t pcidev) { - u32 BIOSImagePhys; + u32 BIOSImageBus; int BIOSImageBAR; u8 *BIOSImage; @@ -195,16 +195,18 @@ void *PCI_mapBIOSImage(pci_dev_t pcidev) specific programming for different cards to solve this problem. */ - if ((BIOSImagePhys = PCI_findBIOSAddr(pcidev, &BIOSImageBAR)) == 0) { + BIOSImageBus = PCI_findBIOSAddr(pcidev, &BIOSImageBAR); + if (BIOSImageBus == 0) { printf("Find bios addr error\n"); return NULL; } - BIOSImage = (u8 *) BIOSImagePhys; + BIOSImage = pci_bus_to_virt(pcidev, BIOSImageBus, + PCI_REGION_MEM, 0, MAP_NOCACHE); /*Change the PCI BAR registers to map it onto the bus.*/ pci_write_config_dword(pcidev, BIOSImageBAR, 0); - pci_write_config_dword(pcidev, PCI_ROM_ADDRESS, BIOSImagePhys | 0x1); + pci_write_config_dword(pcidev, PCI_ROM_ADDRESS, BIOSImageBus | 0x1); udelay(1); @@ -315,7 +317,8 @@ int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp) BE_init(0, 65536, VGAInfo, 0); /*Post all the display controller BIOS'es*/ - PCI_postController(pcidev, VGAInfo); + if (!PCI_postController(pcidev, VGAInfo)) + return false; /*Cleanup and exit the emulator if requested. If the BIOS emulator is needed after booting the card, we will not call BE_exit and diff --git a/drivers/fpga/spartan3.c b/drivers/fpga/spartan3.c index 0fe3041..7a89b56 100644 --- a/drivers/fpga/spartan3.c +++ b/drivers/fpga/spartan3.c @@ -385,34 +385,38 @@ static int Spartan3_ss_load (Xilinx_desc * desc, void *buf, size_t bsize) } while ((*fn->init) (cookie)); /* Load the data */ - while (bytecount < bsize) { - - /* Xilinx detects an error if INIT goes low (active) - while DONE is low (inactive) */ - if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { - puts ("** CRC error during FPGA load.\n"); - return (FPGA_FAIL); - } - val = data [bytecount ++]; - i = 8; - do { - /* Deassert the clock */ - (*fn->clk) (FALSE, TRUE, cookie); - CONFIG_FPGA_DELAY (); - /* Write data */ - (*fn->wr) ((val & 0x80), TRUE, cookie); - CONFIG_FPGA_DELAY (); - /* Assert the clock */ - (*fn->clk) (TRUE, TRUE, cookie); - CONFIG_FPGA_DELAY (); - val <<= 1; - i --; - } while (i > 0); + if(*fn->bwr) + (*fn->bwr) (data, bsize, TRUE, cookie); + else { + while (bytecount < bsize) { + + /* Xilinx detects an error if INIT goes low (active) + while DONE is low (inactive) */ + if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { + puts ("** CRC error during FPGA load.\n"); + return (FPGA_FAIL); + } + val = data [bytecount ++]; + i = 8; + do { + /* Deassert the clock */ + (*fn->clk) (FALSE, TRUE, cookie); + CONFIG_FPGA_DELAY (); + /* Write data */ + (*fn->wr) ((val & 0x80), TRUE, cookie); + CONFIG_FPGA_DELAY (); + /* Assert the clock */ + (*fn->clk) (TRUE, TRUE, cookie); + CONFIG_FPGA_DELAY (); + val <<= 1; + i --; + } while (i > 0); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK - if (bytecount % (bsize / 40) == 0) - putc ('.'); /* let them know we are alive */ + if (bytecount % (bsize / 40) == 0) + putc ('.'); /* let them know we are alive */ #endif + } } CONFIG_FPGA_DELAY (); diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 29bda85..d2c2515 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o +COBJS-$(CONFIG_PPC4XX_I2C) += ppc4xx_i2c.o COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c new file mode 100644 index 0000000..e9548f1 --- /dev/null +++ b/drivers/i2c/ppc4xx_i2c.c @@ -0,0 +1,439 @@ +/* + * (C) Copyright 2007-2009 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * based on work by Anne Sophie Harnois <anne-sophie.harnois@nextream.fr> + * + * (C) Copyright 2001 + * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net + * + * 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 <ppc4xx.h> +#include <4xx_i2c.h> +#include <i2c.h> +#include <asm/io.h> + +#ifdef CONFIG_HARD_I2C + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_I2C_MULTI_BUS) +/* + * Initialize the bus pointer to whatever one the SPD EEPROM is on. + * Default is bus 0. This is necessary because the DDR initialization + * runs from ROM, and we can't switch buses because we can't modify + * the global variables. + */ +#ifndef CONFIG_SYS_SPD_BUS_NUM +#define CONFIG_SYS_SPD_BUS_NUM 0 +#endif +static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = + CONFIG_SYS_SPD_BUS_NUM; +#endif /* CONFIG_I2C_MULTI_BUS */ + +static void _i2c_bus_reset(void) +{ + struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + int i; + u8 dc; + + /* Reset status register */ + /* write 1 in SCMP and IRQA to clear these fields */ + out_8(&i2c->sts, 0x0A); + + /* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */ + out_8(&i2c->extsts, 0x8F); + + /* Place chip in the reset state */ + out_8(&i2c->xtcntlss, IIC_XTCNTLSS_SRST); + + /* Check if bus is free */ + dc = in_8(&i2c->directcntl); + if (!DIRCTNL_FREE(dc)){ + /* Try to set bus free state */ + out_8(&i2c->directcntl, IIC_DIRCNTL_SDAC | IIC_DIRCNTL_SCC); + + /* Wait until we regain bus control */ + for (i = 0; i < 100; ++i) { + dc = in_8(&i2c->directcntl); + if (DIRCTNL_FREE(dc)) + break; + + /* Toggle SCL line */ + dc ^= IIC_DIRCNTL_SCC; + out_8(&i2c->directcntl, dc); + udelay(10); + dc ^= IIC_DIRCNTL_SCC; + out_8(&i2c->directcntl, dc); + } + } + + /* Remove reset */ + out_8(&i2c->xtcntlss, 0); +} + +void i2c_init(int speed, int slaveaddr) +{ + struct ppc4xx_i2c *i2c; + int val, divisor; + int bus; + +#ifdef CONFIG_SYS_I2C_INIT_BOARD + /* + * Call board specific i2c bus reset routine before accessing the + * environment, which might be in a chip on that bus. For details + * about this problem see doc/I2C_Edge_Conditions. + */ + i2c_init_board(); +#endif + + for (bus = 0; bus < CONFIG_SYS_MAX_I2C_BUS; bus++) { + I2C_SET_BUS(bus); + + /* Set i2c pointer after calling I2C_SET_BUS() */ + i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + + /* Handle possible failed I2C state */ + /* FIXME: put this into i2c_init_board()? */ + _i2c_bus_reset(); + + /* clear lo master address */ + out_8(&i2c->lmadr, 0); + + /* clear hi master address */ + out_8(&i2c->hmadr, 0); + + /* clear lo slave address */ + out_8(&i2c->lsadr, 0); + + /* clear hi slave address */ + out_8(&i2c->hsadr, 0); + + /* Clock divide Register */ + /* set divisor according to freq_opb */ + divisor = (get_OPB_freq() - 1) / 10000000; + if (divisor == 0) + divisor = 1; + out_8(&i2c->clkdiv, divisor); + + /* no interrupts */ + out_8(&i2c->intrmsk, 0); + + /* clear transfer count */ + out_8(&i2c->xfrcnt, 0); + + /* clear extended control & stat */ + /* write 1 in SRC SRS SWC SWS to clear these fields */ + out_8(&i2c->xtcntlss, 0xF0); + + /* Mode Control Register + Flush Slave/Master data buffer */ + out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); + + val = in_8(&i2c->mdcntl); + + /* Ignore General Call, slave transfers are ignored, + * disable interrupts, exit unknown bus state, enable hold + * SCL 100kHz normaly or FastMode for 400kHz and above + */ + + val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL; + if (speed >= 400000) + val |= IIC_MDCNTL_FSM; + out_8(&i2c->mdcntl, val); + + /* clear control reg */ + out_8(&i2c->cntl, 0x00); + } + + /* set to SPD bus as default bus upon powerup */ + I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); +} + +/* + * This code tries to use the features of the 405GP i2c + * controller. It will transfer up to 4 bytes in one pass + * on the loop. It only does out_8((u8 *)lbz) to the buffer when it + * is possible to do out16(lhz) transfers. + * + * cmd_type is 0 for write 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + * + * Typical case is a Write of an addr followd by a Read. The + * IBM FAQ does not cover this. On the last byte of the write + * we don't set the creg CHT bit, and on the first bytes of the + * read we set the RPST bit. + * + * It does not support address only transfers, there must be + * a data part. If you want to write the address yourself, put + * it in the data pointer. + * + * It does not support transfer to/from address 0. + * + * It does not check XFRCNT. + */ +static int i2c_transfer(unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], + unsigned short data_len) +{ + struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + u8 *ptr; + int reading; + int tran, cnt; + int result; + int status; + int i; + u8 creg; + + 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; + } + if (addr && addr_len) { + ptr = addr; + cnt = addr_len; + reading = 0; + } else { + ptr = data; + cnt = data_len; + reading = cmd_type; + } + + /* Clear Stop Complete Bit */ + out_8(&i2c->sts, IIC_STS_SCMP); + + /* Check init */ + i = 10; + do { + /* Get status */ + status = in_8(&i2c->sts); + i--; + } while ((status & IIC_STS_PT) && (i > 0)); + + if (status & IIC_STS_PT) { + result = IIC_NOK_TOUT; + return(result); + } + + /* flush the Master/Slave Databuffers */ + out_8(&i2c->mdcntl, in_8(&i2c->mdcntl) | + IIC_MDCNTL_FMDB | IIC_MDCNTL_FSDB); + + /* need to wait 4 OPB clocks? code below should take that long */ + + /* 7-bit adressing */ + out_8(&i2c->hmadr, 0); + out_8(&i2c->lmadr, chip); + + tran = 0; + result = IIC_OK; + creg = 0; + + while (tran != cnt && (result == IIC_OK)) { + int bc,j; + + /* + * Control register = + * Normal transfer, 7-bits adressing, Transfer up to + * bc bytes, Normal start, Transfer is a sequence of transfers + */ + creg |= IIC_CNTL_PT; + + bc = (cnt - tran) > 4 ? 4 : cnt - tran; + creg |= (bc - 1) << 4; + /* if the real cmd type is write continue trans */ + if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt)) + creg |= IIC_CNTL_CHT; + + if (reading) { + creg |= IIC_CNTL_READ; + } else { + for(j = 0; j < bc; j++) { + /* Set buffer */ + out_8(&i2c->mdbuf, ptr[tran + j]); + } + } + out_8(&i2c->cntl, creg); + + /* + * Transfer is in progress + * we have to wait for upto 5 bytes of data + * 1 byte chip address+r/w bit then bc bytes + * of data. + * udelay(10) is 1 bit time at 100khz + * Doubled for slop. 20 is too small. + */ + i = 2 * 5 * 8; + do { + /* Get status */ + status = in_8(&i2c->sts); + udelay(10); + i--; + } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && + (i > 0)); + + if (status & IIC_STS_ERR) { + result = IIC_NOK; + status = in_8(&i2c->extsts); + /* Lost arbitration? */ + if (status & IIC_EXTSTS_LA) + result = IIC_NOK_LA; + /* Incomplete transfer? */ + if (status & IIC_EXTSTS_ICT) + result = IIC_NOK_ICT; + /* Transfer aborted? */ + if (status & IIC_EXTSTS_XFRA) + result = IIC_NOK_XFRA; + } else if ( status & IIC_STS_PT) { + result = IIC_NOK_TOUT; + } + + /* Command is reading => get buffer */ + if ((reading) && (result == IIC_OK)) { + /* Are there data in buffer */ + if (status & IIC_STS_MDBS) { + /* + * even if we have data we have to wait 4OPB + * clocks for it to hit the front of the FIFO, + * after that we can just read. We should check + * XFCNT here and if the FIFO is full there is + * no need to wait. + */ + udelay(1); + for (j = 0; j < bc; j++) + ptr[tran + j] = in_8(&i2c->mdbuf); + } else + result = IIC_NOK_DATA; + } + creg = 0; + tran += bc; + if (ptr == addr && tran == cnt) { + ptr = data; + cnt = data_len; + tran = 0; + reading = cmd_type; + if (reading) + creg = IIC_CNTL_RPST; + } + } + return result; +} + +int i2c_probe(uchar chip) +{ + uchar buf[1]; + + buf[0] = 0; + + /* + * What is needed is to send the chip address and verify that the + * address was <ACK>ed (i.e. there was a chip at that address which + * drove the data line low). + */ + return (i2c_transfer(1, chip << 1, 0, 0, buf, 1) != 0); +} + +static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, + int len, int read) +{ + uchar xaddr[4]; + int ret; + + if (alen > 4) { + printf("I2C: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } + + +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + if ((ret = i2c_transfer(read, chip << 1, &xaddr[4 - alen], alen, + buffer, len)) != 0) { + if (gd->have_console) { + printf("I2C %s: failed %d\n", + read ? "read" : "write", ret); + } + + return 1; + } + + return 0; +} + +int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 1); +} + +int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 0); +} + +#if defined(CONFIG_I2C_MULTI_BUS) +/* + * Functions for multiple I2C bus handling + */ +unsigned int i2c_get_bus_num(void) +{ + return i2c_bus_num; +} + +int i2c_set_bus_num(unsigned int bus) +{ + if (bus >= CONFIG_SYS_MAX_I2C_BUS) + return -1; + + i2c_bus_num = bus; + + return 0; +} +#endif /* CONFIG_I2C_MULTI_BUS */ +#endif /* CONFIG_HARD_I2C */ diff --git a/drivers/input/ps2ser.c b/drivers/input/ps2ser.c index 1b20a76..8d0b6d6 100644 --- a/drivers/input/ps2ser.c +++ b/drivers/input/ps2ser.c @@ -36,8 +36,6 @@ DECLARE_GLOBAL_DATA_PTR; #define PSC_BASE MPC5XXX_PSC2 #elif CONFIG_PS2SERIAL == 3 #define PSC_BASE MPC5XXX_PSC3 -#elif defined(CONFIG_MGT5100) -#error CONFIG_PS2SERIAL must be in 1, 2 or 3 #elif CONFIG_PS2SERIAL == 4 #define PSC_BASE MPC5XXX_PSC4 #elif CONFIG_PS2SERIAL == 5 @@ -87,23 +85,14 @@ int ps2ser_init(void) psc->command = PSC_SEL_MODE_REG_1; /* select clock sources */ -#if defined(CONFIG_MGT5100) - psc->psc_clock_select = 0xdd00; - baseclk = (CONFIG_SYS_MPC5XXX_CLKIN + 16) / 32; -#elif defined(CONFIG_MPC5200) psc->psc_clock_select = 0; baseclk = (gd->ipb_clk + 16) / 32; -#endif /* switch to UART mode */ psc->sicr = 0; /* configure parity, bit length and so on */ -#if defined(CONFIG_MGT5100) - psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE; -#elif defined(CONFIG_MPC5200) psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE; -#endif psc->mode = PSC_MODE_ONE_STOP; /* set up UART divisor */ diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c index 287e555..8255175 100644 --- a/drivers/misc/fsl_law.c +++ b/drivers/misc/fsl_law.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Freescale Semiconductor, Inc. + * Copyright 2008-2010 Freescale Semiconductor, Inc. * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -39,6 +39,8 @@ DECLARE_GLOBAL_DATA_PTR; #define FSL_HW_NUM_LAWS 10 #elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572) || \ defined(CONFIG_P1011) || defined(CONFIG_P1020) || \ + defined(CONFIG_P1012) || defined(CONFIG_P1021) || \ + defined(CONFIG_P1013) || defined(CONFIG_P1022) || \ defined(CONFIG_P2010) || defined(CONFIG_P2020) #define FSL_HW_NUM_LAWS 12 #elif defined(CONFIG_PPC_P4080) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index e665b5e..0f6f8b1 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -1,5 +1,5 @@ /* - * Copyright 2007, Freescale Semiconductor, Inc + * Copyright 2007,2010 Freescale Semiconductor, Inc * Andy Fleming * * Based vaguely on the pxa mmc code: @@ -110,8 +110,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) if (wml_value > 0x10) wml_value = 0x10; - wml_value = 0x100000 | wml_value; - + esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); esdhc_write32(®s->dsaddr, (u32)data->dest); } else { if (wml_value > 0x80) @@ -120,12 +119,12 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); return TIMEOUT; } - wml_value = wml_value << 16 | 0x10; + + esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, + wml_value << 16); esdhc_write32(®s->dsaddr, (u32)data->src); } - esdhc_write32(®s->wml, wml_value); - esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); /* Calculate the timeout period for data transactions */ @@ -265,18 +264,13 @@ void set_sysctl(struct mmc *mmc, uint clock) clk = (pre_div << 8) | (div << 4); - /* On imx the clock must be stopped before changing frequency */ - if (cfg->clk_enable) - esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); + esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); udelay(10000); - clk = SYSCTL_PEREN; - /* On imx systems the clock must be explicitely enabled */ - if (cfg->clk_enable) - clk |= SYSCTL_CKEN; + clk = SYSCTL_PEREN | SYSCTL_CKEN; esdhc_setbits32(®s->sysctl, clk); } @@ -349,6 +343,20 @@ static int esdhc_init(struct mmc *mmc) return ret; } +static void esdhc_reset(struct fsl_esdhc *regs) +{ + unsigned long timeout = 100; /* wait max 100 ms */ + + /* reset the controller */ + esdhc_write32(®s->sysctl, SYSCTL_RSTA); + + /* hardware clears the bit when it is done */ + while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) + udelay(1000); + if (!timeout) + printf("MMC/SD: Reset never completed.\n"); +} + int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) { struct fsl_esdhc *regs; @@ -363,6 +371,9 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) sprintf(mmc->name, "FSL_ESDHC"); regs = (struct fsl_esdhc *)cfg->esdhc_base; + /* First reset the eSDHC controller */ + esdhc_reset(regs); + mmc->priv = cfg; mmc->send_cmd = esdhc_send_cmd; mmc->set_ios = esdhc_set_ios; diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index fdba297..3267c5d 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -537,10 +537,14 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector, ulong start; #if CONFIG_SYS_HZ != 1000 - tout *= CONFIG_SYS_HZ/1000; + if ((ulong)CONFIG_SYS_HZ > 100000) + tout *= (ulong)CONFIG_SYS_HZ / 1000; /* for a big HZ, avoid overflow */ + else + tout = DIV_ROUND_UP(tout * (ulong)CONFIG_SYS_HZ, 1000); #endif /* Wait for command completion */ + reset_timer(); start = get_timer (0); while (flash_is_busy (info, sector)) { if (get_timer (start) > tout) { @@ -602,6 +606,64 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, return retcode; } +static int use_flash_status_poll(flash_info_t *info) +{ +#ifdef CONFIG_SYS_CFI_FLASH_STATUS_POLL + if (info->vendor == CFI_CMDSET_AMD_EXTENDED || + info->vendor == CFI_CMDSET_AMD_STANDARD) + return 1; +#endif + return 0; +} + +static int flash_status_poll(flash_info_t *info, void *src, void *dst, + ulong tout, char *prompt) +{ +#ifdef CONFIG_SYS_CFI_FLASH_STATUS_POLL + ulong start; + int ready; + +#if CONFIG_SYS_HZ != 1000 + if ((ulong)CONFIG_SYS_HZ > 100000) + tout *= (ulong)CONFIG_SYS_HZ / 1000; /* for a big HZ, avoid overflow */ + else + tout = DIV_ROUND_UP(tout * (ulong)CONFIG_SYS_HZ, 1000); +#endif + + /* Wait for command completion */ + reset_timer(); + start = get_timer(0); + while (1) { + switch (info->portwidth) { + case FLASH_CFI_8BIT: + ready = flash_read8(dst) == flash_read8(src); + break; + case FLASH_CFI_16BIT: + ready = flash_read16(dst) == flash_read16(src); + break; + case FLASH_CFI_32BIT: + ready = flash_read32(dst) == flash_read32(src); + break; + case FLASH_CFI_64BIT: + ready = flash_read64(dst) == flash_read64(src); + break; + default: + ready = 0; + break; + } + if (ready) + break; + if (get_timer(start) > tout) { + printf("Flash %s timeout at address %lx data %lx\n", + prompt, (ulong)dst, (ulong)flash_read8(dst)); + return ERR_TIMOUT; + } + udelay(1); /* also triggers watchdog */ + } +#endif /* CONFIG_SYS_CFI_FLASH_STATUS_POLL */ + return ERR_OK; +} + /*----------------------------------------------------------------------- */ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) @@ -749,7 +811,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest, if (!sect_found) sect = find_sector (info, dest); - return flash_full_status_check (info, sect, info->write_tout, "write"); + if (use_flash_status_poll(info)) + return flash_status_poll(info, &cword, dstaddr, + info->write_tout, "write"); + else + return flash_full_status_check(info, sect, + info->write_tout, "write"); } #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE @@ -911,9 +978,15 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, } flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); - retcode = flash_full_status_check (info, sector, - info->buffer_write_tout, - "buffer write"); + if (use_flash_status_poll(info)) + retcode = flash_status_poll(info, src - (1 << shift), + dst - (1 << shift), + info->buffer_write_tout, + "buffer write"); + else + retcode = flash_full_status_check(info, sector, + info->buffer_write_tout, + "buffer write"); break; default: @@ -935,6 +1008,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) int rcode = 0; int prot; flash_sect_t sect; + int st; if (info->flash_id != FLASH_MAN_CFI) { puts ("Can't erase unknown flash type - aborted\n"); @@ -998,10 +1072,20 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) break; } - if (flash_full_status_check - (info, sect, info->erase_blk_tout, "erase")) { + if (use_flash_status_poll(info)) { + cfiword_t cword = (cfiword_t)0xffffffffffffffffULL; + void *dest; + dest = flash_map(info, sect, 0); + st = flash_status_poll(info, &cword, dest, + info->erase_blk_tout, "erase"); + flash_unmap(info, sect, 0, dest); + } else + st = flash_full_status_check(info, sect, + info->erase_blk_tout, + "erase"); + if (st) rcode = 1; - } else if (flash_verbose) + else if (flash_verbose) putc ('.'); } } diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 40002be..d5eb54a 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -31,6 +31,209 @@ #include <nand.h> +#ifdef CONFIG_ATMEL_NAND_HWECC + +/* Register access macros */ +#define ecc_readl(add, reg) \ + readl(AT91_BASE_SYS + add + ATMEL_ECC_##reg) +#define ecc_writel(add, reg, value) \ + writel((value), AT91_BASE_SYS + add + ATMEL_ECC_##reg) + +#include "atmel_nand_ecc.h" /* Hardware ECC registers */ + +/* oob layout for large page size + * bad block info is on bytes 0 and 1 + * the bytes have to be consecutives to avoid + * several NAND_CMD_RNDOUT during read + */ +static struct nand_ecclayout atmel_oobinfo_large = { + .eccbytes = 4, + .eccpos = {60, 61, 62, 63}, + .oobfree = { + {2, 58} + }, +}; + +/* oob layout for small page size + * bad block info is on bytes 4 and 5 + * the bytes have to be consecutives to avoid + * several NAND_CMD_RNDOUT during read + */ +static struct nand_ecclayout atmel_oobinfo_small = { + .eccbytes = 4, + .eccpos = {0, 1, 2, 3}, + .oobfree = { + {6, 10} + }, +}; + +/* + * Calculate HW ECC + * + * function called after a write + * + * mtd: MTD block structure + * dat: raw data (unused) + * ecc_code: buffer for ECC + */ +static int atmel_nand_calculate(struct mtd_info *mtd, + const u_char *dat, unsigned char *ecc_code) +{ + struct nand_chip *nand_chip = mtd->priv; + unsigned int ecc_value; + + /* get the first 2 ECC bytes */ + ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR); + + ecc_code[0] = ecc_value & 0xFF; + ecc_code[1] = (ecc_value >> 8) & 0xFF; + + /* get the last 2 ECC bytes */ + ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, NPR) & ATMEL_ECC_NPARITY; + + ecc_code[2] = ecc_value & 0xFF; + ecc_code[3] = (ecc_value >> 8) & 0xFF; + + return 0; +} + +/* + * HW ECC read page function + * + * mtd: mtd info structure + * chip: nand chip info structure + * buf: buffer to store read data + */ +static int atmel_nand_read_page(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + int eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + uint32_t *eccpos = chip->ecc.layout->eccpos; + uint8_t *p = buf; + uint8_t *oob = chip->oob_poi; + uint8_t *ecc_pos; + int stat; + + /* read the page */ + chip->read_buf(mtd, p, eccsize); + + /* move to ECC position if needed */ + if (eccpos[0] != 0) { + /* This only works on large pages + * because the ECC controller waits for + * NAND_CMD_RNDOUTSTART after the + * NAND_CMD_RNDOUT. + * anyway, for small pages, the eccpos[0] == 0 + */ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, + mtd->writesize + eccpos[0], -1); + } + + /* the ECC controller needs to read the ECC just after the data */ + ecc_pos = oob + eccpos[0]; + chip->read_buf(mtd, ecc_pos, eccbytes); + + /* check if there's an error */ + stat = chip->ecc.correct(mtd, p, oob, NULL); + + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + + /* get back to oob start (end of page) */ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); + + /* read the oob */ + chip->read_buf(mtd, oob, mtd->oobsize); + + return 0; +} + +/* + * HW ECC Correction + * + * function called after a read + * + * mtd: MTD block structure + * dat: raw data read from the chip + * read_ecc: ECC from the chip (unused) + * isnull: unused + * + * Detect and correct a 1 bit error for a page + */ +static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *isnull) +{ + struct nand_chip *nand_chip = mtd->priv; + unsigned int ecc_status, ecc_parity, ecc_mode; + unsigned int ecc_word, ecc_bit; + + /* get the status from the Status Register */ + ecc_status = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, SR); + + /* if there's no error */ + if (likely(!(ecc_status & ATMEL_ECC_RECERR))) + return 0; + + /* get error bit offset (4 bits) */ + ecc_bit = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_BITADDR; + /* get word address (12 bits) */ + ecc_word = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_WORDADDR; + ecc_word >>= 4; + + /* if there are multiple errors */ + if (ecc_status & ATMEL_ECC_MULERR) { + /* check if it is a freshly erased block + * (filled with 0xff) */ + if ((ecc_bit == ATMEL_ECC_BITADDR) + && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) { + /* the block has just been erased, return OK */ + return 0; + } + /* it doesn't seems to be a freshly + * erased block. + * We can't correct so many errors */ + printk(KERN_WARNING "atmel_nand : multiple errors detected." + " Unable to correct.\n"); + return -EIO; + } + + /* if there's a single bit error : we can correct it */ + if (ecc_status & ATMEL_ECC_ECCERR) { + /* there's nothing much to do here. + * the bit error is on the ECC itself. + */ + printk(KERN_WARNING "atmel_nand : one bit error on ECC code." + " Nothing to correct\n"); + return 0; + } + + printk(KERN_WARNING "atmel_nand : one bit error on data." + " (word offset in the page :" + " 0x%x bit offset : 0x%x)\n", + ecc_word, ecc_bit); + /* correct the error */ + if (nand_chip->options & NAND_BUSWIDTH_16) { + /* 16 bits words */ + ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit); + } else { + /* 8 bits words */ + dat[ecc_word] ^= (1 << ecc_bit); + } + printk(KERN_WARNING "atmel_nand : error corrected\n"); + return 1; +} + +/* + * Enable HW ECC : unused on most chips + */ +static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) +{ +} +#endif + static void at91_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { @@ -64,6 +267,11 @@ static int at91_nand_ready(struct mtd_info *mtd) int board_nand_init(struct nand_chip *nand) { +#ifdef CONFIG_ATMEL_NAND_HWECC + static int chip_nr = 0; + struct mtd_info *mtd; +#endif + nand->ecc.mode = NAND_ECC_SOFT; #ifdef CONFIG_SYS_NAND_DBW_16 nand->options = NAND_BUSWIDTH_16; @@ -74,5 +282,62 @@ int board_nand_init(struct nand_chip *nand) #endif nand->chip_delay = 20; +#ifdef CONFIG_ATMEL_NAND_HWECC + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.calculate = atmel_nand_calculate; + nand->ecc.correct = atmel_nand_correct; + nand->ecc.hwctl = atmel_nand_hwctl; + nand->ecc.read_page = atmel_nand_read_page; + nand->ecc.bytes = 4; +#endif + +#ifdef CONFIG_ATMEL_NAND_HWECC + mtd = &nand_info[chip_nr++]; + mtd->priv = nand; + + /* Detect NAND chips */ + if (nand_scan_ident(mtd, 1)) { + printk(KERN_WARNING "NAND Flash not found !\n"); + return -ENXIO; + } + + if (nand->ecc.mode == NAND_ECC_HW) { + /* ECC is calculated for the whole page (1 step) */ + nand->ecc.size = mtd->writesize; + + /* set ECC page size and oob layout */ + switch (mtd->writesize) { + case 512: + nand->ecc.layout = &atmel_oobinfo_small; + ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_528); + break; + case 1024: + nand->ecc.layout = &atmel_oobinfo_large; + ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_1056); + break; + case 2048: + nand->ecc.layout = &atmel_oobinfo_large; + ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_2112); + break; + case 4096: + nand->ecc.layout = &atmel_oobinfo_large; + ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_4224); + break; + default: + /* page size not handled by HW ECC */ + /* switching back to soft ECC */ + nand->ecc.mode = NAND_ECC_SOFT; + nand->ecc.calculate = NULL; + nand->ecc.correct = NULL; + nand->ecc.hwctl = NULL; + nand->ecc.read_page = NULL; + nand->ecc.postpad = 0; + nand->ecc.prepad = 0; + nand->ecc.bytes = 0; + break; + } + } +#endif + return 0; } diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h new file mode 100644 index 0000000..1ee7f99 --- /dev/null +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -0,0 +1,36 @@ +/* + * Error Corrected Code Controller (ECC) - System peripherals regsters. + * Based on AT91SAM9260 datasheet revision B. + * + * 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. + */ + +#ifndef ATMEL_NAND_ECC_H +#define ATMEL_NAND_ECC_H + +#define ATMEL_ECC_CR 0x00 /* Control register */ +#define ATMEL_ECC_RST (1 << 0) /* Reset parity */ + +#define ATMEL_ECC_MR 0x04 /* Mode register */ +#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */ +#define ATMEL_ECC_PAGESIZE_528 (0) +#define ATMEL_ECC_PAGESIZE_1056 (1) +#define ATMEL_ECC_PAGESIZE_2112 (2) +#define ATMEL_ECC_PAGESIZE_4224 (3) + +#define ATMEL_ECC_SR 0x08 /* Status register */ +#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */ +#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */ +#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */ + +#define ATMEL_ECC_PR 0x0c /* Parity register */ +#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */ +#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */ + +#define ATMEL_ECC_NPR 0x10 /* NParity register */ +#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */ + +#endif diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index bfc2acf..4ca738e 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -57,8 +57,6 @@ #define ECC_STATE_ERR_CORR_COMP_P 0x2 #define ECC_STATE_ERR_CORR_COMP_N 0x3 -static emif_registers *const emif_regs = (void *) DAVINCI_ASYNC_EMIF_CNTRL_BASE; - /* * Exploit the little endianness of the ARM to do multi-byte transfers * per device read. This can perform over twice as quickly as individual @@ -93,7 +91,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) /* copy aligned data */ while (len >= 4) { - *(u32 *)buf = readl(nand); + *(u32 *)buf = __raw_readl(nand); buf += 4; len -= 4; } @@ -138,7 +136,7 @@ static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf, /* copy aligned data */ while (len >= 4) { - writel(*(u32 *)buf, nand); + __raw_writel(*(u32 *)buf, nand); buf += 4; len -= 4; } @@ -156,7 +154,8 @@ static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf, } } -static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { struct nand_chip *this = mtd->priv; u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; @@ -164,9 +163,9 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c if (ctrl & NAND_CTRL_CHANGE) { IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); - if ( ctrl & NAND_CLE ) + if (ctrl & NAND_CLE) IO_ADDR_W |= MASK_CLE; - if ( ctrl & NAND_ALE ) + if (ctrl & NAND_ALE) IO_ADDR_W |= MASK_ALE; this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; } @@ -181,24 +180,26 @@ static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) { u_int32_t val; - (void)readl(&(emif_regs->NANDFECC[CONFIG_SYS_NAND_CS - 2])); + (void)__raw_readl(&(davinci_emif_regs->nandfecc[ + CONFIG_SYS_NAND_CS - 2])); - val = readl(&emif_regs->NANDFCR); + val = __raw_readl(&davinci_emif_regs->nandfcr); val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS); val |= DAVINCI_NANDFCR_1BIT_ECC_START(CONFIG_SYS_NAND_CS); - writel(val, &emif_regs->NANDFCR); + __raw_writel(val, &davinci_emif_regs->nandfcr); } static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) { u_int32_t ecc = 0; - ecc = readl(&(emif_regs->NANDFECC[region - 1])); + ecc = __raw_readl(&(davinci_emif_regs->nandfecc[region - 1])); - return(ecc); + return ecc; } -static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u_char *ecc_code) { u_int32_t tmp; const int region = 1; @@ -232,7 +233,8 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u return 0; } -static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) { struct nand_chip *this = mtd->priv; u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) | @@ -268,7 +270,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char * return -1; } } - return(0); + return 0; } #endif /* CONFIG_SYS_NAND_HW_ECC */ @@ -315,15 +317,15 @@ static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode) * Start a new ECC calculation for reading or writing 512 bytes * of data. */ - val = readl(&emif_regs->NANDFCR); + val = __raw_readl(&davinci_emif_regs->nandfcr); val &= ~DAVINCI_NANDFCR_4BIT_ECC_SEL_MASK; val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS); val |= DAVINCI_NANDFCR_4BIT_ECC_SEL(CONFIG_SYS_NAND_CS); val |= DAVINCI_NANDFCR_4BIT_ECC_START; - writel(val, &emif_regs->NANDFCR); + __raw_writel(val, &davinci_emif_regs->nandfcr); break; case NAND_ECC_READSYN: - val = emif_regs->NAND4BITECC1; + val = __raw_readl(&davinci_emif_regs->nand4bitecc[0]); break; default: break; @@ -332,10 +334,12 @@ static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode) static u32 nand_davinci_4bit_readecc(struct mtd_info *mtd, unsigned int ecc[4]) { - ecc[0] = emif_regs->NAND4BITECC1 & NAND_4BITECC_MASK; - ecc[1] = emif_regs->NAND4BITECC2 & NAND_4BITECC_MASK; - ecc[2] = emif_regs->NAND4BITECC3 & NAND_4BITECC_MASK; - ecc[3] = emif_regs->NAND4BITECC4 & NAND_4BITECC_MASK; + int i; + + for (i = 0; i < 4; i++) { + ecc[i] = __raw_readl(&davinci_emif_regs->nand4bitecc[i]) & + NAND_4BITECC_MASK; + } return 0; } @@ -418,32 +422,36 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat, */ /*Take 2 bits from 8th byte and 8 bits from 9th byte */ - writel(((ecc16[4]) >> 6) & 0x3FF, &emif_regs->NAND4BITECCLOAD); + __raw_writel(((ecc16[4]) >> 6) & 0x3FF, + &davinci_emif_regs->nand4biteccload); /* Take 4 bits from 7th byte and 6 bits from 8th byte */ - writel((((ecc16[3]) >> 12) & 0xF) | ((((ecc16[4])) << 4) & 0x3F0), - &emif_regs->NAND4BITECCLOAD); + __raw_writel((((ecc16[3]) >> 12) & 0xF) | ((((ecc16[4])) << 4) & 0x3F0), + &davinci_emif_regs->nand4biteccload); /* Take 6 bits from 6th byte and 4 bits from 7th byte */ - writel((ecc16[3] >> 2) & 0x3FF, &emif_regs->NAND4BITECCLOAD); + __raw_writel((ecc16[3] >> 2) & 0x3FF, + &davinci_emif_regs->nand4biteccload); /* Take 8 bits from 5th byte and 2 bits from 6th byte */ - writel(((ecc16[2]) >> 8) | ((((ecc16[3])) << 8) & 0x300), - &emif_regs->NAND4BITECCLOAD); + __raw_writel(((ecc16[2]) >> 8) | ((((ecc16[3])) << 8) & 0x300), + &davinci_emif_regs->nand4biteccload); /*Take 2 bits from 3rd byte and 8 bits from 4th byte */ - writel((((ecc16[1]) >> 14) & 0x3) | ((((ecc16[2])) << 2) & 0x3FC), - &emif_regs->NAND4BITECCLOAD); + __raw_writel((((ecc16[1]) >> 14) & 0x3) | ((((ecc16[2])) << 2) & 0x3FC), + &davinci_emif_regs->nand4biteccload); /* Take 4 bits form 2nd bytes and 6 bits from 3rd bytes */ - writel(((ecc16[1]) >> 4) & 0x3FF, &emif_regs->NAND4BITECCLOAD); + __raw_writel(((ecc16[1]) >> 4) & 0x3FF, + &davinci_emif_regs->nand4biteccload); /* Take 6 bits from 1st byte and 4 bits from 2nd byte */ - writel((((ecc16[0]) >> 10) & 0x3F) | (((ecc16[1]) << 6) & 0x3C0), - &emif_regs->NAND4BITECCLOAD); + __raw_writel((((ecc16[0]) >> 10) & 0x3F) | (((ecc16[1]) << 6) & 0x3C0), + &davinci_emif_regs->nand4biteccload); /* Take 10 bits from 0th and 1st bytes */ - writel((ecc16[0]) & 0x3FF, &emif_regs->NAND4BITECCLOAD); + __raw_writel((ecc16[0]) & 0x3FF, + &davinci_emif_regs->nand4biteccload); /* * Perform a dummy read to the EMIF Revision Code and Status register. @@ -451,7 +459,7 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat, * writing the ECC values in previous step. */ - val = emif_regs->NANDFSR; + val = __raw_readl(&davinci_emif_regs->nandfsr); /* * Read the syndrome from the NAND Flash 4-Bit ECC 1-4 registers. @@ -467,13 +475,13 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat, * Clear any previous address calculation by doing a dummy read of an * error address register. */ - val = emif_regs->NANDERRADD1; + val = __raw_readl(&davinci_emif_regs->nanderradd1); /* * Set the addr_calc_st bit(bit no 13) in the NAND Flash Control * register to 1. */ - emif_regs->NANDFCR |= 1 << 13; + __raw_writel(1 << 13, &davinci_emif_regs->nandfcr); /* * Wait for the corr_state field (bits 8 to 11)in the @@ -481,12 +489,12 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat, */ i = NAND_TIMEOUT; do { - val = emif_regs->NANDFSR; + val = __raw_readl(&davinci_emif_regs->nandfsr); val &= 0xc00; i--; } while ((i > 0) && val); - iserror = emif_regs->NANDFSR; + iserror = __raw_readl(&davinci_emif_regs->nandfsr); iserror &= EMIF_NANDFSR_ECC_STATE_MASK; iserror = iserror >> 8; @@ -501,32 +509,33 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat, */ if (iserror == ECC_STATE_NO_ERR) { - val = emif_regs->NANDERRVAL1; + val = __raw_readl(&davinci_emif_regs->nanderrval1); return 0; } else if (iserror == ECC_STATE_TOO_MANY_ERRS) { - val = emif_regs->NANDERRVAL1; + val = __raw_readl(&davinci_emif_regs->nanderrval1); return -1; } - numerrors = ((emif_regs->NANDFSR >> 16) & 0x3) + 1; + numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16) + & 0x3) + 1; /* Read the error address, error value and correct */ for (i = 0; i < numerrors; i++) { if (i > 1) { erroraddress = - ((emif_regs->NANDERRADD2 >> + ((__raw_readl(&davinci_emif_regs->nanderradd2) >> (16 * (i & 1))) & 0x3FF); erroraddress = ((512 + 7) - erroraddress); errorvalue = - ((emif_regs->NANDERRVAL2 >> + ((__raw_readl(&davinci_emif_regs->nanderrval2) >> (16 * (i & 1))) & 0xFF); } else { erroraddress = - ((emif_regs->NANDERRADD1 >> + ((__raw_readl(&davinci_emif_regs->nanderradd1) >> (16 * (i & 1))) & 0x3FF); erroraddress = ((512 + 7) - erroraddress); errorvalue = - ((emif_regs->NANDERRVAL1 >> + ((__raw_readl(&davinci_emif_regs->nanderrval1) >> (16 * (i & 1))) & 0xFF); } /* xor the corrupt data with error value */ @@ -540,7 +549,7 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat, static int nand_davinci_dev_ready(struct mtd_info *mtd) { - return emif_regs->NANDFSR & 0x1; + return __raw_readl(&davinci_emif_regs->nandfsr) & 0x1; } static void nand_flash_init(void) @@ -561,21 +570,22 @@ static void nand_flash_init(void) * * *------------------------------------------------------------------*/ acfg1 = 0 - | (0 << 31 ) /* selectStrobe */ - | (0 << 30 ) /* extWait */ - | (1 << 26 ) /* writeSetup 10 ns */ - | (3 << 20 ) /* writeStrobe 40 ns */ - | (1 << 17 ) /* writeHold 10 ns */ - | (1 << 13 ) /* readSetup 10 ns */ - | (5 << 7 ) /* readStrobe 60 ns */ - | (1 << 4 ) /* readHold 10 ns */ - | (3 << 2 ) /* turnAround ?? ns */ - | (0 << 0 ) /* asyncSize 8-bit bus */ + | (0 << 31) /* selectStrobe */ + | (0 << 30) /* extWait */ + | (1 << 26) /* writeSetup 10 ns */ + | (3 << 20) /* writeStrobe 40 ns */ + | (1 << 17) /* writeHold 10 ns */ + | (1 << 13) /* readSetup 10 ns */ + | (5 << 7) /* readStrobe 60 ns */ + | (1 << 4) /* readHold 10 ns */ + | (3 << 2) /* turnAround ?? ns */ + | (0 << 0) /* asyncSize 8-bit bus */ ; - emif_regs->AB1CR = acfg1; /* CS2 */ + __raw_writel(acfg1, &davinci_emif_regs->ab1cr); /* CS2 */ - emif_regs->NANDFCR = 0x00000101; /* NAND flash on CS2 */ + /* NAND flash on CS2 */ + __raw_writel(0x00000101, &davinci_emif_regs->nandfcr); #endif } diff --git a/drivers/mtd/spi/eeprom_m95xxx.c b/drivers/mtd/spi/eeprom_m95xxx.c index 0148d00..632db4e 100644 --- a/drivers/mtd/spi/eeprom_m95xxx.c +++ b/drivers/mtd/spi/eeprom_m95xxx.c @@ -44,6 +44,9 @@ ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len) slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000, CONFIG_DEFAULT_SPI_MODE); + if(!slave) + return 0; + spi_claim_bus(slave); /* command */ @@ -75,6 +78,9 @@ ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len) slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000, CONFIG_DEFAULT_SPI_MODE); + if (!slave) + return 0; + spi_claim_bus(slave); buf[0] = SPI_EEPROM_WREN; diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 5af9cdb..8c4ade5 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -752,7 +752,6 @@ static int fec_probe(bd_t *bd) if (fec_get_hwaddr(edev, ethaddr) == 0) { printf("got MAC address from EEPROM: %pM\n", ethaddr); memcpy(edev->enetaddr, ethaddr, 6); - fec_set_hwaddr(edev); } return 0; diff --git a/drivers/net/mpc5xxx_fec.c b/drivers/net/mpc5xxx_fec.c index 1876b76..c2b1bbd 100644 --- a/drivers/net/mpc5xxx_fec.c +++ b/drivers/net/mpc5xxx_fec.c @@ -336,13 +336,11 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis) */ fec->eth->xmit_fsm = 0x03000000; -#if defined(CONFIG_MPC5200) /* - * Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't + * Turn off COMM bus prefetch in the MPC5200 BestComm. It doesn't * work w/ the current receive task. */ sdma->PtdCntrl |= 0x00000001; -#endif /* * Set priority of different initiators @@ -579,9 +577,7 @@ static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis) /********************************************************************/ static void mpc5xxx_fec_halt(struct eth_device *dev) { -#if defined(CONFIG_MPC5200) struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; -#endif mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv; int counter = 0xffff; @@ -611,13 +607,11 @@ static void mpc5xxx_fec_halt(struct eth_device *dev) SDMA_TASK_DISABLE (FEC_XMIT_TASK_NO); SDMA_TASK_DISABLE (FEC_RECV_TASK_NO); -#if defined(CONFIG_MPC5200) /* - * Turn on COMM bus prefetch in the MGT5200 BestComm after we're + * Turn on COMM bus prefetch in the MPC5200 BestComm after we're * done. It doesn't work w/ the current receive task. */ sdma->PtdCntrl &= ~0x00000001; -#endif /* * Disable the Ethernet Controller diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index fe57926..5a63fa2 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -1,9 +1,10 @@ /* - * Copyright 2007-2009 Freescale Semiconductor, Inc. + * Copyright 2007-2010 Freescale Semiconductor, Inc. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. + * 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 @@ -513,10 +514,15 @@ void ft_fsl_pci_setup(void *blob, const char *pci_alias, struct pci_controller *hose) { int off = fdt_path_offset(blob, pci_alias); + u32 bus_range[2]; - if (off >= 0) { - u32 bus_range[2]; + if (off < 0) + return; + /* We assume a cfg_addr not being set means we didn't setup the controller */ + if ((hose == NULL) || (hose->cfg_addr == NULL)) { + fdt_del_node_and_alias(blob, pci_alias); + } else { bus_range[0] = 0; bus_range[1] = hose->last_busno - hose->first_busno; fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4); diff --git a/drivers/pci/pci_sh4.c b/drivers/pci/pci_sh4.c index c7963ed..62915b6 100644 --- a/drivers/pci/pci_sh4.c +++ b/drivers/pci/pci_sh4.c @@ -4,7 +4,7 @@ * (C) 2007,2008 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> * (C) 2008 Yusuke Goda <goda.yusuke@renesas.com> * - * u-boot/cpu/sh4/pci-sh4.c + * u-boot/arch/sh/cpu/sh4/pci-sh4.c * * See file CREDITS for list of people who contributed to this * project. diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index c4214d9..c1cc23b 100644 --- a/drivers/qe/uec_phy.c +++ b/drivers/qe/uec_phy.c @@ -47,7 +47,7 @@ /*--------------------------------------------------------------------+ * Fixed PHY (PHY-less) support for Ethernet Ports. * - * Copied from cpu/ppc4xx/4xx_enet.c + * Copied from arch/ppc/cpu/ppc4xx/4xx_enet.c *--------------------------------------------------------------------*/ /* diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 71392e6..c731bfb 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -25,11 +25,14 @@ include $(TOPDIR)/config.mk LIB := $(obj)libserial.a +COBJS-$(CONFIG_ALTERA_UART) += altera_uart.o +COBJS-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o COBJS-$(CONFIG_AT91RM9200_USART) += at91rm9200_usart.o COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o COBJS-$(CONFIG_MCFUART) += mcfuart.o COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o +COBJS-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o COBJS-$(CONFIG_SYS_NS16550) += ns16550.o COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o COBJS-$(CONFIG_S3C64XX) += s3c64xx.o diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c new file mode 100644 index 0000000..fb28aa9 --- /dev/null +++ b/drivers/serial/altera_jtag_uart.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + * 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 <watchdog.h> +#include <asm/io.h> +#include <nios2-io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*------------------------------------------------------------------ + * JTAG acts as the serial port + *-----------------------------------------------------------------*/ +static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; + +void serial_setbrg( void ){ return; } +int serial_init( void ) { return(0);} + +void serial_putc (char c) +{ + while (NIOS_JTAG_WSPACE ( readl (&jtag->control)) == 0) + WATCHDOG_RESET (); + writel ((unsigned char)c, &jtag->data); +} + +void serial_puts (const char *s) +{ + while (*s != 0) + serial_putc (*s++); +} + +int serial_tstc (void) +{ + return ( readl (&jtag->control) & NIOS_JTAG_RRDY); +} + +int serial_getc (void) +{ + int c; + unsigned val; + + while (1) { + WATCHDOG_RESET (); + val = readl (&jtag->data); + if (val & NIOS_JTAG_RVALID) + break; + } + c = val & 0x0ff; + return (c); +} diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c new file mode 100644 index 0000000..045f119 --- /dev/null +++ b/drivers/serial/altera_uart.c @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + * 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 <watchdog.h> +#include <asm/io.h> +#include <nios2-io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*------------------------------------------------------------------ + * UART the serial port + *-----------------------------------------------------------------*/ + +static nios_uart_t *uart = (nios_uart_t *) CONFIG_SYS_NIOS_CONSOLE; + +#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) + +/* Everything's already setup for fixed-baud PTF + * assignment + */ +void serial_setbrg (void){ return; } +int serial_init (void) { return (0);} + +#else + +void serial_setbrg (void) +{ + unsigned div; + + div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1; + writel (div, &uart->divisor); + return; +} + +int serial_init (void) +{ + serial_setbrg (); + return (0); +} + +#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ + +/*----------------------------------------------------------------------- + * UART CONSOLE + *---------------------------------------------------------------------*/ +void serial_putc (char c) +{ + if (c == '\n') + serial_putc ('\r'); + while ((readl (&uart->status) & NIOS_UART_TRDY) == 0) + WATCHDOG_RESET (); + writel ((unsigned char)c, &uart->txdata); +} + +void serial_puts (const char *s) +{ + while (*s != 0) { + serial_putc (*s++); + } +} + +int serial_tstc (void) +{ + return (readl (&uart->status) & NIOS_UART_RRDY); +} + +int serial_getc (void) +{ + while (serial_tstc () == 0) + WATCHDOG_RESET (); + return (readl (&uart->rxdata) & 0x00ff ); +} diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c index 0b53140..d93b24b 100644 --- a/drivers/serial/mcfuart.c +++ b/drivers/serial/mcfuart.c @@ -34,7 +34,7 @@ DECLARE_GLOBAL_DATA_PTR; -extern void uart_port_conf(void); +extern void uart_port_conf(int port); int serial_init(void) { @@ -43,7 +43,7 @@ int serial_init(void) uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); - uart_port_conf(); + uart_port_conf(CONFIG_SYS_UART_PORT); /* write to SICR: SIM2 = uart mode,dcd does not affect rx */ uart->ucr = UART_UCR_RESET_RX; diff --git a/drivers/serial/opencores_yanu.c b/drivers/serial/opencores_yanu.c new file mode 100644 index 0000000..f18f7f4 --- /dev/null +++ b/drivers/serial/opencores_yanu.c @@ -0,0 +1,188 @@ +/* + * Copyright 2010, Renato Andreola <renato.andreola@imagos.it> + * + * 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 <watchdog.h> +#include <asm/io.h> +#include <nios2-yanu.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*-----------------------------------------------------------------*/ +/* YANU Imagos serial port */ +/*-----------------------------------------------------------------*/ + +static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE; + +#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) + +/* Everything's already setup for fixed-baud PTF assignment*/ + +void serial_setbrg (void) +{ + int n, k; + const unsigned max_uns = 0xFFFFFFFF; + unsigned best_n, best_m, baud; + + /* compute best N and M couple */ + best_n = YANU_MAX_PRESCALER_N; + for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) { + if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >= + (unsigned)CONFIG_BAUDRATE) { + best_n = n; + break; + } + } + for (k = 0;; k++) { + if ((unsigned)CONFIG_BAUDRATE <= (max_uns >> (15+n-k))) + break; + } + best_m = + ((unsigned)CONFIG_BAUDRATE * (1 << (15 + n - k))) / + ((unsigned)CONFIG_SYS_CLK_FREQ >> k); + + baud = best_m + best_n * YANU_BAUDE; + writel(baud, &uart->baud); + + return; +} + +#else + +void serial_setbrg (void) +{ + int n, k; + const unsigned max_uns = 0xFFFFFFFF; + unsigned best_n, best_m, baud; + + /* compute best N and M couple */ + best_n = YANU_MAX_PRESCALER_N; + for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) { + if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >= + gd->baudrate) { + best_n = n; + break; + } + } + for (k = 0;; k++) { + if (gd->baudrate <= (max_uns >> (15+n-k))) + break; + } + best_m = + (gd->baudrate * (1 << (15 + n - k))) / + ((unsigned)CONFIG_SYS_CLK_FREQ >> k); + + baud = best_m + best_n * YANU_BAUDE; + writel(baud, &uart->baud); + + return; +} + + +#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ + +int serial_init (void) +{ + unsigned action,control; + + /* status register cleanup */ + action = YANU_ACTION_RRRDY | + YANU_ACTION_RTRDY | + YANU_ACTION_ROE | + YANU_ACTION_RBRK | + YANU_ACTION_RFE | + YANU_ACTION_RPE | + YANU_ACTION_RFE | YANU_ACTION_RFIFO_CLEAR | YANU_ACTION_TFIFO_CLEAR; + + writel(action, &uart->action); + + /* control register cleanup */ + /* no interrupts enabled */ + /* one stop bit */ + /* hardware flow control disabled */ + /* 8 bits */ + control = (0x7 << YANU_CONTROL_BITS_POS); + /* enven parity just to be clean */ + control |= YANU_CONTROL_PAREVEN; + /* we set threshold for fifo */ + control |= YANU_CONTROL_RDYDLY * YANU_RXFIFO_DLY; + control |= YANU_CONTROL_TXTHR * YANU_TXFIFO_THR; + + writel(control, &uart->control); + + /* to set baud rate */ + serial_setbrg(); + + return (0); +} + + +/*----------------------------------------------------------------------- + * YANU CONSOLE + *---------------------------------------------------------------------*/ +void serial_putc (char c) +{ + int tx_chars; + unsigned status; + + if (c == '\n') + serial_putc ('\r'); + + while (1) { + status = readl(&uart->status); + tx_chars = (status>>YANU_TFIFO_CHARS_POS) + & ((1<<YANU_TFIFO_CHARS_N)-1); + if (tx_chars < YANU_TXFIFO_SIZE-1) + break; + WATCHDOG_RESET (); + } + + writel((unsigned char)c, &uart->data); +} + +void serial_puts (const char *s) +{ + while (*s != 0) { + serial_putc (*s++); + } +} + + +int serial_tstc(void) +{ + unsigned status ; + + status = readl(&uart->status); + return (((status >> YANU_RFIFO_CHARS_POS) & + ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0); +} + +int serial_getc (void) +{ + while (serial_tstc() == 0) + WATCHDOG_RESET (); + + /* first we pull the char */ + writel(YANU_ACTION_RFIFO_PULL, &uart->action); + + return(readl(&uart->data) & YANU_DATA_CHAR_MASK); +} diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c index c4b36f0..687ffe6 100644 --- a/drivers/spi/mpc8xxx_spi.c +++ b/drivers/spi/mpc8xxx_spi.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2006 Ben Warren, Qstreams Networks Inc. - * With help from the common/soft_spi and cpu/mpc8260 drivers + * With help from the common/soft_spi and arch/ppc/cpu/mpc8260 drivers * * See file CREDITS for list of people who contributed to this * project. diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9ebeb4f..7784d92 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -55,14 +55,14 @@ static struct descriptor { { 0x12, /* bLength */ 1, /* bDescriptorType: UDESC_DEVICE */ - 0x0002, /* bcdUSB: v2.0 */ + cpu_to_le16(0x0200), /* bcdUSB: v2.0 */ 9, /* bDeviceClass: UDCLASS_HUB */ 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */ 64, /* bMaxPacketSize: 64 bytes */ 0x0000, /* idVendor */ 0x0000, /* idProduct */ - 0x0001, /* bcdDevice */ + cpu_to_le16(0x0100), /* bcdDevice */ 1, /* iManufacturer */ 2, /* iProduct */ 0, /* iSerialNumber */ @@ -536,7 +536,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t reg; uint32_t *status_reg; - if (le16_to_cpu(req->index) >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { + if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { printf("The request port(%d) is not configured\n", le16_to_cpu(req->index) - 1); return -1; @@ -630,19 +630,8 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[0] |= USB_PORT_STAT_SUSPEND; if (reg & EHCI_PS_OCA) tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; - if (reg & EHCI_PS_PR && - (portreset & (1 << le16_to_cpu(req->index)))) { - int ret; - /* force reset to complete */ - reg = reg & ~(EHCI_PS_PR | EHCI_PS_CLEAR); - ehci_writel(status_reg, reg); - ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000); - if (!ret) - tmpbuf[0] |= USB_PORT_STAT_RESET; - else - printf("port(%d) reset error\n", - le16_to_cpu(req->index) - 1); - } + if (reg & EHCI_PS_PR) + tmpbuf[0] |= USB_PORT_STAT_RESET; if (reg & EHCI_PS_PP) tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; @@ -699,6 +688,8 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, ehci_writel(status_reg, reg); break; } else { + int ret; + reg |= EHCI_PS_PR; reg &= ~EHCI_PS_PE; ehci_writel(status_reg, reg); @@ -710,8 +701,19 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, wait_ms(50); /* terminate the reset */ ehci_writel(status_reg, reg & ~EHCI_PS_PR); - wait_ms(2); - portreset |= 1 << le16_to_cpu(req->index); + /* + * A host controller must terminate the reset + * and stabilize the state of the port within + * 2 milliseconds + */ + ret = handshake(status_reg, EHCI_PS_PR, 0, + 2 * 1000); + if (!ret) + portreset |= + 1 << le16_to_cpu(req->index); + else + printf("port(%d) reset error\n", + le16_to_cpu(req->index) - 1); } break; default: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 441b1a2..047902a 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -28,6 +28,7 @@ #ifdef CONFIG_PCI_EHCI_DEVICE static struct pci_device_id ehci_pci_ids[] = { /* Please add supported PCI EHCI controller ids here */ + {0x1033, 0x00E0}, {0, 0} }; #endif diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 7aff54b..abdcbb4 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -42,7 +42,7 @@ * * [[GNU/GPL disclaimer]] * - * and in part from AU1x00 OHCI HCD driver "u-boot/cpu/mips/au1x00_usb_ohci.c" + * and in part from AU1x00 OHCI HCD driver "u-boot/arch/mips/cpu/au1x00_usb_ohci.c" * (original copyright message follows): * * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00. diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 29f3ba1..b2e03bc 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -25,11 +25,6 @@ #if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) -#ifndef CONFIG_AT91_LEGACY -#define CONFIG_AT91_LEGACY -#warning Please update to use C structur SoC access ! -#endif - #include <asm/arch/hardware.h> #include <asm/arch/io.h> #include <asm/arch/at91_pmc.h> @@ -37,22 +32,23 @@ int usb_cpu_init(void) { + at91_pmc_t *pmc = (at91_pmc_t *)AT91_PMC_BASE; #if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \ defined(CONFIG_AT91SAM9261) /* Enable PLLB */ - at91_sys_write(AT91_CKGR_PLLBR, get_pllb_init()); - while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) + writel(get_pllb_init(), &pmc->pllbr); + while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) ; #endif /* Enable USB host clock. */ - at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_UHP); + writel(1 << AT91_ID_UHP, &pmc->pcer); #ifdef CONFIG_AT91SAM9261 - at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP | AT91_PMC_HCK0); + writel(AT91_PMC_UHP | AT91_PMC_HCK0, &pmc->scer); #else - at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP); + writel(AT91_PMC_UHP, &pmc->scer); #endif return 0; @@ -60,19 +56,21 @@ int usb_cpu_init(void) int usb_cpu_stop(void) { + at91_pmc_t *pmc = (at91_pmc_t *)AT91_PMC_BASE; + /* Disable USB host clock. */ - at91_sys_write(AT91_PMC_PCDR, 1 << AT91_ID_UHP); + writel(1 << AT91_ID_UHP, &pmc->pcdr); #ifdef CONFIG_AT91SAM9261 - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_HCK0); + writel(AT91_PMC_UHP | AT91_PMC_HCK0, &pmc->scdr); #else - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP); + writel(AT91_PMC_UHP, &pmc->scdr); #endif #if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) /* Disable PLLB */ - at91_sys_write(AT91_CKGR_PLLBR, 0); - while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != 0) + writel(0, &pmc->pllbr); + while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) ; #endif diff --git a/drivers/video/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c index 9ebb0b0..4a9bd07 100644 --- a/drivers/video/ati_radeon_fb.c +++ b/drivers/video/ati_radeon_fb.c @@ -210,7 +210,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) * ToDo: identify these cases */ - DPRINT("radeonfb: Found %ldk of %s %d bits wide videoram\n", + DPRINT("radeonfb: Found %dk of %s %d bits wide videoram\n", rinfo->video_ram / 1024, rinfo->vram_ddr ? "DDR" : "SDRAM", rinfo->vram_width); @@ -586,18 +586,21 @@ int radeon_probe(struct radeonfb_info *rinfo) rinfo->pdev.device = did; rinfo->family = get_radeon_id_family(rinfo->pdev.device); pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, - &rinfo->fb_base_phys); + &rinfo->fb_base_bus); pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, - &rinfo->mmio_base_phys); - rinfo->fb_base_phys &= 0xfffff000; - rinfo->mmio_base_phys &= ~0x04; - - rinfo->mmio_base = (void *)rinfo->mmio_base_phys; - DPRINT("rinfo->mmio_base = 0x%x\n",rinfo->mmio_base); + &rinfo->mmio_base_bus); + rinfo->fb_base_bus &= 0xfffff000; + rinfo->mmio_base_bus &= ~0x04; + + rinfo->mmio_base = pci_bus_to_virt(pdev, rinfo->mmio_base_bus, + PCI_REGION_MEM, 0, MAP_NOCACHE); + DPRINT("rinfo->mmio_base = 0x%p bus=0x%x\n", + rinfo->mmio_base, rinfo->mmio_base_bus); rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16; DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base); /* PostBIOS with x86 emulater */ - BootVideoCardBIOS(pdev, NULL, 0); + if (!BootVideoCardBIOS(pdev, NULL, 0)) + return -1; /* * Check for errata @@ -610,14 +613,15 @@ int radeon_probe(struct radeonfb_info *rinfo) rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram); - rinfo->fb_base = (void *)rinfo->fb_base_phys; - - DPRINT("Radeon: framebuffer base phy address 0x%08x," \ - "MMIO base phy address 0x%08x," \ - "framebuffer local base 0x%08x.\n ", - rinfo->fb_base_phys, rinfo->mmio_base_phys, - rinfo->fb_local_base); - + rinfo->fb_base = pci_bus_to_virt(pdev, rinfo->fb_base_bus, + PCI_REGION_MEM, 0, MAP_NOCACHE); + DPRINT("Radeon: framebuffer base address 0x%08x, " + "bus address 0x%08x\n" + "MMIO base address 0x%08x, bus address 0x%08x, " + "framebuffer local base 0x%08x.\n ", + (u32)rinfo->fb_base, rinfo->fb_base_bus, + (u32)rinfo->mmio_base, rinfo->mmio_base_bus, + rinfo->fb_local_base); return 0; } return -1; @@ -733,13 +737,13 @@ void *video_hw_init(void) } pGD->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS; - pGD->pciBase = rinfo->fb_base_phys; - pGD->frameAdrs = rinfo->fb_base_phys; + pGD->pciBase = (unsigned int)rinfo->fb_base; + pGD->frameAdrs = (unsigned int)rinfo->fb_base; pGD->memSize = 64 * 1024 * 1024; /* Cursor Start Address */ - pGD->dprBase = - (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + rinfo->fb_base_phys; + pGD->dprBase = (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + + (unsigned int)rinfo->fb_base; if ((pGD->dprBase & 0x0fff) != 0) { /* allign it */ pGD->dprBase &= 0xfffff000; @@ -747,8 +751,8 @@ void *video_hw_init(void) } DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase, PATTERN_ADR); - pGD->vprBase = rinfo->fb_base_phys; /* Dummy */ - pGD->cprBase = rinfo->fb_base_phys; /* Dummy */ + pGD->vprBase = (unsigned int)rinfo->fb_base; /* Dummy */ + pGD->cprBase = (unsigned int)rinfo->fb_base; /* Dummy */ /* set up Hardware */ /* Clear video memory (only visible screen area) */ diff --git a/drivers/video/ati_radeon_fb.h b/drivers/video/ati_radeon_fb.h index e981f95..0659045 100644 --- a/drivers/video/ati_radeon_fb.h +++ b/drivers/video/ati_radeon_fb.h @@ -49,8 +49,8 @@ struct radeonfb_info { struct pci_device_id pdev; u16 family; - u32 fb_base_phys; - u32 mmio_base_phys; + u32 fb_base_bus; + u32 mmio_base_bus; void *mmio_base; void *fb_base; diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 49f0a2e..d1f47c9 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -803,8 +803,193 @@ static void inline fill_555rgb_pswap(uchar *fb, int x, #endif /* + * RLE8 bitmap support + */ + +#ifdef CONFIG_VIDEO_BMP_RLE8 +/* Pre-calculated color table entry */ +struct palette { + union { + unsigned short w; /* word */ + unsigned int dw; /* double word */ + } ce; /* color entry */ +}; + +/* + * Helper to draw encoded/unencoded run. + */ +static void draw_bitmap (uchar **fb, uchar *bm, struct palette *p, + int cnt, int enc) +{ + ulong addr = (ulong)*fb; + int *off; + int enc_off = 1; + int i; + + /* + * Setup offset of the color index in the bitmap. + * Color index of encoded run is at offset 1. + */ + off = enc ? &enc_off : &i; + + switch (VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + for (i = 0; i < cnt; i++) + *(unsigned char *)addr++ = bm[*off]; + break; + case GDF_15BIT_555RGB: + case GDF_16BIT_565RGB: + /* differences handled while pre-calculating palette */ + for (i = 0; i < cnt; i++) { + *(unsigned short *)addr = p[bm[*off]].ce.w; + addr += 2; + } + break; + case GDF_32BIT_X888RGB: + for (i = 0; i < cnt; i++) { + *(unsigned long *)addr = p[bm[*off]].ce.dw; + addr += 4; + } + break; + } + *fb = (uchar *)addr; /* return modified address */ +} + +static int display_rle8_bitmap (bmp_image_t *img, int xoff, int yoff, + int width, int height) +{ + unsigned char *bm; + unsigned char *fbp; + unsigned int cnt, runlen; + int decode = 1; + int x, y, bpp, i, ncolors; + struct palette p[256]; + bmp_color_table_entry_t cte; + int green_shift, red_off; + + x = 0; + y = __le32_to_cpu(img->header.height) - 1; + ncolors = __le32_to_cpu(img->header.colors_used); + bpp = VIDEO_PIXEL_SIZE; + fbp = (unsigned char *)((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + xoff) * bpp); + + bm = (uchar *)img + __le32_to_cpu(img->header.data_offset); + + /* pre-calculate and setup palette */ + switch (VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + video_set_lut (i, cte.red, cte.green, cte.blue); + } + break; + case GDF_15BIT_555RGB: + case GDF_16BIT_565RGB: + if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) { + green_shift = 3; + red_off = 10; + } else { + green_shift = 2; + red_off = 11; + } + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + p[i].ce.w = SWAP16((unsigned short) + (((cte.red >> 3) << red_off) | + ((cte.green >> green_shift) << 5) | + cte.blue >> 3)); + } + break; + case GDF_32BIT_X888RGB: + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + p[i].ce.dw = SWAP32((cte.red << 16) | (cte.green << 8) | + cte.blue); + } + break; + default: + printf("RLE Bitmap unsupported in video mode 0x%x\n", + VIDEO_DATA_FORMAT); + return -1; + } + + while (decode) { + switch (bm[0]) { + case 0: + switch (bm[1]) { + case 0: + /* scan line end marker */ + bm += 2; + x = 0; + y--; + fbp = (unsigned char *) + ((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + + xoff) * bpp); + continue; + case 1: + /* end of bitmap data marker */ + decode = 0; + break; + case 2: + /* run offset marker */ + x += bm[2]; + y -= bm[3]; + fbp = (unsigned char *) + ((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + + x + xoff) * bpp); + bm += 4; + break; + default: + /* unencoded run */ + cnt = bm[1]; + runlen = cnt; + bm += 2; + if (y < height) { + if (x >= width) { + x += runlen; + goto next_run; + } + if (x + runlen > width) + cnt = width - x; + + draw_bitmap (&fbp, bm, p, cnt, 0); + x += runlen; + } +next_run: + bm += runlen; + if (runlen & 1) + bm++; /* 0 padding if length is odd */ + } + break; + default: + /* encoded run */ + if (y < height) { /* only draw into visible area */ + cnt = bm[0]; + runlen = cnt; + if (x >= width) { + x += runlen; + bm += 2; + continue; + } + if (x + runlen > width) + cnt = width - x; + + draw_bitmap (&fbp, bm, p, cnt, 1); + x += runlen; + } + bm += 2; + break; + } + } + return 0; +} +#endif + +/* * Display the BMP file located at address bmp_image. - * Only uncompressed */ int video_display_bitmap (ulong bmp_image, int x, int y) { @@ -872,7 +1057,11 @@ int video_display_bitmap (ulong bmp_image, int x, int y) debug ("Display-bmp: %d x %d with %d colors\n", width, height, colors); - if (compression != BMP_BI_RGB) { + if (compression != BMP_BI_RGB +#ifdef CONFIG_VIDEO_BMP_RLE8 + && compression != BMP_BI_RLE8 +#endif + ) { printf ("Error: compression type %ld not supported\n", compression); #ifdef CONFIG_VIDEO_BMP_GZIP @@ -906,6 +1095,13 @@ int video_display_bitmap (ulong bmp_image, int x, int y) ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) + x * VIDEO_PIXEL_SIZE); +#ifdef CONFIG_VIDEO_BMP_RLE8 + if (compression == BMP_BI_RLE8) { + return display_rle8_bitmap(bmp, + x, y, width, height); + } +#endif + /* We handle only 8bpp or 24 bpp bitmap */ switch (le16_to_cpu (bmp->header.bit_count)) { case 8: diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index 5bb8b77..25afae7 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -42,11 +42,10 @@ static int at91_wdt_settimeout(unsigned int timeout) { unsigned int reg; - unsigned int mr; + at91_wdt_t *wd = (at91_wdt_t *) AT91_WDT_BASE; /* Check if disabled */ - mr = at91_sys_read(AT91_WDT_MR); - if (mr & AT91_WDT_WDDIS) { + if (readl(&wd->mr) & AT91_WDT_MR_WDDIS) { printf("sorry, watchdog is disabled\n"); return -1; } @@ -57,19 +56,21 @@ static int at91_wdt_settimeout(unsigned int timeout) * Since WDV is a 12-bit counter, the maximum period is * 4096 / 256 = 16 seconds. */ - reg = AT91_WDT_WDRSTEN /* causes watchdog reset */ - /* | AT91_WDT_WDRPROC causes processor reset only */ - | AT91_WDT_WDDBGHLT /* disabled in debug mode */ - | AT91_WDT_WDD /* restart at any time */ - | (timeout & AT91_WDT_WDV); /* timer value */ - at91_sys_write(AT91_WDT_MR, reg); + + reg = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */ + | AT91_WDT_MR_WDDBGHLT /* disabled in debug mode */ + | AT91_WDT_MR_WDD(0xfff) /* restart at any time */ + | AT91_WDT_MR_WDV(timeout); /* timer value */ + + writel(reg, &wd->mr); return 0; } void hw_watchdog_reset(void) { - at91_sys_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + at91_wdt_t *wd = (at91_wdt_t *) AT91_WDT_BASE; + writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, &wd->cr); } void hw_watchdog_init(void) |