summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2009-08-31 20:21:47 (GMT)
committerWolfgang Denk <wd@denx.de>2009-08-31 20:21:47 (GMT)
commit3aa8b68d80dbcb6829af60485c1e388b39af793d (patch)
treeb76a4e1624cfddceb5358d6221acd08a57c45b74 /drivers
parent3d35d87d5482de23cd5dc4d7721b1086107cae50 (diff)
parent2d04db088e6df8a008bb09f604876a45031df93b (diff)
downloadu-boot-3aa8b68d80dbcb6829af60485c1e388b39af793d.tar.xz
Merge branch 'next' of ../next
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/MCD_dmaApi.c16
-rw-r--r--drivers/misc/fsl_law.c3
-rw-r--r--drivers/mtd/cfi_flash.c15
-rw-r--r--drivers/mtd/jedec_flash.c67
-rw-r--r--drivers/mtd/nand/Makefile3
-rw-r--r--drivers/mtd/nand/davinci_nand.c284
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c2
-rw-r--r--drivers/mtd/nand/kb9202_nand.c150
-rw-r--r--drivers/mtd/nand/kmeter1_nand.c135
-rw-r--r--drivers/mtd/nand/mxc_nand.c880
-rw-r--r--drivers/mtd/nand/nand_base.c75
-rw-r--r--drivers/mtd/onenand/onenand_base.c4
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/bfin_mac.c3
-rw-r--r--drivers/net/cs8900.c276
-rw-r--r--drivers/net/cs8900.h41
-rw-r--r--drivers/net/tsec.c7
-rw-r--r--drivers/pci/fsl_pci_init.c305
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/ds12887.c12
-rw-r--r--drivers/rtc/ds1306.c18
-rw-r--r--drivers/rtc/ds1307.c13
-rw-r--r--drivers/rtc/ds1337.c13
-rw-r--r--drivers/rtc/ds1556.c12
-rw-r--r--drivers/rtc/ds164x.c12
-rw-r--r--drivers/rtc/ds174x.c12
-rw-r--r--drivers/rtc/ds3231.c12
-rw-r--r--drivers/rtc/isl1208.c12
-rw-r--r--drivers/rtc/m41t11.c11
-rw-r--r--drivers/rtc/m41t60.c10
-rw-r--r--drivers/rtc/m41t62.c25
-rw-r--r--drivers/rtc/m41t94.c124
-rw-r--r--drivers/rtc/m48t35ax.c12
-rw-r--r--drivers/rtc/max6900.c10
-rw-r--r--drivers/rtc/mc146818.c12
-rw-r--r--drivers/rtc/mk48t59.c10
-rw-r--r--drivers/rtc/pcf8563.c12
-rw-r--r--drivers/rtc/rs5c372.c14
-rw-r--r--drivers/rtc/rtc4543.c29
-rw-r--r--drivers/rtc/rx8025.c12
-rw-r--r--drivers/rtc/s3c24x0_rtc.c10
-rw-r--r--drivers/rtc/s3c44b0_rtc.c43
-rw-r--r--drivers/rtc/x1205.c29
43 files changed, 2220 insertions, 528 deletions
diff --git a/drivers/dma/MCD_dmaApi.c b/drivers/dma/MCD_dmaApi.c
index 5c95651..0dd3816 100644
--- a/drivers/dma/MCD_dmaApi.c
+++ b/drivers/dma/MCD_dmaApi.c
@@ -486,7 +486,8 @@ int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr,
MCD_modelTaskTable[TASK_FECTX].TDTstart;
MCD_taskTable[channel].TDTend =
MCD_modelTaskTable[TASK_FECTX].TDTend;
- MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable,
+ MCD_startDmaENetXmit((char *)srcAddr, (char *)srcAddr,
+ (char *)destAddr, MCD_taskTable,
channel);
} else if (flags & MCD_FECRX_DMA) {
/* TDTStart and TDTEnd */
@@ -494,7 +495,8 @@ int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr,
MCD_modelTaskTable[TASK_FECRX].TDTstart;
MCD_taskTable[channel].TDTend =
MCD_modelTaskTable[TASK_FECRX].TDTend;
- MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable,
+ MCD_startDmaENetRcv((char *)srcAddr, (char *)srcAddr,
+ (char *)destAddr, MCD_taskTable,
channel);
} else if (flags & MCD_SINGLE_DMA) {
/* this buffer descriptor is used for storing off initial
@@ -532,8 +534,9 @@ int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr,
MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart;
MCD_taskTable[channel].TDTend =
MCD_modelTaskTable[TASK_SINGLENOEU].TDTend;
- MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr,
- destIncr, dmaSize, xferSizeIncr,
+ MCD_startDmaSingleNoEu((char *)srcAddr, srcIncr,
+ (char *)destAddr, destIncr,
+ (int)dmaSize, xferSizeIncr,
flags, (int *)
&(MCD_relocBuffDesc[channel]),
cSave, MCD_taskTable, channel);
@@ -543,8 +546,9 @@ int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr,
MCD_modelTaskTable[TASK_SINGLEEU].TDTstart;
MCD_taskTable[channel].TDTend =
MCD_modelTaskTable[TASK_SINGLEEU].TDTend;
- MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr,
- destIncr, dmaSize, xferSizeIncr,
+ MCD_startDmaSingleEu((char *)srcAddr, srcIncr,
+ (char *)destAddr, destIncr,
+ (int)dmaSize, xferSizeIncr,
flags, (int *)
&(MCD_relocBuffDesc[channel]),
cSave, MCD_taskTable, channel);
diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c
index f7d454d..147fe0a 100644
--- a/drivers/misc/fsl_law.c
+++ b/drivers/misc/fsl_law.c
@@ -39,7 +39,8 @@ DECLARE_GLOBAL_DATA_PTR;
defined(CONFIG_MPC8641) || defined(CONFIG_MPC8610)
#define FSL_HW_NUM_LAWS 10
#elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572) || \
- defined(CONFIG_P2020)
+ defined(CONFIG_P1011) || defined(CONFIG_P1020) || \
+ defined(CONFIG_P2010) || defined(CONFIG_P2020)
#define FSL_HW_NUM_LAWS 12
#else
#error FSL_HW_NUM_LAWS not defined for this platform
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 3ca73e3..6eea49a 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -106,6 +106,8 @@
#define ATM_CMD_SOFTLOCK_START 0x80
#define ATM_CMD_LOCK_SECT 0x40
+#define FLASH_CONTINUATION_CODE 0x7F
+
#define FLASH_OFFSET_MANUFACTURER_ID 0x00
#define FLASH_OFFSET_DEVICE_ID 0x01
#define FLASH_OFFSET_DEVICE_ID2 0x0E
@@ -1541,13 +1543,22 @@ static int cmdset_intel_init(flash_info_t *info, struct cfi_qry *qry)
static void cmdset_amd_read_jedec_ids(flash_info_t *info)
{
+ ushort bankId = 0;
+ uchar manuId;
+
flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
flash_unlock_seq(info, 0);
flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
udelay(1000); /* some flash are slow to respond */
- info->manufacturer_id = flash_read_uchar (info,
- FLASH_OFFSET_MANUFACTURER_ID);
+ manuId = flash_read_uchar (info, FLASH_OFFSET_MANUFACTURER_ID);
+ /* JEDEC JEP106Z specifies ID codes up to bank 7 */
+ while (manuId == FLASH_CONTINUATION_CODE && bankId < 0x800) {
+ bankId += 0x100;
+ manuId = flash_read_uchar (info,
+ bankId | FLASH_OFFSET_MANUFACTURER_ID);
+ }
+ info->manufacturer_id = manuId;
switch (info->chipwidth){
case FLASH_CFI_8BIT:
diff --git a/drivers/mtd/jedec_flash.c b/drivers/mtd/jedec_flash.c
index e48acec..223fb71 100644
--- a/drivers/mtd/jedec_flash.c
+++ b/drivers/mtd/jedec_flash.c
@@ -68,6 +68,17 @@
#define SST39SF010A 0x00B5
#define SST39SF020A 0x00B6
+/* MXIC */
+#define MX29LV040 0x004F
+
+/* WINBOND */
+#define W39L040A 0x00D6
+
+/* AMIC */
+#define A29L040 0x0092
+
+/* EON */
+#define EN29LV040A 0x004F
/*
* Unlock address sets for AMD command sets.
@@ -225,6 +236,62 @@ static const struct amd_flash_info jedec_table[] = {
ERASEINFO(0x10000,8),
}
},
+ {
+ .mfr_id = (u16)MX_MANUFACT,
+ .dev_id = MX29LV040,
+ .name = "MXIC MX29LV040",
+ .uaddr = {
+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x10000, 8),
+ }
+ },
+ {
+ .mfr_id = (u16)WINB_MANUFACT,
+ .dev_id = W39L040A,
+ .name = "WINBOND W39L040A",
+ .uaddr = {
+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x10000, 8),
+ }
+ },
+ {
+ .mfr_id = (u16)AMIC_MANUFACT,
+ .dev_id = A29L040,
+ .name = "AMIC A29L040",
+ .uaddr = {
+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x10000, 8),
+ }
+ },
+ {
+ .mfr_id = (u16)EON_MANUFACT,
+ .dev_id = EN29LV040A,
+ .name = "EON EN29LV040A",
+ .uaddr = {
+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x10000, 8),
+ }
+ },
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
{
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 89ccec2..02449ee 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -38,8 +38,11 @@ COBJS-$(CONFIG_DRIVER_NAND_BFIN) += bfin_nand.o
COBJS-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
+COBJS-$(CONFIG_NAND_KB9202) += kb9202_nand.o
COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
+COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
+COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 7837a8e..37d8b73 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -47,6 +47,16 @@
#include <asm/arch/nand_defs.h>
#include <asm/arch/emif_defs.h>
+/* Definitions for 4-bit hardware ECC */
+#define NAND_TIMEOUT 10240
+#define NAND_ECC_BUSY 0xC
+#define NAND_4BITECC_MASK 0x03FF03FF
+#define EMIF_NANDFSR_ECC_STATE_MASK 0x00000F00
+#define ECC_STATE_NO_ERR 0x0
+#define ECC_STATE_TOO_MANY_ERRS 0x1
+#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;
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -170,6 +180,268 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *
}
#endif /* CONFIG_SYS_NAND_HW_ECC */
+#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
+static struct nand_ecclayout nand_davinci_4bit_layout_oobfirst = {
+/*
+ * TI uses a different layout for 4K page deviecs. Since the
+ * eccpos filed can hold only a limited number of entries, adding
+ * support for 4K page will result in compilation warnings
+ * 4K Support will be added later
+ */
+#ifdef CONFIG_SYS_NAND_PAGE_2K
+ .eccbytes = 40,
+ .eccpos = {
+ 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63,
+ },
+ .oobfree = {
+ {.offset = 2, .length = 22, },
+ },
+#endif
+};
+#endif
+
+static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+ u32 val;
+
+ switch (mode) {
+ case NAND_ECC_WRITE:
+ case NAND_ECC_READ:
+ /*
+ * Start a new ECC calculation for reading or writing 512 bytes
+ * of data.
+ */
+ val = (emif_regs->NANDFCR & ~(3 << 4)) | (1 << 12);
+ emif_regs->NANDFCR = val;
+ break;
+ case NAND_ECC_READSYN:
+ val = emif_regs->NAND4BITECC1;
+ break;
+ default:
+ break;
+ }
+}
+
+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;
+
+ return 0;
+}
+
+static int nand_davinci_4bit_calculate_ecc(struct mtd_info *mtd,
+ const uint8_t *dat,
+ uint8_t *ecc_code)
+{
+ unsigned int hw_4ecc[4] = { 0, 0, 0, 0 };
+ unsigned int const1 = 0, const2 = 0;
+ unsigned char count1 = 0;
+
+ nand_davinci_4bit_readecc(mtd, hw_4ecc);
+
+ /*Convert 10 bit ecc value to 8 bit */
+ for (count1 = 0; count1 < 2; count1++) {
+ const2 = count1 * 5;
+ const1 = count1 * 2;
+
+ /* Take first 8 bits from val1 (count1=0) or val5 (count1=1) */
+ ecc_code[const2] = hw_4ecc[const1] & 0xFF;
+
+ /*
+ * Take 2 bits as LSB bits from val1 (count1=0) or val5
+ * (count1=1) and 6 bits from val2 (count1=0) or
+ * val5 (count1=1)
+ */
+ ecc_code[const2 + 1] =
+ ((hw_4ecc[const1] >> 8) & 0x3) | ((hw_4ecc[const1] >> 14) &
+ 0xFC);
+
+ /*
+ * Take 4 bits from val2 (count1=0) or val5 (count1=1) and
+ * 4 bits from val3 (count1=0) or val6 (count1=1)
+ */
+ ecc_code[const2 + 2] =
+ ((hw_4ecc[const1] >> 22) & 0xF) |
+ ((hw_4ecc[const1 + 1] << 4) & 0xF0);
+
+ /*
+ * Take 6 bits from val3(count1=0) or val6 (count1=1) and
+ * 2 bits from val4 (count1=0) or val7 (count1=1)
+ */
+ ecc_code[const2 + 3] =
+ ((hw_4ecc[const1 + 1] >> 4) & 0x3F) |
+ ((hw_4ecc[const1 + 1] >> 10) & 0xC0);
+
+ /* Take 8 bits from val4 (count1=0) or val7 (count1=1) */
+ ecc_code[const2 + 4] = (hw_4ecc[const1 + 1] >> 18) & 0xFF;
+ }
+ return 0;
+}
+
+
+static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
+ uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned short ecc_10bit[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int i;
+ unsigned int hw_4ecc[4] = { 0, 0, 0, 0 }, iserror = 0;
+ unsigned short *pspare = NULL, *pspare1 = NULL;
+ unsigned int numerrors, erroraddress, errorvalue;
+ u32 val;
+
+ /*
+ * Check for an ECC where all bytes are 0xFF. If this is the case, we
+ * will assume we are looking at an erased page and we should ignore
+ * the ECC.
+ */
+ for (i = 0; i < 10; i++) {
+ if (read_ecc[i] != 0xFF)
+ break;
+ }
+ if (i == 10)
+ return 0;
+
+ /* Convert 8 bit in to 10 bit */
+ pspare = (unsigned short *)&read_ecc[2];
+ pspare1 = (unsigned short *)&read_ecc[0];
+
+ /* Take 10 bits from 0th and 1st bytes */
+ ecc_10bit[0] = (*pspare1) & 0x3FF;
+
+ /* Take 6 bits from 1st byte and 4 bits from 2nd byte */
+ ecc_10bit[1] = (((*pspare1) >> 10) & 0x3F)
+ | (((pspare[0]) << 6) & 0x3C0);
+
+ /* Take 4 bits form 2nd bytes and 6 bits from 3rd bytes */
+ ecc_10bit[2] = ((pspare[0]) >> 4) & 0x3FF;
+
+ /*Take 2 bits from 3rd byte and 8 bits from 4th byte */
+ ecc_10bit[3] = (((pspare[0]) >> 14) & 0x3)
+ | ((((pspare[1])) << 2) & 0x3FC);
+
+ /* Take 8 bits from 5th byte and 2 bits from 6th byte */
+ ecc_10bit[4] = ((pspare[1]) >> 8)
+ | ((((pspare[2])) << 8) & 0x300);
+
+ /* Take 6 bits from 6th byte and 4 bits from 7th byte */
+ ecc_10bit[5] = (pspare[2] >> 2) & 0x3FF;
+
+ /* Take 4 bits from 7th byte and 6 bits from 8th byte */
+ ecc_10bit[6] = (((pspare[2]) >> 12) & 0xF)
+ | ((((pspare[3])) << 4) & 0x3F0);
+
+ /*Take 2 bits from 8th byte and 8 bits from 9th byte */
+ ecc_10bit[7] = ((pspare[3]) >> 6) & 0x3FF;
+
+ /*
+ * Write the parity values in the NAND Flash 4-bit ECC Load register.
+ * Write each parity value one at a time starting from 4bit_ecc_val8
+ * to 4bit_ecc_val1.
+ */
+ for (i = 7; i >= 0; i--)
+ emif_regs->NAND4BITECCLOAD = ecc_10bit[i];
+
+ /*
+ * Perform a dummy read to the EMIF Revision Code and Status register.
+ * This is required to ensure time for syndrome calculation after
+ * writing the ECC values in previous step.
+ */
+
+ val = emif_regs->NANDFSR;
+
+ /*
+ * Read the syndrome from the NAND Flash 4-Bit ECC 1-4 registers.
+ * A syndrome value of 0 means no bit errors. If the syndrome is
+ * non-zero then go further otherwise return.
+ */
+ nand_davinci_4bit_readecc(mtd, hw_4ecc);
+
+ if (hw_4ecc[0] == ECC_STATE_NO_ERR && hw_4ecc[1] == ECC_STATE_NO_ERR &&
+ hw_4ecc[2] == ECC_STATE_NO_ERR && hw_4ecc[3] == ECC_STATE_NO_ERR)
+ return 0;
+
+ /*
+ * Clear any previous address calculation by doing a dummy read of an
+ * error address register.
+ */
+ val = 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;
+
+ /*
+ * Wait for the corr_state field (bits 8 to 11)in the
+ * NAND Flash Status register to be equal to 0x0, 0x1, 0x2, or 0x3.
+ */
+ i = NAND_TIMEOUT;
+ do {
+ val = emif_regs->NANDFSR;
+ val &= 0xc00;
+ i--;
+ } while ((i > 0) && val);
+
+ iserror = emif_regs->NANDFSR;
+ iserror &= EMIF_NANDFSR_ECC_STATE_MASK;
+ iserror = iserror >> 8;
+
+ /*
+ * ECC_STATE_TOO_MANY_ERRS (0x1) means errors cannot be
+ * corrected (five or more errors). The number of errors
+ * calculated (err_num field) differs from the number of errors
+ * searched. ECC_STATE_ERR_CORR_COMP_P (0x2) means error
+ * correction complete (errors on bit 8 or 9).
+ * ECC_STATE_ERR_CORR_COMP_N (0x3) means error correction
+ * complete (error exists).
+ */
+
+ if (iserror == ECC_STATE_NO_ERR) {
+ val = emif_regs->NANDERRVAL1;
+ return 0;
+ } else if (iserror == ECC_STATE_TOO_MANY_ERRS) {
+ val = emif_regs->NANDERRVAL1;
+ return -1;
+ }
+
+ numerrors = ((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 >>
+ (16 * (i & 1))) & 0x3FF);
+ erroraddress = ((512 + 7) - erroraddress);
+ errorvalue =
+ ((emif_regs->NANDERRVAL2 >>
+ (16 * (i & 1))) & 0xFF);
+ } else {
+ erroraddress =
+ ((emif_regs->NANDERRADD1 >>
+ (16 * (i & 1))) & 0x3FF);
+ erroraddress = ((512 + 7) - erroraddress);
+ errorvalue =
+ ((emif_regs->NANDERRVAL1 >>
+ (16 * (i & 1))) & 0xFF);
+ }
+ /* xor the corrupt data with error value */
+ if (erroraddress < 512)
+ dat[erroraddress] ^= errorvalue;
+ }
+
+ return numerrors;
+}
+
static int nand_davinci_dev_ready(struct mtd_info *mtd)
{
return emif_regs->NANDFSR & 0x1;
@@ -215,7 +487,7 @@ void davinci_nand_init(struct nand_chip *nand)
{
nand->chip_delay = 0;
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
- nand->options = NAND_USE_FLASH_BBT;
+ nand->options |= NAND_USE_FLASH_BBT;
#endif
#ifdef CONFIG_SYS_NAND_HW_ECC
nand->ecc.mode = NAND_ECC_HW;
@@ -227,7 +499,15 @@ void davinci_nand_init(struct nand_chip *nand)
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif /* CONFIG_SYS_NAND_HW_ECC */
-
+#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
+ nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
+ nand->ecc.size = 512;
+ nand->ecc.bytes = 10;
+ nand->ecc.calculate = nand_davinci_4bit_calculate_ecc;
+ nand->ecc.correct = nand_davinci_4bit_correct_data;
+ nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc;
+ nand->ecc.layout = &nand_davinci_4bit_layout_oobfirst;
+#endif
/* Set address of hardware control function */
nand->cmd_ctrl = nand_davinci_hwcontrol;
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 77a33c0..50cb4aa 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -662,7 +662,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
static int fsl_elbc_read_page(struct mtd_info *mtd,
struct nand_chip *chip,
- uint8_t *buf)
+ uint8_t *buf, int page)
{
fsl_elbc_read_buf(mtd, buf, mtd->writesize);
fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
diff --git a/drivers/mtd/nand/kb9202_nand.c b/drivers/mtd/nand/kb9202_nand.c
new file mode 100644
index 0000000..b8f46fa
--- /dev/null
+++ b/drivers/mtd/nand/kb9202_nand.c
@@ -0,0 +1,150 @@
+/*
+ * (C) Copyright 2006
+ * KwikByte <kb9200_dev@kwikbyte.com>
+ *
+ * (C) Copyright 2009
+ * Matthias Kaehlcke <matthias@kaehlcke.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 <asm/io.h>
+#include <asm/arch/AT91RM9200.h>
+#include <asm/arch/hardware.h>
+
+#include <nand.h>
+
+/*
+ * hardware specific access to control-lines
+ */
+
+#define MASK_ALE (1 << 22) /* our ALE is A22 */
+#define MASK_CLE (1 << 21) /* our CLE is A21 */
+
+#define KB9202_NAND_NCE (1 << 28) /* EN* on D28 */
+#define KB9202_NAND_BUSY (1 << 29) /* RB* on D29 */
+
+#define KB9202_SMC2_NWS (1 << 2)
+#define KB9202_SMC2_TDF (1 << 8)
+#define KB9202_SMC2_RWSETUP (1 << 24)
+#define KB9202_SMC2_RWHOLD (1 << 29)
+
+/*
+ * Board-specific function to access device control signals
+ */
+static void kb9202_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+
+ /* clear ALE and CLE bits */
+ IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= MASK_CLE;
+
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= MASK_ALE;
+
+ this->IO_ADDR_W = (void *) IO_ADDR_W;
+
+ if (ctrl & NAND_NCE)
+ writel(KB9202_NAND_NCE, AT91C_PIOC_CODR);
+ else
+ writel(KB9202_NAND_NCE, AT91C_PIOC_SODR);
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
+}
+
+
+/*
+ * Board-specific function to access the device ready signal.
+ */
+static int kb9202_nand_ready(struct mtd_info *mtd)
+{
+ return readl(AT91C_PIOC_PDSR) & KB9202_NAND_BUSY;
+}
+
+
+/*
+ * Board-specific NAND init. Copied from include/linux/mtd/nand.h for reference.
+ *
+ * struct nand_chip - NAND Private Flash Chip Data
+ * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
+ * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
+ * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
+ * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
+ * If set to NULL no access to ready/busy is available and the ready/busy information
+ * is read from the chip status register
+ * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
+ * be provided if a hardware ECC is available
+ * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
+ * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
+ * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
+ * special functionality. See the defines for further explanation
+*/
+/*
+ * This routine initializes controller and GPIOs.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+ unsigned int value;
+
+ nand->ecc.mode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = kb9202_nand_hwcontrol;
+ nand->dev_ready = kb9202_nand_ready;
+
+ /* in case running outside of bootloader */
+ writel(1 << AT91C_ID_PIOC, AT91C_PMC_PCER);
+
+ /* setup nand flash access (allow ample margin) */
+ /* 4 wait states, 1 setup, 1 hold, 1 float for 8-bit device */
+ writel(AT91C_SMC2_WSEN | KB9202_SMC2_NWS | KB9202_SMC2_TDF |
+ AT91C_SMC2_DBW_8 | KB9202_SMC2_RWSETUP | KB9202_SMC2_RWHOLD,
+ AT91C_SMC_CSR3);
+
+ /* enable internal NAND controller */
+ value = readl(AT91C_EBI_CSA);
+ value |= AT91C_EBI_CS3A_SMC_SmartMedia;
+ writel(value, AT91C_EBI_CSA);
+
+ /* enable SMOE/SMWE */
+ writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_ASR);
+ writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_PDR);
+ writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_OER);
+
+ /* set NCE to high */
+ writel(KB9202_NAND_NCE, AT91C_PIOC_SODR);
+
+ /* disable output on pin connected to the busy line of the NAND */
+ writel(KB9202_NAND_BUSY, AT91C_PIOC_ODR);
+
+ /* enable the PIO to control NCE and BUSY */
+ writel(KB9202_NAND_NCE | KB9202_NAND_BUSY, AT91C_PIOC_PER);
+
+ /* enable output for NCE */
+ writel(KB9202_NAND_NCE, AT91C_PIOC_OER);
+
+ return (0);
+}
diff --git a/drivers/mtd/nand/kmeter1_nand.c b/drivers/mtd/nand/kmeter1_nand.c
new file mode 100644
index 0000000..e8e5b7b
--- /dev/null
+++ b/drivers/mtd/nand/kmeter1_nand.c
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2009
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <asm/io.h>
+
+#define CONFIG_NAND_MODE_REG (void *)(CONFIG_SYS_NAND_BASE + 0x20000)
+#define CONFIG_NAND_DATA_REG (void *)(CONFIG_SYS_NAND_BASE + 0x30000)
+
+#define read_mode() in_8(CONFIG_NAND_MODE_REG)
+#define write_mode(val) out_8(CONFIG_NAND_MODE_REG, val)
+#define read_data() in_8(CONFIG_NAND_DATA_REG)
+#define write_data(val) out_8(CONFIG_NAND_DATA_REG, val)
+
+#define KPN_RDY2 (1 << 7)
+#define KPN_RDY1 (1 << 6)
+#define KPN_WPN (1 << 4)
+#define KPN_CE2N (1 << 3)
+#define KPN_CE1N (1 << 2)
+#define KPN_ALE (1 << 1)
+#define KPN_CLE (1 << 0)
+
+#define KPN_DEFAULT_CHIP_DELAY 50
+
+static int kpn_chip_ready(void)
+{
+ if (read_mode() & KPN_RDY1)
+ return 1;
+
+ return 0;
+}
+
+static void kpn_wait_rdy(void)
+{
+ int cnt = 1000000;
+
+ while (--cnt && !kpn_chip_ready())
+ udelay(1);
+
+ if (!cnt)
+ printf ("timeout while waiting for RDY\n");
+}
+
+static void kpn_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ u8 reg_val = read_mode();
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ reg_val = reg_val & ~(KPN_ALE + KPN_CLE);
+
+ if (ctrl & NAND_CLE)
+ reg_val = reg_val | KPN_CLE;
+ if (ctrl & NAND_ALE)
+ reg_val = reg_val | KPN_ALE;
+ if (ctrl & NAND_NCE)
+ reg_val = reg_val & ~KPN_CE1N;
+ else
+ reg_val = reg_val | KPN_CE1N;
+
+ write_mode(reg_val);
+ }
+ if (cmd != NAND_CMD_NONE)
+ write_data(cmd);
+
+ /* wait until flash is ready */
+ kpn_wait_rdy();
+}
+
+static u_char kpn_nand_read_byte(struct mtd_info *mtd)
+{
+ return read_data();
+}
+
+static void kpn_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ write_data(buf[i]);
+ kpn_wait_rdy();
+ }
+}
+
+static void kpn_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = read_data();
+}
+
+static int kpn_nand_dev_ready(struct mtd_info *mtd)
+{
+ kpn_wait_rdy();
+
+ return 1;
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+ nand->ecc.mode = NAND_ECC_SOFT;
+
+ /* Reference hardware control function */
+ nand->cmd_ctrl = kpn_nand_hwcontrol;
+ nand->read_byte = kpn_nand_read_byte;
+ nand->write_buf = kpn_nand_write_buf;
+ nand->read_buf = kpn_nand_read_buf;
+ nand->dev_ready = kpn_nand_dev_ready;
+ nand->chip_delay = KPN_DEFAULT_CHIP_DELAY;
+
+ /* reset mode register */
+ write_mode(KPN_CE1N + KPN_CE2N + KPN_WPN);
+ return 0;
+}
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644
index 0000000..647be0b
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,880 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
+ * Copyright 2009 Ilya Yanok, <yanok@emcraft.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#ifdef CONFIG_MX27
+#include <asm/arch/imx-regs.h>
+#endif
+
+#define DRIVER_NAME "mxc_nand"
+
+struct nfc_regs {
+/* NFC RAM BUFFER Main area 0 */
+ uint8_t main_area0[0x200];
+ uint8_t main_area1[0x200];
+ uint8_t main_area2[0x200];
+ uint8_t main_area3[0x200];
+/* SPARE BUFFER Spare area 0 */
+ uint8_t spare_area0[0x10];
+ uint8_t spare_area1[0x10];
+ uint8_t spare_area2[0x10];
+ uint8_t spare_area3[0x10];
+ uint8_t pad[0x5c0];
+/* NFC registers */
+ uint16_t nfc_buf_size;
+ uint16_t reserved;
+ uint16_t nfc_buf_addr;
+ uint16_t nfc_flash_addr;
+ uint16_t nfc_flash_cmd;
+ uint16_t nfc_config;
+ uint16_t nfc_ecc_status_result;
+ uint16_t nfc_rsltmain_area;
+ uint16_t nfc_rsltspare_area;
+ uint16_t nfc_wrprot;
+ uint16_t nfc_unlockstart_blkaddr;
+ uint16_t nfc_unlockend_blkaddr;
+ uint16_t nfc_nf_wrprst;
+ uint16_t nfc_config1;
+ uint16_t nfc_config2;
+};
+
+/*
+ * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation
+ */
+#define NFC_CMD 0x1
+
+/*
+ * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation
+ */
+#define NFC_ADDR 0x2
+
+/*
+ * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation
+ */
+#define NFC_INPUT 0x4
+
+/*
+ * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation
+ */
+#define NFC_OUTPUT 0x8
+
+/*
+ * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation
+ */
+#define NFC_ID 0x10
+
+/*
+ * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation
+ */
+#define NFC_STATUS 0x20
+
+/*
+ * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation
+ */
+#define NFC_INT 0x8000
+
+#define NFC_SP_EN (1 << 2)
+#define NFC_ECC_EN (1 << 3)
+#define NFC_BIG (1 << 5)
+#define NFC_RST (1 << 6)
+#define NFC_CE (1 << 7)
+#define NFC_ONE_CYCLE (1 << 8)
+
+typedef enum {false, true} bool;
+
+struct mxc_nand_host {
+ struct mtd_info mtd;
+ struct nand_chip *nand;
+
+ struct nfc_regs __iomem *regs;
+ int spare_only;
+ int status_request;
+ int pagesize_2k;
+ int clk_act;
+ uint16_t col_addr;
+};
+
+static struct mxc_nand_host mxc_host;
+static struct mxc_nand_host *host = &mxc_host;
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY 2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x) ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+#ifdef CONFIG_MXC_NAND_HWECC
+static struct nand_ecclayout nand_hw_eccoob = {
+ .eccbytes = 5,
+ .eccpos = {6, 7, 8, 9, 10},
+ .oobfree = {{0, 5}, {11, 5}, }
+};
+#else
+static struct nand_ecclayout nand_soft_eccoob = {
+ .eccbytes = 6,
+ .eccpos = {6, 7, 8, 9, 10, 11},
+ .oobfree = {{0, 5}, {12, 4}, }
+};
+#endif
+
+static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size)
+{
+ uint32_t *d = dest;
+
+ size >>= 2;
+ while (size--)
+ __raw_writel(__raw_readl(source++), d++);
+ return dest;
+}
+
+/*
+ * This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+ uint16_t param)
+{
+ uint32_t tmp;
+
+ while (max_retries-- > 0) {
+ if (readw(&host->regs->nfc_config2) & NFC_INT) {
+ tmp = readw(&host->regs->nfc_config2);
+ tmp &= ~NFC_INT;
+ writew(tmp, &host->regs->nfc_config2);
+ break;
+ }
+ udelay(1);
+ }
+ if (max_retries < 0) {
+ MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+ __func__, param);
+ }
+}
+
+/*
+ * This function issues the specified command to the NAND device and
+ * waits for completion.
+ */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
+{
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
+
+ writew(cmd, &host->regs->nfc_flash_cmd);
+ writew(NFC_CMD, &host->regs->nfc_config2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, cmd);
+}
+
+/*
+ * This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command.
+ */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr)
+{
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
+
+ writew(addr, &host->regs->nfc_flash_addr);
+ writew(NFC_ADDR, &host->regs->nfc_config2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, addr);
+}
+
+/*
+ * This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device.
+ */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+ int spare_only)
+{
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+ writew(buf_id, &host->regs->nfc_buf_addr);
+
+ /* Configure spare or page+spare access */
+ if (!host->pagesize_2k) {
+ uint16_t config1 = readw(&host->regs->nfc_config1);
+ if (spare_only)
+ config1 |= NFC_SP_EN;
+ else
+ config1 &= ~(NFC_SP_EN);
+ writew(config1, &host->regs->nfc_config1);
+ }
+
+ writew(NFC_INPUT, &host->regs->nfc_config2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/*
+ * Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer.
+ */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+ int spare_only)
+{
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+ writew(buf_id, &host->regs->nfc_buf_addr);
+
+ /* Configure spare or page+spare access */
+ if (!host->pagesize_2k) {
+ uint32_t config1 = readw(&host->regs->nfc_config1);
+ if (spare_only)
+ config1 |= NFC_SP_EN;
+ else
+ config1 &= ~NFC_SP_EN;
+ writew(config1, &host->regs->nfc_config1);
+ }
+
+ writew(NFC_OUTPUT, &host->regs->nfc_config2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+ uint16_t tmp;
+
+ /* NANDFC buffer 0 is used for device ID output */
+ writew(0x0, &host->regs->nfc_buf_addr);
+
+ /* Read ID into main buffer */
+ tmp = readw(&host->regs->nfc_config1);
+ tmp &= ~NFC_SP_EN;
+ writew(tmp, &host->regs->nfc_config1);
+
+ writew(NFC_ID, &host->regs->nfc_config2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, 0);
+}
+
+/*
+ * This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status.
+ */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+ void __iomem *main_buf = host->regs->main_area1;
+ uint32_t store;
+ uint16_t ret, tmp;
+ /* Issue status request to NAND device */
+
+ /* store the main area1 first word, later do recovery */
+ store = readl(main_buf);
+ /* NANDFC buffer 1 is used for device status */
+ writew(1, &host->regs->nfc_buf_addr);
+
+ /* Read status into main buffer */
+ tmp = readw(&host->regs->nfc_config1);
+ tmp &= ~NFC_SP_EN;
+ writew(tmp, &host->regs->nfc_config1);
+
+ writew(NFC_STATUS, &host->regs->nfc_config2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, 0);
+
+ /*
+ * Status is placed in first word of main buffer
+ * get status, then recovery area 1 data
+ */
+ ret = readw(main_buf);
+ writel(store, main_buf);
+
+ return ret;
+}
+
+/* This function is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+ /*
+ * NFC handles R/B internally. Therefore, this function
+ * always returns status as ready.
+ */
+ return 1;
+}
+
+#ifdef CONFIG_MXC_NAND_HWECC
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+ /*
+ * If HW ECC is enabled, we turn it on during init. There is
+ * no need to enable again here.
+ */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+
+ /*
+ * 1-Bit errors are automatically corrected in HW. No need for
+ * additional correction. 2-Bit errors cannot be corrected by
+ * HW ECC, so we need to return failure
+ */
+ uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result);
+
+ if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+ MTDDEBUG(MTD_DEBUG_LEVEL0,
+ "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+ u_char *ecc_code)
+{
+ return 0;
+}
+#endif
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ uint8_t ret = 0;
+ uint16_t col;
+ uint16_t __iomem *main_buf =
+ (uint16_t __iomem *)host->regs->main_area0;
+ uint16_t __iomem *spare_buf =
+ (uint16_t __iomem *)host->regs->spare_area0;
+ union {
+ uint16_t word;
+ uint8_t bytes[2];
+ } nfc_word;
+
+ /* Check for status request */
+ if (host->status_request)
+ return get_dev_status(host) & 0xFF;
+
+ /* Get column for 16-bit access */
+ col = host->col_addr >> 1;
+
+ /* If we are accessing the spare region */
+ if (host->spare_only)
+ nfc_word.word = readw(&spare_buf[col]);
+ else
+ nfc_word.word = readw(&main_buf[col]);
+
+ /* Pick upper/lower byte of word from RAM buffer */
+ ret = nfc_word.bytes[host->col_addr & 0x1];
+
+ /* Update saved column address */
+ if (nand_chip->options & NAND_BUSWIDTH_16)
+ host->col_addr += 2;
+ else
+ host->col_addr++;
+
+ return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ uint16_t col, ret;
+ uint16_t __iomem *p;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+ col = host->col_addr;
+ /* Adjust saved column address */
+ if (col < mtd->writesize && host->spare_only)
+ col += mtd->writesize;
+
+ if (col < mtd->writesize) {
+ p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
+ } else {
+ p = (uint16_t __iomem *)(host->regs->spare_area0 +
+ ((col - mtd->writesize) >> 1));
+ }
+
+ if (col & 1) {
+ union {
+ uint16_t word;
+ uint8_t bytes[2];
+ } nfc_word[3];
+
+ nfc_word[0].word = readw(p);
+ nfc_word[1].word = readw(p + 1);
+
+ nfc_word[2].bytes[0] = nfc_word[0].bytes[1];
+ nfc_word[2].bytes[1] = nfc_word[1].bytes[0];
+
+ ret = nfc_word[2].word;
+ } else {
+ ret = readw(p);
+ }
+
+ /* Update saved column address */
+ host->col_addr = col + 2;
+
+ return ret;
+}
+
+/*
+ * Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash
+ */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ int n, col, i = 0;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+ len);
+
+ col = host->col_addr;
+
+ /* Adjust saved column address */
+ if (col < mtd->writesize && host->spare_only)
+ col += mtd->writesize;
+
+ n = mtd->writesize + mtd->oobsize - col;
+ n = min(len, n);
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3,
+ "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+ while (n > 0) {
+ void __iomem *p;
+
+ if (col < mtd->writesize) {
+ p = host->regs->main_area0 + (col & ~3);
+ } else {
+ p = host->regs->spare_area0 -
+ mtd->writesize + (col & ~3);
+ }
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+ __LINE__, p);
+
+ if (((col | (unsigned long)&buf[i]) & 3) || n < 4) {
+ union {
+ uint32_t word;
+ uint8_t bytes[4];
+ } nfc_word;
+
+ nfc_word.word = readl(p);
+ nfc_word.bytes[col & 3] = buf[i++];
+ n--;
+ col++;
+
+ writel(nfc_word.word, p);
+ } else {
+ int m = mtd->writesize - col;
+
+ if (col >= mtd->writesize)
+ m += mtd->oobsize;
+
+ m = min(n, m) & ~3;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3,
+ "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+ __func__, __LINE__, n, m, i, col);
+
+ mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m);
+ col += m;
+ i += m;
+ n -= m;
+ }
+ }
+ /* Update saved column address */
+ host->col_addr = col;
+}
+
+/*
+ * Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ int n, col, i = 0;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+ col = host->col_addr;
+
+ /* Adjust saved column address */
+ if (col < mtd->writesize && host->spare_only)
+ col += mtd->writesize;
+
+ n = mtd->writesize + mtd->oobsize - col;
+ n = min(len, n);
+
+ while (n > 0) {
+ void __iomem *p;
+
+ if (col < mtd->writesize) {
+ p = host->regs->main_area0 + (col & ~3);
+ } else {
+ p = host->regs->spare_area0 -
+ mtd->writesize + (col & ~3);
+ }
+
+ if (((col | (int)&buf[i]) & 3) || n < 4) {
+ union {
+ uint32_t word;
+ uint8_t bytes[4];
+ } nfc_word;
+
+ nfc_word.word = readl(p);
+ buf[i++] = nfc_word.bytes[col & 3];
+ n--;
+ col++;
+ } else {
+ int m = mtd->writesize - col;
+
+ if (col >= mtd->writesize)
+ m += mtd->oobsize;
+
+ m = min(n, m) & ~3;
+ mxc_nand_memcpy32((uint32_t *)&buf[i], p, m);
+
+ col += m;
+ i += m;
+ n -= m;
+ }
+ }
+ /* Update saved column address */
+ host->col_addr = col;
+}
+
+/*
+ * Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf.
+ */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ u_char tmp[256];
+ uint bsize;
+
+ while (len) {
+ bsize = min(len, 256);
+ mxc_nand_read_buf(mtd, tmp, bsize);
+
+ if (memcmp(buf, tmp, bsize))
+ return 1;
+
+ buf += bsize;
+ len -= bsize;
+ }
+
+ return 0;
+}
+
+/*
+ * This function is used by upper layer for select and
+ * deselect of the NAND chip
+ */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+
+ switch (chip) {
+ case -1:
+ /* TODO: Disable the NFC clock */
+ if (host->clk_act)
+ host->clk_act = 0;
+ break;
+ case 0:
+ /* TODO: Enable the NFC clock */
+ if (!host->clk_act)
+ host->clk_act = 1;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash
+ */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+ int column, int page_addr)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+ command, column, page_addr);
+
+ /* Reset command state information */
+ host->status_request = false;
+
+ /* Command pre-processing step */
+ switch (command) {
+
+ case NAND_CMD_STATUS:
+ host->col_addr = 0;
+ host->status_request = true;
+ break;
+
+ case NAND_CMD_READ0:
+ host->col_addr = column;
+ host->spare_only = false;
+ break;
+
+ case NAND_CMD_READOOB:
+ host->col_addr = column;
+ host->spare_only = true;
+ if (host->pagesize_2k)
+ command = NAND_CMD_READ0; /* only READ0 is valid */
+ break;
+
+ case NAND_CMD_SEQIN:
+ if (column >= mtd->writesize) {
+ /*
+ * before sending SEQIN command for partial write,
+ * we need read one page out. FSL NFC does not support
+ * partial write. It alway send out 512+ecc+512+ecc ...
+ * for large page nand flash. But for small page nand
+ * flash, it does support SPARE ONLY operation.
+ */
+ if (host->pagesize_2k) {
+ /* call ourself to read a page */
+ mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+ page_addr);
+ }
+
+ host->col_addr = column - mtd->writesize;
+ host->spare_only = true;
+
+ /* Set program pointer to spare region */
+ if (!host->pagesize_2k)
+ send_cmd(host, NAND_CMD_READOOB);
+ } else {
+ host->spare_only = false;
+ host->col_addr = column;
+
+ /* Set program pointer to page start */
+ if (!host->pagesize_2k)
+ send_cmd(host, NAND_CMD_READ0);
+ }
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ send_prog_page(host, 0, host->spare_only);
+
+ if (host->pagesize_2k) {
+ /* data in 4 areas datas */
+ send_prog_page(host, 1, host->spare_only);
+ send_prog_page(host, 2, host->spare_only);
+ send_prog_page(host, 3, host->spare_only);
+ }
+
+ break;
+ }
+
+ /* Write out the command to the device. */
+ send_cmd(host, command);
+
+ /* Write out column address, if necessary */
+ if (column != -1) {
+ /*
+ * MXC NANDFC can only perform full page+spare or
+ * spare-only read/write. When the upper layers
+ * layers perform a read/write buf operation,
+ * we will used the saved column adress to index into
+ * the full page.
+ */
+ send_addr(host, 0);
+ if (host->pagesize_2k)
+ /* another col addr cycle for 2k page */
+ send_addr(host, 0);
+ }
+
+ /* Write out page address, if necessary */
+ if (page_addr != -1) {
+ /* paddr_0 - p_addr_7 */
+ send_addr(host, (page_addr & 0xff));
+
+ if (host->pagesize_2k) {
+ send_addr(host, (page_addr >> 8) & 0xFF);
+ if (mtd->size >= 0x10000000) {
+ /* paddr_8 - paddr_15 */
+ send_addr(host, (page_addr >> 8) & 0xff);
+ send_addr(host, (page_addr >> 16) & 0xff);
+ } else {
+ /* paddr_8 - paddr_15 */
+ send_addr(host, (page_addr >> 8) & 0xff);
+ }
+ } else {
+ /* One more address cycle for higher density devices */
+ if (mtd->size >= 0x4000000) {
+ /* paddr_8 - paddr_15 */
+ send_addr(host, (page_addr >> 8) & 0xff);
+ send_addr(host, (page_addr >> 16) & 0xff);
+ } else {
+ /* paddr_8 - paddr_15 */
+ send_addr(host, (page_addr >> 8) & 0xff);
+ }
+ }
+ }
+
+ /* Command post-processing step */
+ switch (command) {
+
+ case NAND_CMD_RESET:
+ break;
+
+ case NAND_CMD_READOOB:
+ case NAND_CMD_READ0:
+ if (host->pagesize_2k) {
+ /* send read confirm command */
+ send_cmd(host, NAND_CMD_READSTART);
+ /* read for each AREA */
+ send_read_page(host, 0, host->spare_only);
+ send_read_page(host, 1, host->spare_only);
+ send_read_page(host, 2, host->spare_only);
+ send_read_page(host, 3, host->spare_only);
+ } else {
+ send_read_page(host, 0, host->spare_only);
+ }
+ break;
+
+ case NAND_CMD_READID:
+ host->col_addr = 0;
+ send_read_id(host);
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ break;
+
+ case NAND_CMD_STATUS:
+ break;
+
+ case NAND_CMD_ERASE2:
+ break;
+ }
+}
+
+int board_nand_init(struct nand_chip *this)
+{
+ struct system_control_regs *sc_regs =
+ (struct system_control_regs *)IMX_SYSTEM_CTL_BASE;
+ struct mtd_info *mtd;
+ uint16_t tmp;
+ int err = 0;
+
+ /* structures must be linked */
+ mtd = &host->mtd;
+ mtd->priv = this;
+ host->nand = this;
+
+ /* 5 us command delay time */
+ this->chip_delay = 5;
+
+ this->priv = host;
+ this->dev_ready = mxc_nand_dev_ready;
+ this->cmdfunc = mxc_nand_command;
+ this->select_chip = mxc_nand_select_chip;
+ this->read_byte = mxc_nand_read_byte;
+ this->read_word = mxc_nand_read_word;
+ this->write_buf = mxc_nand_write_buf;
+ this->read_buf = mxc_nand_read_buf;
+ this->verify_buf = mxc_nand_verify_buf;
+
+ host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+ host->clk_act = 1;
+
+#ifdef CONFIG_MXC_NAND_HWECC
+ this->ecc.calculate = mxc_nand_calculate_ecc;
+ this->ecc.hwctl = mxc_nand_enable_hwecc;
+ this->ecc.correct = mxc_nand_correct_data;
+ this->ecc.mode = NAND_ECC_HW;
+ this->ecc.size = 512;
+ this->ecc.bytes = 3;
+ this->ecc.layout = &nand_hw_eccoob;
+ tmp = readw(&host->regs->nfc_config1);
+ tmp |= NFC_ECC_EN;
+ writew(tmp, &host->regs->nfc_config1);
+#else
+ this->ecc.layout = &nand_soft_eccoob;
+ this->ecc.mode = NAND_ECC_SOFT;
+ tmp = readw(&host->regs->nfc_config1);
+ tmp &= ~NFC_ECC_EN;
+ writew(tmp, &host->regs->nfc_config1);
+#endif
+
+ /* Reset NAND */
+ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+ /*
+ * preset operation
+ * Unlock the internal RAM Buffer
+ */
+ writew(0x2, &host->regs->nfc_config);
+
+ /* Blocks to be unlocked */
+ writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
+ writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+
+ /* Unlock Block Command for given address range */
+ writew(0x4, &host->regs->nfc_wrprot);
+
+ /* NAND bus width determines access funtions used by upper layer */
+ if (readl(&sc_regs->fmcr) & NF_16BIT_SEL)
+ this->options |= NAND_BUSWIDTH_16;
+
+ host->pagesize_2k = 0;
+
+ return err;
+}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 360b070..426bb95 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -895,7 +895,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
* @buf: buffer to store read data
*/
static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf)
+ uint8_t *buf, int page)
{
chip->read_buf(mtd, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -909,7 +909,7 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @buf: buffer to store read data
*/
static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf)
+ uint8_t *buf, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -919,7 +919,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
- chip->ecc.read_page_raw(mtd, chip, buf);
+ chip->ecc.read_page_raw(mtd, chip, buf, page);
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
@@ -1032,7 +1032,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3
* Not for syndrome calculating ecc controllers which need a special oob layout
*/
static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf)
+ uint8_t *buf, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1068,6 +1068,54 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
+ * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ *
+ * Hardware ECC for large page chips, require OOB to be read first.
+ * For this ECC mode, the write_page method is re-used from ECC_HW.
+ * These methods read/write ECC from the OOB area, unlike the
+ * ECC_HW_SYNDROME support with multiple ECC steps, follows the
+ * "infix ECC" scheme and reads/writes ECC from the data area, by
+ * overwriting the NAND manufacturer bad block markings.
+ */
+static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
+ struct nand_chip *chip, uint8_t *buf, int page)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ uint8_t *ecc_code = chip->buffers->ecccode;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+
+ /* Read the OOB area first */
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+ for (i = 0; i < chip->ecc.total; i++)
+ ecc_code[i] = chip->oob_poi[eccpos[i]];
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ int stat;
+
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, eccsize);
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+
+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ }
+ return 0;
+}
+
+/**
* nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
* @mtd: mtd info structure
* @chip: nand chip info structure
@@ -1077,7 +1125,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* we need a special oob layout and handling.
*/
static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf)
+ uint8_t *buf, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1219,11 +1267,13 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Now read the page into the buffer */
if (unlikely(ops->mode == MTD_OOB_RAW))
- ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+ ret = chip->ecc.read_page_raw(mtd, chip,
+ bufpoi, page);
else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
else
- ret = chip->ecc.read_page(mtd, chip, bufpoi);
+ ret = chip->ecc.read_page(mtd, chip, bufpoi,
+ page);
if (ret < 0)
break;
@@ -2728,6 +2778,17 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.write_page_raw = nand_write_page_raw;
switch (chip->ecc.mode) {
+ case NAND_ECC_HW_OOB_FIRST:
+ /* Similar to NAND_ECC_HW, but a separate read_page handle */
+ if (!chip->ecc.calculate || !chip->ecc.correct ||
+ !chip->ecc.hwctl) {
+ printk(KERN_WARNING "No ECC functions supplied, "
+ "Hardware ECC not possible\n");
+ BUG();
+ }
+ if (!chip->ecc.read_page)
+ chip->ecc.read_page = nand_read_page_hwecc_oob_first;
+
case NAND_ECC_HW:
/* Use standard hwecc read page function ? */
if (!chip->ecc.read_page)
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index d482437..368fa6e 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1010,7 +1010,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
if (ret)
break;
- this->read_spareram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
+ this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
read += thislen;
if (read == len)
break;
@@ -2104,8 +2104,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
if (!this->read_bufferram)
this->read_bufferram = onenand_read_bufferram;
- if (!this->read_spareram)
- this->read_spareram = onenand_read_bufferram;
if (!this->write_bufferram)
this->write_bufferram = onenand_write_bufferram;
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 1c6e402..f6e9f67 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -30,7 +30,7 @@ COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o
COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o
-COBJS-$(CONFIG_DRIVER_CS8900) += cs8900.o
+COBJS-$(CONFIG_CS8900) += cs8900.o
COBJS-$(CONFIG_TULIP) += dc2114x.o
COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o
COBJS-$(CONFIG_DNET) += dnet.o
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 12d98c2..ec45b63 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -186,6 +186,9 @@ static int bfin_EMAC_recv(struct eth_device *dev)
printf("Ethernet: bad frame\n");
break;
}
+
+ debug("%s: len = %d\n", __func__, length - 4);
+
NetRxPackets[rxIdx] =
(volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest);
NetReceive(NetRxPackets[rxIdx], length - 4);
diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c
index 5e2b3b0..587f7f6 100644
--- a/drivers/net/cs8900.c
+++ b/drivers/net/cs8900.c
@@ -1,6 +1,9 @@
/*
* Cirrus Logic CS8900A Ethernet
*
+ * (C) 2009 Ben Warren , biggerbadderben@gmail.com
+ * Converted to use CONFIG_NET_MULTI API
+ *
* (C) 2003 Wolfgang Denk, wd@denx.de
* Extension to synchronize ethaddr environment variable
* against value in EEPROM
@@ -38,220 +41,229 @@
#include <common.h>
#include <command.h>
-#include "cs8900.h"
+#include <asm/io.h>
#include <net.h>
+#include <malloc.h>
+#include "cs8900.h"
#undef DEBUG
/* packet page register access functions */
-#ifdef CS8900_BUS32
+#ifdef CONFIG_CS8900_BUS32
+
+#define REG_WRITE(v, a) writel((v),(a))
+#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))
+
#else
-static unsigned short get_reg_init_bus (int regno)
-{
- /* force 16 bit busmode */
- volatile unsigned char c;
- c = CS8900_BUS16_0;
- c = CS8900_BUS16_1;
- c = CS8900_BUS16_0;
- c = CS8900_BUS16_1;
- c = CS8900_BUS16_0;
+#define REG_WRITE(v, a) writew((v),(a))
+#define REG_READ(a) readw((a))
- CS8900_PPTR = regno;
- return CS8900_PDATA;
+static u16 get_reg_init_bus(struct eth_device *dev, int regno)
+{
+ /* force 16 bit busmode */
+ volatile u8 c;
+ struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
+ uint8_t volatile * const iob = (uint8_t volatile * const)dev->iobase;
+
+ c = readb(iob);
+ c = readb(iob + 1);
+ c = readb(iob);
+ c = readb(iob + 1);
+ c = readb(iob);
+
+ REG_WRITE(regno, &priv->regs->pptr);
+ return REG_READ(&priv->regs->pdata);
}
#endif
-static unsigned short get_reg (int regno)
+static u16 get_reg(struct eth_device *dev, int regno)
{
- CS8900_PPTR = regno;
- return CS8900_PDATA;
+ struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
+ REG_WRITE(regno, &priv->regs->pptr);
+ return REG_READ(&priv->regs->pdata);
}
-static void put_reg (int regno, unsigned short val)
+static void put_reg(struct eth_device *dev, int regno, u16 val)
{
- CS8900_PPTR = regno;
- CS8900_PDATA = val;
+ struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
+ REG_WRITE(regno, &priv->regs->pptr);
+ REG_WRITE(val, &priv->regs->pdata);
}
-static void eth_reset (void)
+static void cs8900_reset(struct eth_device *dev)
{
int tmo;
- unsigned short us;
+ u16 us;
/* reset NIC */
- put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset);
+ put_reg(dev, PP_SelfCTL, get_reg(dev, PP_SelfCTL) | PP_SelfCTL_Reset);
/* wait for 200ms */
- udelay (200000);
+ udelay(200000);
/* Wait until the chip is reset */
- tmo = get_timer (0) + 1 * CONFIG_SYS_HZ;
- while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0)
- && tmo < get_timer (0))
+ tmo = get_timer(0) + 1 * CONFIG_SYS_HZ;
+ while ((((us = get_reg_init_bus(dev, PP_SelfSTAT)) &
+ PP_SelfSTAT_InitD) == 0) && tmo < get_timer(0))
/*NOP*/;
}
-static void eth_reginit (void)
+static void cs8900_reginit(struct eth_device *dev)
{
/* receive only error free packets addressed to this card */
- put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);
+ put_reg(dev, PP_RxCTL,
+ PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);
/* do not generate any interrupts on receive operations */
- put_reg (PP_RxCFG, 0);
+ put_reg(dev, PP_RxCFG, 0);
/* do not generate any interrupts on transmit operations */
- put_reg (PP_TxCFG, 0);
+ put_reg(dev, PP_TxCFG, 0);
/* do not generate any interrupts on buffer operations */
- put_reg (PP_BufCFG, 0);
+ put_reg(dev, PP_BufCFG, 0);
/* enable transmitter/receiver mode */
- put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
+ put_reg(dev, PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
}
-void cs8900_get_enetaddr (void)
+void cs8900_get_enetaddr(struct eth_device *dev)
{
int i;
- uchar enetaddr[6];
-
- /* if the env is setup, then bail */
- if (eth_getenv_enetaddr("ethaddr", enetaddr))
- return;
/* verify chip id */
- if (get_reg_init_bus (PP_ChipID) != 0x630e)
+ if (get_reg_init_bus(dev, PP_ChipID) != 0x630e)
return;
- eth_reset ();
- if ((get_reg (PP_SelfSTAT) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
- (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) {
+ cs8900_reset(dev);
+ if ((get_reg(dev, PP_SelfSTAT) &
+ (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
+ (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) {
/* Load the MAC from EEPROM */
- for (i = 0; i < 6 / 2; i++) {
- unsigned int Addr;
+ for (i = 0; i < 3; i++) {
+ u32 Addr;
- Addr = get_reg (PP_IA + i * 2);
- enetaddr[i * 2] = Addr & 0xFF;
- enetaddr[i * 2 + 1] = Addr >> 8;
+ Addr = get_reg(dev, PP_IA + i * 2);
+ dev->enetaddr[i * 2] = Addr & 0xFF;
+ dev->enetaddr[i * 2 + 1] = Addr >> 8;
}
-
- eth_setenv_enetaddr("ethaddr", enetaddr);
- debug("### Set environment from HW MAC addr = \"%pM\"\n", enetaddr);
}
}
-void eth_halt (void)
+void cs8900_halt(struct eth_device *dev)
{
/* disable transmitter/receiver mode */
- put_reg (PP_LineCTL, 0);
+ put_reg(dev, PP_LineCTL, 0);
/* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */
- get_reg_init_bus (PP_ChipID);
+ get_reg_init_bus(dev, PP_ChipID);
}
-int eth_init (bd_t * bd)
+static int cs8900_init(struct eth_device *dev, bd_t * bd)
{
- uchar enetaddr[6];
+ uchar *enetaddr = dev->enetaddr;
+ u16 id;
/* verify chip id */
- if (get_reg_init_bus (PP_ChipID) != 0x630e) {
- printf ("CS8900 Ethernet chip not found?!\n");
- return 0;
+ id = get_reg_init_bus(dev, PP_ChipID);
+ if (id != 0x630e) {
+ printf ("CS8900 Ethernet chip not found: "
+ "ID=0x%04x instead 0x%04x\n", id, 0x630e);
+ return 1;
}
- eth_reset ();
+ cs8900_reset (dev);
/* set the ethernet address */
- eth_getenv_enetaddr("ethaddr", enetaddr);
- put_reg (PP_IA + 0, enetaddr[0] | (enetaddr[1] << 8));
- put_reg (PP_IA + 2, enetaddr[2] | (enetaddr[3] << 8));
- put_reg (PP_IA + 4, enetaddr[4] | (enetaddr[5] << 8));
+ put_reg(dev, PP_IA + 0, enetaddr[0] | (enetaddr[1] << 8));
+ put_reg(dev, PP_IA + 2, enetaddr[2] | (enetaddr[3] << 8));
+ put_reg(dev, PP_IA + 4, enetaddr[4] | (enetaddr[5] << 8));
- eth_reginit ();
+ cs8900_reginit(dev);
return 0;
}
/* Get a data block via Ethernet */
-int eth_rx (void)
+static int cs8900_recv(struct eth_device *dev)
{
int i;
- unsigned short rxlen;
- unsigned short *addr;
- unsigned short status;
+ u16 rxlen;
+ u16 *addr;
+ u16 status;
- status = get_reg (PP_RER);
+ struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
+
+ status = get_reg(dev, PP_RER);
if ((status & PP_RER_RxOK) == 0)
return 0;
- status = CS8900_RTDATA; /* stat */
- rxlen = CS8900_RTDATA; /* len */
+ status = REG_READ(&priv->regs->rtdata);
+ rxlen = REG_READ(&priv->regs->rtdata);
-#ifdef DEBUG
if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
- printf ("packet too big!\n");
-#endif
- for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0;
+ debug("packet too big!\n");
+ for (addr = (u16 *) NetRxPackets[0], i = rxlen >> 1; i > 0;
i--)
- *addr++ = CS8900_RTDATA;
+ *addr++ = REG_READ(&priv->regs->rtdata);
if (rxlen & 1)
- *addr++ = CS8900_RTDATA;
+ *addr++ = REG_READ(&priv->regs->rtdata);
/* Pass the packet up to the protocol layers. */
NetReceive (NetRxPackets[0], rxlen);
-
return rxlen;
}
/* Send a data block via Ethernet. */
-int eth_send (volatile void *packet, int length)
+static int cs8900_send(struct eth_device *dev,
+ volatile void *packet, int length)
{
- volatile unsigned short *addr;
+ volatile u16 *addr;
int tmo;
- unsigned short s;
+ u16 s;
+ struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
retry:
/* initiate a transmit sequence */
- CS8900_TxCMD = PP_TxCmd_TxStart_Full;
- CS8900_TxLEN = length;
+ REG_WRITE(PP_TxCmd_TxStart_Full, &priv->regs->txcmd);
+ REG_WRITE(length, &priv->regs->txlen);
/* Test to see if the chip has allocated memory for the packet */
- if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
+ if ((get_reg(dev, PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
/* Oops... this should not happen! */
-#ifdef DEBUG
- printf ("cs: unable to send packet; retrying...\n");
-#endif
- for (tmo = get_timer (0) + 5 * CONFIG_SYS_HZ; get_timer (0) < tmo;)
+ debug("cs: unable to send packet; retrying...\n");
+ for (tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
+ get_timer(0) < tmo;)
/*NOP*/;
- eth_reset ();
- eth_reginit ();
+ cs8900_reset(dev);
+ cs8900_reginit(dev);
goto retry;
}
/* Write the contents of the packet */
/* assume even number of bytes */
for (addr = packet; length > 0; length -= 2)
- CS8900_RTDATA = *addr++;
+ REG_WRITE(*addr++, &priv->regs->rtdata);
/* wait for transfer to succeed */
- tmo = get_timer (0) + 5 * CONFIG_SYS_HZ;
- while ((s = get_reg (PP_TER) & ~0x1F) == 0) {
- if (get_timer (0) >= tmo)
+ tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
+ while ((s = get_reg(dev, PP_TER) & ~0x1F) == 0) {
+ if (get_timer(0) >= tmo)
break;
}
/* nothing */ ;
- if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {
-#ifdef DEBUG
- printf ("\ntransmission error %#x\n", s);
-#endif
+ if((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {
+ debug("\ntransmission error %#x\n", s);
}
return 0;
}
-static void cs8900_e2prom_ready(void)
+static void cs8900_e2prom_ready(struct eth_device *dev)
{
- while (get_reg(PP_SelfSTAT) & SI_BUSY)
+ while (get_reg(dev, PP_SelfSTAT) & SI_BUSY)
;
}
@@ -259,12 +271,13 @@ static void cs8900_e2prom_ready(void)
/* read a 16-bit word out of the EEPROM */
/***********************************************************/
-int cs8900_e2prom_read(unsigned char addr, unsigned short *value)
+int cs8900_e2prom_read(struct eth_device *dev,
+ u8 addr, u16 *value)
{
- cs8900_e2prom_ready();
- put_reg(PP_EECMD, EEPROM_READ_CMD | addr);
- cs8900_e2prom_ready();
- *value = get_reg(PP_EEData);
+ cs8900_e2prom_ready(dev);
+ put_reg(dev, PP_EECMD, EEPROM_READ_CMD | addr);
+ cs8900_e2prom_ready(dev);
+ *value = get_reg(dev, PP_EEData);
return 0;
}
@@ -274,16 +287,51 @@ int cs8900_e2prom_read(unsigned char addr, unsigned short *value)
/* write a 16-bit word into the EEPROM */
/***********************************************************/
-int cs8900_e2prom_write(unsigned char addr, unsigned short value)
+int cs8900_e2prom_write(struct eth_device *dev, u8 addr, u16 value)
+{
+ cs8900_e2prom_ready(dev);
+ put_reg(dev, PP_EECMD, EEPROM_WRITE_EN);
+ cs8900_e2prom_ready(dev);
+ put_reg(dev, PP_EEData, value);
+ put_reg(dev, PP_EECMD, EEPROM_WRITE_CMD | addr);
+ cs8900_e2prom_ready(dev);
+ put_reg(dev, PP_EECMD, EEPROM_WRITE_DIS);
+ cs8900_e2prom_ready(dev);
+
+ return 0;
+}
+
+int cs8900_initialize(u8 dev_num, int base_addr)
{
- cs8900_e2prom_ready();
- put_reg(PP_EECMD, EEPROM_WRITE_EN);
- cs8900_e2prom_ready();
- put_reg(PP_EEData, value);
- put_reg(PP_EECMD, EEPROM_WRITE_CMD | addr);
- cs8900_e2prom_ready();
- put_reg(PP_EECMD, EEPROM_WRITE_DIS);
- cs8900_e2prom_ready();
+ struct eth_device *dev;
+ struct cs8900_priv *priv;
+
+ dev = malloc(sizeof(*dev));
+ if (!dev) {
+ free(dev);
+ return 0;
+ }
+ memset(dev, 0, sizeof(*dev));
+
+ priv = malloc(sizeof(*priv));
+ if (!priv) {
+ free(priv);
+ return 0;
+ }
+ 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;
+ sprintf(dev->name, "%s-%hu", CS8900_DRIVERNAME, dev_num);
+ eth_register(dev);
return 0;
}
diff --git a/drivers/net/cs8900.h b/drivers/net/cs8900.h
index f9c32dd..23c5cb0 100644
--- a/drivers/net/cs8900.h
+++ b/drivers/net/cs8900.h
@@ -1,6 +1,11 @@
+#ifndef CS8900_H
+#define CS8900_H
/*
* Cirrus Logic CS8900A Ethernet
*
+ * (C) 2009 Ben Warren , biggerbadderben@gmail.com
+ * Converted to use CONFIG_NET_MULTI API
+ *
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
@@ -35,33 +40,34 @@
#include <asm/types.h>
#include <config.h>
-#ifdef CONFIG_DRIVER_CS8900
-
+#define CS8900_DRIVERNAME "CS8900"
/* although the registers are 16 bit, they are 32-bit aligned on the
EDB7111. so we have to read them as 32-bit registers and ignore the
upper 16-bits. i'm not sure if this holds for the EDB7211. */
-#ifdef CS8900_BUS16
+#ifdef CONFIG_CS8900_BUS16
/* 16 bit aligned registers, 16 bit wide */
#define CS8900_REG u16
- #define CS8900_OFF 0x02
- #define CS8900_BUS16_0 *(volatile u8 *)(CS8900_BASE+0x00)
- #define CS8900_BUS16_1 *(volatile u8 *)(CS8900_BASE+0x01)
-#elif defined(CS8900_BUS32)
+#elif defined(CONFIG_CS8900_BUS32)
/* 32 bit aligned registers, 16 bit wide (we ignore upper 16 bits) */
#define CS8900_REG u32
- #define CS8900_OFF 0x04
#else
#error unknown bussize ...
#endif
-#define CS8900_RTDATA *(volatile CS8900_REG *)(CS8900_BASE+0x00*CS8900_OFF)
-#define CS8900_TxCMD *(volatile CS8900_REG *)(CS8900_BASE+0x02*CS8900_OFF)
-#define CS8900_TxLEN *(volatile CS8900_REG *)(CS8900_BASE+0x03*CS8900_OFF)
-#define CS8900_ISQ *(volatile CS8900_REG *)(CS8900_BASE+0x04*CS8900_OFF)
-#define CS8900_PPTR *(volatile CS8900_REG *)(CS8900_BASE+0x05*CS8900_OFF)
-#define CS8900_PDATA *(volatile CS8900_REG *)(CS8900_BASE+0x06*CS8900_OFF)
+struct cs8900_regs {
+ CS8900_REG rtdata;
+ CS8900_REG pad0;
+ CS8900_REG txcmd;
+ CS8900_REG txlen;
+ CS8900_REG isq;
+ CS8900_REG pptr;
+ CS8900_REG pdata;
+};
+struct cs8900_priv {
+ struct cs8900_regs *regs;
+};
#define ISQ_RxEvent 0x04
#define ISQ_TxEvent 0x08
@@ -251,7 +257,8 @@
#define EEPROM_READ_CMD 0x0200
#define EEPROM_ERASE_CMD 0x0300
-extern int cs8900_e2prom_read(uchar, ushort *);
-extern int cs8900_e2prom_write(uchar, ushort);
+/* Exported functions */
+int cs8900_e2prom_read(struct eth_device *dev, uchar, ushort *);
+int cs8900_e2prom_write(struct eth_device *dev, uchar, ushort);
-#endif /* CONFIG_DRIVER_CS8900 */
+#endif /* CS8900_H */
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 9c9fd37..5c3d261 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -17,6 +17,7 @@
#include <net.h>
#include <command.h>
#include <tsec.h>
+#include <asm/errno.h>
#include "miiphy.h"
@@ -380,6 +381,12 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
return 0;
}
+ if (ctrlc()) {
+ puts("user interrupt!\n");
+ priv->link = 0;
+ return -EINTR;
+ }
+
if ((i++ % 1000) == 0) {
putc('.');
}
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 19cf1ce..885542c 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -35,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR;
*/
#include <pci.h>
+#include <asm/io.h>
#include <asm/fsl_pci.h>
/* Freescale-specific PCI config registers */
@@ -60,35 +61,98 @@ void pciauto_config_init(struct pci_controller *hose);
#define CONFIG_SYS_PCI64_MEMORY_BUS (64ull*1024*1024*1024)
#endif
-int fsl_pci_setup_inbound_windows(struct pci_region *r)
+/* Setup one inbound ATMU window.
+ *
+ * We let the caller decide what the window size should be
+ */
+static void set_inbound_window(volatile pit_t *pi,
+ struct pci_region *r,
+ u64 size)
+{
+ u32 sz = (__ilog2_u64(size) - 1);
+ u32 flag = PIWAR_EN | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
+
+ out_be32(&pi->pitar, r->phys_start >> 12);
+ out_be32(&pi->piwbar, r->bus_start >> 12);
+#ifdef CONFIG_SYS_PCI_64BIT
+ out_be32(&pi->piwbear, r->bus_start >> 44);
+#else
+ out_be32(&pi->piwbear, 0);
+#endif
+ if (r->flags & PCI_REGION_PREFETCH)
+ flag |= PIWAR_PF;
+ out_be32(&pi->piwar, flag | sz);
+}
+
+static int fsl_pci_setup_inbound_windows(struct pci_controller *hose,
+ u64 out_lo, u8 pcie_cap,
+ volatile pit_t *pi)
{
- struct pci_region *rgn_base = r;
- u64 sz = min((u64)gd->ram_size, (1ull << 32) - 1);
+ struct pci_region *r = hose->regions + hose->region_count;
+ u64 sz = min((u64)gd->ram_size, (1ull << 32));
phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS;
pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS;
- pci_size_t pci_sz = 1ull << __ilog2_u64(sz);
+ pci_size_t pci_sz;
- debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
- (u64)bus_start, (u64)phys_start, (u64)pci_sz);
- pci_set_region(r++, bus_start, phys_start, pci_sz,
- PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
- PCI_REGION_PREFETCH);
+ /* we have no space available for inbound memory mapping */
+ if (bus_start > out_lo) {
+ printf ("no space for inbound mapping of memory\n");
+ return 0;
+ }
- sz -= pci_sz;
- bus_start += pci_sz;
- phys_start += pci_sz;
+ /* limit size */
+ if ((bus_start + sz) > out_lo) {
+ sz = out_lo - bus_start;
+ debug ("limiting size to %llx\n", sz);
+ }
pci_sz = 1ull << __ilog2_u64(sz);
- if (sz) {
- debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n",
+ /*
+ * we can overlap inbound/outbound windows on PCI-E since RX & TX
+ * links a separate
+ */
+ if ((pcie_cap == PCI_CAP_ID_EXP) && (pci_sz < sz)) {
+ debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
+ (u64)bus_start, (u64)phys_start, (u64)sz);
+ pci_set_region(r, bus_start, phys_start, sz,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
+ PCI_REGION_PREFETCH);
+
+ /* if we aren't an exact power of two match, pci_sz is smaller
+ * round it up to the next power of two. We report the actual
+ * size to pci region tracking.
+ */
+ if (pci_sz != sz)
+ sz = 2ull << __ilog2_u64(sz);
+
+ set_inbound_window(pi--, r++, sz);
+ sz = 0; /* make sure we dont set the R2 window */
+ } else {
+ debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
(u64)bus_start, (u64)phys_start, (u64)pci_sz);
- pci_set_region(r++, bus_start, phys_start, pci_sz,
+ pci_set_region(r, bus_start, phys_start, pci_sz,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
PCI_REGION_PREFETCH);
+ set_inbound_window(pi--, r++, pci_sz);
+
sz -= pci_sz;
bus_start += pci_sz;
phys_start += pci_sz;
+
+ pci_sz = 1ull << __ilog2_u64(sz);
+ if (sz) {
+ debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n",
+ (u64)bus_start, (u64)phys_start, (u64)pci_sz);
+ pci_set_region(r, bus_start, phys_start, pci_sz,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
+ PCI_REGION_PREFETCH);
+ set_inbound_window(pi--, r++, pci_sz);
+ sz -= pci_sz;
+ bus_start += pci_sz;
+ phys_start += pci_sz;
+ }
}
#if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT)
@@ -104,23 +168,25 @@ int fsl_pci_setup_inbound_windows(struct pci_region *r)
(u64)CONFIG_SYS_PCI64_MEMORY_BUS,
(u64)CONFIG_SYS_PCI_MEMORY_PHYS,
(u64)pci_sz);
- pci_set_region(r++,
+ pci_set_region(r,
CONFIG_SYS_PCI64_MEMORY_BUS,
CONFIG_SYS_PCI_MEMORY_PHYS,
pci_sz,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
PCI_REGION_PREFETCH);
+ set_inbound_window(pi--, r++, pci_sz);
#else
pci_sz = 1ull << __ilog2_u64(sz);
if (sz) {
debug ("R2 bus_start: %llx phys_start: %llx size: %llx\n",
(u64)bus_start, (u64)phys_start, (u64)pci_sz);
- pci_set_region(r++, bus_start, phys_start, pci_sz,
+ pci_set_region(r, bus_start, phys_start, pci_sz,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
PCI_REGION_PREFETCH);
sz -= pci_sz;
bus_start += pci_sz;
phys_start += pci_sz;
+ set_inbound_window(pi--, r++, pci_sz);
}
#endif
@@ -130,99 +196,129 @@ int fsl_pci_setup_inbound_windows(struct pci_region *r)
"inbound windows -- %lld remaining\n", sz);
#endif
- return r - rgn_base;
+ hose->region_count = r - hose->regions;
+
+ return 1;
}
-void fsl_pci_init(struct pci_controller *hose)
+void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data)
{
u16 temp16;
u32 temp32;
- int busno = hose->first_busno;
- int enabled;
+ int enabled, r, inbound = 0;
u16 ltssm;
- u8 temp8;
- int r;
- int bridge;
- int inbound = 0;
- volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) hose->cfg_addr;
- pci_dev_t dev = PCI_BDF(busno,0,0);
+ u8 temp8, pcie_cap;
+ volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr;
+ struct pci_region *reg = hose->regions + hose->region_count;
+ pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0);
/* Initialize ATMU registers based on hose regions and flags */
volatile pot_t *po = &pci->pot[1]; /* skip 0 */
- volatile pit_t *pi = &pci->pit[0]; /* ranges from: 3 to 1 */
+ volatile pit_t *pi = &pci->pit[2]; /* ranges from: 3 to 1 */
+
+ u64 out_hi = 0, out_lo = -1ULL;
+ u32 pcicsrbar, pcicsrbar_sz;
#ifdef DEBUG
int neg_link_w;
#endif
- for (r=0; r<hose->region_count; r++) {
+ pci_setup_indirect(hose, cfg_addr, cfg_data);
+
+ /* Handle setup of outbound windows first */
+ for (r = 0; r < hose->region_count; r++) {
+ unsigned long flags = hose->regions[r].flags;
u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1);
- if (hose->regions[r].flags & PCI_REGION_SYS_MEMORY) { /* inbound */
- u32 flag = PIWAR_EN | PIWAR_LOCAL |
- PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
- pi->pitar = (hose->regions[r].phys_start >> 12);
- pi->piwbar = (hose->regions[r].bus_start >> 12);
-#ifdef CONFIG_SYS_PCI_64BIT
- pi->piwbear = (hose->regions[r].bus_start >> 44);
-#else
- pi->piwbear = 0;
-#endif
- if (hose->regions[r].flags & PCI_REGION_PREFETCH)
- flag |= PIWAR_PF;
- pi->piwar = flag | sz;
- pi++;
- inbound = hose->regions[r].size > 0;
- } else { /* Outbound */
- po->powbar = (hose->regions[r].phys_start >> 12);
- po->potar = (hose->regions[r].bus_start >> 12);
+
+ flags &= PCI_REGION_SYS_MEMORY|PCI_REGION_TYPE;
+ if (flags != PCI_REGION_SYS_MEMORY) {
+ u64 start = hose->regions[r].bus_start;
+ u64 end = start + hose->regions[r].size;
+
+ out_be32(&po->powbar, hose->regions[r].phys_start >> 12);
+ out_be32(&po->potar, start >> 12);
#ifdef CONFIG_SYS_PCI_64BIT
- po->potear = (hose->regions[r].bus_start >> 44);
+ out_be32(&po->potear, start >> 44);
#else
- po->potear = 0;
+ out_be32(&po->potear, 0);
#endif
- if (hose->regions[r].flags & PCI_REGION_IO)
- po->powar = POWAR_EN | sz |
- POWAR_IO_READ | POWAR_IO_WRITE;
- else
- po->powar = POWAR_EN | sz |
- POWAR_MEM_READ | POWAR_MEM_WRITE;
+ if (hose->regions[r].flags & PCI_REGION_IO) {
+ out_be32(&po->powar, POWAR_EN | sz |
+ POWAR_IO_READ | POWAR_IO_WRITE);
+ } else {
+ out_be32(&po->powar, POWAR_EN | sz |
+ POWAR_MEM_READ | POWAR_MEM_WRITE);
+ out_lo = min(start, out_lo);
+ out_hi = max(end, out_hi);
+ }
po++;
}
}
+ debug("Outbound memory range: %llx:%llx\n", out_lo, out_hi);
+
+ /* setup PCSRBAR/PEXCSRBAR */
+ pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff);
+ pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pcicsrbar_sz);
+ pcicsrbar_sz = ~pcicsrbar_sz + 1;
+
+ if (out_hi < (0x100000000ull - pcicsrbar_sz) ||
+ (out_lo > 0x100000000ull))
+ pcicsrbar = 0x100000000ull - pcicsrbar_sz;
+ else
+ pcicsrbar = (out_lo - pcicsrbar_sz) & -pcicsrbar_sz;
+ pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, pcicsrbar);
+
+ out_lo = min(out_lo, (u64)pcicsrbar);
+
+ debug("PCICSRBAR @ 0x%x\n", pcicsrbar);
+
+ pci_set_region(reg++, pcicsrbar, CONFIG_SYS_CCSRBAR_PHYS,
+ pcicsrbar_sz, PCI_REGION_SYS_MEMORY);
+ hose->region_count++;
+
+ /* see if we are a PCIe or PCI controller */
+ pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
+
+ /* inbound */
+ inbound = fsl_pci_setup_inbound_windows(hose, out_lo, pcie_cap, pi);
+
+ for (r = 0; r < hose->region_count; r++)
+ debug("PCI reg:%d %016llx:%016llx %016llx %08x\n", r,
+ (u64)hose->regions[r].phys_start,
+ hose->regions[r].bus_start,
+ hose->regions[r].size,
+ hose->regions[r].flags);
pci_register_hose(hose);
pciauto_config_init(hose); /* grab pci_{mem,prefetch,io} */
hose->current_busno = hose->first_busno;
- pci->pedr = 0xffffffff; /* Clear any errors */
- pci->peer = ~0x20140; /* Enable All Error Interupts except
+ out_be32(&pci->pedr, 0xffffffff); /* Clear any errors */
+ out_be32(&pci->peer, ~0x20140); /* Enable All Error Interupts except
* - Master abort (pci)
* - Master PERR (pci)
* - ICCA (PCIe)
*/
- pci_hose_read_config_dword (hose, dev, PCI_DCR, &temp32);
+ pci_hose_read_config_dword(hose, dev, PCI_DCR, &temp32);
temp32 |= 0xf000e; /* set URR, FER, NFER (but not CER) */
pci_hose_write_config_dword(hose, dev, PCI_DCR, temp32);
- pci_hose_read_config_byte (hose, dev, PCI_HEADER_TYPE, &temp8);
- bridge = temp8 & PCI_HEADER_TYPE_BRIDGE; /* Bridge, such as pcie */
-
- if ( bridge ) {
-
+ if (pcie_cap == PCI_CAP_ID_EXP) {
pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
enabled = ltssm >= PCI_LTSSM_L0;
#ifdef CONFIG_FSL_PCIE_RESET
if (ltssm == 1) {
int i;
- debug("....PCIe link error. "
- "LTSSM=0x%02x.", ltssm);
- pci->pdb_stat |= 0x08000000; /* assert PCIe reset */
- temp32 = pci->pdb_stat;
+ debug("....PCIe link error. " "LTSSM=0x%02x.", ltssm);
+ /* assert PCIe reset */
+ setbits_be32(&pci->pdb_stat, 0x08000000);
+ (void) in_be32(&pci->pdb_stat);
udelay(100);
debug(" Asserting PCIe reset @%x = %x\n",
- &pci->pdb_stat, pci->pdb_stat);
- pci->pdb_stat &= ~0x08000000; /* clear reset */
+ &pci->pdb_stat, in_be32(&pci->pdb_stat));
+ /* clear PCIe reset */
+ clrbits_be32(&pci->pdb_stat, 0x08000000);
asm("sync;isync");
for (i=0; i<100 && ltssm < PCI_LTSSM_L0; i++) {
pci_hose_read_config_word(hose, dev, PCI_LTSSM,
@@ -232,6 +328,12 @@ void fsl_pci_init(struct pci_controller *hose)
"LTSSM=0x%02x.\n", ltssm);
}
enabled = ltssm >= PCI_LTSSM_L0;
+
+ /* we need to re-write the bar0 since a reset will
+ * clear it
+ */
+ pci_hose_write_config_dword(hose, dev,
+ PCI_BASE_ADDRESS_0, pcicsrbar);
}
#endif
@@ -242,8 +344,8 @@ void fsl_pci_init(struct pci_controller *hose)
return;
}
- pci->pme_msg_det = 0xffffffff;
- pci->pme_msg_int_en = 0xffffffff;
+ out_be32(&pci->pme_msg_det, 0xffffffff);
+ out_be32(&pci->pme_msg_int_en, 0xffffffff);
#ifdef DEBUG
pci_hose_read_config_word(hose, dev, PCI_LSR, &temp16);
neg_link_w = (temp16 & 0x3f0 ) >> 4;
@@ -252,14 +354,12 @@ void fsl_pci_init(struct pci_controller *hose)
#endif
hose->current_busno++; /* Start scan with secondary */
pciauto_prescan_setup_bridge(hose, dev, hose->current_busno);
-
}
/* Use generic setup_device to initialize standard pci regs,
* but do not allocate any windows since any BAR found (such
* as PCSRBAR) is not in this cpu's memory space.
*/
-
pciauto_setup_device(hose, dev, 0, hose->pci_mem,
hose->pci_prefetch, hose->pci_io);
@@ -286,7 +386,10 @@ void fsl_pci_init(struct pci_controller *hose)
hose->last_busno = hose->current_busno;
}
- if ( bridge ) { /* update limit regs and subordinate busno */
+ /* if we are PCIe - update limit regs and subordinate busno
+ * for the virtual P2P bridge
+ */
+ if (pcie_cap == PCI_CAP_ID_EXP) {
pciauto_postscan_setup_bridge(hose, dev, hose->last_busno);
}
#else
@@ -294,15 +397,13 @@ void fsl_pci_init(struct pci_controller *hose)
#endif
/* Clear all error indications */
-
- if (bridge)
- pci->pme_msg_det = 0xffffffff;
- pci->pedr = 0xffffffff;
+ if (pcie_cap == PCI_CAP_ID_EXP)
+ out_be32(&pci->pme_msg_det, 0xffffffff);
+ out_be32(&pci->pedr, 0xffffffff);
pci_hose_read_config_word (hose, dev, PCI_DSR, &temp16);
if (temp16) {
- pci_hose_write_config_word(hose, dev,
- PCI_DSR, 0xffff);
+ pci_hose_write_config_word(hose, dev, PCI_DSR, 0xffff);
}
pci_hose_read_config_word (hose, dev, PCI_SEC_STATUS, &temp16);
@@ -311,6 +412,50 @@ void fsl_pci_init(struct pci_controller *hose)
}
}
+int fsl_pci_init_port(struct fsl_pci_info *pci_info,
+ struct pci_controller *hose, int busno)
+{
+ volatile ccsr_fsl_pci_t *pci;
+ struct pci_region *r;
+
+ pci = (ccsr_fsl_pci_t *) pci_info->regs;
+
+ /* on non-PCIe controllers we don't have pme_msg_det so this code
+ * should do nothing since the read will return 0
+ */
+ if (in_be32(&pci->pme_msg_det)) {
+ out_be32(&pci->pme_msg_det, 0xffffffff);
+ debug (" with errors. Clearing. Now 0x%08x",
+ pci->pme_msg_det);
+ }
+
+ r = hose->regions + hose->region_count;
+
+ /* outbound memory */
+ pci_set_region(r++,
+ pci_info->mem_bus,
+ pci_info->mem_phys,
+ pci_info->mem_size,
+ PCI_REGION_MEM);
+
+ /* outbound io */
+ pci_set_region(r++,
+ pci_info->io_bus,
+ pci_info->io_phys,
+ pci_info->io_size,
+ PCI_REGION_IO);
+
+ hose->region_count = r - hose->regions;
+ hose->first_busno = busno;
+
+ fsl_pci_init(hose, (u32)&pci->cfg_addr, (u32)&pci->cfg_data);
+
+ printf("\n PCIE%x on bus %02x - %02x\n", pci_info->pci_num,
+ hose->first_busno, hose->last_busno);
+
+ return(hose->last_busno + 1);
+}
+
/* Enable inbound PCI config cycles for agent/endpoint interface */
void fsl_pci_config_unlock(struct pci_controller *hose)
{
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 822dc1a..ea7d899 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_RTC_ISL1208) += isl1208.o
COBJS-$(CONFIG_RTC_M41T11) += m41t11.o
COBJS-$(CONFIG_RTC_M41T60) += m41t60.o
COBJS-$(CONFIG_RTC_M41T62) += m41t62.o
+COBJS-$(CONFIG_RTC_M41T94) += m41t94.o
COBJS-$(CONFIG_RTC_M48T35A) += m48t35ax.o
COBJS-$(CONFIG_RTC_MAX6900) += max6900.o
COBJS-$(CONFIG_RTC_MC13783) += mc13783-rtc.o
diff --git a/drivers/rtc/ds12887.c b/drivers/rtc/ds12887.c
index 25ca133..486105f 100644
--- a/drivers/rtc/ds12887.c
+++ b/drivers/rtc/ds12887.c
@@ -76,18 +76,6 @@ static void rtc_write (uchar reg, uchar val)
# error Board specific rtc access functions should be supplied
#endif
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
-/* ------------------------------------------------------------------------- */
-
int rtc_get (struct rtc_time *tmp)
{
uchar sec, min, hour, mday, wday, mon, year;
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c
index 75f88a9..288c5f8 100644
--- a/drivers/rtc/ds1306.c
+++ b/drivers/rtc/ds1306.c
@@ -62,9 +62,6 @@
#define RTC_USER_RAM_BASE 0x20
-static unsigned int bin2bcd (unsigned int n);
-static unsigned char bcd2bin (unsigned char c);
-
/* ************************************************************************* */
#ifdef CONFIG_SXNI855T /* !!! SHOULD BE CHANGED TO NEW CODE !!! */
@@ -459,19 +456,4 @@ static void rtc_write (unsigned char reg, unsigned char val)
#endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */
-/* ------------------------------------------------------------------------- */
-
-static unsigned char bcd2bin (unsigned char n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-/* ------------------------------------------------------------------------- */
-
-static unsigned int bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-/* ------------------------------------------------------------------------- */
-
#endif
diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c
index 0650d91..079aa99 100644
--- a/drivers/rtc/ds1307.c
+++ b/drivers/rtc/ds1307.c
@@ -76,8 +76,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin (uchar c);
/*
* Get the current time from the RTC
@@ -195,15 +193,4 @@ static void rtc_write (uchar reg, uchar val)
{
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/ds1337.c b/drivers/rtc/ds1337.c
index 58e3966..a71ab5d 100644
--- a/drivers/rtc/ds1337.c
+++ b/drivers/rtc/ds1337.c
@@ -77,9 +77,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin (uchar c);
-
/*
* Get the current time from the RTC
@@ -191,14 +188,4 @@ static void rtc_write (uchar reg, uchar val)
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/ds1556.c b/drivers/rtc/ds1556.c
index 763d22a..25a0b64 100644
--- a/drivers/rtc/ds1556.c
+++ b/drivers/rtc/ds1556.c
@@ -40,8 +40,6 @@
static uchar rtc_read( unsigned int addr );
static void rtc_write( unsigned int addr, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin(uchar c);
#define RTC_BASE ( CONFIG_SYS_NVRAM_SIZE + CONFIG_SYS_NVRAM_BASE_ADDR )
@@ -195,14 +193,4 @@ static void rtc_write( unsigned int addr, uchar val )
*(volatile unsigned char*)(addr) = val;
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/ds164x.c b/drivers/rtc/ds164x.c
index 1e96679..9f306d1 100644
--- a/drivers/rtc/ds164x.c
+++ b/drivers/rtc/ds164x.c
@@ -41,8 +41,6 @@
static uchar rtc_read(unsigned int addr );
static void rtc_write(unsigned int addr, uchar val);
-static uchar bin2bcd(unsigned int n);
-static unsigned bcd2bin(uchar c);
#define RTC_EPOCH 2000 /* century */
@@ -191,14 +189,4 @@ static void rtc_write( unsigned int addr, uchar val )
*(volatile unsigned char*)(addr) = val;
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/ds174x.c b/drivers/rtc/ds174x.c
index 738d118..5a55dc8 100644
--- a/drivers/rtc/ds174x.c
+++ b/drivers/rtc/ds174x.c
@@ -37,8 +37,6 @@
static uchar rtc_read( unsigned int addr );
static void rtc_write( unsigned int addr, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin(uchar c);
#define RTC_BASE ( CONFIG_SYS_NVRAM_SIZE + CONFIG_SYS_NVRAM_BASE_ADDR )
@@ -192,14 +190,4 @@ static void rtc_write( unsigned int addr, uchar val )
out8( addr, val );
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/ds3231.c b/drivers/rtc/ds3231.c
index ef03358..134a0e4 100644
--- a/drivers/rtc/ds3231.c
+++ b/drivers/rtc/ds3231.c
@@ -79,8 +79,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin (uchar c);
/*
@@ -186,14 +184,4 @@ static void rtc_write (uchar reg, uchar val)
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/isl1208.c b/drivers/rtc/isl1208.c
index 71f63d5..07591b7 100644
--- a/drivers/rtc/isl1208.c
+++ b/drivers/rtc/isl1208.c
@@ -66,8 +66,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin (uchar c);
/*
* Get the current time from the RTC
@@ -160,13 +158,3 @@ static void rtc_write (uchar reg, uchar val)
{
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
diff --git a/drivers/rtc/m41t11.c b/drivers/rtc/m41t11.c
index 3a77c1b..e0c27e1 100644
--- a/drivers/rtc/m41t11.c
+++ b/drivers/rtc/m41t11.c
@@ -45,17 +45,6 @@
#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
-
/* ------------------------------------------------------------------------- */
/*
these are simple defines for the chip local to here so they aren't too
diff --git a/drivers/rtc/m41t60.c b/drivers/rtc/m41t60.c
index e34a5f4..632fe4b 100644
--- a/drivers/rtc/m41t60.c
+++ b/drivers/rtc/m41t60.c
@@ -36,16 +36,6 @@
#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-static unsigned bcd2bin(uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd(unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
/*
* Convert between century and "century bits" (CB1 and CB0). These routines
* assume years are in the range 1900 - 2299.
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index cfe84f9..62c2446 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -31,7 +31,6 @@
#include <command.h>
#include <rtc.h>
#include <i2c.h>
-#include <bcd.h>
#if defined(CONFIG_CMD_DATE)
@@ -76,16 +75,16 @@ int rtc_get(struct rtc_time *tm)
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]);
- tm->tm_sec = BCD2BIN(buf[M41T62_REG_SEC] & 0x7f);
- tm->tm_min = BCD2BIN(buf[M41T62_REG_MIN] & 0x7f);
- tm->tm_hour = BCD2BIN(buf[M41T62_REG_HOUR] & 0x3f);
- tm->tm_mday = BCD2BIN(buf[M41T62_REG_DAY] & 0x3f);
+ tm->tm_sec = bcd2bin(buf[M41T62_REG_SEC] & 0x7f);
+ tm->tm_min = bcd2bin(buf[M41T62_REG_MIN] & 0x7f);
+ tm->tm_hour = bcd2bin(buf[M41T62_REG_HOUR] & 0x3f);
+ tm->tm_mday = bcd2bin(buf[M41T62_REG_DAY] & 0x3f);
tm->tm_wday = buf[M41T62_REG_WDAY] & 0x07;
- tm->tm_mon = BCD2BIN(buf[M41T62_REG_MON] & 0x1f);
+ tm->tm_mon = bcd2bin(buf[M41T62_REG_MON] & 0x1f);
/* assume 20YY not 19YY, and ignore the Century Bit */
/* U-Boot needs to add 1900 here */
- tm->tm_year = BCD2BIN(buf[M41T62_REG_YEAR]) + 100 + 1900;
+ tm->tm_year = bcd2bin(buf[M41T62_REG_YEAR]) + 100 + 1900;
debug("%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -109,19 +108,19 @@ int rtc_set(struct rtc_time *tm)
/* Merge time-data and register flags into buf[0..7] */
buf[M41T62_REG_SSEC] = 0;
buf[M41T62_REG_SEC] =
- BIN2BCD(tm->tm_sec) | (buf[M41T62_REG_SEC] & ~0x7f);
+ bin2bcd(tm->tm_sec) | (buf[M41T62_REG_SEC] & ~0x7f);
buf[M41T62_REG_MIN] =
- BIN2BCD(tm->tm_min) | (buf[M41T62_REG_MIN] & ~0x7f);
+ bin2bcd(tm->tm_min) | (buf[M41T62_REG_MIN] & ~0x7f);
buf[M41T62_REG_HOUR] =
- BIN2BCD(tm->tm_hour) | (buf[M41T62_REG_HOUR] & ~0x3f) ;
+ bin2bcd(tm->tm_hour) | (buf[M41T62_REG_HOUR] & ~0x3f) ;
buf[M41T62_REG_WDAY] =
(tm->tm_wday & 0x07) | (buf[M41T62_REG_WDAY] & ~0x07);
buf[M41T62_REG_DAY] =
- BIN2BCD(tm->tm_mday) | (buf[M41T62_REG_DAY] & ~0x3f);
+ bin2bcd(tm->tm_mday) | (buf[M41T62_REG_DAY] & ~0x3f);
buf[M41T62_REG_MON] =
- BIN2BCD(tm->tm_mon) | (buf[M41T62_REG_MON] & ~0x1f);
+ bin2bcd(tm->tm_mon) | (buf[M41T62_REG_MON] & ~0x1f);
/* assume 20YY not 19YY */
- buf[M41T62_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+ buf[M41T62_REG_YEAR] = bin2bcd(tm->tm_year % 100);
if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE)) {
printf("I2C write failed in %s()\n", __func__);
diff --git a/drivers/rtc/m41t94.c b/drivers/rtc/m41t94.c
new file mode 100644
index 0000000..02b41d9
--- /dev/null
+++ b/drivers/rtc/m41t94.c
@@ -0,0 +1,124 @@
+/*
+ * Driver for ST M41T94 SPI RTC
+ *
+ * Taken from the Linux kernel drivier:
+ * Copyright (C) 2008 Kim B. Heino
+ *
+ * Adaptation for U-Boot:
+ * Copyright (C) 2009
+ * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <rtc.h>
+#include <spi.h>
+
+static struct spi_slave *slave;
+
+#define M41T94_REG_SECONDS 0x01
+#define M41T94_REG_MINUTES 0x02
+#define M41T94_REG_HOURS 0x03
+#define M41T94_REG_WDAY 0x04
+#define M41T94_REG_DAY 0x05
+#define M41T94_REG_MONTH 0x06
+#define M41T94_REG_YEAR 0x07
+#define M41T94_REG_HT 0x0c
+
+#define M41T94_BIT_HALT 0x40
+#define M41T94_BIT_STOP 0x80
+#define M41T94_BIT_CB 0x40
+#define M41T94_BIT_CEB 0x80
+
+int rtc_set(struct rtc_time *tm)
+{
+ u8 buf[8]; /* write cmd + 7 registers */
+ int ret;
+
+ if (!slave) {
+ slave = spi_setup_slave(CONFIG_M41T94_SPI_BUS,
+ CONFIG_M41T94_SPI_CS, 1000000,
+ SPI_MODE_3);
+ if (!slave)
+ return -1;
+ }
+ spi_claim_bus(slave);
+
+ buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */
+ buf[M41T94_REG_SECONDS] = bin2bcd(tm->tm_sec);
+ buf[M41T94_REG_MINUTES] = bin2bcd(tm->tm_min);
+ buf[M41T94_REG_HOURS] = bin2bcd(tm->tm_hour);
+ buf[M41T94_REG_WDAY] = bin2bcd(tm->tm_wday + 1);
+ buf[M41T94_REG_DAY] = bin2bcd(tm->tm_mday);
+ buf[M41T94_REG_MONTH] = bin2bcd(tm->tm_mon + 1);
+
+ buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB;
+ if (tm->tm_year >= 100)
+ buf[M41T94_REG_HOURS] |= M41T94_BIT_CB;
+ buf[M41T94_REG_YEAR] = bin2bcd(tm->tm_year % 100);
+
+ ret = spi_xfer(slave, 64, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+ spi_release_bus(slave);
+ return ret;
+}
+
+int rtc_get(struct rtc_time *tm)
+{
+ u8 buf[2];
+ int ret, hour;
+
+ if (!slave) {
+ slave = spi_setup_slave(CONFIG_M41T94_SPI_BUS,
+ CONFIG_M41T94_SPI_CS, 1000000,
+ SPI_MODE_3);
+ if (!slave)
+ return -1;
+ }
+ spi_claim_bus(slave);
+
+ /* clear halt update bit */
+ ret = spi_w8r8(slave, M41T94_REG_HT);
+ if (ret < 0)
+ return ret;
+ if (ret & M41T94_BIT_HALT) {
+ buf[0] = 0x80 | M41T94_REG_HT;
+ buf[1] = ret & ~M41T94_BIT_HALT;
+ spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+ }
+
+ /* clear stop bit */
+ ret = spi_w8r8(slave, M41T94_REG_SECONDS);
+ if (ret < 0)
+ return ret;
+ if (ret & M41T94_BIT_STOP) {
+ buf[0] = 0x80 | M41T94_REG_SECONDS;
+ buf[1] = ret & ~M41T94_BIT_STOP;
+ spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+ }
+
+ tm->tm_sec = bcd2bin(spi_w8r8(slave, M41T94_REG_SECONDS));
+ tm->tm_min = bcd2bin(spi_w8r8(slave, M41T94_REG_MINUTES));
+ hour = spi_w8r8(slave, M41T94_REG_HOURS);
+ tm->tm_hour = bcd2bin(hour & 0x3f);
+ tm->tm_wday = bcd2bin(spi_w8r8(slave, M41T94_REG_WDAY)) - 1;
+ tm->tm_mday = bcd2bin(spi_w8r8(slave, M41T94_REG_DAY));
+ tm->tm_mon = bcd2bin(spi_w8r8(slave, M41T94_REG_MONTH)) - 1;
+ tm->tm_year = bcd2bin(spi_w8r8(slave, M41T94_REG_YEAR));
+ if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB))
+ tm->tm_year += 100;
+
+ spi_release_bus(slave);
+ return 0;
+}
+
+void rtc_reset(void)
+{
+ /*
+ * Could not be tested as the reset pin is not wired on
+ * the sbc35-ag20 board
+ */
+ return 0;
+}
diff --git a/drivers/rtc/m48t35ax.c b/drivers/rtc/m48t35ax.c
index 1482edd..29b36c1 100644
--- a/drivers/rtc/m48t35ax.c
+++ b/drivers/rtc/m48t35ax.c
@@ -37,8 +37,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin(uchar c);
/* ------------------------------------------------------------------------- */
@@ -157,14 +155,4 @@ static void rtc_write (uchar reg, uchar val)
((CONFIG_SYS_NVRAM_BASE_ADDR + CONFIG_SYS_NVRAM_SIZE - 8) + reg) = val;
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/max6900.c b/drivers/rtc/max6900.c
index 7c99c5e..74637d1 100644
--- a/drivers/rtc/max6900.c
+++ b/drivers/rtc/max6900.c
@@ -51,16 +51,6 @@ static void rtc_write (uchar reg, uchar val)
udelay(2500);
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
/* ------------------------------------------------------------------------- */
int rtc_get (struct rtc_time *tmp)
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
index 38484ce..d68b438 100644
--- a/drivers/rtc/mc146818.c
+++ b/drivers/rtc/mc146818.c
@@ -35,8 +35,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin(uchar c);
#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
#define RTC_SECONDS 0x00
@@ -168,14 +166,4 @@ static void rtc_write (uchar reg, uchar val)
}
#endif
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/mk48t59.c b/drivers/rtc/mk48t59.c
index dabf322..b176882 100644
--- a/drivers/rtc/mk48t59.c
+++ b/drivers/rtc/mk48t59.c
@@ -97,16 +97,6 @@ static void rtc_write (short reg, uchar val)
# error Board specific rtc access functions should be supplied
#endif
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
/* ------------------------------------------------------------------------- */
void *nvram_read(void *dest, const short src, size_t count)
diff --git a/drivers/rtc/pcf8563.c b/drivers/rtc/pcf8563.c
index cd9fb65..339e5f6 100644
--- a/drivers/rtc/pcf8563.c
+++ b/drivers/rtc/pcf8563.c
@@ -36,8 +36,6 @@
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin(uchar c);
/* ------------------------------------------------------------------------- */
@@ -137,14 +135,4 @@ static void rtc_write (uchar reg, uchar val)
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif
diff --git a/drivers/rtc/rs5c372.c b/drivers/rtc/rs5c372.c
index d6cd7c8..90bbb4e 100644
--- a/drivers/rtc/rs5c372.c
+++ b/drivers/rtc/rs5c372.c
@@ -67,9 +67,6 @@ static unsigned int rtc_debug = DEBUG;
#define HOURS_24(n) bcd2bin((n) & 0x3F)
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin (uchar c);
-
static int setup_done = 0;
static int
@@ -291,15 +288,4 @@ rtc_reset (void)
return;
}
-static unsigned int
-bcd2bin (unsigned char n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char
-bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
#endif
diff --git a/drivers/rtc/rtc4543.c b/drivers/rtc/rtc4543.c
index 242d9bc..046aa67 100644
--- a/drivers/rtc/rtc4543.c
+++ b/drivers/rtc/rtc4543.c
@@ -25,7 +25,6 @@
#include <common.h>
#include <command.h>
#include <config.h>
-#include <bcd.h>
#include <rtc.h>
#include <tws.h>
@@ -49,13 +48,13 @@ int rtc_get(struct rtc_time *tm)
/* Read 52 bits into our buffer */
tws_read(buffer, 52);
- tm->tm_sec = BCD2BIN( buffer[0] & 0x7F);
- tm->tm_min = BCD2BIN( buffer[1] & 0x7F);
- tm->tm_hour = BCD2BIN( buffer[2] & 0x3F);
- tm->tm_wday = BCD2BIN( buffer[3] & 0x07);
- tm->tm_mday = BCD2BIN((buffer[3] & 0xF0) >> 4 | (buffer[4] & 0x0F) << 4);
- tm->tm_mon = BCD2BIN((buffer[4] & 0x30) >> 4 | (buffer[5] & 0x0F) << 4);
- tm->tm_year = BCD2BIN((buffer[5] & 0xF0) >> 4 | (buffer[6] & 0x0F) << 4) + 2000;
+ tm->tm_sec = bcd2bin( buffer[0] & 0x7F);
+ tm->tm_min = bcd2bin( buffer[1] & 0x7F);
+ tm->tm_hour = bcd2bin( buffer[2] & 0x3F);
+ tm->tm_wday = bcd2bin( buffer[3] & 0x07);
+ tm->tm_mday = bcd2bin((buffer[3] & 0xF0) >> 4 | (buffer[4] & 0x0F) << 4);
+ tm->tm_mon = bcd2bin((buffer[4] & 0x30) >> 4 | (buffer[5] & 0x0F) << 4);
+ tm->tm_year = bcd2bin((buffer[5] & 0xF0) >> 4 | (buffer[6] & 0x0F) << 4) + 2000;
tm->tm_yday = 0;
tm->tm_isdst = 0;
@@ -81,17 +80,17 @@ int rtc_set(struct rtc_time *tm)
tm->tm_hour, tm->tm_min, tm->tm_sec);
memset(buffer, 0, 7);
- buffer[0] = BIN2BCD(tm->tm_sec);
- buffer[1] = BIN2BCD(tm->tm_min);
- buffer[2] = BIN2BCD(tm->tm_hour);
- buffer[3] = BIN2BCD(tm->tm_wday);
- tmp = BIN2BCD(tm->tm_mday);
+ buffer[0] = bin2bcd(tm->tm_sec);
+ buffer[1] = bin2bcd(tm->tm_min);
+ buffer[2] = bin2bcd(tm->tm_hour);
+ buffer[3] = bin2bcd(tm->tm_wday);
+ tmp = bin2bcd(tm->tm_mday);
buffer[3] |= (tmp & 0x0F) << 4;
buffer[4] = (tmp & 0xF0) >> 4;
- tmp = BIN2BCD(tm->tm_mon);
+ tmp = bin2bcd(tm->tm_mon);
buffer[4] |= (tmp & 0x0F) << 4;
buffer[5] = (tmp & 0xF0) >> 4;
- tmp = BIN2BCD(tm->tm_year % 100);
+ tmp = bin2bcd(tm->tm_year % 100);
buffer[5] |= (tmp & 0x0F) << 4;
buffer[6] = (tmp & 0xF0) >> 4;
diff --git a/drivers/rtc/rx8025.c b/drivers/rtc/rx8025.c
index da87394..64eb1cd 100644
--- a/drivers/rtc/rx8025.c
+++ b/drivers/rtc/rx8025.c
@@ -90,8 +90,6 @@
#define rtc_read(reg) buf[((reg) + 1) & 0xf]
static void rtc_write (uchar reg, uchar val);
-static uchar bin2bcd (unsigned int n);
-static unsigned bcd2bin (uchar c);
/*
* Get the current time from the RTC
@@ -226,14 +224,4 @@ static void rtc_write (uchar reg, uchar val)
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
#endif /* CONFIG_RTC_RX8025 && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/s3c24x0_rtc.c b/drivers/rtc/s3c24x0_rtc.c
index 0d3372f..e10db9a 100644
--- a/drivers/rtc/s3c24x0_rtc.c
+++ b/drivers/rtc/s3c24x0_rtc.c
@@ -58,16 +58,6 @@ static inline void SetRTC_Access(RTC_ACCESS a)
}
}
-static unsigned bcd2bin (uchar n)
-{
- return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
-}
-
-static unsigned char bin2bcd (unsigned int n)
-{
- return (((n / 10) << 4) | (n % 10));
-}
-
/* ------------------------------------------------------------------------- */
int rtc_get (struct rtc_time *tmp)
diff --git a/drivers/rtc/s3c44b0_rtc.c b/drivers/rtc/s3c44b0_rtc.c
index bfb744a..d087d8a 100644
--- a/drivers/rtc/s3c44b0_rtc.c
+++ b/drivers/rtc/s3c44b0_rtc.c
@@ -32,29 +32,28 @@
#include <command.h>
#include <asm/hardware.h>
#include <rtc.h>
-#include <bcd.h>
int rtc_get (struct rtc_time* tm)
{
RTCCON |= 1;
- tm->tm_year = BCD2BIN(BCDYEAR);
- tm->tm_mon = BCD2BIN(BCDMON);
- tm->tm_wday = BCD2BIN(BCDDATE);
- tm->tm_mday = BCD2BIN(BCDDAY);
- tm->tm_hour = BCD2BIN(BCDHOUR);
- tm->tm_min = BCD2BIN(BCDMIN);
- tm->tm_sec = BCD2BIN(BCDSEC);
+ tm->tm_year = bcd2bin(BCDYEAR);
+ tm->tm_mon = bcd2bin(BCDMON);
+ tm->tm_wday = bcd2bin(BCDDATE);
+ tm->tm_mday = bcd2bin(BCDDAY);
+ tm->tm_hour = bcd2bin(BCDHOUR);
+ tm->tm_min = bcd2bin(BCDMIN);
+ tm->tm_sec = bcd2bin(BCDSEC);
if (tm->tm_sec==0) {
/* we have to re-read the rtc data because of the "one second deviation" problem */
/* see RTC datasheet for more info about it */
- tm->tm_year = BCD2BIN(BCDYEAR);
- tm->tm_mon = BCD2BIN(BCDMON);
- tm->tm_mday = BCD2BIN(BCDDAY);
- tm->tm_wday = BCD2BIN(BCDDATE);
- tm->tm_hour = BCD2BIN(BCDHOUR);
- tm->tm_min = BCD2BIN(BCDMIN);
- tm->tm_sec = BCD2BIN(BCDSEC);
+ tm->tm_year = bcd2bin(BCDYEAR);
+ tm->tm_mon = bcd2bin(BCDMON);
+ tm->tm_mday = bcd2bin(BCDDAY);
+ tm->tm_wday = bcd2bin(BCDDATE);
+ tm->tm_hour = bcd2bin(BCDHOUR);
+ tm->tm_min = bcd2bin(BCDMIN);
+ tm->tm_sec = bcd2bin(BCDSEC);
}
RTCCON &= ~1;
@@ -75,13 +74,13 @@ int rtc_set (struct rtc_time* tm)
tm->tm_year -= 2000;
RTCCON |= 1;
- BCDYEAR = BIN2BCD(tm->tm_year);
- BCDMON = BIN2BCD(tm->tm_mon);
- BCDDAY = BIN2BCD(tm->tm_mday);
- BCDDATE = BIN2BCD(tm->tm_wday);
- BCDHOUR = BIN2BCD(tm->tm_hour);
- BCDMIN = BIN2BCD(tm->tm_min);
- BCDSEC = BIN2BCD(tm->tm_sec);
+ BCDYEAR = bin2bcd(tm->tm_year);
+ BCDMON = bin2bcd(tm->tm_mon);
+ BCDDAY = bin2bcd(tm->tm_mday);
+ BCDDATE = bin2bcd(tm->tm_wday);
+ BCDHOUR = bin2bcd(tm->tm_hour);
+ BCDMIN = bin2bcd(tm->tm_min);
+ BCDSEC = bin2bcd(tm->tm_sec);
RTCCON &= 1;
return 0;
diff --git a/drivers/rtc/x1205.c b/drivers/rtc/x1205.c
index 56115b0..7adf377 100644
--- a/drivers/rtc/x1205.c
+++ b/drivers/rtc/x1205.c
@@ -38,7 +38,6 @@
#include <command.h>
#include <rtc.h>
#include <i2c.h>
-#include <bcd.h>
#if defined(CONFIG_CMD_DATE)
@@ -116,13 +115,13 @@ int rtc_get(struct rtc_time *tm)
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]);
- tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
- tm->tm_min = BCD2BIN(buf[CCR_MIN]);
- tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
- tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); /* mon is 0-11 */
- tm->tm_year = BCD2BIN(buf[CCR_YEAR])
- + (BCD2BIN(buf[CCR_Y2K]) * 100);
+ tm->tm_sec = bcd2bin(buf[CCR_SEC]);
+ tm->tm_min = bcd2bin(buf[CCR_MIN]);
+ tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = bcd2bin(buf[CCR_MDAY]);
+ tm->tm_mon = bcd2bin(buf[CCR_MONTH]); /* mon is 0-11 */
+ tm->tm_year = bcd2bin(buf[CCR_YEAR])
+ + (bcd2bin(buf[CCR_Y2K]) * 100);
tm->tm_wday = buf[CCR_WDAY];
debug("%s: tm is secs=%d, mins=%d, hours=%d, "
@@ -143,21 +142,21 @@ int rtc_set(struct rtc_time *tm)
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
- buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+ buf[CCR_SEC] = bin2bcd(tm->tm_sec);
+ buf[CCR_MIN] = bin2bcd(tm->tm_min);
/* set hour and 24hr bit */
- buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+ buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
- buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+ buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
/* month, 1 - 12 */
- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+ buf[CCR_MONTH] = bin2bcd(tm->tm_mon);
/* year, since the rtc epoch*/
- buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
+ buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
buf[CCR_WDAY] = tm->tm_wday & 0x07;
- buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
+ buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100);
/* this sequence is required to unlock the chip */
rtc_write(X1205_REG_SR, X1205_SR_WEL);