* Patch by David Müller, 13 Sep 2003:
authorwdenk <wdenk>
Sat, 13 Sep 2003 19:01:12 +0000 (19:01 +0000)
committerwdenk <wdenk>
Sat, 13 Sep 2003 19:01:12 +0000 (19:01 +0000)
  various changes to VCMA9 board specific files

* Add I2C support for MGT5100 / MPC5200

13 files changed:
CHANGELOG
README
board/mpl/vcma9/cmd_vcma9.c
board/mpl/vcma9/config.mk
board/mpl/vcma9/memsetup.S
board/mpl/vcma9/vcma9.c
board/mpl/vcma9/vcma9.h
cpu/mpc5xxx/Makefile
cpu/mpc5xxx/i2c.c [new file with mode: 0644]
include/configs/IceCube.h
include/configs/VCMA9.h
include/mpc5xxx.h
rtc/s3c24x0_rtc.c

index b034331a51c3672d66ce74affab5bcd6c1df27d9..c058cc43883f2d7da5b5c075de447346ce869ab9 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,11 @@
 Changes for U-Boot 1.0.0:
 ======================================================================
 
+* Patch by David Müller, 13 Sep 2003:
+  various changes to VCMA9 board specific files
+
+* Add I2C support for MGT5100 / MPC5200
+
 * Patch by Rune Torgersen, 11 Sep 2003:
   Changed default memory option on MPC8266ADS to NOT be Page Based
   Interleave, since this doesn't work very well with the standard
diff --git a/README b/README
index 0503ccb140857d5ed4f4408243a35fb0a13a1718..e431c29a744107507b88a9b7fc4f1fa490fa7e6c 100644 (file)
--- a/README
+++ b/README
@@ -203,6 +203,7 @@ Directory Hierarchy:
 - board/mpl/common     Common files for MPL boards
 - board/mpl/pip405     Files specific to PIP405     boards
 - board/mpl/mip405     Files specific to MIP405     boards
+- board/mpl/vcma9      Files specific to VCMA9      boards
 - board/musenki        Files specific to MUSEKNI    boards
 - board/mvs1   Files specific to MVS1       boards
 - board/nx823   Files specific to NX823      boards
@@ -363,7 +364,7 @@ The following options need to be configured:
                CONFIG_IMPA7,       CONFIG_LART,       CONFIG_LUBBOCK,
                CONFIG_INNOVATOROMAP1510,       CONFIG_INNOVATOROMAP1610
                CONFIG_SHANNON,     CONFIG_SMDK2400,   CONFIG_SMDK2410,
-               CONFIG_TRAB,        CONFIG_AT91RM9200DK
+               CONFIG_TRAB,        CONFIG_VCMA9,      CONFIG_AT91RM9200DK
 
 
 - CPU Module Type: (if CONFIG_COGENT is defined)
index 32fa33403f4794bc33ebca5fb36f28f4bd33ba04..3b0453521d8ff80a46d0a7c7ebde1ed2841531a2 100644 (file)
@@ -41,9 +41,12 @@ static uchar cs8900_chksum(ushort data)
 #endif
 
 extern void print_vcma9_info(void);
-extern int vcma9_cantest(void);
+extern int vcma9_cantest(int);
 extern int vcma9_nandtest(void);
-extern int vcma9_dactest(void);
+extern int vcma9_nanderase(void);
+extern int vcma9_nandread(ulong);
+extern int vcma9_nandwrite(ulong);
+extern int vcma9_dactest(int);
 extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 
 /* ------------------------------------------------------------------------- */
