diff options
author | Michael Brandt <Michael.Brandt@stericsson.com> | 2009-11-23 10:42:36 +0100 |
---|---|---|
committer | Michael Brandt <Michael.Brandt@stericsson.com> | 2009-11-23 10:42:36 +0100 |
commit | b065b499073caa5d1579d54246aea3c53f0a365f (patch) | |
tree | 82282dc6e13912d7ad7e4c7c98e868f2222b0d31 /drivers | |
parent | c5fd9311b6c59a5fb4c6e7188c8bef96e3e2d86d (diff) | |
parent | fcffb680e77fcb48598d4a9944dbe2d4503170e0 (diff) |
Merge branch 'master' of http://git.denx.de/u-boot
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/spi/spi_flash.c | 5 | ||||
-rw-r--r-- | drivers/mtd/spi/spi_flash_internal.h | 1 | ||||
-rw-r--r-- | drivers/mtd/spi/stmicro.c | 3 | ||||
-rw-r--r-- | drivers/mtd/spi/winbond.c | 332 | ||||
-rw-r--r-- | drivers/net/cs8900.c | 9 | ||||
-rw-r--r-- | drivers/net/dm9000x.c | 26 | ||||
-rw-r--r-- | drivers/net/fec_mxc.c | 20 | ||||
-rw-r--r-- | drivers/net/smc91111.h | 8 | ||||
-rw-r--r-- | drivers/net/smc911x.c | 4 | ||||
-rw-r--r-- | drivers/pci/fsl_pci_init.c | 32 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
-rw-r--r-- | drivers/rtc/ftrtc010.c | 124 |
13 files changed, 520 insertions, 46 deletions
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index e3e029280..4f11b3631 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.o COBJS-$(CONFIG_SPI_FLASH_SPANSION) += spansion.o COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o +COBJS-$(CONFIG_SPI_FLASH_WINBOND) += winbond.o COBJS-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o COBJS := $(COBJS-y) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 25346a4a1..612f819dc 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -140,6 +140,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, flash = spi_flash_probe_macronix(spi, idcode); break; #endif +#ifdef CONFIG_SPI_FLASH_WINBOND + case 0xef: + flash = spi_flash_probe_winbond(spi, idcode); + break; +#endif #ifdef CONFIG_SPI_FLASH_STMICRO case 0x20: flash = spi_flash_probe_stmicro(spi, idcode); diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 0612383c6..08546fbb0 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -49,3 +49,4 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode); +struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 9b910c13f..ae0d0471f 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -281,7 +281,8 @@ int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len) ret = 0; for (actual = 0; actual < len; actual++) { - cmd[1] = (offset / sector_size) + actual; + cmd[1] = offset >> 16; + offset += sector_size; ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0); if (ret < 0) { diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c new file mode 100644 index 000000000..b8da92319 --- /dev/null +++ b/drivers/mtd/spi/winbond.c @@ -0,0 +1,332 @@ +/* + * Copyright 2008, Network Appliance Inc. + * Author: Jason McMullan <mcmullan <at> netapp.com> + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <malloc.h> +#include <spi_flash.h> + +#include "spi_flash_internal.h" + +/* M25Pxx-specific commands */ +#define CMD_W25_WREN 0x06 /* Write Enable */ +#define CMD_W25_WRDI 0x04 /* Write Disable */ +#define CMD_W25_RDSR 0x05 /* Read Status Register */ +#define CMD_W25_WRSR 0x01 /* Write Status Register */ +#define CMD_W25_READ 0x03 /* Read Data Bytes */ +#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define CMD_W25_PP 0x02 /* Page Program */ +#define CMD_W25_SE 0x20 /* Sector (4K) Erase */ +#define CMD_W25_BE 0xd8 /* Block (64K) Erase */ +#define CMD_W25_CE 0xc7 /* Chip Erase */ +#define CMD_W25_DP 0xb9 /* Deep Power-down */ +#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */ + +#define WINBOND_ID_W25X16 0x3015 +#define WINBOND_ID_W25X32 0x3016 +#define WINBOND_ID_W25X64 0x3017 + +#define WINBOND_SR_WIP (1 << 0) /* Write-in-Progress */ + +struct winbond_spi_flash_params { + uint16_t id; + /* Log2 of page size in power-of-two mode */ + uint8_t l2_page_size; + uint16_t pages_per_sector; + uint16_t sectors_per_block; + uint8_t nr_blocks; + const char *name; +}; + +/* spi_flash needs to be first so upper layers can free() it */ +struct winbond_spi_flash { + struct spi_flash flash; + const struct winbond_spi_flash_params *params; +}; + +static inline struct winbond_spi_flash * +to_winbond_spi_flash(struct spi_flash *flash) +{ + return container_of(flash, struct winbond_spi_flash, flash); +} + +static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { + { + .id = WINBOND_ID_W25X16, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 32, + .name = "W25X16", + }, + { + .id = WINBOND_ID_W25X32, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 64, + .name = "W25X32", + }, + { + .id = WINBOND_ID_W25X64, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "W25X64", + }, +}; + +static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout) +{ + struct spi_slave *spi = flash->spi; + unsigned long timebase; + int ret; + u8 status; + u8 cmd[4] = { CMD_W25_RDSR, 0xff, 0xff, 0xff }; + + ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN); + if (ret) { + debug("SF: Failed to send command %02x: %d\n", cmd, ret); + return ret; + } + + timebase = get_timer(0); + do { + ret = spi_xfer(spi, 8, NULL, &status, 0); + if (ret) { + debug("SF: Failed to get status for cmd %02x: %d\n", cmd, ret); + return -1; + } + + if ((status & WINBOND_SR_WIP) == 0) + break; + + } while (get_timer(timebase) < timeout); + + spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); + + if ((status & WINBOND_SR_WIP) == 0) + return 0; + + debug("SF: Timed out on command %02x: %d\n", cmd, ret); + /* Timed out */ + return -1; +} + +/* + * Assemble the address part of a command for Winbond devices in + * non-power-of-two page size mode. + */ +static void winbond_build_address(struct winbond_spi_flash *stm, u8 *cmd, u32 offset) +{ + unsigned long page_addr; + unsigned long byte_addr; + unsigned long page_size; + unsigned int page_shift; + + /* + * The "extra" space per page is the power-of-two page size + * divided by 32. + */ + page_shift = stm->params->l2_page_size; + page_size = (1 << page_shift); + page_addr = offset / page_size; + byte_addr = offset % page_size; + + cmd[0] = page_addr >> (16 - page_shift); + cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8); + cmd[2] = byte_addr; +} + +static int winbond_read_fast(struct spi_flash *flash, + u32 offset, size_t len, void *buf) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + u8 cmd[5]; + + cmd[0] = CMD_READ_ARRAY_FAST; + winbond_build_address(stm, cmd + 1, offset); + cmd[4] = 0x00; + + return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len); +} + +static int winbond_write(struct spi_flash *flash, + u32 offset, size_t len, const void *buf) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + unsigned long page_addr; + unsigned long byte_addr; + unsigned long page_size; + unsigned int page_shift; + size_t chunk_len; + size_t actual; + int ret; + u8 cmd[4]; + + page_shift = stm->params->l2_page_size; + page_size = (1 << page_shift); + page_addr = offset / page_size; + byte_addr = offset % page_size; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual += chunk_len) { + chunk_len = min(len - actual, page_size - byte_addr); + + cmd[0] = CMD_W25_PP; + cmd[1] = page_addr >> (16 - page_shift); + cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8); + cmd[3] = byte_addr; + debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n", + buf + actual, + cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); + + ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + goto out; + } + + ret = spi_flash_cmd_write(flash->spi, cmd, 4, + buf + actual, chunk_len); + if (ret < 0) { + debug("SF: Winbond Page Program failed\n"); + goto out; + } + + ret = winbond_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret < 0) { + debug("SF: Winbond page programming timed out\n"); + goto out; + } + + page_addr++; + byte_addr = 0; + } + + debug("SF: Winbond: Successfully programmed %u bytes @ 0x%x\n", + len, offset); + ret = 0; + +out: + spi_release_bus(flash->spi); + return ret; +} + +int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + unsigned long sector_size; + unsigned int page_shift; + size_t actual; + int ret; + u8 cmd[4]; + + /* + * This function currently uses sector erase only. + * probably speed things up by using bulk erase + * when possible. + */ + + page_shift = stm->params->l2_page_size; + sector_size = (1 << page_shift) * stm->params->pages_per_sector; + + if (offset % sector_size || len % sector_size) { + debug("SF: Erase offset/length not multiple of sector size\n"); + return -1; + } + + len /= sector_size; + cmd[0] = CMD_W25_SE; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual++) { + winbond_build_address(stm, &cmd[1], offset + actual * sector_size); + printf("Erase: %02x %02x %02x %02x\n", + cmd[0], cmd[1], cmd[2], cmd[3]); + + ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + goto out; + } + + ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); + if (ret < 0) { + debug("SF: Winbond sector erase failed\n"); + goto out; + } + + ret = winbond_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); + if (ret < 0) { + debug("SF: Winbond sector erase timed out\n"); + goto out; + } + } + + debug("SF: Winbond: Successfully erased %u bytes @ 0x%x\n", + len * sector_size, offset); + ret = 0; + +out: + spi_release_bus(flash->spi); + return ret; +} + +struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) +{ + const struct winbond_spi_flash_params *params; + unsigned long page_size; + struct winbond_spi_flash *stm; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { + params = &winbond_spi_flash_table[i]; + if (params->id == ((idcode[1] << 8) | idcode[2])) + break; + } + + if (i == ARRAY_SIZE(winbond_spi_flash_table)) { + debug("SF: Unsupported Winbond ID %02x%02x\n", + idcode[1], idcode[2]); + return NULL; + } + + stm = malloc(sizeof(struct winbond_spi_flash)); + if (!stm) { + debug("SF: Failed to allocate memory\n"); + return NULL; + } + + stm->params = params; + stm->flash.spi = spi; + stm->flash.name = params->name; + + /* Assuming power-of-two page size initially. */ + page_size = 1 << params->l2_page_size; + + stm->flash.write = winbond_write; + stm->flash.erase = winbond_erase; + stm->flash.read = winbond_read_fast; + stm->flash.size = page_size * params->pages_per_sector + * params->sectors_per_block + * params->nr_blocks; + + debug("SF: Detected %s with page size %u, total %u bytes\n", + params->name, page_size, stm->flash.size); + + return &stm->flash; +} diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index 587f7f62a..df360042b 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -56,7 +56,7 @@ #define REG_READ(a) readl((a)) /* we don't need 16 bit initialisation on 32 bit bus */ -#define get_reg_init_bus(x) get_reg((x)) +#define get_reg_init_bus(r,d) get_reg((r),(d)) #else @@ -321,15 +321,16 @@ int cs8900_initialize(u8 dev_num, int base_addr) memset(priv, 0, sizeof(*priv)); priv->regs = (struct cs8900_regs *)base_addr; - /* Load MAC address from EEPROM */ - cs8900_get_enetaddr(dev); - dev->iobase = base_addr; dev->priv = priv; dev->init = cs8900_init; dev->halt = cs8900_halt; dev->send = cs8900_send; dev->recv = cs8900_recv; + + /* Load MAC address from EEPROM */ + cs8900_get_enetaddr(dev); + sprintf(dev->name, "%s-%hu", CS8900_DRIVERNAME, dev_num); eth_register(dev); diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index efe913589..73dd33572 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -284,7 +284,6 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) int i, oft, lnk; u8 io_mode; struct board_info *db = &dm9000_info; - uchar enetaddr[6]; DM9000_DBG("%s\n", __func__); @@ -342,20 +341,11 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) /* Clear interrupt status */ DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS); - /* Set Node address */ - if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { -#if !defined(CONFIG_DM9000_NO_SROM) - for (i = 0; i < 3; i++) - dm9000_read_srom_word(i, enetaddr + 2 * i); - eth_setenv_enetaddr("ethaddr", enetaddr); -#endif - } - - printf("MAC: %pM\n", enetaddr); + printf("MAC: %pM\n", dev->enetaddr); /* fill device MAC address registers */ for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) - DM9000_iow(oft, enetaddr[i]); + DM9000_iow(oft, dev->enetaddr[i]); for (i = 0, oft = 0x16; i < 8; i++, oft++) DM9000_iow(oft, 0xff); @@ -558,6 +548,15 @@ void dm9000_write_srom_word(int offset, u16 val) } #endif +static void dm9000_get_enetaddr(struct eth_device *dev) +{ +#if !defined(CONFIG_DM9000_NO_SROM) + int i; + for (i = 0; i < 3; i++) + dm9000_read_srom_word(i, dev->enetaddr + (2 * i)); +#endif +} + /* Read a byte from I/O port */ @@ -621,6 +620,9 @@ int dm9000_initialize(bd_t *bis) { struct eth_device *dev = &(dm9000_info.netdev); + /* Load MAC address from EEPROM */ + dm9000_get_enetaddr(dev); + dev->init = dm9000_init; dev->halt = dm9000_halt; dev->send = dm9000_send; diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index bd83a249e..ad073077c 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -55,6 +55,8 @@ struct fec_priv gfec = { .tbd_base = NULL, .tbd_index = 0, .bd = NULL, + .rdb_ptr = NULL, + .base_ptr = NULL, }; /* @@ -157,7 +159,9 @@ static int miiphy_restart_aneg(struct eth_device *dev) /* * Set the auto-negotiation advertisement register bits */ - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_ANAR, 0x1e0); + miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_ANAR, + PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | + PHY_ANLPAR_10 | PHY_ANLPAR_PSB_802_3); miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); @@ -228,7 +232,8 @@ static int fec_rbd_init(struct fec_priv *fec, int count, int size) uint32_t p = 0; /* reserve data memory and consider alignment */ - fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); + if (fec->rdb_ptr == NULL) + fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); p = (uint32_t)fec->rdb_ptr; if (!p) { puts("fec_imx27: not enough malloc memory!\n"); @@ -341,8 +346,8 @@ static int fec_open(struct eth_device *edev) writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); miiphy_wait_aneg(edev); - miiphy_speed(edev->name, 0); - miiphy_duplex(edev->name, 0); + miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); + miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR); /* * Enable SmartDMA receive task @@ -363,8 +368,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd) * Datasheet forces the startaddress of each chain is 16 byte * aligned */ - fec->base_ptr = malloc((2 + FEC_RBD_NUM) * - sizeof(struct fec_bd) + DB_ALIGNMENT); + if (fec->base_ptr == NULL) + fec->base_ptr = malloc((2 + FEC_RBD_NUM) * + sizeof(struct fec_bd) + DB_ALIGNMENT); base = (uint32_t)fec->base_ptr; if (!base) { puts("fec_imx27: not enough malloc memory!\n"); @@ -491,8 +497,6 @@ static void fec_halt(struct eth_device *dev) writel(0, &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; - free(fec->rdb_ptr); - free(fec->base_ptr); debug("eth_halt: done\n"); } diff --git a/drivers/net/smc91111.h b/drivers/net/smc91111.h index bb4524106..895c74978 100644 --- a/drivers/net/smc91111.h +++ b/drivers/net/smc91111.h @@ -81,10 +81,10 @@ struct smc91111_priv{ #ifdef CONFIG_PXA250 #ifdef CONFIG_XSENGINE -#define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r<<1)))) -#define SMC_inw(a,r) (*((volatile word *)((a)->iobase+(r<<1)))) +#define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+((r)<<1)))) +#define SMC_inw(a,r) (*((volatile word *)((a)->iobase+((r)<<1)))) #define SMC_inb(a,p) ({ \ - unsigned int __p = (unsigned int)((a)->iobase + (p<<1)); \ + unsigned int __p = (unsigned int)((a)->iobase + ((p)<<1)); \ unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \ if (__p & 2) __v >>= 8; \ else __v &= 0xff; \ @@ -99,7 +99,7 @@ struct smc91111_priv{ __v; }) #define SMC_inb(a,p) ({ \ unsigned int ___v = SMC_inw((a),(p) & ~1); \ - if (p & 1) ___v >>= 8; \ + if ((p) & 1) ___v >>= 8; \ else ___v &= 0xff; \ ___v; }) #else diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index c50758e53..c027abe9f 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -243,7 +243,7 @@ int smc911x_initialize(u8 dev_num, int base_addr) dev = malloc(sizeof(*dev)); if (!dev) { free(dev); - return 0; + return -1; } memset(dev, 0, sizeof(*dev)); @@ -271,5 +271,5 @@ int smc911x_initialize(u8 dev_num, int base_addr) sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num); eth_register(dev); - return 0; + return 1; } diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 8fbab68a2..170cc257c 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -42,6 +42,7 @@ DECLARE_GLOBAL_DATA_PTR; #define FSL_PCI_PBFR 0x44 #define FSL_PCIE_CAP_ID 0x4c #define FSL_PCIE_CFG_RDY 0x4b0 +#define FSL_PROG_IF_AGENT 0x1 void pciauto_prescan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus); @@ -412,28 +413,24 @@ void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) } } +int fsl_is_pci_agent(struct pci_controller *hose) +{ + u8 prog_if; + pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); + + pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if); + + return (prog_if == FSL_PROG_IF_AGENT); +} + int fsl_pci_init_port(struct fsl_pci_info *pci_info, - struct pci_controller *hose, int busno, int pcie_ep) + struct pci_controller *hose, int busno) { volatile ccsr_fsl_pci_t *pci; struct pci_region *r; pci = (ccsr_fsl_pci_t *) pci_info->regs; - if (pcie_ep) { - volatile pit_t *pi = &pci->pit[2]; - - pci_setup_indirect(hose, (u32)&pci->cfg_addr, - (u32)&pci->cfg_data); - out_be32(&pi->pitar, 0); - out_be32(&pi->piwbar, 0); - out_be32(&pi->piwar, PIWAR_EN | PIWAR_LOCAL | - PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_IWS_4K); - - fsl_pci_config_unlock(hose); - return 0; - } - /* on non-PCIe controllers we don't have pme_msg_det so this code * should do nothing since the read will return 0 */ @@ -464,6 +461,11 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info, fsl_pci_init(hose, (u32)&pci->cfg_addr, (u32)&pci->cfg_data); + if (fsl_is_pci_agent(hose)) { + fsl_pci_config_unlock(hose); + hose->last_busno = hose->first_busno; + } + printf(" PCIE%x on bus %02x - %02x\n", pci_info->pci_num, hose->first_busno, hose->last_busno); diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ea7d899ea..772a49a90 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -40,6 +40,7 @@ COBJS-$(CONFIG_RTC_DS1556) += ds1556.o COBJS-$(CONFIG_RTC_DS164x) += ds164x.o COBJS-$(CONFIG_RTC_DS174x) += ds174x.o COBJS-$(CONFIG_RTC_DS3231) += ds3231.o +COBJS-$(CONFIG_RTC_FTRTC010) += ftrtc010.o COBJS-$(CONFIG_RTC_ISL1208) += isl1208.o COBJS-$(CONFIG_RTC_M41T11) += m41t11.o COBJS-$(CONFIG_RTC_M41T60) += m41t60.o diff --git a/drivers/rtc/ftrtc010.c b/drivers/rtc/ftrtc010.c new file mode 100644 index 000000000..c3c0bc2f5 --- /dev/null +++ b/drivers/rtc/ftrtc010.c @@ -0,0 +1,124 @@ +/* + * Faraday FTRTC010 Real Time Clock + * + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang <ratbert@faraday-tech.com> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <config.h> +#include <common.h> +#include <rtc.h> +#include <asm/io.h> + +struct ftrtc010 { + unsigned int sec; /* 0x00 */ + unsigned int min; /* 0x04 */ + unsigned int hour; /* 0x08 */ + unsigned int day; /* 0x0c */ + unsigned int alarm_sec; /* 0x10 */ + unsigned int alarm_min; /* 0x14 */ + unsigned int alarm_hour; /* 0x18 */ + unsigned int record; /* 0x1c */ + unsigned int cr; /* 0x20 */ +}; + +/* + * RTC Control Register + */ +#define FTRTC010_CR_ENABLE (1 << 0) +#define FTRTC010_CR_INTERRUPT_SEC (1 << 1) /* per second irq */ +#define FTRTC010_CR_INTERRUPT_MIN (1 << 2) /* per minute irq */ +#define FTRTC010_CR_INTERRUPT_HR (1 << 3) /* per hour irq */ +#define FTRTC010_CR_INTERRUPT_DAY (1 << 4) /* per day irq */ + +static struct ftrtc010 *rtc = (struct ftrtc010 *)CONFIG_FTRTC010_BASE; + +static void ftrtc010_enable (void) +{ + writel (FTRTC010_CR_ENABLE, &rtc->cr); +} + +/* + * return current time in seconds + */ +static unsigned long ftrtc010_time (void) +{ + unsigned long day; + unsigned long hour; + unsigned long minute; + unsigned long second; + unsigned long second2; + + do { + second = readl (&rtc->sec); + day = readl (&rtc->day); + hour = readl (&rtc->hour); + minute = readl (&rtc->min); + second2 = readl (&rtc->sec); + } while (second != second2); + + return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second; +} + +/* + * Get the current time from the RTC + */ + +int rtc_get (struct rtc_time *tmp) +{ + unsigned long now; + + debug ("%s(): record register: %x\n", + __func__, readl (&rtc->record)); + + now = ftrtc010_time () + readl (&rtc->record); + + to_tm (now, tmp); + + return 0; +} + +/* + * Set the RTC + */ +int rtc_set (struct rtc_time *tmp) +{ + unsigned long new; + unsigned long now; + + debug ("%s(): DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + __func__, + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + new = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour, + tmp->tm_min, tmp->tm_sec); + + now = ftrtc010_time (); + + debug ("%s(): write %lx to record register\n", __func__, new - now); + + writel (new - now, &rtc->record); + + return 0; +} + +void rtc_reset (void) +{ + debug ("%s()\n", __func__); + ftrtc010_enable (); +} |