From 531716e1710083f91d9fa351f89d18e271b5c577 Mon Sep 17 00:00:00 2001 From: wdenk Date: Sat, 13 Sep 2003 19:01:12 +0000 Subject: [PATCH] =?UTF-8?q?*=20Patch=20by=20David=20M=FCller,=2013=20Sep?= =?UTF-8?q?=202003:=20=20=20various=20changes=20to=20VCMA9=20board=20speci?= =?UTF-8?q?fic=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add I2C support for MGT5100 / MPC5200 --- CHANGELOG | 5 + README | 3 +- board/mpl/vcma9/cmd_vcma9.c | 46 ++++- board/mpl/vcma9/config.mk | 14 +- board/mpl/vcma9/memsetup.S | 59 ++++++- board/mpl/vcma9/vcma9.c | 127 ++++++++++---- board/mpl/vcma9/vcma9.h | 24 ++- cpu/mpc5xxx/Makefile | 2 +- cpu/mpc5xxx/i2c.c | 338 ++++++++++++++++++++++++++++++++++++ include/configs/IceCube.h | 20 ++- include/configs/VCMA9.h | 9 +- include/mpc5xxx.h | 29 ++++ rtc/s3c24x0_rtc.c | 18 +- 13 files changed, 616 insertions(+), 78 deletions(-) create mode 100644 cpu/mpc5xxx/i2c.c diff --git a/CHANGELOG b/CHANGELOG index b034331a51c..c058cc43883 100644 --- 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 0503ccb1408..e431c29a744 100644 --- 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) diff --git a/board/mpl/vcma9/cmd_vcma9.c b/board/mpl/vcma9/cmd_vcma9.c index 32fa33403f4..3b0453521d8 100644 --- a/board/mpl/vcma9/cmd_vcma9.c +++ b/board/mpl/vcma9/cmd_vcma9.c @@ -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" +); + diff --git a/board/mpl/vcma9/config.mk b/board/mpl/vcma9/config.mk index 95d69cc6cc8..942d42ef6a2 100644 --- a/board/mpl/vcma9/config.mk +++ b/board/mpl/vcma9/config.mk @@ -1,5 +1,5 @@ # -# (C) Copyright 2002 +# (C) Copyright 2002, 2003 # David Mueller, ELSOFT AG, # # 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 diff --git a/board/mpl/vcma9/memsetup.S b/board/mpl/vcma9/memsetup.S index 7b4193d0e88..ab6590153cd 100644 --- a/board/mpl/vcma9/memsetup.S +++ b/board/mpl/vcma9/memsetup.S @@ -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 + .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 + BURST_EN .word 0x30 .word 0x30 diff --git a/board/mpl/vcma9/vcma9.c b/board/mpl/vcma9/vcma9.c index 359e565761a..33cec025291 100644 --- a/board/mpl/vcma9/vcma9.c +++ b/board/mpl/vcma9/vcma9.c @@ -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) { - return(*(volatile uchar *)PLD_ID_REG); + VCMA9_PLD * const pld = VCMA9_GetBase_PLD(); + + return(pld->ID); } -static uchar Get_PLD_BOARD(void) +static u8 Get_PLD_BOARD(void) { - return(*(volatile uchar *)PLD_BOARD_REG); + VCMA9_PLD * const pld = VCMA9_GetBase_PLD(); + + return(pld->BOARD); } -static uchar Get_PLD_Version(void) +static u8 Get_PLD_SDRAM(void) +{ + VCMA9_PLD * const pld = VCMA9_GetBase_PLD(); + + return(pld->SDRAM); +} + +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]); + } } diff --git a/board/mpl/vcma9/vcma9.h b/board/mpl/vcma9/vcma9.h index 068eb212e68..c0167d51684 100644 --- a/board/mpl/vcma9/vcma9.h +++ b/board/mpl/vcma9/vcma9.h @@ -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 +/* 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 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) +#define VCMA9_PLD_BASE 0x2C000100 +static inline VCMA9_PLD * const VCMA9_GetBase_PLD(void) +{ + return (VCMA9_PLD * const)VCMA9_PLD_BASE; +} diff --git a/cpu/mpc5xxx/Makefile b/cpu/mpc5xxx/Makefile index 74ec64c5b15..a65bc2232eb 100644 --- a/cpu/mpc5xxx/Makefile +++ b/cpu/mpc5xxx/Makefile @@ -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 index 00000000000..640d14022fc --- /dev/null +++ b/cpu/mpc5xxx/i2c.c @@ -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 + +#ifdef CONFIG_HARD_I2C + +#include +#include + +#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(®s->msr); + + while (timeout-- && (status & I2C_BB)) { +#if 1 + volatile int temp; + mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); + temp = mpc_reg_in(®s->mdr); + mpc_reg_out(®s->mcr, 0, I2C_STA); + mpc_reg_out(®s->mcr, 0, 0); + mpc_reg_out(®s->mcr, I2C_EN, 0); +#endif + udelay(1000); + status = mpc_reg_in(®s->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(®s->msr); + + while (timeout-- && !(*status & I2C_IF)) { + udelay(1000); + *status = mpc_reg_in(®s->msr); + } + + if (!(*status & I2C_IF)) { + return -1; + } + + mpc_reg_out(®s->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(®s->mcr, I2C_TX, I2C_TX); + mpc_reg_out(®s->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(®s->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(®s->mcr, 0, I2C_TX); + + for (i = 0; i < len; ++i) { + buf[rdcount] = mpc_reg_in(®s->mdr); + + if (dummy) { + dummy = 0; + } else { + rdcount++; + } + + + if (wait_for_pin(&status)) { + return -4; + } + } + + mpc_reg_out(®s->mcr, I2C_TXAK, I2C_TXAK); + buf[rdcount++] = mpc_reg_in(®s->mdr); + + if (wait_for_pin(&status)) { + return -5; + } + + mpc_reg_out(®s->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(®s->mcr, 0, 0); + mpc_reg_out(®s->madr, saddr << 1, 0); + + /* Set clock + */ + mpc_reg_out(®s->mfdr, speed, 0); + + /* Enable module + */ + mpc_reg_out(®s->mcr, I2C_EN, I2C_INIT_MASK); + mpc_reg_out(®s->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(®s->mcr, I2C_STA, I2C_STA); + + if (! do_address(chip, 0)) { + mpc_reg_out(®s->mcr, 0, I2C_STA); + break; + } + + mpc_reg_out(®s->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(®s->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(®s->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(®s->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(®s->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(®s->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 */ diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h index 9d914a6bb3a..c2c398c75f4 100644 --- a/include/configs/IceCube.h +++ b/include/configs/IceCube.h @@ -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 @@ -98,6 +99,23 @@ /* * 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 diff --git a/include/configs/VCMA9.h b/include/configs/VCMA9.h index c0103fc335a..9f868f8c879 100644 --- a/include/configs/VCMA9.h +++ b/include/configs/VCMA9.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2002 + * (C) Copyright 2002, 2003 * Sysgo Real-Time Solutions, GmbH * Marius Groeger * Gary Jennejohn @@ -160,9 +160,10 @@ #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 */ @@ -197,8 +198,6 @@ */ #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 diff --git a/include/mpc5xxx.h b/include/mpc5xxx.h index 02683e38208..b38d7d4a0c2 100644 --- a/include/mpc5xxx.h +++ b/include/mpc5xxx.h @@ -108,6 +108,9 @@ #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) @@ -197,6 +200,24 @@ #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); diff --git a/rtc/s3c24x0_rtc.c b/rtc/s3c24x0_rtc.c index bf8008d8da5..9e2191e873c 100644 --- a/rtc/s3c24x0_rtc.c +++ b/rtc/s3c24x0_rtc.c @@ -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); } /* ------------------------------------------------------------------------- */