@@ -126,18 +129,53 @@ int do_vcma9(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 #endif
 #if 0
        if (strcmp(argv[1], "cantest") == 0) {
-               vcma9_cantest();
+               if (argc >= 3)
+                       vcma9_cantest(strcmp(argv[2], "s") ? 0 : 1);
+               else
+                       vcma9_cantest(0);
                return 0;
        }
        if (strcmp(argv[1], "nandtest") == 0) {
                vcma9_nandtest();
                return 0;
        }
+       if (strcmp(argv[1], "nanderase") == 0) {
+               vcma9_nanderase();
+               return 0;
+       }
+       if (strcmp(argv[1], "nandread") == 0) {
+               ulong offset = 0;
+
+               if (argc >= 3)
+                       offset = simple_strtoul(argv[2], NULL, 16);
+
+               vcma9_nandread(offset);
+               return 0;
+       }
+       if (strcmp(argv[1], "nandwrite") == 0) {
+               ulong offset = 0;
+
+               if (argc >= 3)
+                       offset = simple_strtoul(argv[2], NULL, 16);
+
+               vcma9_nandwrite(offset);
+               return 0;
+       }
        if (strcmp(argv[1], "dactest") == 0) {
-               vcma9_dactest();
+               if (argc >= 3)
+                       vcma9_dactest(strcmp(argv[2], "s") ? 0 : 1);
+               else
+               vcma9_dactest(0);
                return 0;
        }
 #endif
 
        return (do_mplcommon(cmdtp, flag, argc, argv));
 }
+
+U_BOOT_CMD(
+       vcma9, 6, 1, do_vcma9,
+       "vcma9   - VCMA9 specific commands\n",
+       "flash mem [SrcAddr]\n    - updates U-Boot with image in memory\n"
+);
+
index 95d69cc6cc80422741b419cc060e97e8939d4aad..942d42ef6a27580d4ef5caa14caeeaf3f29bcf8c 100644 (file)
@@ -1,5 +1,5 @@
 #
-# (C) Copyright 2002
+# (C) Copyright 2002, 2003
 # David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
 #
 # MPL VCMA9 board with S3C2410X (ARM920T) cpu
@@ -8,17 +8,17 @@
 #
 
 #
-# MPL VCMA9 has 1 bank of 64 MB DRAM
-#
-# 3000'0000 to 3400'0000
+# MPL VCMA9 has 1 bank of minimal 16 MB DRAM
+# from 0x30000000
 #
 # Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
-# optionally with a ramdisk at 3080'0000
+# optionally with a ramdisk at 3040'0000
 #
-# we load ourself to 33F8'0000
+# we load ourself to 30F8'0000
 #
-# download area is 3300'0000
+# download area is 3080'0000
 #
 
 
+#TEXT_BASE = 0x30F80000
 TEXT_BASE = 0x33F80000
index 7b4193d0e88421c54489364b5d164b9977c4f6d6..ab6590153cdaad2cd0ee024e0bf07353f29906ba 100644 (file)
@@ -34,7 +34,9 @@
 
 /* some parameters for the board */
 
-#define BWSCON 0x48000000
+#define BWSCON         0x48000000
+#define PLD_BASE       0x2C000000
+#define SDRAM_REG      0x2C000106
 
 /* BWSCON */
 #define DW8                    (0x0)
@@ -43,6 +45,9 @@
 #define WAIT                   (0x1<<2)
 #define UBLB                   (0x1<<3)
 
+/* BANKSIZE */
+#define BURST_EN               (0x1<<7)
+
 #define B1_BWSCON              (DW16)
 #define B2_BWSCON              (DW32)
 #define B3_BWSCON              (DW32)
@@ -130,24 +135,39 @@ memsetup:
        /* memory control configuration */
        /* make r0 relative the current location so that it */
        /* reads SMRDATA out of FLASH rather than memory ! */
-       ldr     r0, =SMRDATA
+       ldr     r0, =CSDATA
        ldr     r1, _TEXT_BASE
        sub     r0, r0, r1
        ldr     r1, =BWSCON     /* Bus Width Status Controller */
-       add     r2, r0, #13*4
+       add     r2, r0, #CSDATA_END-CSDATA
 0:
        ldr     r3, [r0], #4
        str     r3, [r1], #4
        cmp     r2, r0
        bne     0b
 
+       /* PLD access is now possible */
+       /* r0 == SDRAMDATA */
+       /* r1 == SDRAM controller regs */
+       ldr     r2, =PLD_BASE
+       ldrb    r3, [r2, #SDRAM_REG-PLD_BASE]
+       mov     r4, #SDRAMDATA1_END-SDRAMDATA
+       /* calculate start and end point */
+       mla     r0, r3, r4, r0 
+       add     r2, r0, r4
+0:
+       ldr     r3, [r0], #4
+       str     r3, [r1], #4
+       cmp     r2, r0
+       bne     0b
+       
        /* everything is fine now */
        mov     pc, lr
 
        .ltorg
 /* the literal pools origin */
 
-SMRDATA:
+CSDATA:
     .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
     .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
     .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
@@ -155,9 +175,38 @@ SMRDATA:
     .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
     .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
     .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
+CSDATA_END:
+
+SDRAMDATA:
+/* 4Mx8x4 */
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0x32 + BURST_EN
+    .word 0x30
+    .word 0x30
+SDRAMDATA1_END:
+
+/* 8Mx8x4 (not implemented yet) */
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0x32 + BURST_EN
+    .word 0x30
+    .word 0x30
+    
+/* 2Mx8x4 (not implemented yet) */
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0x32 + BURST_EN
+    .word 0x30
+    .word 0x30
+    
+/* 4Mx8x2 (not implemented yet) */
     .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
     .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
     .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
-    .word 0x32
+    .word 0x32 + BURST_EN
     .word 0x30
     .word 0x30
index 359e565761aa96a4bb8d1c379cd14bf6eb05850e..33cec02529161749ef8f265d6a76665508241b2a 100644 (file)
@@ -130,16 +130,6 @@ int board_init(void)
        return 0;
 }
 
-int dram_init(void)
-{
-       DECLARE_GLOBAL_DATA_PTR;
-
-       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-       gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
-
-       return 0;
-}
-
 /*
  * NAND flash initialization.
  */
@@ -162,9 +152,16 @@ static inline void NF_Reset(void)
 
 static inline void NF_Init(void)
 {
+#if 0 /* a little bit too optimistic */
 #define TACLS   0
 #define TWRPH0  3
 #define TWRPH1  0
+#else
+#define TACLS   0
+#define TWRPH0  4
+#define TWRPH1  2
+#endif
+
     NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
     /*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
     /* 1  1    1     1,   1      xxx,  r xxx,   r xxx */
@@ -177,15 +174,12 @@ void
 nand_init(void)
 {
        S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
-       unsigned totlen;
 
        NF_Init();
 #ifdef DEBUG
        printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
 #endif
-       totlen = nand_probe((ulong)nand) >> 20;
-
-       printf ("%4lu MB\n", totlen >> 20);
+       printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
 }
 #endif
 
@@ -193,29 +187,40 @@ nand_init(void)
  * Get some Board/PLD Info
  */
 
-static uchar Get_PLD_ID(void)
+static u8 Get_PLD_ID(void)
+{
+       VCMA9_PLD * const pld = VCMA9_GetBase_PLD();
+       
+       return(pld->ID);
+}
+
+static u8 Get_PLD_BOARD(void)
 {
-       return(*(volatile uchar *)PLD_ID_REG);
+       VCMA9_PLD * const pld = VCMA9_GetBase_PLD();
+       
+       return(pld->BOARD);
 }
 
-static uchar Get_PLD_BOARD(void)
+static u8 Get_PLD_SDRAM(void)
 {
-       return(*(volatile uchar *)PLD_BOARD_REG);
+       VCMA9_PLD * const pld = VCMA9_GetBase_PLD();
+       
+       return(pld->SDRAM);
 }
 
-static uchar Get_PLD_Version(void)
+static u8 Get_PLD_Version(void)
 {
        return((Get_PLD_ID() >> 4) & 0x0F);
 }
 
-static uchar Get_PLD_Revision(void)
+static u8 Get_PLD_Revision(void)
 {
        return(Get_PLD_ID() & 0x0F);
 }
 
 static int Get_Board_Config(void)
 {
-       uchar config = Get_PLD_BOARD() & 0x03;
+       u8 config = Get_PLD_BOARD() & 0x03;
 
        if (config == 3)
            return 1;
@@ -228,6 +233,54 @@ static uchar Get_Board_PCB(void)
        return(((Get_PLD_BOARD() >> 4) & 0x03) + 'A');
 }
 
+static u8 Get_SDRAM_ChipNr(void)
+{
+       switch ((Get_PLD_SDRAM() >> 4) & 0x0F) {
+               case 0: return 4;
+               case 1: return 1;
+               case 2: return 2;
+               default: return 0;
+       }
+}
+
+static ulong Get_SDRAM_ChipSize(void)
+{
+       switch (Get_PLD_SDRAM() & 0x0F) {
+               case 0: return 16 * (1024*1024);
+               case 1: return 32 * (1024*1024);
+               case 2: return  8 * (1024*1024);
+               case 3: return  8 * (1024*1024);
+               default: return 0;
+       }       
+}
+static const char * Get_SDRAM_ChipGeom(void)
+{
+       switch (Get_PLD_SDRAM() & 0x0F) {
+               case 0: return "4Mx8x4";
+               case 1: return "8Mx8x4";
+               case 2: return "2Mx8x4";
+               case 3: return "4Mx8x2";
+               default: return "unknown";
+       }
+}
+
+static void Show_VCMA9_Info(char *board_name, char *serial)
+{
+       printf("Board: %s SN: %s  PCB Rev: %c PLD(%d,%d)\n",
+               board_name, serial, Get_Board_PCB(), Get_PLD_Version(), Get_PLD_Revision());
+       printf("SDRAM: %d chips %s\n", Get_SDRAM_ChipNr(), Get_SDRAM_ChipGeom());
+}
+
+int dram_init(void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+       gd->bd->bi_dram[0].size = Get_SDRAM_ChipSize() * Get_SDRAM_ChipNr();
+
+       return 0;
+}
+
 /* ------------------------------------------------------------------------- */
 
 /*
@@ -240,8 +293,6 @@ int checkboard(void)
        int i;
        backup_t *b = (backup_t *) s;
 
-       puts("Board: ");
-
        i = getenv_r("serial#", s, 32);
        if ((i < 0) || strncmp (s, "VCMA9", 5)) {
                get_backup_values (b);
@@ -249,32 +300,23 @@ int checkboard(void)
                        puts ("### No HW ID - assuming VCMA9");
                } else {
                        b->serial_name[5] = 0;
-                       printf ("%s-%d PCB Rev %c SN: %s", b->serial_name, Get_Board_Config(),
-                                       Get_Board_PCB(), &b->serial_name[6]);
+                       Show_VCMA9_Info(b->serial_name, &b->serial_name[6]);
                }
        } else {
                s[5] = 0;
-               printf ("%s-%d PCB Rev %c SN: %s", s, Get_Board_Config(), Get_Board_PCB(),
-                               &s[6]);
+               Show_VCMA9_Info(s, &s[6]);
        }
-       printf("\n");
+       /*printf("\n");*/
        return(0);
 }
 
 
-void print_vcma9_rev(void)
-{
-       printf("Board: VCMA9-%d PCB Rev: %c (PLD Ver: %d, Rev: %d)\n",
-               Get_Board_Config(), Get_Board_PCB(),
-               Get_PLD_Version(), Get_PLD_Revision());
-}
-
 extern void mem_test_reloc(void);
 
 int last_stage_init(void)
 {
        mem_test_reloc();
-       print_vcma9_rev();
+       checkboard();
        show_stdio_dev();
        check_env();
        return 0;
@@ -295,6 +337,15 @@ int overwrite_console(void)
 * Print VCMA9 Info
 ************************************************************************/
 void print_vcma9_info(void)
-{
-    print_vcma9_rev();
+{      
+       unsigned char s[50];
+       int i;
+       
+       if ((i = getenv_r("serial#", s, 32)) < 0) {
+               puts ("### No HW ID - assuming VCMA9");
+               printf("i %d", i*24);
+       } else {
+               s[5] = 0;
+               Show_VCMA9_Info(s, &s[6]);
+       }
 }
index 068eb212e681b28aa9c8a05842eb686263af3f46..c0167d51684c4bd1450e327d4f95e93e270f4724 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2002
+ * (C) Copyright 2002, 2003
  * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
  *
  * See file CREDITS for list of people who contributed to this
@@ -116,11 +116,19 @@ static inline u32 NF_Read_ECC(void)
 
 #endif
 
-
-#define PLD_BASE_ADDRESS               0x2C000100
-#define PLD_ID_REG                     (PLD_BASE_ADDRESS + 0)
-#define PLD_NIC_REG                    (PLD_BASE_ADDRESS + 1)
-#define PLD_CAN_REG                    (PLD_BASE_ADDRESS + 2)
-#define PLD_MISC_REG                   (PLD_BASE_ADDRESS + 3)
-#define PLD_GPCD_REG                   (PLD_BASE_ADDRESS + 4)
-#define PLD_BOARD_REG                  (PLD_BASE_ADDRESS + 5)
+/* VCMA9 PLD regsiters */
+typedef struct {
+       S3C24X0_REG8    ID;
+       S3C24X0_REG8    NIC;
+       S3C24X0_REG8    CAN;
+       S3C24X0_REG8    MISC;
+       S3C24X0_REG8    GPCD;
+       S3C24X0_REG8    BOARD;
+       S3C24X0_REG8    SDRAM;
+} /*__attribute__((__packed__))*/ VCMA9_PLD;
+
+#define VCMA9_PLD_BASE 0x2C000100
+static inline VCMA9_PLD * const VCMA9_GetBase_PLD(void)
+{
+       return (VCMA9_PLD * const)VCMA9_PLD_BASE;
+}
index 74ec64c5b15982072b07624b2507b1eb5475761c..a65bc2232eb82680e86022147a307204d3f79bca 100644 (file)
@@ -27,7 +27,7 @@ LIB   = lib$(CPU).a
 
 START  = start.o
 ASOBJS = io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o
-OBJS   = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o \
+OBJS   = i2c.o traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o \
          loadtask.o fec.o pci_mpc5200.o
 
 all:   .depend $(START) $(ASOBJS) $(LIB)
diff --git a/cpu/mpc5xxx/i2c.c b/cpu/mpc5xxx/i2c.c
new file mode 100644 (file)
index 0000000..640d140
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_HARD_I2C
+
+#include <mpc5xxx.h>
+#include <i2c.h>
+
+#ifdef CFG_I2C_MODULE
+#define I2C_BASE       MPC5XXX_I2C2
+#else
+#define I2C_BASE       MPC5XXX_I2C1
+#endif
+
+#define I2C_TIMEOUT    100
+#define I2C_RETRIES    3
+
+static int  mpc_reg_in    (volatile u32 *reg);
+static void mpc_reg_out   (volatile u32 *reg, int val, int mask);
+static int  wait_for_bb   (void);
+static int  wait_for_pin  (int *status);
+static int  do_address    (uchar chip, char rdwr_flag);
+static int  send_bytes    (uchar chip, char *buf, int len);
+static int  receive_bytes (uchar chip, char *buf, int len);
+
+static int mpc_reg_in(volatile u32 *reg)
+{
+       return *reg >> 24;
+       __asm__ __volatile__ ("eieio");
+}
+
+static void mpc_reg_out(volatile u32 *reg, int val, int mask)
+{
+       int tmp;
+
+       if (!mask) {
+               *reg = val << 24;
+       } else {
+               tmp = mpc_reg_in(reg);
+               *reg = ((tmp & ~mask) | (val & mask)) << 24;
+       }
+       __asm__ __volatile__ ("eieio");
+
+       return;
+}
+
+static int wait_for_bb(void)
+{
+       struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 timeout = I2C_TIMEOUT;
+       int                 status;
+
+       status = mpc_reg_in(&regs->msr);
+
+       while (timeout-- && (status & I2C_BB)) {
+#if 1
+               volatile int temp;
+               mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+               temp = mpc_reg_in(&regs->mdr);
+               mpc_reg_out(&regs->mcr, 0, I2C_STA);
+               mpc_reg_out(&regs->mcr, 0, 0);
+               mpc_reg_out(&regs->mcr, I2C_EN, 0);
+#endif
+               udelay(1000);
+               status = mpc_reg_in(&regs->msr);
+       }
+
+       return (status & I2C_BB);
+}
+
+static int wait_for_pin(int *status)
+{
+       struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 timeout = I2C_TIMEOUT;
+
+       *status = mpc_reg_in(&regs->msr);
+
+       while (timeout-- && !(*status & I2C_IF)) {
+               udelay(1000);
+               *status = mpc_reg_in(&regs->msr);
+       }
+
+       if (!(*status & I2C_IF)) {
+               return -1;
+       }
+
+       mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+       return 0;
+}
+
+static int do_address(uchar chip, char rdwr_flag)
+{
+       struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 status;
+
+       chip <<= 1;
+
+       if (rdwr_flag) {
+               chip |= 1;
+       }
+
+       mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
+       mpc_reg_out(&regs->mdr, chip, 0);
+
+        if (wait_for_pin(&status)) {
+                return -2;
+        }
+
+        if (status & I2C_RXAK) {
+                return -3;
+        }
+
+       return 0;
+}
+
+static int send_bytes(uchar chip, char *buf, int len)
+{
+       struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 wrcount;
+       int                 status;
+
+       for (wrcount = 0; wrcount < len; ++wrcount) {
+
+               mpc_reg_out(&regs->mdr, buf[wrcount], 0);
+
+               if (wait_for_pin(&status)) {
+                       break;
+               }
+
+               if (status & I2C_RXAK) {
+                       break;
+               }
+
+       }
+
+       return !(wrcount == len);
+}
+
+static int receive_bytes(uchar chip, char *buf, int len)
+{
+       struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 dummy   = 1;
+       int                 rdcount = 0;
+       int                 status;
+       int                 i;
+
+       mpc_reg_out(&regs->mcr, 0, I2C_TX);
+
+       for (i = 0; i < len; ++i) {
+               buf[rdcount] = mpc_reg_in(&regs->mdr);
+
+               if (dummy) {
+                       dummy = 0;
+               } else {
+                       rdcount++;
+               }
+
+
+               if (wait_for_pin(&status)) {
+                       return -4;
+               }
+       }
+
+       mpc_reg_out(&regs->mcr, I2C_TXAK, I2C_TXAK);
+       buf[rdcount++] = mpc_reg_in(&regs->mdr);
+
+       if (wait_for_pin(&status)) {
+               return -5;
+       }
+
+       mpc_reg_out(&regs->mcr, 0, I2C_TXAK);
+
+       return 0;
+}
+
+/**************** I2C API ****************/
+
+void i2c_init(int speed, int saddr)
+{
+       struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+
+       mpc_reg_out(&regs->mcr, 0, 0);
+       mpc_reg_out(&regs->madr, saddr << 1, 0);
+
+       /* Set clock
+        */
+       mpc_reg_out(&regs->mfdr, speed, 0);
+
+       /* Enable module
+        */
+       mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
+       mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+       return;
+}
+
+int i2c_probe(uchar chip)
+{
+       struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 i;
+
+       for (i = 0; i < I2C_RETRIES; i++) {
+               mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+
+               if (! do_address(chip, 0)) {
+                       mpc_reg_out(&regs->mcr, 0, I2C_STA);
+                       break;
+               }
+
+               mpc_reg_out(&regs->mcr, 0, I2C_STA);
+               udelay(500);
+       }
+
+       return (i == I2C_RETRIES);
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+       uchar                xaddr[4];
+       struct mpc5xxx_i2c * regs        = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                  ret         = -1;
+
+       xaddr[0] = (addr >> 24) & 0xFF;
+       xaddr[1] = (addr >> 16) & 0xFF;
+       xaddr[2] = (addr >>  8) & 0xFF;
+       xaddr[3] =  addr        & 0xFF;
+
+       if (wait_for_bb()) {
+               printf("i2c_read: bus is busy\n");
+               goto Done;
+       }
+
+       mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+       if (do_address(chip, 0)) {
+               printf("i2c_read: failed to address chip\n");
+               goto Done;
+       }
+
+       if (send_bytes(chip, &xaddr[4-alen], alen)) {
+               printf("i2c_read: send_bytes failed\n");
+               goto Done;
+       }
+
+       mpc_reg_out(&regs->mcr, I2C_RSTA, I2C_RSTA);
+       if (do_address(chip, 1)) {
+               printf("i2c_read: failed to address chip\n");
+               goto Done;
+       }
+
+       if (receive_bytes(chip, buf, len)) {
+               printf("i2c_read: receive_bytes failed\n");
+               goto Done;
+       }
+
+       ret = 0;
+Done:
+       mpc_reg_out(&regs->mcr, 0, I2C_STA);
+       return ret;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+       uchar               xaddr[4];
+       struct mpc5xxx_i2c *regs        = (struct mpc5xxx_i2c *)I2C_BASE;
+       int                 ret         = -1;
+
+       xaddr[0] = (addr >> 24) & 0xFF;
+       xaddr[1] = (addr >> 16) & 0xFF;
+       xaddr[2] = (addr >>  8) & 0xFF;
+       xaddr[3] =  addr        & 0xFF;
+
+        if (wait_for_bb()) {
+               printf("i2c_write: bus is busy\n");
+               goto Done;
+       }
+
+        mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+        if (do_address(chip, 0)) {
+               printf("i2c_write: failed to address chip\n");
+               goto Done;
+       }
+
+       if (send_bytes(chip, &xaddr[4-alen], alen)) {
+               printf("i2c_write: send_bytes failed\n");
+               goto Done;
+       }
+
+       if (send_bytes(chip, buf, len)) {
+               printf("i2c_write: send_bytes failed\n");
+               goto Done;
+       }
+
+       ret = 0;
+Done:
+       mpc_reg_out(&regs->mcr, 0, I2C_STA);
+       return ret;
+}
+
+uchar i2c_reg_read(uchar chip, uchar reg)
+{
+       char buf;
+
+       i2c_read(chip, reg, 1, &buf, 1);
+
+       return buf;
+}
+
+void i2c_reg_write(uchar chip, uchar reg, uchar val)
+{
+       i2c_write(chip, reg, 1, &val, 1);
+
+       return;
+}
+
+#endif /* CONFIG_HARD_I2C */
index 9d914a6bb3a04924e72b3a5b9eb241ff07a3e124..c2c398c75f47bdd27051b5a7b8a99ecc0fd2d372 100644 (file)
@@ -83,7 +83,8 @@
 /*
  * Supported commands
  */
-#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | ADD_PCI_CMD)
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | ADD_PCI_CMD | \
+                                CFG_CMD_I2C | CFG_CMD_EEPROM)
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 /*
  * I2C configuration
  */
+#define CONFIG_HARD_I2C                1       /* I2C with hardware support */
+#define CFG_I2C_MODULE         1       /* If defined then I2C module #2 is used
+                                        * otherwise I2C module #1 is used */
+#ifdef CONFIG_MPC5200
+#define CFG_I2C_SPEED          0x3D    /* 86KHz given 133MHz IPBI */
+#else
+#define CFG_I2C_SPEED          0x35    /* 86KHz given 33MHz IPBI */
+#endif
+#define CFG_I2C_SLAVE          0x7F
+
+/*
+ * EEPROM configuration
+ */
+#define CFG_I2C_EEPROM_ADDR            0x50    /* 1010000x */
+#define CFG_I2C_EEPROM_ADDR_LEN                1
+#define CFG_EEPROM_PAGE_WRITE_BITS     3
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 35
 
 /*
  * Flash configuration
index c0103fc335a4544ede765490337439895233d833..9f868f8c8790bb4dad25555ad5b664aa30f6c498 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2002
+ * (C) Copyright 2002, 2003
  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Marius Groeger <mgroeger@sysgo.de>
  * Gary Jennejohn <gj@denx.de>
 #define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
 
 #define CFG_MEMTEST_START      0x30000000      /* memtest works on     */
-#define CFG_MEMTEST_END                0x33F80000      /* 63.5 MB in DRAM      */
+#define CFG_MEMTEST_END                0x30F80000      /* 15.5 MB in DRAM      */
+
 #define CFG_ALT_MEMTEST
-#define        CFG_LOAD_ADDR           0x33000000      /* default load address */
+#define        CFG_LOAD_ADDR           0x30800000      /* default load address */
 
 
 #undef  CFG_CLKS_IN_HZ         /* everything, incl board info, in Hz */
  */
 #define CONFIG_NR_DRAM_BANKS   1          /* we have 1 bank of DRAM */
 #define PHYS_SDRAM_1           0x30000000 /* SDRAM Bank #1 */
-#define PHYS_SDRAM_1_SIZE      0x04000000 /* 64 MB */
-
 #define PHYS_FLASH_1           0x00000000 /* Flash Bank #1 */
 
 #define CFG_FLASH_BASE         PHYS_FLASH_1
index 02683e3820804a4a905d9f1496e632f4ece08349..b38d7d4a0c28a78564de1895fe7dff0111b52e2e 100644 (file)
 
 #define        MPC5XXX_FEC             (CFG_MBAR + 0x3000)
 
+#define MPC5XXX_I2C1           (CFG_MBAR + 0x3D00)
+#define MPC5XXX_I2C2           (CFG_MBAR + 0x3D40)
+
 #if defined(CONFIG_MGT5100)
 #define MPC5XXX_SRAM           (CFG_MBAR + 0x4000)
 #define MPC5XXX_SRAM_SIZE      (8*1024)
 #define MPC5XXX_GPT0_ENABLE            (MPC5XXX_GPT + 0x0)
 #define MPC5XXX_GPT0_COUNTER           (MPC5XXX_GPT + 0x4)
 
+/* I2Cn control register bits */
+#define I2C_EN         0x80
+#define I2C_IEN                0x40
+#define I2C_STA                0x20
+#define I2C_TX         0x10
+#define I2C_TXAK       0x08
+#define I2C_RSTA       0x04
+#define I2C_INIT_MASK  (I2C_EN | I2C_STA | I2C_TX | I2C_RSTA)
+
+/* I2Cn status register bits */
+#define I2C_CF         0x80
+#define I2C_AAS                0x40
+#define I2C_BB         0x20
+#define I2C_AL         0x10
+#define I2C_SRW                0x04
+#define I2C_IF         0x02
+#define I2C_RXAK       0x01
+
 /* Programmable Serial Controller (PSC) status register bits */
 #define PSC_SR_CDE             0x0080
 #define PSC_SR_RXRDY           0x0100
@@ -505,6 +526,14 @@ struct mpc5xxx_sdma {
        volatile u32 EU37;              /* SDMA + 0xfc */
 };
 
+struct mpc5xxx_i2c {
+       volatile u32 madr;              /* I2Cn + 0x00 */
+       volatile u32 mfdr;              /* I2Cn + 0x04 */
+       volatile u32 mcr;               /* I2Cn + 0x08 */
+       volatile u32 msr;               /* I2Cn + 0x0C */
+       volatile u32 mdr;               /* I2Cn + 0x10 */
+};
+
 /* function prototypes */
 void loadtask(int basetask, int tasks);
 
index bf8008d8da557defb3200ba08894a80dbf51ee20..9e2191e873cc781eac528e91dfe457b55d9c9306 100644 (file)
@@ -80,13 +80,15 @@ void rtc_get (struct rtc_time *tmp)
        SetRTC_Access(RTC_ENABLE);
 
        /* read RTC registers */
-       sec     = rtc->BCDSEC;
-       min     = rtc->BCDMIN;
-       hour    = rtc->BCDHOUR;
-       mday    = rtc->BCDDATE;
-       wday    = rtc->BCDDAY;
-       mon     = rtc->BCDMON;
-       year    = rtc->BCDYEAR;
+       do {
+               sec     = rtc->BCDSEC;
+               min     = rtc->BCDMIN;
+               hour    = rtc->BCDHOUR;
+               mday    = rtc->BCDDATE;
+               wday    = rtc->BCDDAY;
+               mon     = rtc->BCDMON;
+               year    = rtc->BCDYEAR;
+       } while (sec != rtc->BCDSEC);
 
        /* read ALARM registers */
        a_sec   = rtc->ALMSEC;
@@ -170,7 +172,7 @@ void rtc_reset (void)
        S3C24X0_RTC * const rtc = S3C24X0_GetBase_RTC();
 
        rtc->RTCCON = (rtc->RTCCON & ~0x06) | 0x08;
-       rtc->RTCCON &= ~0x08;
+       rtc->RTCCON &= ~(0x08|0x01);
 }
 
 /* ------------------------------------------------------------------------- */