summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brandt <Michael.Brandt@stericsson.com>2009-10-22 09:51:29 +0200
committerMichael Brandt <Michael.Brandt@stericsson.com>2009-10-22 09:51:29 +0200
commiteb3f0f68ba384f179bb57ad8d5b0cd095eb4d7a4 (patch)
tree98b64d6c34d3da35ed1ffe225a2404c277115373
parente71fc7b2b3a228383e770a7d78150497d9c48d3c (diff)
new files for u8500 support.
-rwxr-xr-xboard/st/u8500/Makefile52
-rwxr-xr-xboard/st/u8500/common.h134
-rwxr-xr-xboard/st/u8500/config.mk5
-rwxr-xr-xboard/st/u8500/emmc.c404
-rwxr-xr-xboard/st/u8500/emmc.h37
-rwxr-xr-xboard/st/u8500/flash.c109
-rwxr-xr-xboard/st/u8500/gpio.c253
-rwxr-xr-xboard/st/u8500/gpio.h524
-rwxr-xr-xboard/st/u8500/i2c.c3029
-rwxr-xr-xboard/st/u8500/i2c.h848
-rwxr-xr-xboard/st/u8500/init_mmc.c363
-rwxr-xr-xboard/st/u8500/init_mmc.h44
-rwxr-xr-xboard/st/u8500/mmc.c2580
-rwxr-xr-xboard/st/u8500/mmc.h263
-rwxr-xr-xboard/st/u8500/mmc_p.h316
-rwxr-xr-xboard/st/u8500/mmc_utils.c956
-rwxr-xr-xboard/st/u8500/mmc_utils.h108
-rwxr-xr-xboard/st/u8500/u8500.c140
-rwxr-xr-xcommon/env_emmc.c224
-rwxr-xr-xcpu/arm_cortexa9/Makefile47
-rwxr-xr-xcpu/arm_cortexa9/config.mk36
-rwxr-xr-xcpu/arm_cortexa9/cpu.c249
-rwxr-xr-xcpu/arm_cortexa9/start.S524
-rwxr-xr-xcpu/arm_cortexa9/start.S.bak502
-rwxr-xr-xcpu/arm_cortexa9/stw8500/Makefile46
-rwxr-xr-xcpu/arm_cortexa9/stw8500/interrupts.c181
-rwxr-xr-xcpu/arm_cortexa9/stw8500/timer.c70
-rwxr-xr-xcpu/arm_cortexa9/u-boot.lds58
-rwxr-xr-xinclude/asm-arm/arch-stw8500/bits.h59
-rwxr-xr-xinclude/asm-arm/arch-stw8500/common.h134
-rwxr-xr-xinclude/asm-arm/arch-stw8500/emmc.h37
-rwxr-xr-xinclude/asm-arm/arch-stw8500/gpio.h524
-rwxr-xr-xinclude/asm-arm/arch-stw8500/mmc.h85
-rwxr-xr-xinclude/asm-arm/arch-stw8500/mtu.h66
-rwxr-xr-xinclude/configs/u8500.h226
35 files changed, 13233 insertions, 0 deletions
diff --git a/board/st/u8500/Makefile b/board/st/u8500/Makefile
new file mode 100755
index 000000000..78eece7fe
--- /dev/null
+++ b/board/st/u8500/Makefile
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2009
+# ST-Ericsson, <www.stericsson.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+CFLAGS += -D__RELEASE -D__STN_8500
+LIB = $(obj)lib$(BOARD).a
+
+COBJS := u8500.o flash.o gpio.o i2c.o mmc.o mmc_utils.o init_mmc.o emmc.o
+SOBJS :=
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/st/u8500/common.h b/board/st/u8500/common.h
new file mode 100755
index 000000000..b6185081a
--- /dev/null
+++ b/board/st/u8500/common.h
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+#include <common.h>
+
+#define PASS (1)
+#define FAIL (0)
+
+#define IO(addr) (*((u32*) (addr)))
+#define HIO(addr) (*((u16*) (addr)))
+#define BIO(addr) (*((u8*) (addr)))
+
+/*
+ * macro to get at IO space
+ */
+#define IO_ADDRESS(x) (x)
+
+#define REG_WRITE_BITS(reg,val,mask,sb) (writel(((readl(reg) & ~(mask)) | (((val)<<(sb)) & (mask))), reg))
+
+#define nmdk_error(format, arg...) printf(": " format "\n" , ## arg)
+
+#if !defined(FALSE) && !defined(TRUE)
+typedef enum {FALSE, TRUE} t_bool;
+#else /* FALSE & TRUE already defined */
+typedef enum {BOOL_FALSE, BOOL_TRUE} t_bool;
+#endif /* !defined(FALSE) && !defined(TRUE) */
+
+/*-----------------------------------------------------------------------------
+ * Bit mask definition
+ *---------------------------------------------------------------------------*/
+#define MASK_NULL8 0x00
+#define MASK_NULL16 0x0000
+#define MASK_NULL32 0x00000000
+#define MASK_ALL8 0xFF
+#define MASK_ALL16 0xFFFF
+#define MASK_ALL32 0xFFFFFFFF
+
+#define MASK_BIT0 (1UL<<0)
+#define MASK_BIT1 (1UL<<1)
+#define MASK_BIT2 (1UL<<2)
+#define MASK_BIT3 (1UL<<3)
+#define MASK_BIT4 (1UL<<4)
+#define MASK_BIT5 (1UL<<5)
+#define MASK_BIT6 (1UL<<6)
+#define MASK_BIT7 (1UL<<7)
+#define MASK_BIT8 (1UL<<8)
+#define MASK_BIT9 (1UL<<9)
+#define MASK_BIT10 (1UL<<10)
+#define MASK_BIT11 (1UL<<11)
+#define MASK_BIT12 (1UL<<12)
+#define MASK_BIT13 (1UL<<13)
+#define MASK_BIT14 (1UL<<14)
+#define MASK_BIT15 (1UL<<15)
+#define MASK_BIT16 (1UL<<16)
+#define MASK_BIT17 (1UL<<17)
+#define MASK_BIT18 (1UL<<18)
+#define MASK_BIT19 (1UL<<19)
+#define MASK_BIT20 (1UL<<20)
+#define MASK_BIT21 (1UL<<21)
+#define MASK_BIT22 (1UL<<22)
+#define MASK_BIT23 (1UL<<23)
+#define MASK_BIT24 (1UL<<24)
+#define MASK_BIT25 (1UL<<25)
+#define MASK_BIT26 (1UL<<26)
+#define MASK_BIT27 (1UL<<27)
+#define MASK_BIT28 (1UL<<28)
+#define MASK_BIT29 (1UL<<29)
+#define MASK_BIT30 (1UL<<30)
+#define MASK_BIT31 (1UL<<31)
+
+#define NOMADIK_INTERNAL_ERROR (-8)
+#define NOMADIK_NOT_CONFIGURED (-7)
+#define NOMADIK_REQUEST_PENDING (-6)
+#define NOMADIK_REQUEST_NOT_APPLICABLE (-5)
+#define NOMADIK_INVALID_PARAMETER (-4)
+#define NOMADIK_UNSUPPORTED_FEATURE (-3)
+#define NOMADIK_UNSUPPORTED_HW (-2)
+#define NOMADIK_ERROR (-1)
+#define NOMADIK_OK ( 0)
+#define NOMADIK_INTERNAL_EVENT ( 1)
+#define NOMADIK_REMAINING_PENDING_EVENTS ( 2)
+#define NOMADIK_REMAINING_FILTER_PENDING_EVENTS ( 3)
+#define NOMADIK_NO_MORE_PENDING_EVENT ( 4)
+#define NOMADIK_NO_MORE_FILTER_PENDING_EVENT ( 5)
+#define NOMADIK_NO_PENDING_EVENT_ERROR ( 7)
+
+
+#define NOMADIK_MAX_ERROR_VALUE (-65) /* HW specific error codes
+ * should start from this offset
+ */
+/*-----------------------------------------------------------------------------
+ * Bit setting or clearing
+ *---------------------------------------------------------------------------*/
+#define NOMADIK_SET_BITS(reg,mask) ((reg) |= (mask))
+#define NOMADIK_CLEAR_BITS(reg,mask) ((reg) &= ~(mask))
+#define NOMADIK_READ_BITS(reg,mask) ((reg) & (mask))
+#define NOMADIK_WRITE_BITS(reg,val,mask) ((reg) = (((reg) & ~(mask)) | ((val) & (mask))))
+#define NOMADIK_READ_REG(reg) (reg)
+#define NOMADIK_WRITE_REG(reg,val) ((reg) = (val))
+
+/*
+ * Definition of the different kind of addresses manipulated into a system with MMU
+ * (handle physical AND logical addresses)
+ */
+
+typedef u32 t_physical_address;
+typedef u32 t_logical_address;
+
+/*function prototypes*/
+void gpio_init(void);
+int emmc_init (u8);
+
+#endif /* _COMMON_H_ */
diff --git a/board/st/u8500/config.mk b/board/st/u8500/config.mk
new file mode 100755
index 000000000..a75eda429
--- /dev/null
+++ b/board/st/u8500/config.mk
@@ -0,0 +1,5 @@
+#
+# image should be loaded at 0x01000000
+#
+
+TEXT_BASE = 0x07F80000
diff --git a/board/st/u8500/emmc.c b/board/st/u8500/emmc.c
new file mode 100755
index 000000000..780ddaebc
--- /dev/null
+++ b/board/st/u8500/emmc.c
@@ -0,0 +1,404 @@
+/*
+* (C) Copyright 2009
+* ST-Ericsson, <www.stericsson.com>
+*
+* See file CREDITS for list of people who contributed to this
+* project.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+* MA 02111-1307 USA
+*/
+/* --- includes ----------------------------------------------------------- */
+#include "common.h" /* XXX: Arrgghh! "common.h" includes <common.h> */
+#include <command.h>
+#include "mmc.h"
+#include "emmc.h"
+#include "gpio.h"
+
+#define PIB_EMMC_ADDR 0x00
+/* ========================================================================
+Name: init_emmc
+Description: init embedded multimedia card interface
+
+======================================================================== */
+int emmc_init(u8 card_num)
+{
+ t_mmc_error mmc_error;
+ t_mmc_error response;
+ gpio_error gpioerror;
+ int error;
+
+#ifndef CONFIG_U8500_V1
+/* Initialize the base address of eMMC */
+ mmc_error = mmc_init(card_num, CFG_EMMC_BASE);
+
+ if (MMC_OK != mmc_error)
+ {
+ printf("emmc_init() %d \n", mmc_error);
+ goto end;
+ }
+
+ /* Initialize the gpio alternate function for eMMC */
+ struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_6_BASE);
+ p_gpio_register -> gpio_dats |= 0x0000FFE0;
+ p_gpio_register -> gpio_pdis &= ~0x0000FFE0;
+
+ //enable the alternate function of EMMC
+ gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC");
+ if(gpioerror != GPIO_OK)
+ {
+ printf("emmc_init() gpio_altfuncenable %d failed\n", gpioerror);
+ goto end;
+ }
+
+#else
+/* Initialize the base address of PoP eMMC */
+ mmc_error = mmc_init(card_num, CFG_POP_EMMC_BASE);
+
+ if (MMC_OK != mmc_error)
+ {
+ printf("emmc_init() %d \n", mmc_error);
+ goto end;
+ }
+ //enable the alternate function of PoP EMMC
+ gpioerror = gpio_altfuncenable(GPIO_ALT_POP_EMMC, "EMMC");
+ if (gpioerror != GPIO_OK) {
+ printf("emmc_init() gpio_altfuncenable %d failed \n",
+ gpioerror);
+ goto end;
+ }
+#endif
+ //Power-on the controller
+ response = mmc_poweron(card_num);
+ if (response != MMC_OK)
+ {
+ printf("Error in eMMC power on, response is %d\n",response);
+ goto end;
+ }
+ // Initialise the cards,get CID and CSD on the bus
+ response = mmc_initializeCards(card_num);
+
+ if (response != MMC_OK)
+ {
+ printf(" Error in eMMC initialization\n");
+ goto end;
+ }
+
+ error = emmc_write_pib();
+ if(error)
+ printf("PIB info writing into eMMC failed\n");
+ printf("eMMC done\n");
+
+ return 0;
+
+end:
+#ifndef CONFIG_U8500_V1
+ gpio_altfuncdisable(GPIO_ALT_EMMC, "EMMC");
+#else
+ gpio_altfuncdisable(GPIO_ALT_POP_EMMC, "EMMC");
+#endif
+ mmc_poweroff(card_num);
+ return 1;
+}
+
+int emmc_write_pib(void)
+{
+ int i;
+ t_mmc_error mmc_error;
+ u32 block_offset = PIB_EMMC_ADDR;
+ u8 emmc_last_sector[512];
+ u8 card_num = 4;
+
+ for (i = 0; i < 0x1BF; i++) {
+ emmc_last_sector[i] = 0;
+ }
+ emmc_last_sector[0x1BF] = 0x03;
+ emmc_last_sector[0x1C0] = 0xD0;
+ emmc_last_sector[0x1C1] = 0xFF;
+ emmc_last_sector[0x1C2] = 0x83;
+ emmc_last_sector[0x1C3] = 0x03;
+ emmc_last_sector[0x1C4] = 0xD0;
+ emmc_last_sector[0x1C5] = 0xFF;
+ emmc_last_sector[0x1C6] = 0x00;
+ emmc_last_sector[0x1C7] = 0x00;
+ emmc_last_sector[0x1C8] = 0x0A;
+ emmc_last_sector[0x1C9] = 0x00;
+ emmc_last_sector[0x1CA] = 0x00;
+ emmc_last_sector[0x1CB] = 0x40;
+ emmc_last_sector[0x1CC] = 0x00;
+ emmc_last_sector[0x1CD] = 0x00;
+ emmc_last_sector[0x1CE] = 0x00;
+ emmc_last_sector[0x1CF] = 0x03;
+ emmc_last_sector[0x1D0] = 0xD0;
+ emmc_last_sector[0x1D1] = 0xFF;
+ emmc_last_sector[0x1D2] = 0x83;
+ emmc_last_sector[0x1D3] = 0x03;
+ emmc_last_sector[0x1D4] = 0xD0;
+ emmc_last_sector[0x1D5] = 0xFF;
+ emmc_last_sector[0x1D6] = 0x00;
+ emmc_last_sector[0x1D7] = 0x40;
+ emmc_last_sector[0x1D8] = 0x0A;
+ emmc_last_sector[0x1D9] = 0x00;
+ emmc_last_sector[0x1DA] = 0x00;
+ emmc_last_sector[0x1DB] = 0x00;
+ emmc_last_sector[0x1DC] = 0x08;
+ emmc_last_sector[0x1DD] = 0x00;
+ emmc_last_sector[0x1DE] = 0x00;
+ emmc_last_sector[0x1DF] = 0x03;
+ emmc_last_sector[0x1E0] = 0xD0;
+ emmc_last_sector[0x1E1] = 0xFF;
+ emmc_last_sector[0x1E2] = 0x83;
+ emmc_last_sector[0x1E3] = 0x03;
+ emmc_last_sector[0x1E4] = 0xD0;
+ emmc_last_sector[0x1E5] = 0xFF;
+ emmc_last_sector[0x1E6] = 0x00;
+ emmc_last_sector[0x1E7] = 0x40;
+ emmc_last_sector[0x1E8] = 0x12;
+ emmc_last_sector[0x1E9] = 0x00;
+ emmc_last_sector[0x1EA] = 0x00;
+ emmc_last_sector[0x1EB] = 0xC0;
+ emmc_last_sector[0x1EC] = 0x22;
+ emmc_last_sector[0x1ED] = 0x00;
+ emmc_last_sector[0x1EE] = 0x00;
+ emmc_last_sector[0x1EF] = 0x03;
+ emmc_last_sector[0x1F0] = 0xD0;
+ emmc_last_sector[0x1F1] = 0xFF;
+ emmc_last_sector[0x1F2] = 0x0C;
+ emmc_last_sector[0x1F3] = 0x03;
+ emmc_last_sector[0x1F4] = 0xD0;
+ emmc_last_sector[0x1F5] = 0xFF;
+ emmc_last_sector[0x1F6] = 0x00;
+ emmc_last_sector[0x1F7] = 0x00;
+ emmc_last_sector[0x1F8] = 0x35;
+ emmc_last_sector[0x1F9] = 0x00;
+ emmc_last_sector[0x1FA] = 0x00;
+ emmc_last_sector[0x1FB] = 0x00;
+ emmc_last_sector[0x1FC] = 0xC0;
+ emmc_last_sector[0x1FD] = 0x00;
+ emmc_last_sector[0x1FE] = 0x55;
+ emmc_last_sector[0x1FF] = 0xAA;
+
+/* HACK required for HREF board as erase block size = 512KB */
+/*
+ mmc_error = mmc_erase(card_num, 0x0, 0x1FF);
+ if (mmc_error != MMC_OK) {
+ printf(" eMMC erase failed in PIB \n");
+ return 1;
+ }
+*/
+ mmc_error =
+ mmc_writeblocks(card_num, block_offset, (u32 *) emmc_last_sector,
+ 512, 1);
+ if (mmc_error != MMC_OK) {
+ printf(" eMMC PIB write failed \n");
+ return 1;
+ }
+ return 0;
+}
+
+int emmc_erase(u32 start, u32 end)
+{
+ t_mmc_error mmc_error;
+ u8 card_num = 4;
+ printf("emmc erase start \n");
+ mmc_error = mmc_erase(card_num, start, end);
+ if (mmc_error != MMC_OK) {
+ printf(" eMMC erase failed \n");
+ return 1;
+ }
+ printf("emmc erase done \n");
+ return 0;
+}
+
+int emmc_read(u32 block_offset, u32 read_buffer, u32 filesize)
+{
+ t_mmc_error mmc_error;
+ u32 remaining;
+ u8 card_num = 4;
+ u8 *mem_address = (u8 *) read_buffer;
+ u32 n=filesize,blocks;
+
+ remaining = filesize;
+
+ printf(" eMMC read start filesize=0x%x \n", filesize);
+
+ blocks = (n%512==0)?(n/512):(n/512)+1;
+
+ while(blocks>=8)
+ {
+ mmc_error = mmc_readblocks(card_num, block_offset, (u32 *) mem_address, 512, 8);
+ if (mmc_error != MMC_OK)
+ {
+ printf(" eMMC read blocks failed \n");
+ return 1;
+ }
+
+ block_offset += 4096;
+ mem_address += 4096;
+ blocks -=8;
+ remaining -= 4096;
+ }
+ if(blocks)
+ {
+ mmc_error = mmc_readblocks(card_num, block_offset, (u32 *) mem_address, 512, blocks);
+ if (mmc_error != MMC_OK)
+ {
+ printf(" eMMC read blocks failed \n");
+ return 1;
+ }
+ }
+ printf(" eMMC read done \n");
+ return 0;
+}
+
+int emmc_write(u32 block_offset, u32 write_buffer, u32 filesize)
+{
+ t_mmc_error mmc_error;
+ u32 remaining;
+ u8 card_num = 4;
+ u8 *mem_address = (u8 *) write_buffer;
+ u32 n=filesize,blocks;
+
+ remaining = filesize;
+
+ printf(" eMMC write start filesize=0x%x \n", filesize);
+
+ blocks = (n%512==0)?(n/512):(n/512)+1;
+ while(blocks>=8)
+ {
+ mmc_error = mmc_writeblocks(card_num, block_offset, (u32 *) mem_address,512, 8);
+ if (mmc_error != MMC_OK)
+ {
+ printf(" eMMC write blocks failed \n");
+ return 1;
+ }
+
+ block_offset += 4096;
+ mem_address += 4096;
+ blocks -=8;
+ remaining -= 4096;
+ }
+ if(blocks)
+ {
+
+ mmc_error = mmc_writeblocks(card_num, block_offset, (u32 *) mem_address,512, blocks);
+ if (mmc_error != MMC_OK)
+ {
+ printf(" eMMC write blocks failed \n");
+ return 1;
+ }
+
+ }
+
+ printf(" eMMC write done \n");
+ return 0;
+}
+
+/*
+ * command line commands
+ */
+#ifdef CONFIG_CMD_EMMC
+int do_emmc_erase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ u32 start_address;
+ u32 end_address;
+ int load_result = 1;
+ u32 error_name = 0;
+
+ start_address = simple_strtoul (argv[1],0,16);
+ end_address = simple_strtoul (argv[2],0,16);
+
+ printf("emmc_erase :: start address = %x end_address=0x%x\n",start_address,end_address);
+
+ load_result = emmc_erase(start_address,end_address);
+ if (load_result != 0)
+ {
+ error_name = (unsigned long) (-load_result);
+ printf("emmc_erase error : failed \n");
+ }
+ return(0);
+}
+
+U_BOOT_CMD(
+ emmc_erase, 3, 0, do_emmc_erase,
+ "- erase the eMMC flash \n",
+ "start_address- start address of the eMMC block\n"
+ "end_address- end address of the eMMC block\n"
+);
+
+int do_emmc_read (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ u32 ram_address;
+ u32 block_offset;
+ u32 filesize;
+ int load_result = 1;
+ u32 error_name = 0;
+
+ ram_address = simple_strtoul (argv[1],0,16);
+ block_offset = simple_strtoul (argv[2],0,16);
+ filesize = simple_strtoul (argv[3],0,16);
+
+ printf("emmc_read :: ram address = 0x%x block address=0x%x \n",ram_address,block_offset);
+
+ load_result = emmc_read(block_offset,ram_address,filesize);
+ if (load_result != 0)
+ {
+ error_name = (unsigned long) (-load_result);
+ printf("emmc_read error : in reading data from eMMC block \n");
+ }
+ return(0);
+}
+
+U_BOOT_CMD(
+ emmc_read, 4, 0, do_emmc_read,
+ "- read file from emmc flash \n",
+ "ram_address - read from eMMC and copy into ram address\n"
+ "block_offset - address to read the file from the eMMC block \n"
+ "filesize - size of the file \n"
+);
+
+int do_emmc_write (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ u32 ram_address;
+ u32 block_offset;
+ u32 filesize;
+ int load_result = 1;
+ u32 error_name = 0;
+
+ ram_address = simple_strtoul (argv[1],0,16);
+ block_offset = simple_strtoul (argv[2],0,16);
+ filesize = simple_strtoul (argv[3],0,16);
+
+ printf("emmc_write :: ram address = %x block address=0x%x \n",ram_address,block_offset);
+
+ load_result = emmc_write(block_offset,ram_address,filesize);
+ if (load_result != 0)
+ {
+ error_name = (unsigned long) (-load_result);
+ printf("emmc_read error : in writing data into eMMC block \n");
+ }
+ return(0);
+}
+
+U_BOOT_CMD(
+ emmc_write, 4, 0, do_emmc_write,
+ "- write file from emmc flash \n",
+ "ram_address - write to eMMC by copying from ram address\n"
+ "block_offset - address to write the file into the eMMC block \n"
+ "filesize - size of the file \n"
+);
+
+#endif /* CONFIG_CMD_EMMC */
+/* ------------------------------- End of file ---------------------------- */
diff --git a/board/st/u8500/emmc.h b/board/st/u8500/emmc.h
new file mode 100755
index 000000000..aa4b48df0
--- /dev/null
+++ b/board/st/u8500/emmc.h
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _STM_EMMC_H
+#define _STM_EMMC_H
+
+
+#include <common.h>
+
+extern int emmc_init (u8);
+int emmc_erase(u32, u32);
+int emmc_read (u32,u32,u32);
+int emmc_write(u32,u32,u32);
+int emmc_write_pib(void);
+
+
+#endif /* !defined(_STM_EMMC_H) */
diff --git a/board/st/u8500/flash.c b/board/st/u8500/flash.c
new file mode 100755
index 000000000..299c31992
--- /dev/null
+++ b/board/st/u8500/flash.c
@@ -0,0 +1,109 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Support for ST NOR flash M30L0R7KB02AQ and M30L0R7KT02AQ */
+
+#include <common.h>
+#include <linux/byteorder/swab.h>
+
+#undef DEBUG_FLASH
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/* Board support for 1 or 2 flash devices */
+#undef FLASH_PORT_WIDTH32
+#define FLASH_PORT_WIDTH16
+
+#ifdef FLASH_PORT_WIDTH16
+#define FLASH_PORT_WIDTH ushort
+#define FLASH_PORT_WIDTHV vu_short
+#define SWAP(x) __swab16(x)
+#else
+#define FLASH_PORT_WIDTH ulong
+#define FLASH_PORT_WIDTHV vu_long
+#define SWAP(x) __swab32(x)
+#endif
+
+#define FPW FLASH_PORT_WIDTH
+#define FPWV FLASH_PORT_WIDTHV
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+unsigned long flash_init(void);
+/*static ulong flash_get_size(FPW * addr, flash_info_t * info);
+static int write_data(flash_info_t * info, ulong dest, FPW data);
+static void flash_get_offsets(ulong base, flash_info_t * info);*/
+void inline spin_wheel(void);
+void flash_print_info(flash_info_t * info);
+void flash_unprotect_sectors(FPWV * addr);
+int flash_erase(flash_info_t * info, int s_first, int s_last);
+int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init(void)
+{
+ ulong size = 0;
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info(flash_info_t * info)
+{
+}
+
+/* unprotects a sector for write and erase
+ * on some intel parts, this unprotects the entire chip, but it
+ * wont hurt to call this additional times per sector...
+ */
+void flash_unprotect_sectors(FPWV * addr)
+{
+ return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase(flash_info_t * info, int s_first, int s_last)
+{
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ return 0;
+}
+
+void inline spin_wheel(void)
+{
+}
diff --git a/board/st/u8500/gpio.c b/board/st/u8500/gpio.c
new file mode 100755
index 000000000..4062d022b
--- /dev/null
+++ b/board/st/u8500/gpio.c
@@ -0,0 +1,253 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/* --- includes ----------------------------------------------------------- */
+
+#include "gpio.h"
+
+static struct gpio_register *addr_gpio_register[GPIO_BLOCKS_COUNT];
+
+int sz_altfun_tbl;
+
+struct gpio_altfun_data altfun_table[] = {
+ {.altfun = GPIO_ALT_UART_0_MODEM,.start = 0,.end = 3,.cont = 1,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_UART_0_MODEM,.start = 33,.end = 36,.cont = 0,.type =
+ GPIO_ALTF_C,},
+ {.altfun = GPIO_ALT_UART_1,.start = 4,.end = 7,.cont = 0,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_UART_2,.start = 18,.end = 19,.cont = 1,.type =
+ GPIO_ALTF_B,},
+ {.altfun = GPIO_ALT_UART_2,.start = 29,.end = 32,.cont = 0,.type =
+ GPIO_ALTF_C,},
+ {.altfun = GPIO_ALT_MSP_0,.start = 12,.end = 17,.cont = 1,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_MSP_0,.start = 21,.end = 21,.cont = 0,.type =
+ GPIO_ALTF_B,},
+ {.altfun = GPIO_ALT_MSP_1,.start = 33,.end = 36,.cont = 0,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_MSP_2,.start = 192,.end = 196,.cont = 0,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_LCD_PANEL,.start = 64,.end = 93,.cont = 1,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_LCD_PANEL,.start = 150,.end = 171,.cont = 0,.type =
+ GPIO_ALTF_B,},
+ {.altfun = GPIO_ALT_SD_CARD0,.start = 18,.end = 28,.cont = 0,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_MM_CARD0,.start = 18,.end = 32,.cont = 0,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_USB_OTG,.start = 256,.end = 267,.cont = 0,.type =
+ GPIO_ALTF_A,},
+ {.altfun = GPIO_ALT_EMMC,.start = 197,.end = 207,.cont = 0,.type =
+ GPIO_ALTF_A,},
+#ifdef CONFIG_STM_8500_V1
+ {.altfun = GPIO_ALT_POP_EMMC,.start = 128,.end = 138,.cont = 0,.type =
+ GPIO_ALTF_A,},
+#endif
+};
+
+/*
+ * Static Function declarations
+ */
+gpio_error gpio_setpinconfig(gpio_pin pin_id, gpio_config * config)
+{
+ struct gpio_register *p_gpio_register = addr_gpio_register[GPIO_BLOCK(pin_id)];
+ u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
+ gpio_error gpio_error = GPIO_OK;
+ u32 temp_reg;
+
+ switch (config->mode) {
+ case GPIO_ALTF_A:
+ temp_reg = readl(&p_gpio_register->gpio_afsa);
+ temp_reg |= mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsa);
+ temp_reg = readl(&p_gpio_register->gpio_afsb);
+ temp_reg &= ~mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsb);
+ break;
+ case GPIO_ALTF_B:
+ temp_reg = readl(&p_gpio_register->gpio_afsa);
+ temp_reg &= ~mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsa);
+ temp_reg = readl(&p_gpio_register->gpio_afsb);
+ temp_reg |= mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsb);
+ break;
+ case GPIO_ALTF_C:
+ temp_reg = readl(&p_gpio_register->gpio_afsa);
+ temp_reg |= mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsa);
+ temp_reg = readl(&p_gpio_register->gpio_afsb);
+ temp_reg |= mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsb);
+ break;
+ case GPIO_MODE_SOFTWARE:
+ temp_reg = readl(&p_gpio_register->gpio_afsa);
+ temp_reg &= ~mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsa);
+ temp_reg = readl(&p_gpio_register->gpio_afsb);
+ temp_reg &= ~mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsb);
+
+ switch (config->direction) {
+ case GPIO_DIR_INPUT:
+ writel(mask, &p_gpio_register->gpio_dirc);
+ break;
+ case GPIO_DIR_OUTPUT:
+ writel(mask, &p_gpio_register->gpio_dirs);
+ break;
+ case GPIO_DIR_LEAVE_UNCHANGED:
+ break;
+ default:
+ return (GPIO_INVALID_PARAMETER);
+ }
+
+ break;
+ case GPIO_MODE_LEAVE_UNCHANGED:
+ break;
+ default:
+ return (GPIO_INVALID_PARAMETER);
+ }
+ return (gpio_error);
+}
+
+gpio_error gpio_resetgpiopin(gpio_pin pin_id, char *dev_name)
+{
+ struct gpio_register *p_gpio_register = addr_gpio_register[GPIO_BLOCK(pin_id)];
+ u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
+ gpio_error gpio_error = GPIO_OK;
+ u32 temp_reg;
+
+ temp_reg = readl(&p_gpio_register->gpio_afsa);
+ temp_reg &= ~mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsa);
+ temp_reg = readl(&p_gpio_register->gpio_afsb);
+ temp_reg &= ~mask;
+ writel(temp_reg, &p_gpio_register->gpio_afsb);
+ writel(mask, &p_gpio_register->gpio_dirc);
+
+ return (gpio_error);
+}
+
+gpio_config altfun_pinconfig;
+gpio_error gpio_altfunction(gpio_alt_function alt_func,
+ int which_altfunc, char *dev_name)
+{
+ int i, j, start, end;
+ gpio_error error = -1;
+
+ for (i = 0; i < sz_altfun_tbl; i++) {
+ if (altfun_table[i].altfun == alt_func)
+ break;
+ }
+ start = altfun_table[i].start;
+ end = altfun_table[i].end;
+ for (j = start; j <= end; j++) {
+ {
+ if (which_altfunc == GPIO_ALTF_FIND) {
+ altfun_pinconfig.mode =
+ altfun_table[i].type;
+ } else {
+ altfun_pinconfig.mode = which_altfunc;
+ }
+ altfun_pinconfig.direction = GPIO_DIR_OUTPUT;
+ altfun_pinconfig.dev_name = dev_name;
+
+ if (which_altfunc != GPIO_ALTF_DISABLE) {
+ error =
+ gpio_setpinconfig(j,
+ &altfun_pinconfig);
+ } else {
+ error = gpio_resetgpiopin(j, dev_name);
+ }
+ if (!error)
+ continue;
+ nmdk_error
+ ("GPIO %d configuration failure (nmdk_error:%d)",
+ j, error);
+ error = GPIO_INVALID_PARAMETER;
+ return (error);
+ }
+ }
+ return (error);
+}
+
+int gpio_writepin(gpio_pin pin_id, gpio_data value, char *dev_name)
+{
+ struct gpio_register *p_gpio_register = addr_gpio_register[GPIO_BLOCK(pin_id)];
+ u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
+
+ switch (value) {
+ case GPIO_DATA_HIGH:
+ writel(mask, &p_gpio_register->gpio_dats);
+ break;
+ case GPIO_DATA_LOW:
+ writel(mask, &p_gpio_register->gpio_datc);
+ break;
+ default:
+ nmdk_error("Invalid value passed in %s", __FUNCTION__);
+ return GPIO_INVALID_PARAMETER;
+ }
+ return GPIO_OK;
+}
+
+int gpio_readpin(gpio_pin pin_id, gpio_data * p_value)
+{
+ struct gpio_register *p_gpio_register = addr_gpio_register[GPIO_BLOCK(pin_id)];
+ u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
+
+ if ((readl(&p_gpio_register->gpio_dat) & mask) != 0) {
+ *p_value = GPIO_DATA_HIGH;
+ } else {
+ *p_value = GPIO_DATA_LOW;
+ }
+ return GPIO_OK;
+}
+
+
+int gpio_altfuncenable(gpio_alt_function altfunc, char *dev_name)
+{
+ return (int)gpio_altfunction(altfunc, GPIO_ALTF_FIND, dev_name);
+}
+
+int gpio_altfuncdisable(gpio_alt_function altfunc, char *dev_name)
+{
+ return (int)gpio_altfunction(altfunc, GPIO_ALTF_DISABLE, dev_name);
+}
+
+void gpio_init(void)
+{
+
+ sz_altfun_tbl = sizeof(altfun_table) / sizeof(altfun_table[0]);
+
+ addr_gpio_register[0] =(void *) IO_ADDRESS(CFG_GPIO_0_BASE);
+ addr_gpio_register[1] =(void *) IO_ADDRESS(CFG_GPIO_1_BASE);
+ addr_gpio_register[2] =(void *) IO_ADDRESS(CFG_GPIO_2_BASE);
+ addr_gpio_register[3] =(void *) IO_ADDRESS(CFG_GPIO_3_BASE);
+ addr_gpio_register[4] =(void *) IO_ADDRESS(CFG_GPIO_4_BASE);
+ addr_gpio_register[5] =(void *) IO_ADDRESS(CFG_GPIO_5_BASE);
+ addr_gpio_register[6] =(void *) IO_ADDRESS(CFG_GPIO_6_BASE);
+ addr_gpio_register[7] =(void *) IO_ADDRESS(CFG_GPIO_7_BASE);
+ addr_gpio_register[8] =(void *) IO_ADDRESS(CFG_GPIO_8_BASE);
+
+ return;
+}
diff --git a/board/st/u8500/gpio.h b/board/st/u8500/gpio.h
new file mode 100755
index 000000000..37908ad37
--- /dev/null
+++ b/board/st/u8500/gpio.h
@@ -0,0 +1,524 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _MOP500_GPIO_h
+#define _MOP500_GPIO_h
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include "common.h"
+#include <configs/u8500.h>
+
+#define GPIO_TOTAL_PINS 268
+
+#define GPIO_PINS_PER_BLOCK 32
+#define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK +1)
+#define GPIO_BLOCK(pin) ( ( ( pin + GPIO_PINS_PER_BLOCK ) >> 5) - 1 )
+
+
+struct gpio_register {
+ u32 gpio_dat; /* GPIO data register *//*0x000 */
+ u32 gpio_dats; /* GPIO data Set register *//*0x004 */
+ u32 gpio_datc; /* GPIO data Clear register *//*0x008 */
+ u32 gpio_pdis; /* GPIO Pull disable register *//*0x00C */
+ u32 gpio_dir; /* GPIO data direction register *//*0x010 */
+ u32 gpio_dirs; /* GPIO data dir Set register *//*0x014 */
+ u32 gpio_dirc; /* GPIO data dir Clear register *//*0x018 */
+ u32 gpio_slpm; /* GPIO Sleep mode register *//*0x01C */
+ u32 gpio_afsa; /* GPIO AltFun A Select reg *//*0x020 */
+ u32 gpio_afsb; /* GPIO AltFun B Select reg *//*0x024 */
+ u32 gpio_lowemi; /* GPIO low EMI Select reg *//*0x028 */
+ u32 reserved_1[(0x040 - 0x02C) >> 2]; /*0x028-0x3C Reserved*/
+ u32 gpio_rimsc; /* GPIO rising edge intr set/clear *//*0x040 */
+ u32 gpio_fimsc; /* GPIO falling edge interrupt set/clear register *//*0x044 */
+ u32 gpio_mis; /* GPIO masked interrupt status register *//*0x048 */
+ u32 gpio_ic; /* GPIO Interrupt Clear register *//*0x04C */
+ u32 gpio_rwimsc; /* GPIO Rising-edge Wakeup IMSC register *//*0x050 */
+ u32 gpio_fwimsc; /* GPIO Falling-edge Wakeup IMSC register *//*0x054 */
+ u32 gpio_wks; /* GPIO Wakeup Status register *//*0x058 */
+};
+
+/* Error values returned by functions */
+typedef enum {
+ GPIO_OK = 0, /* (0) */
+ GPIO_UNSUPPORTED_HW = -2, /* NOMADIK_UNSUPPORTED_HW, (-2) */
+ GPIO_UNSUPPORTED_FEATURE = -3, /* NOMADIK_UNSUPPORTED_FEATURE, (-3) */
+ GPIO_INVALID_PARAMETER = -4, /* NOMADIK_INVALID_PARAMETER, (-4) */
+ GPIO_REQUEST_NOT_APPLICABLE = -5, /* NOMADIK_REQUEST_NOT_APPLICABLE, (-5) */
+ GPIO_REQUEST_PENDING = -6, /* NOMADIK_REQUEST_PENDING, (-6) */
+ GPIO_NOT_CONFIGURED = -7, /* NOMADIK_NOT_CONFIGURED, (-7) */
+ GPIO_INTERNAL_ERROR = -8, /* NOMADIK_INTERNAL_ERROR, (-8) */
+ GPIO_INTERNAL_EVENT = 1, /* NOMADIK_INTERNAL_EVENT,*/
+ GPIO_REMAINING_EVENT = 2, /* NOMADIK_REMAINING_PENDING_EVENTS,*/
+ GPIO_NO_MORE_PENDING_EVENT = 3, /* NOMADIK_NO_MORE_PENDING_EVENT,*/
+ GPIO_INVALID_CLIENT = -25,
+ GPIO_INVALID_PIN = -26,
+ GPIO_PIN_BUSY = -27,
+ GPIO_PIN_NOT_ALLOCATED = -28,
+ GPIO_WRONG_CLIENT = -29,
+ GPIO_UNSUPPORTED_ALTFUNC = -30,
+
+} gpio_error;
+
+/*GPIO DEVICE ID */
+typedef enum {
+ GPIO_DEVICE_ID_0,
+ GPIO_DEVICE_ID_1,
+ GPIO_DEVICE_ID_2,
+ GPIO_DEVICE_ID_3,
+ GPIO_DEVICE_ID_INVALID
+} gpio_device_id;
+
+/*
+ * Pin description To be used in SOFTWARE mode: refers to a pin.
+ */
+typedef enum {
+ GPIO_PIN_0,
+ GPIO_PIN_1,
+ GPIO_PIN_2,
+ GPIO_PIN_3,
+ GPIO_PIN_4,
+ GPIO_PIN_5,
+ GPIO_PIN_6,
+ GPIO_PIN_7,
+ GPIO_PIN_8,
+ GPIO_PIN_9,
+ GPIO_PIN_10,
+ GPIO_PIN_11,
+ GPIO_PIN_12,
+ GPIO_PIN_13,
+ GPIO_PIN_14,
+ GPIO_PIN_15,
+ GPIO_PIN_16,
+ GPIO_PIN_17,
+ GPIO_PIN_18,
+ GPIO_PIN_19,
+ GPIO_PIN_20,
+ GPIO_PIN_21,
+ GPIO_PIN_22,
+ GPIO_PIN_23,
+ GPIO_PIN_24,
+ GPIO_PIN_25,
+ GPIO_PIN_26,
+ GPIO_PIN_27,
+ GPIO_PIN_28,
+ GPIO_PIN_29,
+ GPIO_PIN_30,
+ GPIO_PIN_31,
+ GPIO_PIN_32,
+ GPIO_PIN_33,
+ GPIO_PIN_34,
+ GPIO_PIN_35,
+ GPIO_PIN_36,
+ GPIO_PIN_37,
+ GPIO_PIN_38,
+ GPIO_PIN_39,
+ GPIO_PIN_40,
+ GPIO_PIN_41,
+ GPIO_PIN_42,
+ GPIO_PIN_43,
+ GPIO_PIN_44,
+ GPIO_PIN_45,
+ GPIO_PIN_46,
+ GPIO_PIN_47,
+ GPIO_PIN_48,
+ GPIO_PIN_49,
+ GPIO_PIN_50,
+ GPIO_PIN_51,
+ GPIO_PIN_52,
+ GPIO_PIN_53,
+ GPIO_PIN_54,
+ GPIO_PIN_55,
+ GPIO_PIN_56,
+ GPIO_PIN_57,
+ GPIO_PIN_58,
+ GPIO_PIN_59,
+ GPIO_PIN_60,
+ GPIO_PIN_61,
+ GPIO_PIN_62,
+ GPIO_PIN_63,
+ GPIO_PIN_64,
+ GPIO_PIN_65,
+ GPIO_PIN_66,
+ GPIO_PIN_67,
+ GPIO_PIN_68,
+ GPIO_PIN_69,
+ GPIO_PIN_70,
+ GPIO_PIN_71,
+ GPIO_PIN_72,
+ GPIO_PIN_73,
+ GPIO_PIN_74,
+ GPIO_PIN_75,
+ GPIO_PIN_76,
+ GPIO_PIN_77,
+ GPIO_PIN_78,
+ GPIO_PIN_79,
+ GPIO_PIN_80,
+ GPIO_PIN_81,
+ GPIO_PIN_82,
+ GPIO_PIN_83,
+ GPIO_PIN_84,
+ GPIO_PIN_85,
+ GPIO_PIN_86,
+ GPIO_PIN_87,
+ GPIO_PIN_88,
+ GPIO_PIN_89,
+ GPIO_PIN_90,
+ GPIO_PIN_91,
+ GPIO_PIN_92,
+ GPIO_PIN_93,
+ GPIO_PIN_94,
+ GPIO_PIN_95,
+ GPIO_PIN_96,
+ GPIO_PIN_97,
+ GPIO_PIN_98,
+ GPIO_PIN_99,
+ GPIO_PIN_100,
+ GPIO_PIN_101,
+ GPIO_PIN_102,
+ GPIO_PIN_103,
+ GPIO_PIN_104,
+ GPIO_PIN_105,
+ GPIO_PIN_106,
+ GPIO_PIN_107,
+ GPIO_PIN_108,
+ GPIO_PIN_109,
+ GPIO_PIN_110,
+ GPIO_PIN_111,
+ GPIO_PIN_112,
+ GPIO_PIN_113,
+ GPIO_PIN_114,
+ GPIO_PIN_115,
+ GPIO_PIN_116,
+ GPIO_PIN_117,
+ GPIO_PIN_118,
+ GPIO_PIN_119,
+ GPIO_PIN_120,
+ GPIO_PIN_121,
+ GPIO_PIN_122,
+ GPIO_PIN_123,
+ GPIO_PIN_124,
+ GPIO_PIN_125,
+ GPIO_PIN_126,
+ GPIO_PIN_127,
+ GPIO_PIN_128,
+ GPIO_PIN_129,
+ GPIO_PIN_130,
+ GPIO_PIN_131,
+ GPIO_PIN_132,
+ GPIO_PIN_133,
+ GPIO_PIN_134,
+ GPIO_PIN_135,
+ GPIO_PIN_136,
+ GPIO_PIN_137,
+ GPIO_PIN_138,
+ GPIO_PIN_139,
+ GPIO_PIN_140,
+ GPIO_PIN_141,
+ GPIO_PIN_142,
+ GPIO_PIN_143,
+ GPIO_PIN_144,
+ GPIO_PIN_145,
+ GPIO_PIN_146,
+ GPIO_PIN_147,
+ GPIO_PIN_148,
+ GPIO_PIN_149,
+ GPIO_PIN_150,
+ GPIO_PIN_151,
+ GPIO_PIN_152,
+ GPIO_PIN_153,
+ GPIO_PIN_154,
+ GPIO_PIN_155,
+ GPIO_PIN_156,
+ GPIO_PIN_157,
+ GPIO_PIN_158,
+ GPIO_PIN_159,
+ GPIO_PIN_160,
+ GPIO_PIN_161,
+ GPIO_PIN_162,
+ GPIO_PIN_163,
+ GPIO_PIN_164,
+ GPIO_PIN_165,
+ GPIO_PIN_166,
+ GPIO_PIN_167,
+ GPIO_PIN_168,
+ GPIO_PIN_169,
+ GPIO_PIN_170,
+ GPIO_PIN_171,
+ GPIO_PIN_172,
+ GPIO_PIN_173,
+ GPIO_PIN_174,
+ GPIO_PIN_175,
+ GPIO_PIN_176,
+ GPIO_PIN_177,
+ GPIO_PIN_178,
+ GPIO_PIN_179,
+ GPIO_PIN_180,
+ GPIO_PIN_181,
+ GPIO_PIN_182,
+ GPIO_PIN_183,
+ GPIO_PIN_184,
+ GPIO_PIN_185,
+ GPIO_PIN_186,
+ GPIO_PIN_187,
+ GPIO_PIN_188,
+ GPIO_PIN_189,
+ GPIO_PIN_190,
+ GPIO_PIN_191,
+ GPIO_PIN_192,
+ GPIO_PIN_193,
+ GPIO_PIN_194,
+ GPIO_PIN_195,
+ GPIO_PIN_196,
+ GPIO_PIN_197,
+ GPIO_PIN_198,
+ GPIO_PIN_199,
+ GPIO_PIN_200,
+ GPIO_PIN_201,
+ GPIO_PIN_202,
+ GPIO_PIN_203,
+ GPIO_PIN_204,
+ GPIO_PIN_205,
+ GPIO_PIN_206,
+ GPIO_PIN_207,
+ GPIO_PIN_208,
+ GPIO_PIN_209,
+ GPIO_PIN_210,
+ GPIO_PIN_211,
+ GPIO_PIN_212,
+ GPIO_PIN_213,
+ GPIO_PIN_214,
+ GPIO_PIN_215,
+ GPIO_PIN_216,
+ GPIO_PIN_217,
+ GPIO_PIN_218,
+ GPIO_PIN_219,
+ GPIO_PIN_220,
+ GPIO_PIN_221,
+ GPIO_PIN_222,
+ GPIO_PIN_223,
+ GPIO_PIN_224,
+ GPIO_PIN_225,
+ GPIO_PIN_226,
+ GPIO_PIN_227,
+ GPIO_PIN_228,
+ GPIO_PIN_229,
+ GPIO_PIN_230,
+ GPIO_PIN_231,
+ GPIO_PIN_232,
+ GPIO_PIN_233,
+ GPIO_PIN_234,
+ GPIO_PIN_235,
+ GPIO_PIN_236,
+ GPIO_PIN_237,
+ GPIO_PIN_238,
+ GPIO_PIN_239,
+ GPIO_PIN_240,
+ GPIO_PIN_241,
+ GPIO_PIN_242,
+ GPIO_PIN_243,
+ GPIO_PIN_244,
+ GPIO_PIN_245,
+ GPIO_PIN_246,
+ GPIO_PIN_247,
+ GPIO_PIN_248,
+ GPIO_PIN_249,
+ GPIO_PIN_250,
+ GPIO_PIN_251,
+ GPIO_PIN_252,
+ GPIO_PIN_253,
+ GPIO_PIN_254,
+ GPIO_PIN_255,
+ GPIO_PIN_256,
+ GPIO_PIN_257,
+ GPIO_PIN_258,
+ GPIO_PIN_259,
+ GPIO_PIN_260,
+ GPIO_PIN_261,
+ GPIO_PIN_262,
+ GPIO_PIN_263,
+ GPIO_PIN_264,
+ GPIO_PIN_265,
+ GPIO_PIN_266,
+ GPIO_PIN_267
+} gpio_pin;
+
+/*
+ * Alternate Function:
+ * refered in altfun_table to pointout particular altfun to be enabled
+ * when using GPIO_ALT_FUNCTION A/B/C enable/disable operation
+ */
+typedef enum {
+ GPIO_ALT_UART_0_MODEM,
+ GPIO_ALT_UART_0_NO_MODEM,
+ GPIO_ALT_UART_1,
+ GPIO_ALT_UART_2,
+ GPIO_ALT_I2C_0,
+ GPIO_ALT_I2C_1,
+ GPIO_ALT_MSP_0,
+ GPIO_ALT_MSP_1,
+ GPIO_ALT_MSP_2,
+ GPIO_ALT_MSP_3,
+ GPIO_ALT_MSP_4,
+ GPIO_ALT_MSP_5,
+ GPIO_ALT_SSP_0,
+ GPIO_ALT_SSP_1,
+ GPIO_ALT_MM_CARD0,
+ GPIO_ALT_SD_CARD0,
+ GPIO_ALT_DMA_0,
+ GPIO_ALT_DMA_1,
+ GPIO_ALT_HSI0,
+ GPIO_ALT_CCIR656_INPUT,
+ GPIO_ALT_CCIR656_OUTPUT,
+ GPIO_ALT_LCD_PANEL,
+ GPIO_ALT_MDIF,
+ GPIO_ALT_SDRAM,
+ GPIO_ALT_HAMAC_AUDIO_DBG,
+ GPIO_ALT_HAMAC_VIDEO_DBG,
+ GPIO_ALT_CLOCK_RESET,
+ GPIO_ALT_TSP,
+ GPIO_ALT_IRDA,
+ GPIO_ALT_USB_MINIMUM,
+ GPIO_ALT_USB_I2C,
+ GPIO_ALT_OWM,
+ GPIO_ALT_PWL,
+ GPIO_ALT_FSMC,
+ GPIO_ALT_COMP_FLASH,
+ GPIO_ALT_SRAM_NOR_FLASH,
+ GPIO_ALT_FSMC_ADDLINE_0_TO_15,
+ GPIO_ALT_SCROLL_KEY,
+ GPIO_ALT_MSHC,
+ GPIO_ALT_HPI,
+ GPIO_ALT_USB_OTG,
+ GPIO_ALT_SDIO,
+ GPIO_ALT_HSMMC,
+ GPIO_ALT_FSMC_ADD_DATA_0_TO_25,
+ GPIO_ALT_HSI1,
+ GPIO_ALT_NOR,
+ GPIO_ALT_NAND,
+ GPIO_ALT_KEYPAD,
+ GPIO_ALT_VPIP,
+ GPIO_ALT_CAM,
+ GPIO_ALT_CCP1,
+ GPIO_ALT_EMMC,
+#ifdef CONFIG_NOMADIK_8500_V1
+ GPIO_ALT_POP_EMMC,
+#endif
+ GPIO_ALT_FUNMAX /* Add new alt func before this */
+} gpio_alt_function;
+
+/* Defines pin assignment(Software mode or Alternate mode) */
+typedef enum {
+ GPIO_MODE_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_MODE_SOFTWARE, /* Pin connected to GPIO (SW controlled) */
+ GPIO_ALTF_A, /* Pin connected to alternate function 1 (HW periph 1) */
+ GPIO_ALTF_B, /* Pin connected to alternate function 2 (HW periph 2) */
+ GPIO_ALTF_C, /* Pin connected to alternate function 3 (HW periph 3) */
+ GPIO_ALTF_FIND, /* Pin connected to alternate function 3 (HW periph 3) */
+ GPIO_ALTF_DISABLE /* Pin connected to alternate function 3 (HW periph 3) */
+} gpio_mode;
+
+/* Defines GPIO pin direction */
+typedef enum {
+ GPIO_DIR_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_DIR_INPUT, /* GPIO set as input */
+ GPIO_DIR_OUTPUT /* GPIO set as output */
+} gpio_direction;
+
+/* Interrupt trigger mode */
+typedef enum {
+ GPIO_TRIG_LEAVE_UNCHANGED, /* Parameter will be ignored by the function */
+ GPIO_TRIG_DISABLE, /* Triggers no IT */
+ GPIO_TRIG_RISING_EDGE, /* Triggers an IT on a rising edge */
+ GPIO_TRIG_FALLING_EDGE, /* Triggers an IT on a falling edge */
+ GPIO_TRIG_BOTH_EDGES, /* Triggers an IT on a rising and a falling edge */
+ GPIO_TRIG_HIGH_LEVEL, /* Triggers an IT on a high level */
+ GPIO_TRIG_LOW_LEVEL /* Triggers an IT on a low level */
+} gpio_trig; /* Interrupt trigger mode, or disable */
+
+/* Configuration parameters for one GPIO pin.*/
+typedef struct {
+ gpio_mode mode; /* Defines mode (SOFTWARE or Alternate). */
+ gpio_direction direction; /* Define pin direction (in SOFTWARE mode only). */
+ gpio_trig trig; /* Interrupt trigger (in SOFTWARE mode only) */
+ char *dev_name; /* Name of client driver who owns the gpio pin */
+} gpio_config;
+
+/* GPIO pin data*/
+typedef enum {
+ GPIO_DATA_LOW, /* GPIO pin status is low. */
+ GPIO_DATA_HIGH /* GPIO pin status is high. */
+} gpio_data;
+
+/* GPIO behaviour in sleep mode */
+typedef enum {
+ GPIO_SLEEP_MODE_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_SLEEP_MODE_INPUT_DEFAULTVOLT, /* GPIO is an input with pull up/down enabled
+ when in sleep mode. */
+ GPIO_SLEEP_MODE_CONTROLLED_BY_GPIO /* GPIO pin is controlled by GPIO IP. So mode,
+ direction and data values for GPIO pin in
+ sleep mode are determined by configuration
+ set to GPIO pin before entering to sleep mode. */
+} gpio_sleep_mode;
+
+/* GPIO ability to wake the system up from sleep mode.*/
+typedef enum {
+ GPIO_WAKE_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_WAKE_DISABLE, /* GPIO will not wake the system from sleep mode. */
+ GPIO_WAKE_LOW_LEVEL, /* GPIO will wake the system up on a LOW level. */
+ GPIO_WAKE_HIGH_LEVEL, /* GPIO will wake the system up on a HIGH level. */
+ GPIO_WAKE_RISING_EDGE, /* GPIO will wake the system up on a RISING edge. */
+ GPIO_WAKE_FALLING_EDGE, /* GPIO will wake the system up on a FALLING edge. */
+ GPIO_WAKE_BOTH_EDGES /* GPIO will wake the system up on both RISING and FALLING edge. */
+} gpio_wake;
+
+/* Configuration parameters for one GPIO pin in sleep mode.*/
+typedef struct {
+ gpio_sleep_mode sleep_mode; /* GPIO behaviour in sleep mode. */
+ gpio_wake wake; /* GPIO ability to wake up the system. */
+} gpio_sleep_config;
+
+/*------------------------------------------------------------------------
+ * Functions declaration
+ * refer ./Documentation/arm/STM-Nomadik/gpio_user_guide.txt
+ *----------------------------------------------------------------------*/
+
+extern gpio_error gpio_setpinconfig(gpio_pin pin_id, gpio_config * pin_config);
+extern gpio_error gpio_resetpinconfig(gpio_pin pin_id, char *dev_name);
+extern int gpio_writepin(gpio_pin pin_id, gpio_data value, char *dev_name);
+extern int gpio_readpin(gpio_pin pin_id, gpio_data * value);
+extern int gpio_altfuncenable(gpio_alt_function altfunc,
+ char *dev_name);
+extern int gpio_altfuncdisable(gpio_alt_function altfunc,
+ char *dev_name);
+
+struct gpio_altfun_data {
+ u16 altfun;
+ u16 start;
+ u16 end;
+ t_bool cont;
+ u8 type;
+};
+
+#endif /* __INC_GPIO_H */
diff --git a/board/st/u8500/i2c.c b/board/st/u8500/i2c.c
new file mode 100755
index 000000000..9c23c29db
--- /dev/null
+++ b/board/st/u8500/i2c.c
@@ -0,0 +1,3029 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "i2c.h"
+
+/*---------------------------------------------------------------------------
+ * defines
+ *---------------------------------------------------------------------------*/
+/* 8500 has 4 I2C controllers */
+t_i2c_registers *gp_i2c_registers[4];
+
+#define I2C_ENDAD_COUNTER 500000
+#define I2C_INT_ENDED_COUNTER 5
+#define I2C_BTF_COUNTER 5
+#define I2C_BTF_COUNTER_POLLING 10
+#define I2C_FIFO_FLUSH_COUNTER 500
+
+/*-----------------------------------------------------------------------------
+Global variables
+-----------------------------------------------------------------------------*/
+
+/* 8500 has 4 I2C Controllers */
+ volatile t_i2c_system_context g_i2c_system_context[4];
+
+#undef I2C_DEBUG
+#ifdef I2C_DEBUG
+#define info(fmt,args...) printf("I2C: "fmt, ##args)
+#else
+#define info(fmt,args...) (void) 0;
+#endif
+
+
+/*-----------------------------------------------------------------------------
+ Configuration functions
+-----------------------------------------------------------------------------*/
+/****************************************************************************/
+/* NAME : I2C_Init */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Initialize the given I2C controller by specifying the */
+/* base logical address. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* t_logical_address : The controller's logical address */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are invalid */
+/* I2C_UNSUPPORTED_HW if peripheral ids are not matched */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_Init(t_i2c_device_id id, t_logical_address address)
+{
+ t_i2c_registers *p_i2c_registers;
+
+ /*
+ Check if the controller id is valid.
+ */
+
+
+ if (((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id) ) || (NULL == address))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+
+ p_i2c_registers = (t_i2c_registers *) address;
+
+
+ if
+ (
+ (I2C_P_ID_0 != p_i2c_registers->periph_id_0)
+ || (I2C_P_ID_1 != p_i2c_registers->periph_id_1)
+ || (I2C_P_ID_2 != p_i2c_registers->periph_id_2)
+ || (I2C_P_ID_3 != p_i2c_registers->periph_id_3)
+ || (I2C_CELL_ID_0 != p_i2c_registers->cell_id_0)
+ || (I2C_CELL_ID_1 != p_i2c_registers->cell_id_1)
+ || (I2C_CELL_ID_2 != p_i2c_registers->cell_id_2)
+ || (I2C_CELL_ID_3 != p_i2c_registers->cell_id_3)
+ )
+ {
+ return(I2C_UNSUPPORTED_HW);
+ }
+
+
+ /*
+ Initialize the right structure and save the base address.
+ */
+ g_i2c_system_context[id].base_address = address;
+ g_i2c_system_context[id].freq_scl = 0;
+ g_i2c_system_context[id].freq_input = 0;
+ g_i2c_system_context[id].mode = I2C_FREQ_MODE_STANDARD;
+ g_i2c_system_context[id].own_address = 0;
+ g_i2c_system_context[id].enabled = FALSE;
+ g_i2c_system_context[id].slave_address = 0;
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_MODE;
+ g_i2c_system_context[id].data = 0;
+ g_i2c_system_context[id].databuffer = NULL;
+ g_i2c_system_context[id].count_data = 0;
+ g_i2c_system_context[id].register_index = 0;
+ g_i2c_system_context[id].operation = (t_i2c_operation) I2C_NO_OPERATION;
+ g_i2c_system_context[id].active_event = I2C_NO_EVENT;
+ g_i2c_system_context[id].transfer_data = 0;
+ g_i2c_system_context[id].multi_operation = FALSE;
+
+ /* g_i2c_system_context[id].i2c_device_context... to be initialized*/
+ g_i2c_system_context[id].digital_filter_control = I2C_DIGITAL_FILTERS_OFF;
+ g_i2c_system_context[id].dma_sync_logic_control = I2C_DISABLE;
+ g_i2c_system_context[id].start_byte_procedure = I2C_DISABLE;
+ g_i2c_system_context[id].slave_data_setup_time = 0; /* TBD */
+ g_i2c_system_context[id].high_speed_master_code = 0;
+ g_i2c_system_context[id].bus_control_mode = I2C_BUS_SLAVE_MODE;
+ g_i2c_system_context[id].i2c_loopback_mode = I2C_DISABLE;
+ g_i2c_system_context[id].general_call_mode_handling = I2C_NO_GENERAL_CALL_HANDLING;
+
+ g_i2c_system_context[id].index_transfer_mode = I2C_TRANSFER_MODE_POLLING;
+ g_i2c_system_context[id].data_transfer_mode = I2C_TRANSFER_MODE_POLLING;
+ g_i2c_system_context[id].i2c_transmit_interrupt_threshold = 1;
+ g_i2c_system_context[id].i2c_receive_interrupt_threshold = 1;
+ g_i2c_system_context[id].transmit_burst_length = 0;
+ g_i2c_system_context[id].receive_burst_length = 0;
+ g_i2c_system_context[id].index_format = I2C_NO_INDEX;
+ g_i2c_system_context[id].current_bus_config = I2C_CURRENT_BUS_SLAVE_TRANSMITTER;
+ g_i2c_system_context[id].std = FALSE;
+
+
+ /*Disable the interrupts */
+ I2C_WRITE_REG(p_i2c_registers->imscr,I2C_CLEAR);
+ /* Disable the controller */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ return(I2C_OK);
+}
+
+
+/****************************************************************************/
+/* NAME : I2C_SetDeviceConfiguration */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Configure the given I2C controller, by clearing */
+/* registers, setting the input clock. The controller and */
+/* interrupts are disabled after this routine */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* t_i2c_device_config : pointer to the structer containg */
+/* the configuration */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not invalid*/
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_SetDeviceConfiguration(t_i2c_device_id id, t_i2c_device_config *p_device_config)
+{
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+
+
+ /* Check if parameters are valid.*/
+
+ if (NULL == p_device_config || ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id)))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* Disable the controller.*/
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ /* Save the value.*/
+ g_i2c_system_context[id].enabled = FALSE;
+
+ /* Now save the input parameters.*/
+ g_i2c_system_context[id].digital_filter_control = p_device_config->i2c_digital_filter_control;
+ g_i2c_system_context[id].slave_data_setup_time = p_device_config->slave_data_setup_time;
+ g_i2c_system_context[id].dma_sync_logic_control = p_device_config->i2c_dma_sync_logic_control;
+ g_i2c_system_context[id].start_byte_procedure = p_device_config->i2c_start_byte_procedure;
+ g_i2c_system_context[id].high_speed_master_code = p_device_config->i2c_high_speed_master_code;
+ g_i2c_system_context[id].freq_input = p_device_config->input_frequency;
+ g_i2c_system_context[id].own_address = p_device_config->controller_i2c_address;
+
+ /* Clear registers.*/
+ I2C_WRITE_REG(p_i2c_registers->cr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->scr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->hsmcr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->tftr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->rftr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->dmar, I2C_CLEAR);
+
+ /* Set own address.*/
+ error_status = i2cp_SetOwnAddress(id, (u16) g_i2c_system_context[id].own_address);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+
+ /* set the digital filter */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->cr,
+ I2C_CR_FON,
+ I2C_CR_SHIFT_FON,
+ (u32) g_i2c_system_context[id].digital_filter_control
+ );
+
+ /* Set the DMA sync logic */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->cr,
+ I2C_CR_DMA_SLE,
+ I2C_CR_SHIFT_DMA_SLE,
+ (u32) g_i2c_system_context[id].dma_sync_logic_control
+ );
+
+ /* Set the Slave Data Set up Time */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->scr,
+ I2C_SCR_DATA_SETUP_TIME,
+ I2C_SCR_SHIFT_DATA_SETUP_TIME,
+ g_i2c_system_context[id].slave_data_setup_time
+ );
+
+ /* Disable generation of interrupts.*/
+ I2C_DisableIRQSrc((t_i2c_irq_src_id) (((u32) id << (u32) I2CID_SHIFT) | (u32) I2C_IRQ_SRC_ALL)); /*
+ Single Interrupt source matches
+ the sequence of device ids they
+ are used interchangeably.
+ */
+
+ /* Enable the I2C Controller */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ return(error_status);
+
+}
+
+/****************************************************************************/
+/* NAME : I2C_SetTransferConfiguration */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Configure the given I2C controller for transfer mode, */
+/* baud rate, general call handling and bus access mode. */
+/* Additionally fifo levels, loopback control and DMA */
+/* burst length are also configured. */
+/* This routine enable the I2C controller */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* t_i2c_transfer_config :pointer to the structure containing */
+/* the configuration */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/* I2C_UNSUPPORTED_FEATURE if required index and data */
+/* transfer modes are not supported. */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+
+/****************************************************************************/
+ t_i2c_error I2C_SetTransferConfiguration(t_i2c_device_id id, t_i2c_transfer_config *p_transfer_config)
+{
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+
+ /* Check if parameters are valid.*/
+
+ if (NULL == p_transfer_config || ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id)))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+
+ /*
+ Error handling for unsopported features according to the platform
+ */
+ if
+ (
+ (
+ I2C_TRANSFER_MODE_POLLING != p_transfer_config->index_transfer_mode
+ && I2C_TRANSFER_MODE_POLLING == p_transfer_config->data_transfer_mode
+ )
+ || ( (I2C_TRANSFER_MODE_INTERRUPT == p_transfer_config->index_transfer_mode)
+ && (I2C_TRANSFER_MODE_DMA == p_transfer_config->data_transfer_mode)
+ )
+
+ || (I2C_TRANSFER_MODE_DMA == p_transfer_config->index_transfer_mode)
+ )
+ {
+ return(I2C_UNSUPPORTED_FEATURE);
+ }
+
+ /*
+ Clear all the existing state of the controller by clearing PE bit
+ */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ /* Now save the input parameters.*/
+ g_i2c_system_context[id].i2c_loopback_mode = p_transfer_config->i2c_loopback_mode;
+ g_i2c_system_context[id].general_call_mode_handling = p_transfer_config->i2c_slave_general_call_mode;
+ g_i2c_system_context[id].index_transfer_mode = p_transfer_config->index_transfer_mode;
+
+ /*Index transfer mode is still relevant even if I2C_NO_INDEX is
+ used since then this mode is used for the address transmission */
+
+ g_i2c_system_context[id].data_transfer_mode = p_transfer_config->data_transfer_mode;
+ g_i2c_system_context[id].i2c_transmit_interrupt_threshold = p_transfer_config->i2c_transmit_interrupt_threshold;
+ g_i2c_system_context[id].i2c_receive_interrupt_threshold = p_transfer_config->i2c_receive_interrupt_threshold;
+ g_i2c_system_context[id].transmit_burst_length = p_transfer_config->transmit_burst_length;
+ g_i2c_system_context[id].receive_burst_length = p_transfer_config->receive_burst_length;
+ g_i2c_system_context[id].freq_scl = p_transfer_config->i2c_transfer_frequency;
+ g_i2c_system_context[id].bus_control_mode = p_transfer_config->bus_control_mode;
+
+ g_i2c_system_context[id].multi_operation = FALSE;
+ g_i2c_system_context[id].register_index = 0; /* The index of the slave's registers*/
+ g_i2c_system_context[id].index_format = I2C_NO_INDEX;
+
+
+ /* Set the SCL bus clock frequency. -> transfer frequency*/
+ error_status = i2cp_SetBusClock(id, g_i2c_system_context[id].freq_scl, g_i2c_system_context[id].freq_input);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+
+ /*Set the loop back mode */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->cr,
+ I2C_CR_LM,
+ I2C_CR_SHIFT_LM,
+ (u32) g_i2c_system_context[id].i2c_loopback_mode
+ );
+
+ /* Enable the general call handing in the controller*/
+ /* Only possible general call handing in this controller is
+ in the software mode.
+ */
+ if (I2C_HARDWARE_GENERAL_CALL_HANDLING == g_i2c_system_context[id].general_call_mode_handling)
+ {
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_SGCM);
+ }
+ else
+ {
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_SGCM);
+ }
+
+ /* Disable the Tx DMA */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_DMA_TX_EN);
+
+ /* Disable the Rx DMA */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_DMA_RX_EN);
+
+ /* configure the Tx DMA burst size */
+ if (g_i2c_system_context[id].transmit_burst_length >= 1)
+ {
+ /* set the DMA Tx request mode to Burst */
+ I2C_SET_BIT(p_i2c_registers->dmar, I2C_DMA_BURST_TX);
+
+ /* Set the Destination Burst Size */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->dmar,
+ I2C_DMA_DBSIZE_TX,
+ I2C_DMA_SHIFT_DBSIZE_TX,
+ g_i2c_system_context[id].transmit_burst_length
+ );
+ }
+ else
+ {
+ /* Set the DMA Tx Request mode to Single */
+ I2C_CLR_BIT(p_i2c_registers->dmar, I2C_DMA_BURST_TX);
+ }
+
+ /* configure the Rx DMA burst size */
+ if (g_i2c_system_context[id].receive_burst_length >= 1)
+ {
+ /* set the DMA Rx request mode to Burst */
+ I2C_SET_BIT(p_i2c_registers->dmar, I2C_DMA_BURST_RX);
+
+ /* Set the source burst size */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->dmar,
+ I2C_DMA_SBSIZE_RX,
+ I2C_DMA_SHIFT_SBSIZE_RX,
+ g_i2c_system_context[id].receive_burst_length
+ );
+ }
+ else
+ {
+ /* Set the DMA Rx Request mode to Single */
+ I2C_CLR_BIT(p_i2c_registers->dmar, I2C_DMA_BURST_RX);
+ }
+
+ /* Set the Bus control mode */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->cr,
+ I2C_CR_OM,
+ I2C_CR_SHIFT_OM,
+ (u32) g_i2c_system_context[id].bus_control_mode
+ );
+
+ /* Set the Transmit Fifo threshold value */
+ p_i2c_registers->tftr = g_i2c_system_context[id].i2c_transmit_interrupt_threshold;
+
+ /* Set the Receive Fifo Threshold value */
+ p_i2c_registers->rftr = g_i2c_system_context[id].i2c_receive_interrupt_threshold;
+
+ /*Disable the interrupts if index transfer mode is polling */
+ if (I2C_TRANSFER_MODE_POLLING == g_i2c_system_context[id].index_transfer_mode)
+ {
+ I2C_DisableIRQSrc((t_i2c_irq_src_id) (((u32) id << (u32) I2CID_SHIFT) | (u32) I2C_IRQ_SRC_ALL));
+ }
+
+ /* Now restore CR register with the values it has before it was disabled.*/
+ /*Enable the I2C Controller and set the enable status in the global structure */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+ g_i2c_system_context[id].enabled = TRUE;
+
+ return(error_status);
+
+}
+
+/****************************************************************************/
+/* NAME : I2C_SetTransferMode */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Set the transfer modes for the index and data transfer */
+/* on the given I2C controller */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* t_i2c_transfer_mode : Index transfer mode */
+/* t_i2c_transfer_mode : data transger mode */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/* I2C_UNSUPPORTED_FEATURE if required index and data */
+/* transfer modes are not supported. */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_SetTransferMode
+(
+ t_i2c_device_id id,
+ t_i2c_transfer_mode index_transfer_mode,
+ t_i2c_transfer_mode data_transfer_mode
+)
+{
+ info(
+ "Id is %d, index and data transfer modes are %lx and %lx",
+ id,
+ (u32) index_transfer_mode,
+ (u32) data_transfer_mode
+ );
+
+ if
+ (
+ (I2C_TRANSFER_MODE_POLLING != index_transfer_mode && I2C_TRANSFER_MODE_POLLING == data_transfer_mode)
+ || ( (I2C_TRANSFER_MODE_INTERRUPT == index_transfer_mode)
+ && (I2C_TRANSFER_MODE_DMA == data_transfer_mode)
+ )
+
+ || (I2C_TRANSFER_MODE_DMA == index_transfer_mode)
+ )
+ {
+ return(I2C_UNSUPPORTED_FEATURE);
+ }
+
+
+ /* Check if parameters are valid.*/
+
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ g_i2c_system_context[id].index_transfer_mode = index_transfer_mode;
+
+ /*Index transfer mode is still relevant even if I2C_NO_INDEX is
+ used since then this mode is used for the addres transmission */
+
+ g_i2c_system_context[id].data_transfer_mode = data_transfer_mode;
+
+ /*Disable the interrupts if index tranfer mode is polling */
+ if (I2C_TRANSFER_MODE_POLLING == index_transfer_mode)
+ {
+
+ I2C_DisableIRQSrc((t_i2c_irq_src_id) (((u32) id << (u32) I2CID_SHIFT) | (u32) I2C_IRQ_SRC_ALL));
+
+ }
+
+ return(I2C_OK);
+}
+
+/****************************************************************************/
+/* NAME : I2C_SetBusControlMode */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Set the bus control mode for the data transfer on the */
+/* given I2C controller. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* t_i2c_bus_control_mode : The mode in which I2C bus */
+/* is accessed */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+
+/****************************************************************************/
+ t_i2c_error I2C_SetBusControlMode(t_i2c_device_id id, t_i2c_bus_control_mode bus_control_mode)
+{
+
+
+ t_i2c_registers *p_i2c_registers;
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+
+ /* Check if parameters are valid.*/
+
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ g_i2c_system_context[id].bus_control_mode = bus_control_mode;
+
+ /* Disable the I2C controller before configuring */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ /* Set the Bus control mode */
+ I2C_WRITE_FIELD
+ (
+ p_i2c_registers->cr,
+ I2C_CR_OM,
+ I2C_CR_SHIFT_OM,
+ (u32) g_i2c_system_context[id].bus_control_mode
+ );
+
+ /* Enable the I2C controller */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ return(I2C_OK);
+}
+
+/*-----------------------------------------------------------------------------
+ Configuration functions
+-----------------------------------------------------------------------------*/
+/****************************************************************************/
+/* NAME : I2C_FlushFifo */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Flush the transmit or receive FIFO */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* t_i2c_fifo : FIFO to be flused */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* = I2C_INVALID_PARAMETER - if input id is wrong */
+/* = I2C_HW_FAILED - if FIFO flush bit is not reset */
+/* itself after setting. This could be happen if */
+/* i2c clock frequency is not set */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+
+/****************************************************************************/
+ t_i2c_error I2C_FlushFifo(t_i2c_device_id id, t_i2c_fifo fifo)
+{
+
+ u32 loop_counter;
+ t_i2c_registers *p_i2c_registers;
+
+ /* Check parameters valid */
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ switch (fifo)
+ {
+ case I2C_TRANSMIT_FIFO:
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_FTX); /* Flush the Tx Fifo */
+
+ /*Wait till for the Tx Flush bit to reset */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->cr, I2C_CR_FTX, I2C_CR_SHIFT_FTX)
+ && loop_counter < I2C_FIFO_FLUSH_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_FIFO_FLUSH_COUNTER)
+ {
+ return(I2C_HW_FAILED);
+ }
+ break;
+
+ case I2C_RECEIVE_FIFO:
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_FRX); /* Flush the Rx Fifo */
+
+ /* Wait till Rx flush bit to reset */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->cr, I2C_CR_FRX, I2C_CR_SHIFT_FRX)
+ && loop_counter < I2C_FIFO_FLUSH_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_FIFO_FLUSH_COUNTER)
+ {
+ return(I2C_HW_FAILED);
+ }
+ break;
+ }
+
+ return(I2C_OK);
+
+}
+
+
+
+
+
+/****************************************************************************/
+/* NAME : I2C_Enable */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :Enable the given I2C controller. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_Enable(t_i2c_device_id id)
+{
+ t_i2c_registers *p_i2c_registers;
+
+ /* Check if parameters are valid.*/
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ g_i2c_system_context[id].enabled = TRUE;
+ return(I2C_OK);
+}
+
+/****************************************************************************/
+/* NAME : I2C_Disable */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :Disble the given I2C controller. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to disabled */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_Disable(t_i2c_device_id id)
+{
+ t_i2c_registers *p_i2c_registers;
+
+ /* Check if parameters are valid.*/
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ g_i2c_system_context[id].enabled = FALSE;
+ return(I2C_OK);
+
+}
+
+
+
+/****************************************************************************/
+/* NAME : I2C_WriteSingleData */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :This routine is used to write a single data byte to */
+/* a receiver. Writing can be done to a slave device by */
+/* using the indexed modes. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* u16 : The address of the slave to be accessed */
+/* u16 : The index of the register on the receiver */
+/* to which data is written */
+/* t_unit16 :The format of the index on receiver side */
+/* u8 : The data byte to be written to the slave device */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/* I2C_SLAVE_ADDRESS_NOT_VALID If requested slave address */
+/* is not valid */
+/* I2C_CONTROLLER_BUSY if I2C controller is busy */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_WriteSingleData
+(
+ t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 data
+)
+{
+
+/*
+Steps:
+ - Check Mode
+ - Polling
+ - Interrupt
+ - DMA
+*/
+
+ volatile u32 mcr = 0;
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+ info(
+ "Id is %d, Address is %x, Index format is %d and value is %d, Data is %d",
+ id,
+ slave_address,
+ index_format,
+ index_value,
+ data
+ );
+
+ /* Check if parameters are valid.*/
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ if (!i2cp_AddressIsValid(slave_address))
+ {
+ return(I2C_SLAVE_ADDRESS_NOT_VALID);
+ }
+
+ /* Index transfers are only valid in case the Bus Control Mode is not slave*/
+ if ((I2C_BUS_MASTER_MODE != g_i2c_system_context[id].bus_control_mode) && (I2C_NO_INDEX != index_format))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* Check if not busy.*/
+ if ((g_i2c_system_context[id].operation != I2C_NO_OPERATION))
+ {
+ return(I2C_CONTROLLER_BUSY);
+ }
+
+ /* Save parameters.*/
+ g_i2c_system_context[id].slave_address = slave_address;
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_MODE;
+ g_i2c_system_context[id].register_index = index_value;
+ g_i2c_system_context[id].index_format = index_format;
+ g_i2c_system_context[id].data = data;
+ g_i2c_system_context[id].databuffer = NULL;
+ g_i2c_system_context[id].count_data = 1;
+ g_i2c_system_context[id].operation = I2C_WRITE;
+ g_i2c_system_context[id].active_event = I2C_NO_EVENT;
+ g_i2c_system_context[id].transfer_data = 0;
+ g_i2c_system_context[id].multi_operation = FALSE;
+
+ /* Disable all the interrupts to remove previously garbage interrupts */
+ switch(id)
+ {
+ case I2C0 :
+ I2C_DisableIRQSrc(I2C0_IRQ_SRC_ALL);
+ break;
+ case I2C1 :
+ I2C_DisableIRQSrc(I2C1_IRQ_SRC_ALL);
+ break;
+ case I2C2:
+ I2C_DisableIRQSrc(I2C2_IRQ_SRC_ALL);
+ break;
+ case I2C3:
+ I2C_DisableIRQSrc(I2C3_IRQ_SRC_ALL);
+ break;
+ default:
+ break;
+ }
+/* I2C_DisableIRQSrc((I2C0 == id) ? I2C0_IRQ_SRC_ALL : I2C1_IRQ_SRC_ALL);*/
+
+ /* Check if I2C controller is Master */
+ if (I2C_BUS_MASTER_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ /* Master control configuration */
+
+ /* Set the Master write operation */
+ I2C_CLR_BIT(mcr, I2C_MCR_OP);
+
+ /* start byte procedure configuration */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_SB, I2C_MCR_SHIFT_SB, (u32) g_i2c_system_context[id].start_byte_procedure);
+
+ /* Check the General call handling */
+ if (g_i2c_system_context[id].general_call_mode_handling != I2C_NO_GENERAL_CALL_HANDLING)
+ {
+ /* The Transaction is intiated by a general call command */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 0);
+ }
+ else
+ {
+ /* Check if Slave address is 10 bit */
+ if (g_i2c_system_context[id].slave_address < 1024 && g_i2c_system_context[id].slave_address > 127)
+ {
+ /* Set the Address mode to 10 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 2);
+ }
+ else
+ {
+ /* Set the Address mode to 7 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 1);
+ }
+ }
+
+ /* Store the HS master code */
+ if (I2C_FREQ_MODE_HIGH_SPEED == g_i2c_system_context[id].mode)
+ {
+ p_i2c_registers->hsmcr = g_i2c_system_context[id].high_speed_master_code;
+ }
+
+ /* Store the Slave addres in the Master control register */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_A10, I2C_MCR_SHIFT_A10, slave_address);
+
+ /* Configure the STOP condition*/
+ /* Current transaction is terminated by STOP condition */
+ I2C_SET_BIT(mcr, I2C_MCR_STOP);
+
+ /* Configuring the Frame length */
+ switch (index_format)
+ {
+ case I2C_NO_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 1);
+ break;
+
+ case I2C_BYTE_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 2);
+ break;
+
+ case I2C_HALF_WORD_LITTLE_ENDIAN:
+ case I2C_HALF_WORD_BIG_ENDIAN:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 3);
+ break;
+
+ default:
+ break;
+ }
+
+ /*Write the MCR register */
+ p_i2c_registers->mcr = mcr;
+
+ }
+
+ switch (g_i2c_system_context[id].index_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ /*
+ Index Transfer
+ */
+ if (I2C_BUS_SLAVE_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ error_status = i2cp_SlaveIndexReceive(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+ else
+ {
+ error_status = i2cp_MasterIndexTransmit(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+
+ /*
+ Data Transfer
+ */
+ switch (g_i2c_system_context[id].data_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ error_status = i2cp_TransmitDataPolling(id, (u8 *) &g_i2c_system_context[id].data);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+
+ /* Stop Signal to be sent/received for transfer completion*/
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ break;
+ }
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ return(error_status);
+
+}
+
+/****************************************************************************/
+/* NAME : I2C_WriteMultipleData */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :This routine is used to write a multiple data byte to */
+/* a receiver. Writing can be done to a slave device by */
+/* using the indexed modes. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* u16 : The address of the slave to be accessed */
+/* u16 : The index of the register on the receiver */
+/* to which data is written */
+/* t_unit16 :The format of the index on receiver side */
+/* u8* : The data buffer to be written to the */
+/* slave device */
+/* t_unit32 : no of bytes to be transfered */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/* I2C_SLAVE_ADDRESS_NOT_VALID If requested slave address */
+/* is not valid */
+/* I2C_CONTROLLER_BUSY if I2C controller is busy */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_WriteMultipleData
+(
+ t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 *p_data,
+ u32 count
+)
+{
+
+/*
+Steps:
+ - Check Mode
+ - Polling
+ - Interrupt
+ - DMA
+*/
+ volatile u32 mcr = 0;
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+ info(
+ "Id is %d, Address is %x, Index format is %d and value is %d, Data count is %d and @ is %p",
+ id,
+ slave_address,
+ index_format,
+ index_value,
+ count,
+ (void *) p_data
+ );
+
+ /* Check if parameters are valid.*/
+ if (((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id)) || (NULL == p_data))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ if (!i2cp_AddressIsValid(slave_address))
+ {
+ return(I2C_SLAVE_ADDRESS_NOT_VALID);
+ }
+
+ /* Index transfers are only valid in case the Bus Control Mode is not slave*/
+ if ((I2C_BUS_MASTER_MODE != g_i2c_system_context[id].bus_control_mode) && (I2C_NO_INDEX != index_format))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* Check if not busy.*/
+ if ((g_i2c_system_context[id].operation != I2C_NO_OPERATION))
+ {
+ return(I2C_CONTROLLER_BUSY);
+ }
+
+ /* Save parameters.*/
+ g_i2c_system_context[id].slave_address = slave_address;
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_MODE;
+ g_i2c_system_context[id].register_index = index_value;
+ g_i2c_system_context[id].index_format = index_format;
+ g_i2c_system_context[id].data = 0;
+ g_i2c_system_context[id].databuffer = p_data;
+ g_i2c_system_context[id].count_data = count;
+ g_i2c_system_context[id].operation = I2C_WRITE;
+ g_i2c_system_context[id].active_event = I2C_NO_EVENT;
+ g_i2c_system_context[id].transfer_data = 0;
+ g_i2c_system_context[id].multi_operation = TRUE;
+
+ /* Disable all the interrupts to remove previously garbage interrupts */
+ switch(id)
+ {
+ case I2C0 :
+ I2C_DisableIRQSrc(I2C0_IRQ_SRC_ALL);
+ break;
+ case I2C1 :
+ I2C_DisableIRQSrc(I2C1_IRQ_SRC_ALL);
+ break;
+ case I2C2:
+ I2C_DisableIRQSrc(I2C2_IRQ_SRC_ALL);
+ break;
+ case I2C3:
+ I2C_DisableIRQSrc(I2C3_IRQ_SRC_ALL);
+ break;
+ default:
+ break;
+ }
+ /*I2C_DisableIRQSrc((I2C0 == id) ? I2C0_IRQ_SRC_ALL : I2C1_IRQ_SRC_ALL);*/
+
+ /* Check if I2C controller is Master */
+ if (I2C_BUS_MASTER_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ /* Master control configuration */
+
+ /* Set the Master write operation */
+ I2C_CLR_BIT(mcr, I2C_MCR_OP);
+
+ /* start byte procedure configuration */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_SB, I2C_MCR_SHIFT_SB, (u32) g_i2c_system_context[id].start_byte_procedure);
+
+ /* Check the General call handling */
+ if (g_i2c_system_context[id].general_call_mode_handling != I2C_NO_GENERAL_CALL_HANDLING)
+ {
+ /* The Transaction is intiated by a general call command */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 0);
+ }
+ else
+ {
+ /* Check if Slave address is 10 bit */
+ if (g_i2c_system_context[id].slave_address < 1024 && g_i2c_system_context[id].slave_address > 127)
+ {
+ /* Set the Address mode to 10 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 2);
+ }
+ else
+ {
+ /* Set the Address mode to 7 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 1);
+ }
+ }
+
+ /* Store the HS master code */
+ if (I2C_FREQ_MODE_HIGH_SPEED == g_i2c_system_context[id].mode)
+ {
+ p_i2c_registers->hsmcr = g_i2c_system_context[id].high_speed_master_code;
+ }
+
+ /* Store the Slave addres in the Master control register */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_A10, I2C_MCR_SHIFT_A10, slave_address);
+
+ /* Configure the STOP condition*/
+ /* Current transaction is terminated by STOP condition */
+ I2C_SET_BIT(mcr, I2C_MCR_STOP);
+
+ /* Configuring the Frame length */
+ switch (index_format)
+ {
+ case I2C_NO_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, count);
+ break;
+
+ case I2C_BYTE_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, (count + 1));
+ break;
+
+ case I2C_HALF_WORD_LITTLE_ENDIAN:
+ case I2C_HALF_WORD_BIG_ENDIAN:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, (count + 2));
+ break;
+
+ default:
+ break;
+ }
+
+ p_i2c_registers->mcr = mcr;
+ }
+
+ switch (g_i2c_system_context[id].index_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ /*
+ Index Transfer
+ */
+ if (I2C_BUS_SLAVE_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ error_status = i2cp_SlaveIndexReceive(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+ else
+ {
+ error_status = i2cp_MasterIndexTransmit(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+
+ /*
+ Data Transfer
+ */
+ switch (g_i2c_system_context[id].data_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ error_status = i2cp_TransmitDataPolling(id, g_i2c_system_context[id].databuffer);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ break;
+ }
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ return(error_status);
+
+}
+
+/****************************************************************************/
+/* NAME : I2C_ReadSingleData */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :This routine is used to read a single data byte from */
+/* a transmitter. Read can be done from a slave device by */
+/* using the indexed modes. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* u16 : The address of the slave to be accessed */
+/* u16 : The index of the register on the transmitter */
+/* from which data is read */
+/* t_unit16 :The format of the index on tranmitter side */
+/* u8 : The data to be read from the tranmitter */
+/* t_unit32 : no of bytes to be transfered */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/* I2C_SLAVE_ADDRESS_NOT_VALID If requested slave address */
+/* is not valid */
+/* I2C_CONTROLLER_BUSY if I2C controller is busy */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_ReadSingleData
+(
+ t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 *p_data
+)
+{
+
+/*
+Steps:
+ - Check Mode
+ - Polling
+ - Interrupt
+ - DMA
+*/
+ volatile u32 mcr = 0;
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+ info(
+ "Id is %d, Address is %x, Index format is %d and value is %d, Data count is %d and @ is %p",
+ id,
+ slave_address,
+ index_format,
+ index_value,
+ (void *) p_data
+ );
+
+ /* Check if parameters are valid.*/
+ if (((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id)) || (NULL == p_data))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ if (!i2cp_AddressIsValid(slave_address))
+ {
+ return(I2C_SLAVE_ADDRESS_NOT_VALID);
+ }
+
+ /* Index transfers are only valid in case the Bus Control Mode is not slave*/
+ if ((I2C_BUS_MASTER_MODE != g_i2c_system_context[id].bus_control_mode) && (I2C_NO_INDEX != index_format))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* Check if not busy.*/
+ if ((g_i2c_system_context[id].operation != I2C_NO_OPERATION))
+ {
+ return(I2C_CONTROLLER_BUSY);
+ }
+
+ /* Save parameters.*/
+ g_i2c_system_context[id].slave_address = slave_address;
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_MODE;
+ g_i2c_system_context[id].register_index = index_value;
+ g_i2c_system_context[id].index_format = index_format;
+ g_i2c_system_context[id].data = 0;
+ g_i2c_system_context[id].databuffer = p_data;
+ g_i2c_system_context[id].count_data = 1;
+ g_i2c_system_context[id].operation = I2C_READ;
+ g_i2c_system_context[id].active_event = I2C_NO_EVENT;
+ g_i2c_system_context[id].transfer_data = 0;
+ g_i2c_system_context[id].multi_operation = FALSE;
+
+ /* Disable all the interrupts to remove previously garbage interrupts */
+ switch(id)
+ {
+ case I2C0 :
+ I2C_DisableIRQSrc(I2C0_IRQ_SRC_ALL);
+ break;
+ case I2C1 :
+ I2C_DisableIRQSrc(I2C1_IRQ_SRC_ALL);
+ break;
+ case I2C2:
+ I2C_DisableIRQSrc(I2C2_IRQ_SRC_ALL);
+ break;
+ case I2C3:
+ I2C_DisableIRQSrc(I2C3_IRQ_SRC_ALL);
+ break;
+ default:
+ break;
+ }
+
+ /*I2C_DisableIRQSrc((id == I2C0) ? I2C0_IRQ_SRC_ALL : I2C1_IRQ_SRC_ALL);*/
+
+ /* Check if I2C controller is Master */
+ if (I2C_BUS_MASTER_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+
+ /* start byte procedure configuration */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_SB, I2C_MCR_SHIFT_SB, (u32) g_i2c_system_context[id].start_byte_procedure);
+
+ /* Check the General call handling */
+ if (g_i2c_system_context[id].general_call_mode_handling != I2C_NO_GENERAL_CALL_HANDLING)
+ {
+ /* The Transaction is intiated by a general call command */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 0);
+ }
+ else
+ {
+ /* Check if Slave address is 10 bit */
+ if (g_i2c_system_context[id].slave_address < 1024 && g_i2c_system_context[id].slave_address > 127)
+ {
+ /* Set the Address mode to 10 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 2);
+ }
+ else
+ {
+ /* Set the Address mode to 7 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 1);
+ }
+ }
+
+ /* Store the HS master code */
+ if (I2C_FREQ_MODE_HIGH_SPEED == g_i2c_system_context[id].mode)
+ {
+ p_i2c_registers->hsmcr = g_i2c_system_context[id].high_speed_master_code;
+ }
+
+ /* Store the Slave addres in the Master control register */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_A10, I2C_MCR_SHIFT_A10, slave_address);
+
+ if
+ (
+ (g_i2c_system_context[id].slave_address < 1024 && g_i2c_system_context[id].slave_address > 127)
+ && (I2C_NO_INDEX == index_format)
+ )
+ {
+ /* Set the Master write operation */
+ I2C_CLR_BIT(mcr, I2C_MCR_OP);
+
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 0);
+
+ /* Current transaction is not terminated by STOP condition,
+ a repeated start operation will be fallowed */
+ I2C_CLR_BIT(mcr, I2C_MCR_STOP);
+
+ /*Write MCR register */
+ p_i2c_registers->mcr = mcr;
+
+ /* Enable the I2C controller */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+ }
+ else
+ {
+ /* Master control configuration */
+ if (I2C_NO_INDEX != index_format)
+ {
+ /* Set the Master write operation */
+ I2C_CLR_BIT(mcr, I2C_MCR_OP);
+ }
+ else
+ {
+ /* Set the Master read operation */
+ I2C_SET_BIT(mcr, I2C_MCR_OP);
+ }
+
+ /* Configuring the Frame length */
+ switch (index_format)
+ {
+ case I2C_NO_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 1);
+
+ /* Current transaction is terminated by STOP condition */
+ I2C_SET_BIT(mcr, I2C_MCR_STOP);
+ break;
+
+ case I2C_BYTE_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 1);
+
+ /* Current transaction is not terminated by STOP condition,
+ a repeated start operation will be fallowed */
+ I2C_CLR_BIT(mcr, I2C_MCR_STOP);
+ break;
+
+ case I2C_HALF_WORD_LITTLE_ENDIAN:
+ case I2C_HALF_WORD_BIG_ENDIAN:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 2);
+
+ /* Current transaction is not terminated by STOP condition,
+ a repeated start operation will be fallowed */
+ I2C_CLR_BIT(mcr, I2C_MCR_STOP);
+ break;
+
+ default:
+ break;
+ }
+
+ /*Write MCR register */
+ p_i2c_registers->mcr = mcr;
+
+ }
+ }
+
+ switch (g_i2c_system_context[id].index_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ /*
+ Index Transfer
+ */
+ if (I2C_BUS_SLAVE_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ error_status = i2cp_SlaveIndexReceive(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+ else
+ {
+ error_status = i2cp_MasterIndexTransmit(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+
+ /*
+ Data Transfer
+ */
+ switch (g_i2c_system_context[id].data_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ error_status = i2cp_ReceiveDataPolling(id, g_i2c_system_context[id].databuffer);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+
+ /* Stop Signal to be sent/received for transfer completion*/
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ break;
+ }
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ return(error_status);
+
+}
+
+/****************************************************************************/
+/* NAME : I2C_ReadMultipleData */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :This routine is used to read a multiple data byte from */
+/* a transmitter. Read can be done from a slave device by */
+/* using the indexed modes. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be initialized */
+/* u16 : The address of the slave to be accessed */
+/* u16 : The index of the register on the transmitter */
+/* from which data is read */
+/* t_unit16 :The format of the index on tranmitter side */
+/* u8* : The data buffer to be written to the */
+/* slave device */
+/* t_unit32 : no of bytes to be transfered */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/* I2C_SLAVE_ADDRESS_NOT_VALID If requested slave address */
+/* is not valid */
+/* I2C_CONTROLLER_BUSY if I2C controller is busy */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_ReadMultipleData
+(
+ t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 *p_data,
+ u32 count
+)
+{
+
+/*
+Steps:
+ - Check Mode
+ - Polling
+ - Interrupt
+ - DMA
+*/
+ volatile u32 mcr = 0;
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+ info(
+ "Id is %d, Address is %x, Index format is %d and value is %d, Data count is %d and @ is %p",
+ id,
+ slave_address,
+ index_format,
+ index_value,
+ count,
+ (void *) p_data
+ );
+
+ /* Check if parameters are valid.*/
+ if (((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id) ) || (NULL == p_data))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+
+ if (!i2cp_AddressIsValid(slave_address))
+ {
+ return(I2C_SLAVE_ADDRESS_NOT_VALID);
+ }
+
+ /* Index transfers are only valid in case the Bus Control Mode is not slave*/
+ if ((I2C_BUS_MASTER_MODE != g_i2c_system_context[id].bus_control_mode) && (I2C_NO_INDEX != index_format))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* Check if not busy.*/
+ if ((g_i2c_system_context[id].operation != I2C_NO_OPERATION))
+ {
+ return(I2C_CONTROLLER_BUSY);
+ }
+
+ /* Save parameters.*/
+ g_i2c_system_context[id].slave_address = slave_address;
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_MODE;
+ g_i2c_system_context[id].register_index = index_value;
+ g_i2c_system_context[id].index_format = index_format;
+ g_i2c_system_context[id].data = 0;
+ g_i2c_system_context[id].databuffer = p_data;
+ g_i2c_system_context[id].count_data = count;
+ g_i2c_system_context[id].operation = I2C_READ;
+ g_i2c_system_context[id].active_event = I2C_NO_EVENT;
+ g_i2c_system_context[id].transfer_data = 0;
+ g_i2c_system_context[id].multi_operation = TRUE;
+
+ /* Disable all the interrupts to remove previously garbage interrupts */
+ switch(id)
+ {
+ case I2C0 :
+ I2C_DisableIRQSrc(I2C0_IRQ_SRC_ALL);
+ break;
+ case I2C1 :
+ I2C_DisableIRQSrc(I2C1_IRQ_SRC_ALL);
+ break;
+ case I2C2:
+ I2C_DisableIRQSrc(I2C2_IRQ_SRC_ALL);
+ break;
+ case I2C3:
+ I2C_DisableIRQSrc(I2C3_IRQ_SRC_ALL);
+ break;
+ default:
+ break;
+ }
+/* I2C_DisableIRQSrc((I2C0 == id) ? I2C0_IRQ_SRC_ALL : I2C1_IRQ_SRC_ALL);*/
+
+ /* Check if I2C controller is Master */
+ if (I2C_BUS_MASTER_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+
+ /* start byte procedure configuration */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_SB, I2C_MCR_SHIFT_SB, (u32) g_i2c_system_context[id].start_byte_procedure);
+
+ /* Check the General call handling */
+ if (g_i2c_system_context[id].general_call_mode_handling != I2C_NO_GENERAL_CALL_HANDLING)
+ {
+ /* The Transaction is intiated by a general call command */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 0);
+ }
+ else
+ {
+ /* Check if Slave address is 10 bit */
+ if (g_i2c_system_context[id].slave_address < 1024 && g_i2c_system_context[id].slave_address > 127)
+ {
+ /* Set the Address mode to 10 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 2);
+ }
+ else
+ {
+ /* Set the Address mode to 7 bit */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_AM, I2C_MCR_SHIFT_AM, 1);
+ }
+ }
+
+ /* Store the HS master code */
+ if (I2C_FREQ_MODE_HIGH_SPEED == g_i2c_system_context[id].mode)
+ {
+ p_i2c_registers->hsmcr = g_i2c_system_context[id].high_speed_master_code;
+ }
+
+ /* Store the Slave addres in the Master control register */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_A10, I2C_MCR_SHIFT_A10, slave_address);
+
+ if
+ (
+ (g_i2c_system_context[id].slave_address < 1024 && g_i2c_system_context[id].slave_address > 127)
+ && (I2C_NO_INDEX == index_format)
+ )
+ {
+ /* Set the Master write operation */
+ I2C_CLR_BIT(mcr, I2C_MCR_OP);
+
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 0);
+
+ /* Current transaction is not terminated by STOP condition,
+ a repeated start operation will be fallowed */
+ I2C_CLR_BIT(mcr, I2C_MCR_STOP);
+
+ /*Write MCR register */
+ p_i2c_registers->mcr = mcr;
+
+ /* Enable the I2C controller */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+ }
+ else
+ {
+ /* Master control configuration */
+ if (I2C_NO_INDEX != index_format)
+ {
+ /* Set the Master write operation */
+ I2C_CLR_BIT(mcr, I2C_MCR_OP);
+ }
+ else
+ {
+ /* Set the Master read operation */
+ I2C_SET_BIT(mcr, I2C_MCR_OP);
+ }
+
+ /* Configuring the Frame length */
+ switch (index_format)
+ {
+ case I2C_NO_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, count);
+
+ /* Current transaction is terminated by STOP condition */
+ I2C_SET_BIT(mcr, I2C_MCR_STOP);
+ break;
+
+ case I2C_BYTE_INDEX:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 1);
+
+ /* Current transaction is not terminated by STOP condition,
+ a repeated start operation will be fallowed */
+ I2C_CLR_BIT(mcr, I2C_MCR_STOP);
+ break;
+
+ case I2C_HALF_WORD_LITTLE_ENDIAN:
+ case I2C_HALF_WORD_BIG_ENDIAN:
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, 2);
+
+ /* Current transaction is not terminated by STOP condition,
+ a repeated start operation will be fallowed */
+ I2C_CLR_BIT(mcr, I2C_MCR_STOP);
+ break;
+
+ default:
+ break;
+ }
+
+ /*Write MCR register */
+ p_i2c_registers->mcr = mcr;
+
+ }
+ }
+
+ switch (g_i2c_system_context[id].index_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ /*
+ Index Transfer
+ */
+ if (I2C_BUS_SLAVE_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ error_status = i2cp_SlaveIndexReceive(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+ else
+ {
+ error_status = i2cp_MasterIndexTransmit(id);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ }
+
+ /*
+ Data Transfer
+ */
+ switch (g_i2c_system_context[id].data_transfer_mode)
+ {
+ case I2C_TRANSFER_MODE_POLLING:
+ error_status = i2cp_ReceiveDataPolling(id, g_i2c_system_context[id].databuffer);
+ if (I2C_OK != error_status)
+ {
+ return(error_status);
+ }
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ break;
+ }
+ break;
+
+ case I2C_TRANSFER_MODE_INTERRUPT:
+ case I2C_TRANSFER_MODE_DMA:
+ default:
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ return(error_status);
+
+}
+
+/****************************************************************************/
+/* NAME : I2C_Cancel */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : This routine is used to cancel the current transfer */
+/* operation, if any. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller to be canceled */
+/* InOut : None */
+/* : t_i2c_active_event: It will contain the result of */
+/* the operation */
+/* */
+/* RETURN : t_i2c_error */
+/* I2C_OK if it is ok */
+/* I2C_INVALID_PARAMETER if input parameters are not valid */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_i2c_error I2C_Cancel(t_i2c_device_id id, t_i2c_active_event *event) /*Only IT mode*/
+{
+ /* Check if parameters are valid.*/
+ if ((NULL == event) || ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id)))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ if (I2C_NO_EVENT == g_i2c_system_context[id].active_event)
+ {
+ event->type = I2C_NO_EVENT;
+ event->transfer_data = 0;
+ event->id = id;
+ }
+ else
+ {
+ event->type = I2C_CANCEL_EVENT;
+ event->transfer_data = g_i2c_system_context[id].transfer_data;
+ event->id = id;
+ g_i2c_system_context[id].active_event = I2C_CANCEL_EVENT;
+ }
+
+ i2cp_Abort(id);
+
+ /*Set the I2C operation to No operation */
+ g_i2c_system_context[id].operation = (t_i2c_operation) I2C_NO_OPERATION;
+
+ return(I2C_OK);
+}
+
+
+
+/****************************************************************************/
+/* NAME : I2C_IsEventActive */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :This routine is used to determine if the given event */
+/* is still active. */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_active_event: the Event to be checked */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_bool : TRUE or FALSE */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+ t_bool I2C_IsEventActive(t_i2c_active_event *event)
+{
+ if (event->type == g_i2c_system_context[event->id].active_event)
+ {
+ return(TRUE);
+ }
+ else
+ {
+ return(FALSE);
+ }
+}
+
+
+/****************************************************************************/
+/* NAME : I2C_Reset */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION :Reset the I2C Registers for given I2C controller */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The ID of the controller for reset */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/* return I2C_INVALID_PARAMETER if id is not correct */
+/* else I2C_OK */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+/****************************************************************************/
+t_i2c_error I2C_Reset(t_i2c_device_id id)
+{
+ t_i2c_registers *p_i2c_registers;
+
+ /* Check if parameters are valid.*/
+ if ((I2C0 != id) && (I2C1 != id) && (I2C2 != id) && (I2C3 != id))
+ {
+ return(I2C_INVALID_PARAMETER);
+ }
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+
+ /* Clear registers.*/
+ I2C_WRITE_REG(p_i2c_registers->cr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->scr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->hsmcr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->mcr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->tftr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->rftr, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->dmar, I2C_CLEAR);
+ I2C_WRITE_REG(p_i2c_registers->icr, 0x31F0008);
+ I2C_WRITE_REG(p_i2c_registers->imscr,I2C_CLEAR);
+
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_FTX); /* Flush the Tx Fifo */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_FRX); /* Flush the Rx Fifo */
+
+ /*
+ Initialize the right structure to default state
+ */
+ g_i2c_system_context[id].freq_scl = 0;
+ g_i2c_system_context[id].freq_input = 0;
+ g_i2c_system_context[id].mode = I2C_FREQ_MODE_STANDARD;
+ g_i2c_system_context[id].own_address = 0;
+ g_i2c_system_context[id].enabled = FALSE;
+ g_i2c_system_context[id].slave_address = 0;
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_MODE;
+ g_i2c_system_context[id].data = 0;
+ g_i2c_system_context[id].databuffer = NULL;
+ g_i2c_system_context[id].count_data = 0;
+ g_i2c_system_context[id].register_index = 0;
+ g_i2c_system_context[id].operation = (t_i2c_operation) I2C_NO_OPERATION;
+ g_i2c_system_context[id].active_event = I2C_NO_EVENT;
+ g_i2c_system_context[id].transfer_data = 0;
+ g_i2c_system_context[id].multi_operation = FALSE;
+
+ /* g_i2c_system_context[id].i2c_device_context... to be initialized*/
+ g_i2c_system_context[id].digital_filter_control = I2C_DIGITAL_FILTERS_OFF;
+ g_i2c_system_context[id].dma_sync_logic_control = I2C_DISABLE;
+ g_i2c_system_context[id].start_byte_procedure = I2C_DISABLE;
+ g_i2c_system_context[id].slave_data_setup_time = 0; /* TBD */
+ g_i2c_system_context[id].high_speed_master_code = 0;
+ g_i2c_system_context[id].bus_control_mode = I2C_BUS_SLAVE_MODE;
+ g_i2c_system_context[id].i2c_loopback_mode = I2C_DISABLE;
+ g_i2c_system_context[id].general_call_mode_handling = I2C_NO_GENERAL_CALL_HANDLING;
+
+ g_i2c_system_context[id].index_transfer_mode = I2C_TRANSFER_MODE_POLLING;
+ g_i2c_system_context[id].data_transfer_mode = I2C_TRANSFER_MODE_POLLING;
+ g_i2c_system_context[id].i2c_transmit_interrupt_threshold = 1;
+ g_i2c_system_context[id].i2c_receive_interrupt_threshold = 1;
+ g_i2c_system_context[id].transmit_burst_length = 0;
+ g_i2c_system_context[id].receive_burst_length = 0;
+ g_i2c_system_context[id].index_format = I2C_NO_INDEX;
+ g_i2c_system_context[id].current_bus_config = I2C_CURRENT_BUS_SLAVE_TRANSMITTER;
+ g_i2c_system_context[id].std =FALSE;
+
+ return(I2C_OK);
+}
+
+/*-----------------------------------------------------------------------------
+ Private functions
+-----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_SetOwnAddress
+Description : Set the I2C bus address of the controller.
+In : t_i2c_registers* p_i2c_registers : pointer to the controller's
+ registers.
+ u32 address : the slave address of the
+ controller.
+InOut : None
+Out : None
+Return value: Always ok / I2C_SLAVE_ADDRESS_NOT_VALID
+Type : Private
+Comments :
+
+
+ In all cases, the bits are not cleared when the interface is disabled
+ (PE = 0b).
+-----------------------------------------------------------------------------*/
+ t_i2c_error i2cp_SetOwnAddress(t_i2c_device_id id, u16 address)
+{
+ t_i2c_registers *p_i2c_registers;
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* CM: check if the given address is valid ???*/
+ if (!i2cp_AddressIsValid(address))
+ {
+ return(I2C_SLAVE_ADDRESS_NOT_VALID);
+ }
+
+ if (address < 1024 && address > 127)
+ {
+ /* Set Slave address mode to 10 bit addressing mode */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_SAM);
+ I2C_WRITE_FIELD(p_i2c_registers->scr, I2C_SCR_ADDR, I2C_SCR_SHIFT_ADDR, address);
+ }
+ else
+ {
+ /* Set the slave address mode to 7 bit addressing mode */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_SAM);
+ I2C_WRITE_FIELD(p_i2c_registers->scr, I2C_SCR_ADDR, I2C_SCR_SHIFT_ADDR, address);
+ }
+
+ return(I2C_OK);
+}
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_SetBusClock
+Description : Set the I2C bus clock for the given controller.
+In : t_i2c_registers* p_i2c_registers : pointer to the controller's
+ registers.
+ u32 freq_scl : the I2C bus frequency freq_scl (Hz).
+ u32 freq_input : the input clock frequency (Hz).
+InOut : None
+Out : None
+Return value: I2C_OK : no error.
+ I2C_INVALID_PARAMETER : wrong id parameter.
+ I2C_freq_scl_NOT_SUPPORTED : freq_scl is not supported.
+Type : Private
+Comments : The freq_input parameter is only necessary to calculate the I2C bus
+ frequency and is not used for other purposes.
+ It is not necessary to save the freq_scl as it has been already
+ saved by I2C_Config().
+
+-----------------------------------------------------------------------------*/
+t_i2c_error i2cp_SetBusClock(t_i2c_device_id id, u32 freq_scl, u32 freq_input)
+{
+
+
+ /* To be defined */
+ u32 value;
+ t_i2c_registers *p_i2c_registers;
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ /* Standard mode */
+ if (freq_scl <= (u32) I2C_MAX_STANDARD_SCL)
+ {
+ value = (u32) (freq_input / (freq_scl * 2));
+
+ /*Set the Standard mode in the control register */
+ I2C_WRITE_FIELD(p_i2c_registers->cr, I2C_CR_SM, I2C_CR_SHIFT_SM, 0x0);
+
+ /* set the Baud rate counter 2 value */
+ I2C_WRITE_FIELD(p_i2c_registers->brcr, I2C_BRCR_BRCNT2, I2C_BRCR_SHIFT_BRCNT2, value);
+
+ /* Make ensure that BRCNT value set to be zero */
+ I2C_WRITE_FIELD(p_i2c_registers->brcr, I2C_BRCR_BRCNT1, I2C_BRCR_SHIFT_BRCNT1, 0);
+
+ /*Update the Frequency mode in the global strcture */
+ g_i2c_system_context[id].mode = I2C_FREQ_MODE_STANDARD;
+ }
+ else /* Fast Mode */
+ if (freq_scl <= (u32) I2C_MAX_FAST_SCL)
+ {
+ value = (u32) (freq_input / ((freq_scl * 3) / 2));
+
+ /*Set the Fast mode in the control register */
+ I2C_WRITE_FIELD(p_i2c_registers->cr, I2C_CR_SM, I2C_CR_SHIFT_SM, 0x1);
+
+ /* set the Baud rate counter 2 value */
+ I2C_WRITE_FIELD(p_i2c_registers->brcr, I2C_BRCR_BRCNT2, I2C_BRCR_SHIFT_BRCNT2, value);
+
+ /* Make ensure that BRCNT value set to be zero */
+ I2C_WRITE_FIELD(p_i2c_registers->brcr, I2C_BRCR_BRCNT1, I2C_BRCR_SHIFT_BRCNT1, 0);
+
+ /*Update the Frequency mode in the global strcture */
+ g_i2c_system_context[id].mode = I2C_FREQ_MODE_FAST;
+ }
+ else /* High Speed Mode */
+ if (freq_scl <= (u32) I2C_MAX_HIGH_SPEED_SCL)
+ {
+ value = (u32) (freq_input / ((freq_scl * 3) / 2));
+
+ /*Set the High speed mode in the control register */
+ I2C_WRITE_FIELD(p_i2c_registers->cr, I2C_CR_SM, I2C_CR_SHIFT_SM, 0x2);
+
+ /* set the Baud rate counter 1 value */
+ I2C_WRITE_FIELD(p_i2c_registers->brcr, I2C_BRCR_BRCNT1, I2C_BRCR_SHIFT_BRCNT1, value);
+
+ /*Update the Frequency mode in the global strcture */
+ g_i2c_system_context[id].mode = I2C_FREQ_MODE_HIGH_SPEED;
+ }
+ else
+ {
+ return(I2C_LINE_FREQ_NOT_SUPPORTED);
+ }
+
+ return(I2C_OK);
+
+}
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_AddressIsValid
+Description : Check if the given address is valid.
+In : u16 address : the slave address to be checked.
+InOut : None
+Out : None
+Return value: TRUE : address is valid.
+ FALSE : address is not valid.
+Type : Private
+Comments : Note that the least-significant bit of the address parameter
+ is not relevant for the addressing of the slave device, for
+ example 0xE2 and 0xE3 will address the same slave device.
+
+
+ Reserved addresses:
+ SLAVE ADDRESS R/W BIT RANGE DESCRIPTION
+ 0000 000 0 0 General call address
+ 0000 000 1 1 START byte(1)
+ 0000 001 X 2-3 CBUS address(2)
+ 0000 010 X 4-5 Reserved for different bus format(3)
+ 0000 011 X 6-7 Reserved for future purposes
+ 0000 1XX X 8-15 Hs-mode master code
+
+ 1111 1XX X 248-255 Reserved for future purposes
+ 1111 0XX X 240-247 10-bit slave addressing
+
+ Note that with 7-bit address:
+ 0000xxxx and 1111xxxx are reserved.
+-----------------------------------------------------------------------------*/
+t_bool i2cp_AddressIsValid(u16 address)
+{
+ /* Check if more than 10 bits are needed.*/
+ if (address > 1023)
+ {
+ return(FALSE);
+ }
+
+ /* 7-bit address. LSB is not considered.*/
+ /*Address 0x4 is enabled to support the ST Pepper pot camera */
+ if (address < 128 && !(address == 0 || address == 0x4))
+ {
+ if ((address < 8) || (address > 119))
+ {
+ return(FALSE);
+ }
+ }
+
+ /* CM: add here the 10-bit check.*/
+ return(TRUE);
+}
+
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_Abort
+Description : Abort the current transfer operation of the given controller.
+In : t_i2c_device_id id : the controller to be aborted.
+InOut : None
+Out : None
+Return : I2C_OK : always no error.
+Type : Private
+Comments : This is called when an unexpected event happens (internal error).
+-----------------------------------------------------------------------------*/
+void i2cp_Abort(t_i2c_device_id id)
+{
+
+ t_i2c_registers *p_i2c_registers;
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+ /*Disable the interrupts */
+ I2C_WRITE_REG(p_i2c_registers->imscr,I2C_CLEAR);
+
+ /*Disable the Controller */
+ I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ /*Enable the controller */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE);
+
+ /*Set the I2C operation to No operation */
+ g_i2c_system_context[id].operation = (t_i2c_operation) I2C_NO_OPERATION;
+}
+
+
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_SlaveIndexReceive
+Description :
+In : t_i2c_id : I2C Controller id
+
+InOut : None
+Out : t_i2c_error error status
+Return value: I2C_OK : no error
+ I2C_INVALID_PARAMETER : wrong id parameter.
+
+Type : Private
+Comments : This function perform the operations, when
+ I2C controller addressed as a slave
+-----------------------------------------------------------------------------*/
+t_i2c_error i2cp_SlaveIndexReceive(t_i2c_device_id id)
+{
+
+ u32 loop_counter = 0;
+ t_i2c_registers *p_i2c_registers;
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ if (I2C_WRITE == g_i2c_system_context[id].operation)
+ {
+ /* SLAVE TRANSMITTER */
+ /* Waiting for the Read from slave request */
+ loop_counter = 0;
+ while
+ (
+ (!I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_RFSR, I2C_INT_SHIFT_RFSR))
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ i2cp_Abort(id);
+ return(I2C_ADDRESS_MATCH_FAILED);
+ }
+
+ /* Acknowledge the Read from slave request */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_RFSR);
+
+ /* Read from slave request recieved */
+ /* Flush the Tx Fifo */
+ I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_FTX);
+
+ /*Wait till for the Tx Flush bit to reset */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->cr, I2C_CR_FTX, I2C_CR_SHIFT_FTX)
+ && loop_counter < I2C_FIFO_FLUSH_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_FIFO_FLUSH_COUNTER)
+ {
+ return(I2C_HW_FAILED);
+ }
+
+ /* update the status */
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_TRANSMITTER_MODE;
+ g_i2c_system_context[id].active_event = I2C_READ_FROM_SLAVE_REQUEST_EVENT;
+ g_i2c_system_context[id].current_bus_config = I2C_CURRENT_BUS_SLAVE_TRANSMITTER;
+
+ }
+ else
+ {
+ /* SLAVE RECEIVER */
+ /* Waiting for the Write to slave request */
+ loop_counter = 0;
+ while
+ (
+ (!I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_WTSR, I2C_INT_SHIFT_WTSR))
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ i2cp_Abort(id);
+ return(I2C_ADDRESS_MATCH_FAILED);
+ }
+
+ /* Acknowledge the Write to slave request */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_WTSR);
+
+ /* update the status */
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_TRANSMITTER_MODE;
+ g_i2c_system_context[id].active_event = I2C_WRITE_TO_SLAVE_REQUEST_EVENT;
+ g_i2c_system_context[id].current_bus_config = I2C_CURRENT_BUS_SLAVE_RECEIVER;
+
+ }
+
+ /* Update the status of the I2C controller */
+ if (I2C_READ == g_i2c_system_context[id].operation)
+ {
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_RECEIVER_MODE;
+ }
+ else
+ {
+ g_i2c_system_context[id].status = I2C_STATUS_SLAVE_TRANSMITTER_MODE;
+ }
+
+ return(I2C_OK);
+}
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_TransmitDataPolling
+Description : Transmit the data in the polling mode
+In : t_i2c_id : I2C Controller id
+
+InOut : None
+Out : t_i2c_error error status
+Return value: I2C_OK : no error
+ I2C_INVALID_PARAMETER : wrong id parameter.
+
+Type : Private
+Comments :
+-----------------------------------------------------------------------------*/
+t_i2c_error i2cp_TransmitDataPolling(t_i2c_device_id id, volatile u8 *p_data)
+{
+
+ u32 loop_counter = 0;
+ t_i2c_registers *p_i2c_registers;
+ t_i2c_error error_status;
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ if (I2C_BUS_SLAVE_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ /* Slave tranmitter */
+ while (g_i2c_system_context[id].count_data != 0)
+ {
+ /* Check for Tx Fifo not full */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_TXFF, I2C_INT_SHIFT_TXFF)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ return(I2C_TRANSMIT_FIFO_FULL);
+ }
+ }
+
+ p_i2c_registers->tfr = *p_data;
+
+ g_i2c_system_context[id].transfer_data++;
+ g_i2c_system_context[id].count_data--;
+ p_data++;
+ g_i2c_system_context[id].active_event = I2C_DATA_TX_EVENT;
+ }
+
+ /* End of Data transfer */
+ /* Check for the Slave tranaction done */
+ loop_counter = 0;
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_STD, I2C_INT_SHIFT_STD)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_INTERNAL_ERROR);
+ }
+
+ /* Slave Transaction has been done */
+ /* Acknowledge the Slave Transaction done */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_STD);
+
+ g_i2c_system_context[id].active_event = I2C_TRANSFER_OK_EVENT;
+ return(I2C_OK);
+ }
+ else
+ {
+ /* Master Transmitter */
+ while (g_i2c_system_context[id].count_data != 0)
+ {
+ /* Check for Tx Fifo not full */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_TXFF, I2C_INT_SHIFT_TXFF)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_TRANSMIT_FIFO_FULL);
+ }
+
+ p_i2c_registers->tfr = *p_data;
+
+ g_i2c_system_context[id].transfer_data++;
+ g_i2c_system_context[id].count_data--;
+ p_data++;
+ g_i2c_system_context[id].active_event = I2C_DATA_TX_EVENT;
+ }
+
+ /* End of Data transfer */
+
+ loop_counter = 0;
+ /* Check whether the Stop bit has been programmed or not */
+ if(I2C_READ_FIELD(p_i2c_registers->mcr, I2C_MCR_STOP, I2C_MCR_SHIFT_STOP))
+ {
+ /* Check for the Master transaction Done */
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_MTD, I2C_INT_SHIFT_MTD)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ }
+ else
+ {
+ /* Check for the Master transaction Done Without Stop */
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_MTDWS, I2C_INT_SHIFT_MTDWS)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ }
+
+
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ i2cp_Abort(id);
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_INTERNAL_ERROR);
+ }
+
+
+ /* Master Transaction has been done */
+ /* Acknowledge the Master Transaction Done */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTD);
+
+ /* Master Transaction Without Stop has been done */
+ /* Acknowledge the Master Transaction Done Without Stop */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTDWS);
+
+
+ g_i2c_system_context[id].active_event = I2C_TRANSFER_OK_EVENT;
+
+ g_i2c_system_context[id].operation = I2C_NO_OPERATION;
+ return(I2C_OK);
+ }
+
+}
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_ReceiveDataPolling
+Description : Receiving the data in polling mode
+In : t_i2c_id : I2C Controller id
+
+InOut : None
+Out : t_i2c_error error status
+Return value: I2C_OK : no error
+ I2C_WRONG_PARAMETER : wrong id parameter.
+
+Type : Private
+Comments :
+-----------------------------------------------------------------------------*/
+t_i2c_error i2cp_ReceiveDataPolling(t_i2c_device_id id, u8 *p_data)
+{
+
+ u32 loop_counter = 0;
+ t_i2c_error error_status;
+ t_i2c_registers *p_i2c_registers;
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ if (I2C_BUS_SLAVE_MODE == g_i2c_system_context[id].bus_control_mode)
+ {
+ /* Slave Receiver */
+ while (g_i2c_system_context[id].count_data != 0)
+ {
+ /* Wait for the Rx Fifo empty */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_RXFE, I2C_INT_SHIFT_RXFE)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_RECEIVE_FIFO_EMPTY);
+ }
+
+ /* Read the data byte from Rx Fifo */
+ *p_data = (u8) p_i2c_registers->rfr;
+
+ g_i2c_system_context[id].transfer_data++;
+ g_i2c_system_context[id].count_data--;
+ p_data++;
+ g_i2c_system_context[id].active_event = I2C_DATA_RX_EVENT;
+ } /* Data Reception has been completed */
+
+ /* Check for the slave transaction done */
+ loop_counter = 0;
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_STD, I2C_INT_SHIFT_STD)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_INTERNAL_ERROR);
+ }
+
+ /* Slave Transaction has been done */
+ /* Acknowledge the Slave Transaction Done */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_STD);
+ g_i2c_system_context[id].active_event = I2C_TRANSFER_OK_EVENT;
+ g_i2c_system_context[id].operation = I2C_NO_OPERATION;
+
+ return(I2C_OK);
+ }
+ else
+ {
+ /* Master Receiver */
+ while (g_i2c_system_context[id].count_data != 0)
+ {
+ /* Wait for the Rx Fifo empty */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_RXFE, I2C_INT_SHIFT_RXFE)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_RECEIVE_FIFO_EMPTY);
+ }
+
+ /* Read the data byte from Rx Fifo */
+ *p_data = (u8) p_i2c_registers->rfr;
+
+ g_i2c_system_context[id].transfer_data++;
+ g_i2c_system_context[id].count_data--;
+ p_data++;
+ g_i2c_system_context[id].active_event = I2C_DATA_RX_EVENT;
+ } /* Data reception has been completed */
+
+ loop_counter = 0;
+ /* Check whether the Stop bit has been programmed or not */
+ if(I2C_READ_FIELD(p_i2c_registers->mcr, I2C_MCR_STOP, I2C_MCR_SHIFT_STOP))
+ {
+ /* Check for the Master transaction Done */
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_MTD, I2C_INT_SHIFT_MTD)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ }
+ else
+ {
+ /* Check for the Master transaction Done Without Stop */
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_MTDWS, I2C_INT_SHIFT_MTDWS)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ }
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_INTERNAL_ERROR);
+ }
+
+ /* Master Transaction has been done */
+ /* Acknowledge the Master Transaction Done */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTD);
+
+ /* Master Transaction Without Stop has been done */
+ /* Acknowledge the Master Transaction Done Without Stop */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTDWS);
+
+ g_i2c_system_context[id].active_event = I2C_TRANSFER_OK_EVENT;
+ g_i2c_system_context[id].operation = I2C_NO_OPERATION;
+
+ }
+
+ return(I2C_OK);
+}
+
+/*-----------------------------------------------------------------------------
+Name : i2cp_MasterIndexTransmit
+Description : Transmits the index to slave
+In : t_i2c_id : I2C Controller id
+
+InOut : None
+Out : t_i2c_error error status
+Return value: I2C_OK : no error
+ I2C_WRONG_PARAMETER : wrong id parameter.
+
+Type : Private
+Comments :
+-----------------------------------------------------------------------------*/
+t_i2c_error i2cp_MasterIndexTransmit(t_i2c_device_id id)
+{
+
+ volatile u32 mcr = 0;
+ u32 loop_counter = 0;
+ t_i2c_error error_status = I2C_OK;
+ t_i2c_registers *p_i2c_registers;
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ switch (g_i2c_system_context[id].index_format)
+ {
+ case I2C_NO_INDEX:
+ if (g_i2c_system_context[id].slave_address <= 127)
+ {
+ return(I2C_OK);
+ }
+
+ break;
+
+ case I2C_BYTE_INDEX:
+ /* Checking for the Tx fifo not full */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_TXFF, I2C_INT_SHIFT_TXFF)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_TRANSMIT_FIFO_FULL);
+ }
+
+ p_i2c_registers->tfr = (0xFF & g_i2c_system_context[id].register_index);
+
+ g_i2c_system_context[id].active_event = I2C_INDEX_TX_EVENT;
+ g_i2c_system_context[id].index_format = I2C_NO_INDEX;
+
+ break;
+
+ case I2C_HALF_WORD_LITTLE_ENDIAN:
+ /* Checking for the Tx Fifo not full */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_TXFF, I2C_INT_SHIFT_TXFF)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_TRANSMIT_FIFO_FULL);
+ }
+
+ p_i2c_registers->tfr = (0xFF & (u32) g_i2c_system_context[id].register_index);
+
+ p_i2c_registers->tfr = (g_i2c_system_context[id].register_index >> 8);
+
+ g_i2c_system_context[id].index_format = I2C_NO_INDEX;
+ g_i2c_system_context[id].active_event = I2C_INDEX_TX_EVENT;
+ break;
+
+ case I2C_HALF_WORD_BIG_ENDIAN:
+ /* Cheking for the Tx Fifo full */
+ loop_counter = 0;
+ while
+ (
+ I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_TXFF, I2C_INT_SHIFT_TXFF)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_TRANSMIT_FIFO_FULL);
+ }
+
+ p_i2c_registers->tfr = (g_i2c_system_context[id].register_index >> 8);
+
+ p_i2c_registers->tfr = (0xFF & g_i2c_system_context[id].register_index);
+
+ g_i2c_system_context[id].index_format = I2C_NO_INDEX;
+ g_i2c_system_context[id].active_event = I2C_INDEX_TX_EVENT;
+ break;
+
+ default:
+ break;
+ }
+
+ if (g_i2c_system_context[id].operation == I2C_READ)
+ {
+ loop_counter = 0;
+ /* Check whether the Stop bit has been programmed or not */
+ if(I2C_READ_FIELD(p_i2c_registers->mcr, I2C_MCR_STOP, I2C_MCR_SHIFT_STOP))
+ {
+ /* Check for the Master transaction Done */
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_MTD, I2C_INT_SHIFT_MTD)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ }
+ else
+ {
+ /* Check for the Master transaction Done Without Stop */
+ while
+ (
+ !I2C_READ_FIELD(p_i2c_registers->risr, I2C_INT_MTDWS, I2C_INT_SHIFT_MTDWS)
+ && loop_counter < I2C_ENDAD_COUNTER
+ )
+ {
+ loop_counter++;
+ };
+ }
+
+ if (loop_counter >= I2C_ENDAD_COUNTER)
+ {
+ error_status = i2cp_GetAbortCause(id);
+ if (error_status != I2C_OK)
+ {
+ return(error_status);
+ }
+ else
+ {
+ i2cp_Abort(id);
+ }
+
+ return(I2C_INTERNAL_ERROR);
+ }
+
+ /* Master Transaction has been done */
+ /* Acknowledge the Master Transaction Done */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTD);
+
+ /* Master Transaction Without Stop has been done */
+ /* Acknowledge the Master Transaction Done Without Stop */
+ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTDWS);
+
+ /* Master control configuration for read operation */
+ I2C_SET_BIT(mcr, I2C_MCR_OP);
+
+ /* Configure the STOP condition*/
+ I2C_SET_BIT(mcr, I2C_MCR_STOP);
+
+ /* Configuring the Frame length */
+ I2C_WRITE_FIELD(mcr, I2C_MCR_LENGTH, I2C_MCR_SHIFT_LENGTH, g_i2c_system_context[id].count_data);
+
+ I2C_WRITE_FIELD(p_i2c_registers->mcr,I2C_MCR_LENGTH_STOP_OP,I2C_MCR_SHIFT_LENGTH_STOP_OP,mcr);
+
+ }
+
+ /* added to remove the warning unused variable */
+ error_status = error_status;
+
+ /* Update the status of the I2C controller */
+ if (I2C_READ == g_i2c_system_context[id].operation)
+ {
+ g_i2c_system_context[id].status = I2C_STATUS_MASTER_RECEIVER_MODE;
+ }
+ else
+ {
+ g_i2c_system_context[id].status = I2C_STATUS_MASTER_TRANSMITTER_MODE;
+ }
+
+ return(I2C_OK);
+}
+
+
+/* Private function valid for HS controller */
+
+
+/****************************************************************************/
+/* NAME : i2cp_GetAbortCause */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Get the abort Cause */
+/* */
+/* PARAMETERS : */
+/* : t_i2c_device_id : The controller that aborted */
+/* InOut : None */
+/* : None */
+/* */
+/* RETURN : t_i2c_error */
+/*--------------------------------------------------------------------------*/
+/* Type : */
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES : */
+
+/****************************************************************************/
+t_i2c_error i2cp_GetAbortCause(t_i2c_device_id id)
+{
+ u8 abort_cause;
+ t_i2c_error error_status;
+
+ t_i2c_registers *p_i2c_registers;
+
+ p_i2c_registers = (t_i2c_registers *) g_i2c_system_context[id].base_address;
+
+ if (I2C_READ_FIELD(p_i2c_registers->sr, I2C_SR_STATUS, I2C_SR_SHIFT_STATUS) == 3)
+ {
+ abort_cause = (u8) I2C_READ_FIELD(p_i2c_registers->sr, I2C_SR_CAUSE, I2C_SR_SHIFT_CAUSE);
+
+ switch (abort_cause)
+ {
+ case 0:
+ error_status = I2C_ACK_FAIL_ON_ADDRESS;
+ break;
+
+ case 1:
+ error_status = I2C_ACK_FAIL_ON_DATA;
+ break;
+
+ case 2:
+ error_status = I2C_ACK_IN_HS_MODE;
+ break;
+
+ case 3:
+ error_status = I2C_ARBITRATION_LOST;
+ break;
+
+ case 4:
+ error_status = I2C_BUS_ERROR_DETECTED_START;
+ break;
+
+ case 5:
+ error_status = I2C_BUS_ERROR_DETECTED_STOP;
+ break;
+
+ case 6:
+ error_status = I2C_OVERFLOW;
+ break;
+
+ default:
+ error_status = I2C_INTERNAL_ERROR;
+ break;
+ }
+
+ return(error_status);
+ }
+
+ return(I2C_OK);
+}
+
+
+/****************************************************************************/
+/* NAME : I2C_SetBaseAddress */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : This routine initializes I2C register base address. */
+/* */
+/* PARAMETERS : */
+/* IN : id : I2C controller id */
+/* i2c_base_address : I2C registers base address */
+/* OUT : None */
+/* */
+/* RETURN : None */
+/*--------------------------------------------------------------------------*/
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES: */
+/* 1) Global variable gp_registers (register base address) */
+/* is being modified */
+
+/****************************************************************************/
+void I2C_SetBaseAddress(t_i2c_device_id id, t_logical_address address)
+{
+ /* Initializing the I2C controller base address */
+ gp_i2c_registers[id] = (t_i2c_registers *) address;
+}
+
+/****************************************************************************/
+/* NAME : I2C_DisableIRQSrc */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION : Disable the given I2C controller to generate interrupts. */
+/* */
+/* PARAMETERS : */
+/* IN : t_i2c_irq_src_id id : the IRQ source to be disabled. */
+/* OUT : None */
+/* */
+/* RETURN : None */
+/*--------------------------------------------------------------------------*/
+/* REENTRANCY : Non Re-entrant */
+/* REENTRANCY ISSUES: */
+
+/****************************************************************************/
+void I2C_DisableIRQSrc(t_i2c_irq_src_id irq_id)
+{
+
+ gp_i2c_registers[GETDEVICE((u32)irq_id)]->imscr &= ~((u32)I2C_IRQ_SRC_ALL & (u32)irq_id);
+
+}
diff --git a/board/st/u8500/i2c.h b/board/st/u8500/i2c.h
new file mode 100755
index 000000000..3a5b93625
--- /dev/null
+++ b/board/st/u8500/i2c.h
@@ -0,0 +1,848 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#ifndef _U8500_I2C_H_
+#define _U8500_I2C_H_
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include "common.h"
+#include <configs/u8500.h>
+
+#define MASK_BIT0 (1UL<<0)
+#define MASK_BIT1 (1UL<<1)
+#define MASK_BIT2 (1UL<<2)
+#define MASK_BIT3 (1UL<<3)
+#define MASK_BIT4 (1UL<<4)
+#define MASK_BIT5 (1UL<<5)
+#define MASK_BIT6 (1UL<<6)
+#define MASK_BIT7 (1UL<<7)
+#define MASK_BIT8 (1UL<<8)
+#define MASK_BIT9 (1UL<<9)
+#define MASK_BIT10 (1UL<<10)
+#define MASK_BIT11 (1UL<<11)
+#define MASK_BIT12 (1UL<<12)
+#define MASK_BIT13 (1UL<<13)
+#define MASK_BIT14 (1UL<<14)
+#define MASK_BIT15 (1UL<<15)
+#define MASK_BIT16 (1UL<<16)
+#define MASK_BIT17 (1UL<<17)
+#define MASK_BIT18 (1UL<<18)
+#define MASK_BIT19 (1UL<<19)
+#define MASK_BIT20 (1UL<<20)
+#define MASK_BIT21 (1UL<<21)
+#define MASK_BIT22 (1UL<<22)
+#define MASK_BIT23 (1UL<<23)
+#define MASK_BIT24 (1UL<<24)
+#define MASK_BIT25 (1UL<<25)
+#define MASK_BIT26 (1UL<<26)
+#define MASK_BIT27 (1UL<<27)
+#define MASK_BIT28 (1UL<<28)
+#define MASK_BIT29 (1UL<<29)
+#define MASK_BIT30 (1UL<<30)
+#define MASK_BIT31 (1UL<<31)
+/*-----------------------------------------------------------------------------
+ Typedefs
+-----------------------------------------------------------------------------*/
+typedef enum{
+ I2C0,
+ I2C1,
+ I2C2,
+ I2C3
+}t_i2c_device_id;
+
+
+
+/*-----------------------------------------------------------------------------
+
+ Generic Macros
+
+-----------------------------------------------------------------------------*/
+
+#define I2C_SET_BIT(reg_name,mask) ((reg_name) |= (mask))
+#define I2C_CLR_BIT(reg_name,mask) ((reg_name) &= ~(mask))
+#define I2C_WRITE_BIT(reg_name,val,mask) ((reg_name) = (((reg_name) & ~(mask)) | ((val) & (mask))))
+#define I2C_TEST_BIT(reg_name,val) ((reg_name) & (mask))
+#define I2C_WRITE_REG(reg_name,val) ((reg_name) = (val))
+#define I2C_READ_REG(reg_name) (reg_name)
+#define I2C_CLEAR 0x00000000
+
+
+#define I2C_WRITE_FIELD(reg_name,mask,shift,value) \
+ (reg_name = ((reg_name & ~mask) | (value << shift)))
+
+
+#define I2C_READ_FIELD(reg_name,mask,shift) ((reg_name & mask) >> shift )
+
+typedef volatile struct
+{
+
+
+ u32 cr; /* Control Register 0x00 */
+ u32 scr; /* Slave Address Register 0x04 */
+ u32 hsmcr; /* HS Master code Register 0x08 */
+ u32 mcr; /* Master Control Register 0x0C */
+ u32 tfr; /* Transmit Fifo Register 0x10 */
+ u32 sr; /* Status Register 0x14 */
+ u32 rfr; /* Receiver Fifo Register 0x18 */
+ u32 tftr; /* Transmit Fifo Threshold Register 0x1C */
+ u32 rftr; /* Receiver Fifo Threshold Register 0x20 */
+ u32 dmar; /* DMA register 0x24 */
+ u32 brcr; /* Baud Rate Counter Register 0x28 */
+ u32 imscr; /* Interrupt Mask Set and Clear Register 0x2C */
+ u32 risr; /* Raw interrupt status register 0x30 */
+ u32 misr; /* Masked interrupt status register 0x34 */
+ u32 icr; /* Interrupt Set and Clear Register 0x38 */
+ u32 reserved_1[(0xFE0 - 0x3c) >> 2]; /* Reserved 0x03C to 0xFE0*/
+ u32 periph_id_0; /*peripheral ID 0 0xFE0 */
+ u32 periph_id_1; /*peripheral ID 1 0xFE4 */
+ u32 periph_id_2; /*peripheral ID 2 0xFE8 */
+ u32 periph_id_3; /*peripheral ID 3 0xFEC */
+ u32 cell_id_0; /*I2C cell ID 0 0xFF0 */
+ u32 cell_id_1; /*I2C cell ID 1 0xFF4 */
+ u32 cell_id_2; /*I2C cell ID 2 0xFF8 */
+ u32 cell_id_3; /*I2C cell ID 3 0xFFC */
+
+
+}t_i2c_registers;
+
+
+
+/* Control Register */
+ /* Mask values for control register mask */
+#define I2C_CR_PE MASK_BIT0 /* Peripheral enable*/
+#define I2C_CR_OM 0x6 /* Operation mode */
+#define I2C_CR_SAM MASK_BIT3 /* Slave Addressing mode */
+#define I2C_CR_SM 0x30 /* Speed mode */
+#define I2C_CR_SGCM MASK_BIT6 /* Slave General call mode */
+#define I2C_CR_FTX MASK_BIT7 /* Flush Transmit */
+#define I2C_CR_FRX MASK_BIT8 /* Flush Receive */
+#define I2C_CR_DMA_TX_EN MASK_BIT9 /* DMA TX Enable */
+#define I2C_CR_DMA_RX_EN MASK_BIT10 /* DMA Rx Enable */
+#define I2C_CR_DMA_SLE MASK_BIT11 /* DMA Synchronization Logic enable */
+#define I2C_CR_LM MASK_BIT12 /* Loop back mode */
+#define I2C_CR_FON 0x6000 /* Filtering On */
+
+ /* shift valus for control register bit fields */
+#define I2C_CR_SHIFT_PE 0 /* Peripheral enable*/
+#define I2C_CR_SHIFT_OM 1 /* Operation mode */
+#define I2C_CR_SHIFT_SAM 3 /* Slave Addressing mode */
+#define I2C_CR_SHIFT_SM 4 /* Speed mode */
+#define I2C_CR_SHIFT_SGCM 6 /* Slave General call mode */
+#define I2C_CR_SHIFT_FTX 7 /* Flush Transmit */
+#define I2C_CR_SHIFT_FRX 8 /* Flush Receive */
+#define I2C_CR_SHIFT_DMA_TX_EN 9 /* DMA TX Enable */
+#define I2C_CR_SHIFT_DMA_RX_EN 10 /* DMA Rx Enable */
+#define I2C_CR_SHIFT_DMA_SLE 11 /* DMA Synchronization Logic enable */
+#define I2C_CR_SHIFT_LM 12 /* Loop back mode */
+#define I2C_CR_SHIFT_FON 13 /* Filtering On */
+
+
+/* Slave control register*/
+ /* Mask values slave control register */
+#define I2C_SCR_ADDR 0x3FF
+#define I2C_SCR_DATA_SETUP_TIME 0xFFFF0000
+
+ /* Shift values for Slave control register */
+#define I2C_SCR_SHIFT_ADDR 0
+#define I2C_SCR_SHIFT_DATA_SETUP_TIME 16
+
+
+
+/* Master Control Register */
+ /* Mask values for Master control register */
+#define I2C_MCR_OP MASK_BIT0 /* Operation */
+#define I2C_MCR_A7 0xFE /* LSB bits of the Address(7-bit ) */
+#define I2C_MCR_EA10 0x700 /* Extended Address */
+#define I2C_MCR_SB MASK_BIT11 /* Start byte procedure */
+#define I2C_MCR_AM 0x3000 /* Address type */
+#define I2C_MCR_STOP MASK_BIT14 /* stop condition */
+#define I2C_MCR_LENGTH 0x3FF8000 /* Frame length */
+#define I2C_MCR_A10 0x7FE /* Define to set the 10 bit address */
+
+#define I2C_MCR_LENGTH_STOP_OP 0x3FFC001 /*mask for length field,stop and operation */
+ /* Shift values for Master control values */
+
+#define I2C_MCR_SHIFT_OP 0 /* Operation */
+#define I2C_MCR_SHIFT_A7 1 /* LSB bits of the Address(7-bit ) */
+#define I2C_MCR_SHIFT_EA10 8 /* Extended Address */
+#define I2C_MCR_SHIFT_SB 11 /* Start byte procedure */
+#define I2C_MCR_SHIFT_AM 12 /* Address type */
+#define I2C_MCR_SHIFT_STOP 14 /* stop condition */
+#define I2C_MCR_SHIFT_LENGTH 15 /* Frame length */
+#define I2C_MCR_SHIFT_A10 1 /* define to set the 10 bit addres */
+
+#define I2C_MCR_SHIFT_LENGTH_STOP_OP 0
+
+/* Status Register */
+ /* Mask values for Status register */
+#define I2C_SR_OP 0x3 /* Operation */
+#define I2C_SR_STATUS 0xC /* Controller Status */
+#define I2C_SR_CAUSE 0x70 /* Abort Cause */
+#define I2C_SR_TYPE 0x180 /* Receive Type */
+#define I2C_SR_LENGTH 0xFF700 /* Transfer length */
+
+/* Shift values for Status register */
+#define I2C_SR_SHIFT_OP 0 /* Operation */
+#define I2C_SR_SHIFT_STATUS 2 /* Controller Status */
+#define I2C_SR_SHIFT_CAUSE 4 /* Abort Cause */
+#define I2C_SR_SHIFT_TYPE 7 /* Receive Type */
+#define I2C_SR_SHIFT_LENGTH 9 /* Transfer length */
+
+
+/* DMA Register */
+ /* Mask values for DMA register */
+#define I2C_DMA_SBSIZE_RX 0x7 /* Source Burst Size Rx */
+#define I2C_DMA_BURST_RX MASK_BIT3 /* Burst Rx */
+#define I2C_DMA_DBSIZE_TX 0x700 /* Destination Burst Size Tx */
+#define I2C_DMA_BURST_TX MASK_BIT11 /* Burst Tx */
+
+ /* Shift values for DMA register */
+#define I2C_DMA_SHIFT_SBSIZE_RX 0 /* Source Burst Size Rx */
+#define I2C_DMA_SHIFT_BURST_RX 3 /* Burst Rx */
+#define I2C_DMA_SHIFT_DBSIZE_TX 8 /* Destination Burst Size Tx */
+#define I2C_DMA_SHIFT_BURST_TX 11 /* Burst Tx */
+
+/* Baud rate counter registers */
+ /* Mask values for Baud rate counter register */
+#define I2C_BRCR_BRCNT2 0xFFFF /* Baud rate counter value for HS mode */
+#define I2C_BRCR_BRCNT1 0xFFFF0000 /* Baud rate counter value for Standard and Fast mode*/
+
+/* Shift values for the Baud rate counter register */
+#define I2C_BRCR_SHIFT_BRCNT2 0
+#define I2C_BRCR_SHIFT_BRCNT1 16
+
+
+
+/* Interrupt Register */
+ /* Mask values for Interrupt registers */
+#define I2C_INT_TXFE MASK_BIT0 /* Tx fifo empty */
+#define I2C_INT_TXFNE MASK_BIT1 /* Tx Fifo nearly empty */
+#define I2C_INT_TXFF MASK_BIT2 /* Tx Fifo Full */
+#define I2C_INT_TXFOVR MASK_BIT3 /* Tx Fifo over run */
+#define I2C_INT_RXFE MASK_BIT4 /* Rx Fifo Empty */
+#define I2C_INT_RXFNF MASK_BIT5 /* Rx Fifo nearly empty */
+#define I2C_INT_RXFF MASK_BIT6 /* Rx Fifo Full */
+#define I2C_INT_RFSR MASK_BIT16 /* Read From slave request */
+#define I2C_INT_RFSE MASK_BIT17 /* Read from slave empty */
+#define I2C_INT_WTSR MASK_BIT18 /* Write to Slave request */
+#define I2C_INT_MTD MASK_BIT19 /* Master Transcation Done*/
+#define I2C_INT_STD MASK_BIT20 /* Slave Transaction Done */
+#define I2C_INT_MAL MASK_BIT24 /* Master Arbitation Lost */
+#define I2C_INT_BERR MASK_BIT25 /* Bus Error */
+#define I2C_INT_MTDWS MASK_BIT28 /* Master Transcation Done Without Stop*/
+ /* Shift values for Interrupt registers */
+#define I2C_INT_SHIFT_TXFE 0 /* Tx fifo empty */
+#define I2C_INT_SHIFT_TXFNE 1 /* Tx Fifo nearly empty */
+#define I2C_INT_SHIFT_TXFF 2 /* Tx Fifo Full */
+#define I2C_INT_SHIFT_TXFOVR 3 /* Tx Fifo over run */
+#define I2C_INT_SHIFT_RXFE 4 /* Rx Fifo Empty */
+#define I2C_INT_SHIFT_RXFNF 5 /* Rx Fifo nearly empty */
+#define I2C_INT_SHIFT_RXFF 6 /* Rx Fifo Full */
+#define I2C_INT_SHIFT_RFSR 16 /* Read From slave request */
+#define I2C_INT_SHIFT_RFSE 17 /* Read from slave empty */
+#define I2C_INT_SHIFT_WTSR 18 /* Write to Slave request */
+#define I2C_INT_SHIFT_MTD 19 /* Master Transcation Done */
+#define I2C_INT_SHIFT_STD 20 /* Slave Transaction Done */
+#define I2C_INT_SHIFT_MAL 24 /* Master Arbitation Lost */
+#define I2C_INT_SHIFT_BERR 25 /* Bus Error */
+#define I2C_INT_SHIFT_MTDWS 28 /* Master Transcation Done Without Stop*/
+
+
+
+/*-----------------------------------------------------------------------------
+ Typedefs
+-----------------------------------------------------------------------------*/
+typedef enum {
+ I2C_FREQ_MODE_STANDARD, /* Standard mode. */
+ I2C_FREQ_MODE_FAST, /* Fast mode. */
+ I2C_FREQ_MODE_HIGH_SPEED /* High Speed mode. */
+} t_i2c_freq_mode;
+
+typedef enum {
+ I2C_BUS_SLAVE_MODE = 0, /* Slave Mode */
+ I2C_BUS_MASTER_MODE, /* Master Mode */
+ I2C_BUS_MASTER_SLAVE_MODE /* Dual Configuration Mode */
+} t_i2c_bus_control_mode;
+
+typedef enum {
+ I2C_CURRENT_BUS_SLAVE_TRANSMITTER,
+ I2C_CURRENT_BUS_SLAVE_RECEIVER,
+ I2C_CURRENT_BUS_MASTER_TRANSMITTER,
+ I2C_CURRENT_BUS_MASTER_RECEIVER
+}t_i2c_current_bus_configuration;
+
+typedef enum {
+ I2C_TRANSFER_MODE_POLLING,
+ I2C_TRANSFER_MODE_INTERRUPT,
+ I2C_TRANSFER_MODE_DMA
+}t_i2c_transfer_mode;
+
+typedef enum {
+ I2C_DISABLE,
+ I2C_ENABLE
+}t_i2c_control;
+
+typedef enum {
+ I2C_COMMAND_SEND_START,
+ I2C_COMMAND_SEND_STOP,
+ I2C_COMMAND_SEND_ACKNOWLEDGE,
+ I2C_COMMAND_CLEAR_ACKNOWLEDGE,
+ I2C_COMMAND_SET_TRANSMIT_DMA,
+ I2C_COMMAND_CLEAR_TRANSMIT_DMA,
+ I2C_COMMAND_SET_RECEIVE_DMA,
+ I2C_COMMAND_CLEAR_RECEIVE_DMA
+}t_i2c_command;
+
+
+typedef enum {
+ I2C_STATUS_SLAVE_MODE, /* Controller is in slave mode.*/
+ I2C_STATUS_MASTER_MODE, /* Controller is in master mode.*/
+ I2C_STATUS_MASTER_TRANSMITTER_MODE, /* Controller is in master transmitter mode.*/
+ I2C_STATUS_MASTER_RECEIVER_MODE, /* Controller is in master receiver mode.*/
+ I2C_STATUS_SLAVE_TRANSMITTER_MODE, /* Controller is in slave transmitter mode.*/
+ I2C_STATUS_SLAVE_RECEIVER_MODE /* Controller is in slave receiver mode.*/
+} t_i2c_device_status;
+
+
+typedef enum {
+ I2C_TRANSMIT_FIFO,
+ I2C_RECEIVE_FIFO
+}t_i2c_fifo;
+
+
+typedef enum {
+ I2C_DIGITAL_FILTERS_OFF,
+ I2C_DIGITAL_FILTERS_1_CLK_SPIKES,
+ I2C_DIGITAL_FILTERS_2_CLK_SPIKES,
+ I2C_DIGITAL_FILTERS_4_CLK_SPIKES
+}t_i2c_digital_filter;
+
+
+typedef struct {
+ t_i2c_digital_filter i2c_digital_filter_control;
+ t_i2c_control i2c_dma_sync_logic_control;
+ t_i2c_control i2c_start_byte_procedure; /*ONLY VALID FOR MASTER MODE TRANSACTIONS*/
+ u8 i2c_high_speed_master_code; /*ONLY VALID FOR MASTER MODE TRANSACTIONS*/
+ u16 slave_data_setup_time; /* Only valid for HS controller */
+ u16 controller_i2c_address;
+ u32 input_frequency;
+} t_i2c_device_config;
+
+typedef enum {
+ I2C_NO_GENERAL_CALL_HANDLING,
+ I2C_SOFTWARE_GENERAL_CALL_HANDLING,
+ I2C_HARDWARE_GENERAL_CALL_HANDLING
+} t_i2c_general_call_handling;
+
+typedef struct {
+ t_i2c_control i2c_loopback_mode;
+ t_i2c_general_call_handling i2c_slave_general_call_mode;
+ t_i2c_transfer_mode index_transfer_mode;
+ t_i2c_transfer_mode data_transfer_mode;
+ t_i2c_bus_control_mode bus_control_mode;
+ u8 i2c_transmit_interrupt_threshold;
+ u8 i2c_receive_interrupt_threshold;
+ u8 transmit_burst_length;
+ u8 receive_burst_length;
+ u32 i2c_transfer_frequency;
+} t_i2c_transfer_config;
+
+
+
+typedef struct {
+ t_logical_address base_address; /* The controller's logical base address. */
+ t_i2c_device_id id; /* The controller's id. */
+ t_i2c_freq_mode freq_mode; /* Standard ,Fast mode or Hs Mode. */
+ t_bool is_enabled; /* True means controller is enabled. */
+ t_i2c_bus_control_mode bus_control_mode;
+ t_i2c_current_bus_configuration current_bus_config;
+ t_i2c_general_call_handling general_call_handling;
+ u32 freq_scl; /* The I2C bus SCL clock frequency (Hz). */
+ u32 freq_input; /* The controller's input clock frequency (Hz). */
+ u32 own_address; /* The controller's slave address. */
+} t_i2c_info; /* Used to provide information to the user. */
+
+
+typedef enum {
+ /*Common to all platforms*/
+ I2C_STATE_GENERAL_CALL_DETECTED = MASK_BIT0,
+ I2C_STATE_ARBITRATION_LOST = MASK_BIT2,
+ I2C_STATE_BUSY = MASK_BIT12,
+
+ I2C_STATE_TRANSFER_COMPLETE = MASK_BIT16,
+ I2C_STATE_ABORT_NACK_ON_ADDRESS = MASK_BIT17,
+ I2C_STATE_ABORT_NACK_ON_DATA = MASK_BIT18,
+ I2C_STATE_ABORT_ACK_ON_MASTER_CODE = MASK_BIT19,
+ I2C_STATE_BUS_ERROR_DETECTED_START = MASK_BIT20,
+ I2C_STATE_BUS_ERROR_DETECTED_STOP = MASK_BIT21,
+ I2C_STATE_OVERFLOW = MASK_BIT22,
+ I2C_STATE_HARDWARE_GENERAL_CALL = MASK_BIT23
+} t_i2c_device_states;
+
+
+typedef enum {
+ I2C_NO_PENDG_EVENT_ERROR = 7, /*U8500_NO_PENDG_EVENT_ERROR,*/
+ I2C_NO_MORE_FILTER_PENDG_EVENT = 5, /*U8500_NO_MORE_FILTER_PENDG_EVENT,*/
+ I2C_NO_MORE_PENDG_EVENT = 5, /*U8500_NO_MORE_PENDG_EVENT,*/
+ I2C_REMAG_FILTER_PENDG_EVENTS = 3,/*U8500_REMAG_FILTER_PENDG_EVENTS,*/
+ I2C_REMAG_PENDG_EVENTS = 2,/*U8500_REMAG_PENDG_EVENTS,*/
+ I2C_INTERNAL_EVENT = 1,/*U8500_INTERNAL_EVENT,*/
+ I2C_OK = 0, /*U8500_OK,*/ /* No error. */
+ I2C_INTERNAL_ERROR = -8, /*U8500_INTERNAL_ERROR,*/
+ I2C_NOT_CONFIGURED = -7, /*U8500_NOT_CONFIGURED,*/
+ I2C_REQUEST_PENDG = -6, /*U8500_REQUEST_PENDG,*/
+ I2C_REQUEST_NOT_APPLICABLE = -5, /*U8500_REQUEST_NOT_APPLICABLE,*/
+ I2C_INVALID_PARAMETER = -4, /*U8500_VALID_PARAMETER,*/
+ I2C_UNSUPPORTED_FEATURE = -3, /*U8500_UNSUPPORTED_FEATURE,*/
+ I2C_UNSUPPORTED_HW = -2, /*U8500_UNSUPPORTED_HW,*/
+ I2C_HW_FAILED = -66, /*(U8500_MAX_ERROR_VALUE -1),*/ /* Generic hardware error. */
+ I2C_SW_FAILED = -67, /*(U8500_MAX_ERROR_VALUE -2),*/ /* Generic software error. */
+ I2C_CONTROLLER_BUSY = -68, /*(U8500_MAX_ERROR_VALUE -3),*/ /* Transfer on going. */
+ I2C_LINE_FREQ_NOT_SUPPORTED = -69, /*(U8500_MAX_ERROR_VALUE -4),*/ /* SCL bus frequency not supported. */
+ I2C_PUT_FREQ_NOT_SUPPORTED = -70, /*(U8500_MAX_ERROR_VALUE -5),*/ /* Input frequency not supported. */
+ I2C_DDC_MODE_NOT_SUPPORTED = -71, /*(U8500_MAX_ERROR_VALUE -6),*/ /* DDC mode not supported. */
+ I2C_SLAVE_ADDRESS_NOT_VALID = -72, /*(U8500_MAX_ERROR_VALUE -7),*/ /* Slave address is reserved or not valid. */
+
+ I2C_BYTE_TRANSFER_FAILED = -165, /*(U8500_MAX_ERROR_VALUE -100),*/
+ I2C_ADDRESS_MATCH_FAILED = -166, /*(U8500_MAX_ERROR_VALUE -101),*/
+ I2C_START_BYTE_FAILED = -167, /*(U8500_MAX_ERROR_VALUE -102),*/
+ I2C_ACKNOWLEDGE_FAILURE = -168, /*(U8500_MAX_ERROR_VALUE -103),*/
+ I2C_STOP_FAILED = -169, /*(U8500_MAX_ERROR_VALUE -104),*/
+ I2C_ARBITRATION_LOST = -170, /*(U8500_MAX_ERROR_VALUE -105),*/
+ I2C_BUS_ERROR = -171, /*(U8500_MAX_ERROR_VALUE -106),*/
+ I2C_10_BIT_ADDRESS_FAILED = -172, /*(U8500_MAX_ERROR_VALUE -107),*/
+ I2C_SCL_FALL_FAILED = -173, /*(U8500_MAX_ERROR_VALUE -108),*/
+ I2C_END_ADDRESS_FAILED = -174, /*(U8500_MAX_ERROR_VALUE -109),*/
+
+ I2C_TRANSMIT_FIFO_FULL = -175, /*(U8500_MAX_ERROR_VALUE -200),*/
+ I2C_RECEIVE_FIFO_EMPTY = -176, /*(U8500_MAX_ERROR_VALUE -201),*/
+ I2C_ACK_FAIL_ON_ADDRESS = -177, /*(U8500_MAX_ERROR_VALUE -202),*/
+ I2C_ACK_FAIL_ON_DATA = -178, /*(U8500_MAX_ERROR_VALUE -203),*/
+ I2C_ACK_IN_HS_MODE = -179, /*(U8500_MAX_ERROR_VALUE -204),*/
+ I2C_BUS_ERROR_DETECTED_START = -180, /*(U8500_MAX_ERROR_VALUE -205),*/
+ I2C_BUS_ERROR_DETECTED_STOP = -181, /*(U8500_MAX_ERROR_VALUE -206),*/
+ I2C_OVERFLOW = -182, /*(U8500_MAX_ERROR_VALUE -207)*/
+} t_i2c_error;
+
+typedef enum
+{
+ /*Common to all platforms*/
+ I2C_NO_EVENT = MASK_BIT0, /* No activity. */
+ I2C_TRANSFER_OK_EVENT = MASK_BIT1, /* Transfer operation ended correctly. */
+ I2C_CANCEL_EVENT = MASK_BIT2, /* Transfer operation cancelled by the user. */
+ I2C_INTERNAL_ERROR_EVENT = MASK_BIT3, /* Internal error happened. */
+ I2C_ARBITRATION_LOST_ERROR_EVENT = MASK_BIT4, /* Arbitration Lost happened. */
+
+ I2C_AF_ERROR_EVENT = MASK_BIT5, /* Acknowledge Failure happened. */
+ I2C_BUS_ERROR_EVENT = MASK_BIT6, /* Bus Error happened. */
+ I2C_START_EVENT = MASK_BIT7, /* START generated. */
+ I2C_INDEX_TX_EVENT = MASK_BIT8, /* Register index byte transmitted. */
+ I2C_DATA_TX_EVENT = MASK_BIT9, /* Data byte transmitted. */
+ I2C_DATA_RX_EVENT = MASK_BIT10, /* Data byte received. */
+ I2C_WAITG_DATA_RX_EVENT = MASK_BIT11, /* Waiting for a data byte. */
+
+
+ I2C_TRANSMIT_FIFO_EMPTY_EVENT = MASK_BIT12,
+ I2C_TRANSMIT_FIFO_NEARLY_EMPTY_EVENT = MASK_BIT13,
+ I2C_TRANSMIT_FIFO_FULL_EVENT = MASK_BIT14,
+ I2C_TRANSMIT_FIFO_OVERRUN_EVENT = MASK_BIT15,
+ I2C_RECEIVE_FIFO_EMPTY_EVENT = MASK_BIT16,
+ I2C_RECEIVE_FIFO_NEARLY_FULL_EVENT = MASK_BIT17,
+ I2C_RECEIVE_FIFO_FULL_EVENT = MASK_BIT18,
+ I2C_READ_FROM_SLAVE_REQUEST_EVENT = MASK_BIT19,
+ I2C_READ_FROM_SLAVE_EMPTY_EVENT = MASK_BIT20,
+ I2C_WRITE_TO_SLAVE_REQUEST_EVENT = MASK_BIT21,
+ I2C_MASTER_TRANSACTION_DONE_EVENT = MASK_BIT22,
+ I2C_SLAVE_TRANSACTION_DONE_EVENT = MASK_BIT23,
+ I2C_ABORT_NACK_ON_ADDRESS_EVENT = MASK_BIT24,
+ I2C_ABORT_NACK_ON_DATA_EVENT = MASK_BIT25,
+ I2C_ABORT_ACK_ON_MASTER_CODE_EVENT = MASK_BIT26,
+ I2C_BUS_ERROR_DETECTED_START_EVENT = MASK_BIT27,
+ I2C_BUS_ERROR_DETECTED_STOP_EVENT = MASK_BIT28,
+ I2C_OVERFLOW_EVENT = MASK_BIT29,
+ I2C_MASTER_TRANSACTION_DONE_WITHOUT_STOP_EVENT = MASK_BIT30
+} t_i2c_event; /* Inform the I2C HCL user about the last occurred event.*/
+
+
+typedef enum
+{
+ I2C_NO_INDEX, /* Current transfer is non-indexed */
+ I2C_BYTE_INDEX, /* Current transfer uses 8-bit index */
+ I2C_HALF_WORD_LITTLE_ENDIAN, /* Current transfer uses 16-bit index
+ in little endian mode */
+ I2C_HALF_WORD_BIG_ENDIAN /* Current transfer uses 16-bit index
+ in big endian mode */
+}t_i2c_index_format;
+
+typedef struct {
+ t_i2c_device_id id;
+ t_i2c_event type; /* The active event. */
+ u32 transfer_data; /* Number of data bytes actually transferred. */
+} t_i2c_active_event;
+
+typedef t_i2c_device_id t_i2c_irq_status;
+
+/*-----------------------------------------------------------------------------
+ Configuration functions
+-----------------------------------------------------------------------------*/
+ t_i2c_error I2C_Init (t_i2c_device_id id,
+ t_logical_address address);
+
+ t_i2c_error I2C_SetDeviceConfiguration (t_i2c_device_id id,
+ t_i2c_device_config *p_device_config);
+
+ t_i2c_error I2C_SetTransferConfiguration (t_i2c_device_id id,
+ t_i2c_transfer_config *p_transfer_config);
+
+ t_i2c_error I2C_SetTransferMode ( t_i2c_device_id id,
+ t_i2c_transfer_mode index_transfer_mode,
+ t_i2c_transfer_mode data_transfer_mode);
+
+ t_i2c_error I2C_SetBusControlMode (t_i2c_device_id id,
+ t_i2c_bus_control_mode bus_control_mode);
+
+ t_i2c_error I2C_SendCommand ( t_i2c_device_id,
+ t_i2c_command);
+
+
+/*-----------------------------------------------------------------------------
+ Configuration functions
+-----------------------------------------------------------------------------*/
+ t_i2c_error I2C_FlushFifo(t_i2c_device_id , t_i2c_fifo );
+
+/*-----------------------------------------------------------------------------
+ Status functions
+-----------------------------------------------------------------------------*/
+ t_i2c_error I2C_GetInfo ( t_i2c_device_id id,
+ t_i2c_info *p_info);
+/*-----------------------------------------------------------------------------
+ Operative functions
+-----------------------------------------------------------------------------*/
+ t_i2c_error I2C_Enable (t_i2c_device_id id);
+
+ t_i2c_error I2C_Disable (t_i2c_device_id id);
+
+ t_i2c_error I2C_WriteSingleData (t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 data);
+
+ t_i2c_error I2C_WriteMultipleData (t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 *p_data,
+ u32 count);
+
+ t_i2c_error I2C_ReadSingleData (t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 *p_data);
+
+ t_i2c_error I2C_ReadMultipleData (t_i2c_device_id id,
+ u16 slave_address,
+ t_i2c_index_format index_format,
+ u16 index_value,
+ u8 *p_data,
+ u32 count);
+
+
+ t_i2c_error I2C_Cancel ( t_i2c_device_id id,
+ t_i2c_active_event *event);/*Only IT mode*/
+
+
+ t_bool I2C_IsEventActive ( t_i2c_active_event* event);
+
+ t_bool I2C_AcknowledgeEvent ( t_i2c_active_event* event);
+
+
+ t_i2c_error I2C_GetInputClock( t_i2c_device_id id,
+ u32 *p_fIn);
+
+ t_i2c_error I2C_GetBusClock( t_i2c_device_id id,
+ u32 *p_fSCL);
+
+ t_i2c_error I2C_GetEnabled( t_i2c_device_id id,
+ t_bool *p_status);
+
+ t_i2c_error I2C_GetDeviceConfiguration( t_i2c_device_id id,
+ t_i2c_device_config *p_device_config);
+
+ t_i2c_error I2C_GetTransferConfiguration(t_i2c_device_id id,
+ t_i2c_transfer_config *p_transfer_config);
+
+ t_i2c_error I2C_GetTransferMode( t_i2c_device_id id,
+ t_i2c_transfer_mode *p_index_transfer_mode,
+ t_i2c_transfer_mode *p_data_transfer_mode);
+
+ t_i2c_error I2C_GetBusControlMode( t_i2c_device_id id,
+ t_i2c_current_bus_configuration
+ *p_i2c_current_transfer_mode,
+ t_i2c_bus_control_mode *p_bus_control_mode);
+
+
+/*-----------------------------------------------------------------------------
+ Power Management functions
+-----------------------------------------------------------------------------*/
+ t_i2c_error I2C_Reset(t_i2c_device_id id);
+
+ void I2C_SaveDeviceContext (t_i2c_device_id id);
+
+ void I2C_RestoreDeviceContext(t_i2c_device_id id);
+
+
+/* Start of _I2CP_H_*/
+
+/*Peripheral ID s */
+
+#define I2C_P_ID_0 0x24
+#define I2C_P_ID_1 0x00
+#define I2C_P_ID_2 0x38
+#define I2C_P_ID_3 0x00
+#define I2C_CELL_ID_0 0x0D
+#define I2C_CELL_ID_1 0xF0
+#define I2C_CELL_ID_2 0x05
+#define I2C_CELL_ID_3 0xB1
+
+/*-----------------------------------------------------------------------------
+
+ Constants
+
+-----------------------------------------------------------------------------*/
+typedef enum {
+ I2C_NO_OPERATION = 0xFF,
+ I2C_WRITE = 0x00,
+ I2C_READ = 0x01
+} t_i2c_operation;
+
+/*-----------------------------------------------------------------------------
+ Typedefs
+-----------------------------------------------------------------------------*/
+typedef enum {
+ I2C_MAX_STANDARD_SCL = 100000, /* Max clock frequency (Hz) for Standard Mode.*/
+ I2C_MAX_FAST_SCL = 400000, /* Max clock frequency (Hz) for Fast Mode.*/
+ I2C_MAX_HIGH_SPEED_SCL = 3400000 /* Max clock frequency (Hz) for HS Mode.*/
+} I2C_MaxClocks;
+
+typedef enum {
+ I2C_DDC1, /* DDC1 mode.*/
+ I2C_DDC2B, /* DD2 B mode.*/
+ I2C_DDC2AB /* DDC2 AB mode (I2C).*/
+} t_i2c_ddc_mode;
+
+typedef enum {
+ I2C_IT_TXFE = MASK_BIT0, /* Tx fifo empty */
+ I2C_IT_TXFNE = MASK_BIT1, /* Tx Fifo nearly empty */
+ I2C_IT_TXFF = MASK_BIT2, /* Tx Fifo Full */
+ I2C_IT_TXOVR = MASK_BIT3, /* Tx Fifo over run */
+ I2C_IT_RXFE = MASK_BIT4, /* Rx Fifo Empty */
+ I2C_IT_RXFNF = MASK_BIT5, /* Rx Fifo nearly empty */
+ I2C_IT_RXFF = MASK_BIT6, /* Rx Fifo Full */
+ I2C_IT_RFSR = MASK_BIT16, /* Read From slave request */
+ I2C_IT_RFSE = MASK_BIT17, /* Read from slave empty */
+ I2C_IT_WTSR = MASK_BIT18, /* Write Slave request */
+ I2C_IT_MTD = MASK_BIT19, /* Master Transcation Done */
+ I2C_IT_STD = MASK_BIT20, /* Slave Transaction Done */
+ I2C_IT_MAL = MASK_BIT24, /* Master Arbitation Lost */
+ I2C_IT_BERR = MASK_BIT25, /* Bus Error */
+ I2C_IT_MTDWS = MASK_BIT28 /* Master Transcation Done Without Stop */
+}t_i2c_interrupt; /* IRQ source numbers.*/
+
+
+typedef enum {
+ I2C_NO_REG_INDEX_OP, /* Do not send any register index.*/
+ I2C_8_BIT_REG_INDEX_OP, /* Send a 8-bit register index.*/
+ I2C_16_BIT_REG_INDEX_OP /* Send a 16-bit register index.*/
+} t_i2c_reg_op;
+
+typedef u32 t_i2c_device_context[5];
+
+typedef struct {
+ /*Device configuration*/
+ t_logical_address base_address; /* The controller's base address.*/
+ u32 freq_scl; /* The I2C bus SCL clock frequency (Hz).*/
+ u16 own_address; /* The controller's slave address.*/
+ t_i2c_device_context i2c_device_context;
+ t_i2c_digital_filter digital_filter_control;
+ t_i2c_control dma_sync_logic_control;
+ t_i2c_control start_byte_procedure;
+ u8 high_speed_master_code;
+ u16 slave_data_setup_time;
+
+ /*Transfer configuration*/
+ u32 freq_input; /* The controller's input clock frequency (Hz).*/
+ t_i2c_freq_mode mode; /* Standard or Fast mode.*/
+ t_i2c_operation operation; /* Write or read.*/
+ t_i2c_bus_control_mode bus_control_mode;
+ t_i2c_control i2c_loopback_mode;
+ t_i2c_general_call_handling general_call_mode_handling;
+ t_i2c_transfer_mode index_transfer_mode;
+ t_i2c_transfer_mode data_transfer_mode;
+ u8 i2c_transmit_interrupt_threshold;
+ u8 i2c_receive_interrupt_threshold;
+ u8 transmit_burst_length;
+ u8 receive_burst_length;
+ u16 burst_length;
+ u16 slave_address; /* The slave to talk to.*/
+ u16 register_index; /* The index of the slave's registers*/
+ t_i2c_index_format index_format;
+ t_bool multi_operation;
+
+ /*Device Status*/
+ t_bool enabled; /* True means controller is enabled.*/
+ u32 count_data; /* The number of bytes to be transferred.*/
+ u32 transfer_data; /* Number of transferred data bytes.*/
+ u8* databuffer; /* Pointer to the data buffer. Used in Multi operation.*/
+ t_i2c_current_bus_configuration current_bus_config;
+ t_i2c_device_status status; /* The controller's status.*/
+ u8 data; /* Used in Single operation.*/
+ t_i2c_event active_event; /* The current active event.*/
+ t_bool std; /*This variable is used to store the STD interrupt */
+ /*status for 10 bit slave transmitter case */
+
+} t_i2c_system_context;
+
+
+/*-----------------------------------------------------------------------------
+
+ Private service functions
+
+-----------------------------------------------------------------------------*/
+ t_i2c_error i2cp_SetOwnAddress(t_i2c_device_id id, u16 address);
+ t_i2c_error i2cp_SetBusClock(t_i2c_device_id id, u32 fSCL, u32 fIn);
+ t_bool i2cp_AddressIsValid(u16 address);
+ void i2cp_Abort(t_i2c_device_id id);
+
+ t_i2c_error i2cp_SlaveIndexReceive(t_i2c_device_id id );
+ t_i2c_error i2cp_TransmitDataPolling (t_i2c_device_id id, volatile u8* p_data);
+ t_i2c_error i2cp_ReceiveDataPolling(t_i2c_device_id id, u8* p_data );
+ t_i2c_error i2cp_MasterIndexTransmit(t_i2c_device_id id );
+
+
+ t_i2c_error i2cp_GetAbortCause(t_i2c_device_id id );
+
+/* End of _I2CP_H_*/
+
+
+typedef enum
+{
+
+
+ I2C0_IRQ_SRC_TRANSMIT_FIFO_EMPTY = MASK_BIT0,
+ I2C0_IRQ_SRC_TRANSMIT_FIFO_NEARLY_EMPTY = MASK_BIT1,
+ I2C0_IRQ_SRC_TRANSMIT_FIFO_FULL = MASK_BIT2,
+ I2C0_IRQ_SRC_TRANSMIT_FIFO_OVERRUN = MASK_BIT3,
+ I2C0_IRQ_SRC_RECEIVE_FIFO_EMPTY = MASK_BIT4,
+ I2C0_IRQ_SRC_RECEIVE_FIFO_NEARLY_FULL = MASK_BIT5,
+ I2C0_IRQ_SRC_RECEIVE_FIFO_FULL = MASK_BIT6,
+ I2C0_IRQ_SRC_READ_FROM_SLAVE_REQUEST = MASK_BIT16,
+ I2C0_IRQ_SRC_READ_FROM_SLAVE_EMPTY = MASK_BIT17,
+ I2C0_IRQ_SRC_WRITE_TO_SLAVE_REQUEST = MASK_BIT18,
+ I2C0_IRQ_SRC_MASTER_TRANSACTION_DONE = MASK_BIT19,
+ I2C0_IRQ_SRC_SLAVE_TRANSACTION_DONE = MASK_BIT20,
+ I2C0_IRQ_SRC_MASTER_ARBITRATION_LOST = MASK_BIT24,
+ I2C0_IRQ_SRC_BUS_ERROR = MASK_BIT25,
+ I2C0_IRQ_SRC_MASTER_TRANSACTION_DONE_WITHOUT_STOP = MASK_BIT28,
+ I2C0_IRQ_SRC_ALL = 0x131F007F,
+
+ I2C1_IRQ_SRC_TRANSMIT_FIFO_EMPTY = MASK_BIT29 | MASK_BIT0,
+ I2C1_IRQ_SRC_TRANSMIT_FIFO_NEARLY_EMPTY = MASK_BIT29 | MASK_BIT1,
+ I2C1_IRQ_SRC_TRANSMIT_FIFO_FULL = MASK_BIT29 | MASK_BIT2,
+ I2C1_IRQ_SRC_TRANSMIT_FIFO_OVERRUN = MASK_BIT29 | MASK_BIT3,
+ I2C1_IRQ_SRC_RECEIVE_FIFO_EMPTY = MASK_BIT29 | MASK_BIT4,
+ I2C1_IRQ_SRC_RECEIVE_FIFO_NEARLY_FULL = MASK_BIT29 | MASK_BIT5,
+ I2C1_IRQ_SRC_RECEIVE_FIFO_FULL = MASK_BIT29 | MASK_BIT6,
+ I2C1_IRQ_SRC_READ_FROM_SLAVE_REQUEST = MASK_BIT29 | MASK_BIT16,
+ I2C1_IRQ_SRC_READ_FROM_SLAVE_EMPTY = MASK_BIT29 | MASK_BIT17,
+ I2C1_IRQ_SRC_WRITE_TO_SLAVE_REQUEST = MASK_BIT29 | MASK_BIT18,
+ I2C1_IRQ_SRC_MASTER_TRANSACTION_DONE = MASK_BIT29 | MASK_BIT19,
+ I2C1_IRQ_SRC_SLAVE_TRANSACTION_DONE = MASK_BIT29 | MASK_BIT20,
+ I2C1_IRQ_SRC_MASTER_ARBITRATION_LOST = MASK_BIT29 | MASK_BIT24,
+ I2C1_IRQ_SRC_BUS_ERROR = MASK_BIT29 | MASK_BIT25,
+ I2C1_IRQ_SRC_MASTER_TRANSACTION_DONE_WITHOUT_STOP = MASK_BIT29 | MASK_BIT28,
+ I2C1_IRQ_SRC_ALL = MASK_BIT29 | 0x131F007F,
+
+
+ I2C2_IRQ_SRC_TRANSMIT_FIFO_EMPTY = MASK_BIT30 | MASK_BIT0,
+ I2C2_IRQ_SRC_TRANSMIT_FIFO_NEARLY_EMPTY = MASK_BIT30 | MASK_BIT1,
+ I2C2_IRQ_SRC_TRANSMIT_FIFO_FULL = MASK_BIT30 | MASK_BIT2,
+ I2C2_IRQ_SRC_TRANSMIT_FIFO_OVERRUN = MASK_BIT30 | MASK_BIT3,
+ I2C2_IRQ_SRC_RECEIVE_FIFO_EMPTY = MASK_BIT30 | MASK_BIT4,
+ I2C2_IRQ_SRC_RECEIVE_FIFO_NEARLY_FULL = MASK_BIT30 | MASK_BIT5,
+ I2C2_IRQ_SRC_RECEIVE_FIFO_FULL = MASK_BIT30 | MASK_BIT6,
+ I2C2_IRQ_SRC_READ_FROM_SLAVE_REQUEST = MASK_BIT30 | MASK_BIT16,
+ I2C2_IRQ_SRC_READ_FROM_SLAVE_EMPTY = MASK_BIT30 | MASK_BIT17,
+ I2C2_IRQ_SRC_WRITE_TO_SLAVE_REQUEST = MASK_BIT30 | MASK_BIT18,
+ I2C2_IRQ_SRC_MASTER_TRANSACTION_DONE = MASK_BIT30 | MASK_BIT19,
+ I2C2_IRQ_SRC_SLAVE_TRANSACTION_DONE = MASK_BIT30 | MASK_BIT20,
+ I2C2_IRQ_SRC_MASTER_ARBITRATION_LOST = MASK_BIT30 | MASK_BIT24,
+ I2C2_IRQ_SRC_BUS_ERROR = MASK_BIT30 | MASK_BIT25,
+ I2C2_IRQ_SRC_MASTER_TRANSACTION_DONE_WITHOUT_STOP = MASK_BIT30 | MASK_BIT28,
+ I2C2_IRQ_SRC_ALL = MASK_BIT30 | 0x131F007F,
+
+
+
+ I2C3_IRQ_SRC_TRANSMIT_FIFO_EMPTY = MASK_BIT30 | MASK_BIT29 | MASK_BIT0,
+ I2C3_IRQ_SRC_TRANSMIT_FIFO_NEARLY_EMPTY = MASK_BIT30 | MASK_BIT29 | MASK_BIT1,
+ I2C3_IRQ_SRC_TRANSMIT_FIFO_FULL = MASK_BIT30 | MASK_BIT29 | MASK_BIT2,
+ I2C3_IRQ_SRC_TRANSMIT_FIFO_OVERRUN = MASK_BIT30 | MASK_BIT29 | MASK_BIT3,
+ I2C3_IRQ_SRC_RECEIVE_FIFO_EMPTY = MASK_BIT30 | MASK_BIT29 | MASK_BIT4,
+ I2C3_IRQ_SRC_RECEIVE_FIFO_NEARLY_FULL = MASK_BIT30 | MASK_BIT29 | MASK_BIT5,
+ I2C3_IRQ_SRC_RECEIVE_FIFO_FULL = MASK_BIT30 | MASK_BIT29 | MASK_BIT6,
+ I2C3_IRQ_SRC_READ_FROM_SLAVE_REQUEST = MASK_BIT30 | MASK_BIT29 | MASK_BIT16,
+ I2C3_IRQ_SRC_READ_FROM_SLAVE_EMPTY = MASK_BIT30 | MASK_BIT29 | MASK_BIT17,
+ I2C3_IRQ_SRC_WRITE_TO_SLAVE_REQUEST = MASK_BIT30 | MASK_BIT29 | MASK_BIT18,
+ I2C3_IRQ_SRC_MASTER_TRANSACTION_DONE = MASK_BIT30 | MASK_BIT29 | MASK_BIT19,
+ I2C3_IRQ_SRC_SLAVE_TRANSACTION_DONE = MASK_BIT30 | MASK_BIT29 | MASK_BIT20,
+ I2C3_IRQ_SRC_MASTER_ARBITRATION_LOST = MASK_BIT30 | MASK_BIT29 | MASK_BIT24,
+ I2C3_IRQ_SRC_BUS_ERROR = MASK_BIT30 | MASK_BIT29 | MASK_BIT25,
+ I2C3_IRQ_SRC_MASTER_TRANSACTION_DONE_WITHOUT_STOP = MASK_BIT30 | MASK_BIT29 | MASK_BIT28,
+ I2C3_IRQ_SRC_ALL = MASK_BIT30 | MASK_BIT29 |0x131F007F
+
+
+} t_i2c_irq_src_id;
+
+
+
+/* Macros for handling the device id */
+#define I2CID_SHIFT 29
+#define GETDEVICE(irqsrc) ((t_i2c_device_id)((irqsrc >>I2CID_SHIFT ) & 0x3))
+
+/* a macro for masking all interrupts */
+#define I2C_IRQ_SRC_ALL I2C0_IRQ_SRC_ALL
+
+typedef u32 t_i2c_irq_src; /*Combination of various interrupt sources
+ described by t_i2c_irq_src_id*/
+
+/*-----------------------------------------------------------------------------
+ Events and interrupts management functions
+-----------------------------------------------------------------------------*/
+void I2C_SetBaseAddress (t_i2c_device_id id, t_logical_address address );
+void I2C_DisableIRQSrc (t_i2c_irq_src_id id);
+#endif /* _U8500_I2C_H_ */
diff --git a/board/st/u8500/init_mmc.c b/board/st/u8500/init_mmc.c
new file mode 100755
index 000000000..dc2a7ea4f
--- /dev/null
+++ b/board/st/u8500/init_mmc.c
@@ -0,0 +1,363 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/* --- includes ----------------------------------------------------------- */
+#include "common.h"
+#include "mmc.h"
+#include "init_mmc.h"
+#include "gpio.h"
+#include "mmc_utils.h"
+#include "i2c.h"
+
+#ifdef CONFIG_CMD_FAT
+#include <part.h>
+#include <fat.h>
+#endif
+
+#define LOOP(x) {int i;for(i=0;i<1000;i++);}
+#ifdef CONFIG_CMD_FAT
+static block_dev_desc_t mmc_dev;
+u32 CSD[4];
+char MMC_CmdBuffer[1024] ;
+
+extern long do_fat_read (const char *filename, void *buffer, unsigned long maxsize,int dols);
+
+block_dev_desc_t * mmc_get_dev(int dev)
+{
+ return (block_dev_desc_t *)(&mmc_dev);
+}
+
+unsigned long mmc_block_read(int dev, unsigned long blknr,lbaint_t blkcnt,
+ void *dest)
+{
+ unsigned long src= blknr;
+
+#if 0
+ unsigned long rc = 0;
+ unsigned long i;
+
+ for(i = 0; i < blkcnt; i++)
+ {
+ mmc_readblock (1, (u32) (512 * src), (u32 *)dest, 512, MMCPOLLING);
+ rc ++;
+ src++;
+ dest += 512;
+ }
+#endif
+ printf("mmc_block_read: dev# %d, blknr %d, blkcnt %d\n",
+ dev, blknr, blkcnt);
+ /* card#, read offset, buffer, blocksize, transfer mode */
+ mmc_readblock (1, (u32) (512 * src), (u32 *)dest, 512, MMCPOLLING);
+ return 1;
+}
+
+t_mmc_error mmc_fat_read_file (char *filename, u32 address, u32 FileSize)
+{
+ u8 *mem_address = (u8 *) address;
+ t_mmc_error mmc_error = MMC_OK;
+
+ if((do_fat_read(filename,mem_address,FileSize,0)) < 0)
+ {
+ printf("error in reading %s file\n",filename);
+ mmc_error = MMC_INVALID_PARAMETER;
+ }
+ return mmc_error;
+}
+
+int mmc_hw_init (void)
+{
+ t_mmc_error response;
+
+ /* save the GPIO0 AFSELA register*/
+ gpio_altfuncenable(GPIO_ALT_SD_CARD0, "MMC");
+ /* Power-on the controller*/
+ response = mmc_enable ();
+
+ if (response != MMC_OK)
+ {
+ response = mmc_enable ();
+ if (response != MMC_OK)
+ {
+ printf ("Error in card power on\n");
+ goto end;
+ }
+ }
+ /* Initialise the cards on the bus, if any*/
+ response = mmc_initCard ();
+ if (response != MMC_OK)
+ {
+ printf ("Error in card initialization\n");
+ goto end;
+ }
+ response = mmc_readcsd (CSD);
+ if (response != MMC_OK)
+ {
+ printf ("Error while fetching card info\n");
+ goto end;
+ }
+
+ return 0;
+ end:
+ return 1;
+}
+
+/*
+ * init_mmc_fat - initialise MMC HW and register as FAT device
+ */
+int init_mmc_fat(void)
+{
+ unsigned int size;
+ unsigned int sizemult;
+ unsigned long num_sects;
+ unsigned long sect_size; /* in bytes */
+ unsigned long mmc_size;
+
+ if(mmc_hw_init())
+ {
+ goto end;
+ }
+ /*read block len*/
+ sect_size = 1<<((CSD[2] << 12 )>>28);
+ /*c_size */
+ size = ((CSD[2] & 0x3ff)<<2) + (CSD[1]>>30) ;
+ /*size of multiplier */
+ sizemult = (CSD[1] << 14 )>>29;
+
+ num_sects = (size+1)*(1<<(sizemult+2));
+ /* memory capcity of the Inserted Card */
+ mmc_size = (num_sects * sect_size)/(1024 * 1024);
+ printf("Memory Card size = %d MiB \n", mmc_size);
+ printf("sector size is %d, num_sects %d\n", sect_size, num_sects);
+
+ mmc_dev.if_type = IF_TYPE_MMC;
+ mmc_dev.part_type = PART_TYPE_DOS;
+ mmc_dev.dev = 0;
+ mmc_dev.lun = 0;
+ mmc_dev.type = 0;
+ mmc_dev.blksz = 512;
+ mmc_dev.lba = num_sects; /* XXX: assumes 512 blksize */
+ sprintf((char*)mmc_dev.vendor, "Unknown vendor");
+ sprintf((char*)mmc_dev.product, "Unknown product");
+ sprintf((char*)mmc_dev.revision, "N/A");
+ mmc_dev.removable = 0;
+ mmc_dev.block_read = mmc_block_read;
+
+ /* do fat registration with the SD/MMC device*/
+ if (fat_register_device(&mmc_dev, 1) != 0) {
+ printf("could not register as FAT device\n");
+ goto end;
+ }
+#if 0
+ printf(" Size \t FileName \n");
+ do_fat_read("/", NULL, 0, 1);
+ /* do fat read for the commands to be executed*/
+ if (do_fat_read("command.txt", &MMC_CmdBuffer[0], sizeof(MMC_CmdBuffer), 0)
+ == -1) {
+ printf(" No command.txt found in the Card\n");
+ return (0);
+ }
+ setenv("bootcmd", MMC_CmdBuffer);
+#endif
+ return(0);
+end:
+ gpio_altfuncdisable(GPIO_ALT_SD_CARD0, "MMC");
+ mmc_disable();
+ return 1;
+}
+#endif /* CONFIG_CMD_FAT */
+
+#define I2C_SCL_FREQ 100000 /* I2C bus clock frequency.*/
+#define I2C_INPUT_FREQ 48000000 /* Input clock frequency.*/
+#define I2C0_SLAVE_ADDRESS (0x84 >>1) /*GPIO expander slave address*/
+#define REG_CHIP_ID_INDEX 0x80
+#define HS_MASTER_CODE 0x01 /* High speed Master code */
+#define TX_FIFO_THRESHOLD 0x4 /* The threshold below or equal to which the transmit FIFO generates interrupt */
+#define RX_FIFO_THRESHOLD 0x4 /* The threshold above or equal to which the receive FIFO generates interrupt */
+#define BURST_LENGTH 0 /* The burst length used in the DMA operation */
+#define SLAVE_SETUP_TIME 14 /* Slave data setup time */
+
+
+void config_extended_gpio(void)
+{
+ t_i2c_error error_status;
+ t_i2c_device_config i2c_device_config;
+ t_i2c_transfer_config i2c_transfer_config;
+ t_i2c_error error_i2c;
+ u8 read_data = 0;
+ u8 dataArr[2]={0x06,0x06};
+
+ I2C_SetBaseAddress(I2C0, CFG_I2C0_BASE);
+ error_i2c = I2C_Init(I2C0, CFG_I2C0_BASE);
+
+ i2c_device_config.controller_i2c_address = 0;
+ i2c_device_config.input_frequency = I2C_INPUT_FREQ;
+ i2c_device_config.i2c_digital_filter_control = I2C_DIGITAL_FILTERS_OFF;
+ i2c_device_config.i2c_dma_sync_logic_control = I2C_DISABLE;
+ i2c_device_config.i2c_start_byte_procedure = I2C_DISABLE;
+
+ i2c_transfer_config.i2c_transfer_frequency = I2C_SCL_FREQ;
+ i2c_transfer_config.bus_control_mode = I2C_BUS_MASTER_MODE;
+
+ i2c_transfer_config.i2c_transmit_interrupt_threshold = TX_FIFO_THRESHOLD;
+ i2c_transfer_config.i2c_receive_interrupt_threshold = RX_FIFO_THRESHOLD;
+ i2c_transfer_config.transmit_burst_length = BURST_LENGTH;
+ i2c_transfer_config.receive_burst_length = BURST_LENGTH;
+ i2c_transfer_config.i2c_loopback_mode = I2C_DISABLE;
+ i2c_transfer_config.index_transfer_mode = I2C_TRANSFER_MODE_POLLING;
+ i2c_transfer_config.data_transfer_mode = I2C_TRANSFER_MODE_POLLING;
+ i2c_transfer_config.bus_control_mode = I2C_BUS_MASTER_MODE;
+ i2c_transfer_config.i2c_slave_general_call_mode = I2C_NO_GENERAL_CALL_HANDLING;
+
+ i2c_device_config.slave_data_setup_time = SLAVE_SETUP_TIME;
+
+ error_status = I2C_SetDeviceConfiguration(I2C0, &i2c_device_config);
+ if (I2C_OK != error_status)
+ {
+ printf("\n Error in I2C_SetDeviceConfiguration; err = %d", error_status);
+ return;
+ }
+
+ error_status = I2C_SetTransferConfiguration(I2C0, &i2c_transfer_config);
+ if (I2C_OK != error_status)
+ {
+ printf("\n Error in I2C_SetTransferConfiguration; err = %d", error_status);
+ return;
+ }
+ LOOP(10);
+ error_status = I2C_ReadSingleData (I2C0, I2C0_SLAVE_ADDRESS, I2C_BYTE_INDEX, 0x80, &read_data);
+ LOOP(1);
+ printf("\nGPIO expander Chip ID %x\n", read_data);
+
+ if(error_status){
+ printf("\n Error in I2C_ReadSingleData = %d", error_status);
+ return;
+ }
+ if (read_data == 0x01) /*If chip is = 0x1, the platform is MOP500, so config STMPE*/
+ {
+ printf("\nMOP500 platform\n");
+ //config_stmpe();
+ error_status = I2C_WriteSingleData(I2C0, I2C0_SLAVE_ADDRESS, I2C_BYTE_INDEX, 0x89, 0x0C);
+ LOOP(5);
+ error_status = I2C_WriteSingleData(I2C0, I2C0_SLAVE_ADDRESS, I2C_BYTE_INDEX, 0x83, 0x0C);
+ LOOP(5);
+ }
+ else if(read_data==0x03) /* If chip is = 0x3,the platform is HREF, so config Toshiba controller*/
+ {
+ printf("\nHREF platform\n");
+ //following code is for HREF
+ //set the direction of the GPIO KPY9 and KPY10
+ error_status = I2C_WriteSingleData(I2C0, I2C0_SLAVE_ADDRESS, I2C_BYTE_INDEX, 0xC8, 0x06);
+ LOOP(5);
+ dataArr[0]= 0x06;
+ dataArr[1]= 0x06;
+
+ error_status = I2C_WriteMultipleData(I2C0, I2C0_SLAVE_ADDRESS, I2C_BYTE_INDEX, 0xC4, dataArr,2);
+ LOOP(5);
+ if(error_status)
+ printf("Error in I2C_WriteMultipleData error = %d",error_status);
+
+ }
+ else
+ printf("\nunknown platform: chip ID = %x\n", read_data);
+ return;
+
+
+}
+
+
+/* ========================================================================
+ Achraf
+ Name: init_mmc_card
+ Description: init VIC, GPIO and MMC
+
+ ======================================================================== */
+int mmc_legacy_init(int dev)
+{
+ /*config extended GPIO pins for Level shifter and SDMMC_ENABLE */
+ config_extended_gpio();
+
+ init_mmc();
+
+#ifndef CONFIG_CMD_FAT
+ if (display_file_list("*") == MMC_CMD_RSP_TIMEOUT)
+ {
+ printf("MMC card not available on board\n");
+ }
+#endif
+ return 0;
+}
+
+/* ========================================================================
+ Name: init_mmc
+ Description: init multimedia card interface
+
+ ======================================================================== */
+static int init_mmc(void)
+{
+ t_mmc_error mmc_error;
+ struct gpio_register * gpio_base_address;
+
+ /* Initialize the base address of MMC-SD */
+ mmc_error = mmc_init (0,CFG_MMC_BASE);
+
+ if (MMC_OK != mmc_error)
+ {
+ printf("mmc_init():: %d \n", mmc_error);
+ return 1 ;
+ }
+
+ gpio_base_address = (void *) IO_ADDRESS(CFG_GPIO_0_BASE);
+ gpio_base_address -> gpio_dats |= 0x1FFC0000;
+ gpio_base_address -> gpio_pdis &= ~0x1FFC0000;
+
+#if 0
+#ifdef CONFIG_CMD_FAT
+ if(init_mmc_fat())
+ {
+ printf(" MMC Card not found \n");
+ }
+#endif
+#endif
+ if (mmc_hw_init() != 0) {
+ printf("mmc_init: hw init failed\n");
+ }
+ mmc_dev.if_type = IF_TYPE_MMC;
+ mmc_dev.part_type = PART_TYPE_DOS;
+ mmc_dev.dev = 0;
+ mmc_dev.lun = 0;
+ mmc_dev.type = 0;
+ mmc_dev.blksz = 512;
+ mmc_dev.lba = 0x20000; /* XXX: use real size, here 64 MB */
+ sprintf((char*)mmc_dev.vendor, "Unknown vendor");
+ sprintf((char*)mmc_dev.product, "Unknown product");
+ sprintf((char*)mmc_dev.revision, "N/A");
+ mmc_dev.removable = 0;
+ mmc_dev.block_read = mmc_block_read;
+ if (fat_register_device(&mmc_dev, 1) != 0) {
+ printf("mmc_init: could not register as FAT device\n");
+ }
+
+ return 0;
+}
+
+
+/* ------------------------------- End of file ---------------------------- */
diff --git a/board/st/u8500/init_mmc.h b/board/st/u8500/init_mmc.h
new file mode 100755
index 000000000..24ec9e689
--- /dev/null
+++ b/board/st/u8500/init_mmc.h
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __INIT_MMC_H
+#define __INIT_MMC_H
+#define PUBLIC /* Extern by default */
+
+#include <common.h>
+
+typedef void (*t_callback_fct) (u32);
+typedef struct
+{
+ t_callback_fct fct;
+ u32 param;
+} t_callback;
+
+static int init_mmc(void);
+int init_mmc_fat(void);
+t_mmc_error mmc_fat_read_file (char *, u32, u32);
+int mmc_hw_init (void);
+unsigned long mmc_block_read(int dev,unsigned long blknr,lbaint_t blkcnt,void *dest);
+
+
+#endif /* !defined(__INIT_MMC_H) */
diff --git a/board/st/u8500/mmc.c b/board/st/u8500/mmc.c
new file mode 100755
index 000000000..e80f8315f
--- /dev/null
+++ b/board/st/u8500/mmc.c
@@ -0,0 +1,2580 @@
+/*
+* (C) Copyright 2009
+* STEricsson, <www.stericsson.com>
+*
+* See file CREDITS for list of people who contributed to this
+* project.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+* MA 02111-1307 USA
+*/
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include <configs/u8500.h>
+#include "common.h"
+#include "mmc.h"
+#include "mmc_p.h"
+
+#define MAX_NUM_CARDS 5
+t_mmc_register *t_mmc0; /* Removed so it can be used in mmc_utils.c, by Chris S. */
+t_mmc_register *t_mmc4;
+t_mmc_register *t_mmc[MAX_NUM_CARDS];
+u32 t_mmc_rel_addr = 0x00010000;
+u32 emmc_rel_addr = 0x00100000;
+u8 no_of_cards = 0;
+u8 mmc_card = 0, sd_card = 0;
+u32 clockfreq;
+t_mmc_card_info card_array[30];
+t_mmc_device_mode device_mode = POLLING_MODE;
+u32 *source_buffer;
+u32 *dest_buffer;
+u16 total_no_of_bytes = 0;
+u8 selected_card = 0;
+t_mmc_error transfer_error = MMC_CMD_CRC_FAIL;
+u32 pwddata[8];
+t_mmc_event mmc_event; // For event management
+u32 write_freq = 0;
+
+/* Private Functions*/
+t_mmc_error mmc_cmderror(u8);
+t_mmc_error mmc_cmdresp145error(u8, u8);
+t_mmc_error mmc_cmdresp2error(u8);
+t_mmc_error mmc_cmdresp3error(u8);
+t_mmc_error mmc_cmdresp6error(u8, u16 *, u8);
+t_mmc_error mmc_cmdresp7error(u8);
+t_mmc_error mmc_findblocklen(u16 nobytes, u8 * power);
+t_mmc_error mmc_sendstatus(u8, u32 *);
+t_mmc_error mmc_iscardprogramming(u8, u8 *);
+
+/****************************************************************************/
+/* NAME : mmc_init() */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine initializes the MMC registers, checks */
+/* Peripheral and PCell Id and clears all interrupts. */
+/* PARAMETERS : */
+/* IN : t_logical_address MMCBaseAddress:MMC registers base address */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error : MMC error code */
+/****************************************************************************/
+
+t_mmc_error mmc_init(u8 card_num, t_logical_address MMCBaseAddress)
+{
+ t_mmc_error error;
+ if (card_num == 0)
+ t_mmc0 = (t_mmc_register *) MMCBaseAddress;
+ else if (card_num == 4)
+ t_mmc[card_num] = (t_mmc_register *) MMCBaseAddress;
+ error = MMC_OK;
+
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_setpowerstate() */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets the power status of the controller. */
+/* */
+/* PARAMETERS : */
+/* IN : t_mmc_Power_state Power state to set */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error : MMC error code */
+/****************************************************************************/
+t_mmc_error mmc_setpowerstate(t_mmc_power_state MMCPowerState)
+{
+ t_mmc_error error;
+
+ MMC_SET_CTRL(t_mmc0->mmc_Power, MMCPowerState);
+ error = MMC_OK;
+
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_getpowerstate() */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine returns the power status of the controller. */
+/* */
+/* PARAMETERS : */
+/* IN : t_mmc_Power_state Power state to set */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error : MMC error code */
+/****************************************************************************/
+
+t_mmc_power_state mmc_getpowerstate()
+{
+ t_mmc_power_state state;
+ state = MMC_READ_BITS(t_mmc0->mmc_Power, MMC_Power_MASK_CTRL, sbMMC_Power_CTRL);
+ return (state);
+}
+
+/*****************************************************************************/
+/* NAME : mmc_setoperatingvoltage */
+/*-------------------------------------------------------------------------- */
+/* DESCRIPTION: This routine sets the operating voltage range of . */
+/* the controller */
+/* PARAMETERS : */
+/* IN : u8 The encoded value of the output voltage range to set.*/
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error : MMC error code */
+/*****************************************************************************/
+
+t_mmc_error mmc_setoperatingvoltage(u8 value)
+{
+ t_mmc_error error;
+ if (value < 16)
+ {
+ MMC_SET_VOLT(t_mmc0->mmc_Power, value);
+ error = MMC_OK;
+ }
+ else
+ error = MMC_INVALID_PARAMETER;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_getoperatingvoltage */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine returns the encoded value of the current */
+/* operating voltage range */
+/* PARAMETERS : */
+/* IN : */
+/* OUT : */
+/* */
+/* RETURN : u8 The encoded value of the output voltage range to set*/
+/****************************************************************************/
+
+u8 mmc_getoperatingvoltage()
+{
+ u8 voltage;
+ voltage =
+ MMC_READ_BITS(t_mmc0->mmc_Power, MMC_Power_MASK_VOLT,sbMMC_Power_VOLT);
+ return (voltage);
+}
+
+/****************************************************************************/
+/* NAME : mmc_configbus */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine configures the bus in open drain or . */
+/* push-pull mode */
+/* PARAMETERS : */
+/* IN : t_mmc_bus_configuration Bus configuration to set */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_configbus(t_mmc_bus_configuration busconfig)
+{
+ t_mmc_error error;
+ MMC_SET_OPEND(t_mmc0->mmc_Power, busconfig.mode);
+ MMC_SET_ROD(t_mmc0->mmc_Power, busconfig.rodctrl);
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_setclock */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets the clock state as enabled or disabled. */
+/* */
+/* PARAMETERS : */
+/* IN : t_mmc_state clock state to set. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_setclock(t_mmc_state busstate)
+{
+ t_mmc_error error;
+ MMC_SET_CENABLE(t_mmc0->mmc_Clock, busstate);
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_configclockcontrol */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets configurations for clock and bus mode. */
+/* */
+/* PARAMETERS : */
+/* IN : t_mmc_Clock_control clock control state to set. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_configclockcontrol(t_mmc_clock_control clockcontrol)
+{
+ t_mmc_error error;
+
+ MMC_SET_PWRSAVE(t_mmc0->mmc_Clock, clockcontrol.pwrsave);
+ MMC_SET_BYPASS(t_mmc0->mmc_Clock, clockcontrol.bypass);
+ MMC_SET_WIDEBUS(t_mmc0->mmc_Clock, clockcontrol.widebus);
+ error = MMC_OK;
+
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_setclockfrequency */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets clock frequency for MMCI controller. */
+/* */
+/* PARAMETERS : */
+/* IN : u8 Clock divider value for desired frequency. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+/* COMMENT: Clock frequency is calculated by this formula: */
+/* MCICLK = MCLK/(2 * [Clock_div +1]) */
+
+/****************************************************************************/
+
+t_mmc_error mmc_setclockfrequency(u8 clockdiv)
+{
+ t_mmc_error error;
+
+ MMC_SET_CLKDIV(t_mmc0->mmc_Clock, clockdiv);
+ error = MMC_OK;
+
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_sendcommand */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sends command and enable Command path */
+/* state machine. */
+/* PARAMETERS : */
+/* IN : t_mmc_Command_index: Command to send. */
+/* u32: argument to send. */
+/* t_mmc_Command_control: Command control parameters to set. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_sendcommand(t_mmc_command_index commandindex, u32 argument,
+ t_mmc_command_control commcontrol)
+{
+ t_mmc_error error;
+ u32 reg;
+
+ if (commandindex != MMC_NO_CMD)
+ {
+ reg = commandindex;
+ t_mmc0->mmc_Argument = argument;
+ reg |= (commcontrol.IsRespExpected << 6);
+ reg |= (commcontrol.IsLongResp << 7);
+ reg |= (commcontrol.IsInterruptMode << 8);
+ reg |= (commcontrol.IsPending << 9);
+ reg |= (commcontrol.cmdpath << 10);
+ t_mmc0->mmc_Command = reg;
+ }
+
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_getresponse */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine returns command index of last command for */
+/* which response received. */
+/* PARAMETERS : */
+/* IN : */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_Command_index command index of last command */
+
+/****************************************************************************/
+
+t_mmc_command_index mmc_getcommandresponse()
+{
+ t_mmc_command_index respcommand;
+ respcommand = t_mmc0->mmc_RespCommand;
+ return respcommand;
+}
+
+/****************************************************************************/
+/* NAME : mmc_getresponse */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine returns response received from the card for */
+/* the last command. */
+/* PARAMETERS : */
+/* IN : t_mmc_response_type Expected response type */
+/* u32 * u32 pointer to store response. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_getresponse(t_mmc_response_type resptype, u32 * response)
+{
+ t_mmc_error error;
+ if (resptype == MMC_SHORT_RESP)
+ *response = (t_mmc0->mmc_Response0);
+ else
+ {
+ *response = t_mmc0->mmc_Response0;
+ *(response + 1) = t_mmc0->mmc_Response1;
+ *(response + 2) = t_mmc0->mmc_Response2;
+ *(response + 3) = t_mmc0->mmc_Response3;
+ }
+
+ error = MMC_OK;
+ return error;
+
+}
+
+/****************************************************************************/
+/* NAME : mmc_setdatapath */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine enables/disables the data path for data transfer.*/
+/* */
+/* PARAMETERS : */
+/* IN : t_mmc_state Specifies the state of the */
+/* data path, whether to enabled or disabled. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_setdatapath(t_mmc_state datapath)
+{
+ t_mmc_error error;
+ MMC_SET_DATAPATH(t_mmc0->mmc_DataCtrl, datapath);
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_setdatatimeout */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets the data timeout period in card bus */
+/* clock periods */
+/* PARAMETERS : */
+/* IN : u32 Specifies the timeout value of the data path. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_setdatatimeout(u32 datatimeout)
+{
+ t_mmc_error error;
+ t_mmc0->mmc_DataTimer = datatimeout;
+ error = MMC_OK;
+ return error;
+
+}
+
+/******************************************************************************/
+/* NAME : mmc_setdatalength */
+/*----------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets the data length (in bytes) for the data */
+/* transfer. */
+/* PARAMETERS : */
+/* IN : u16 Specifies the number of data bytes to be transferred.*/
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/******************************************************************************/
+
+t_mmc_error mmc_setdatalength(u16 datalength)
+{
+ t_mmc_error error;
+
+ t_mmc0->mmc_DataLength = datalength;
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_setdatablocklength */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets the data block size (in an encoded fashion)*/
+/* for block data transfer. */
+/* PARAMETERS : */
+/* IN : u8 Specifies the data block size for block transfer. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_setdatablocklength(u8 blocksize)
+{
+ t_mmc_error error;
+ if (blocksize <= MAXBSIZEPOWER)
+ {
+ MMC_SET_BLOCKSIZE(t_mmc0->mmc_DataCtrl, blocksize);
+ error = MMC_OK;
+ }
+ else
+ error = MMC_INVALID_PARAMETER;
+ return error;
+
+}
+
+/****************************************************************************/
+/* NAME : mmc_settransferdirection */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: routine sets direction for data transfer, whether */
+/* the transfer is a read or write. */
+/* PARAMETERS : */
+/* IN : t_mmc_transfer_direction the direction for data transfer. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_settransferdirection(t_mmc_transfer_direction transdir)
+{
+ t_mmc_error error = MMC_OK;
+ MMC_SET_DATADIR(t_mmc0->mmc_DataCtrl, transdir);
+ return error;
+}
+
+/***********************************************************************************/
+/* NAME : mmc_settransfertype */
+/*---------------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets whether data transfer is */
+/* in stream mode or block mode. */
+/* PARAMETERS : */
+/* IN : t_mmc_transfer_type Specifies the transfer type for data transfer.*/
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/***********************************************************************************/
+
+t_mmc_error mmc_settransfertype(t_mmc_transfer_type transtype)
+{
+ t_mmc_error error = MMC_OK;
+ MMC_SET_MODE(t_mmc0->mmc_DataCtrl, transtype);
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_handledma */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine enables or disables data transfer through DMA. */
+/* PARAMETERS : */
+/* IN : t_mmc_state Specifies whether to enable/disable DMA for */
+/* data transfer. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_handledma(t_mmc_state dmastate)
+{
+ t_mmc_error error = MMC_OK;
+ MMC_SET_DMA(t_mmc0->mmc_DataCtrl, dmastate);
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_getdatacounter */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine returns number of data elements (in bytes) */
+/* yet to be transferred. */
+/* PARAMETERS : */
+/* IN : */
+/* OUT : */
+/* */
+/* RETURN : u16 */
+
+/****************************************************************************/
+
+u16 mmc_getdatacounter()
+{
+ u16 no_of_elements;
+ no_of_elements = t_mmc0->mmc_DataCnt;
+ return no_of_elements;
+}
+
+/****************************************************************************/
+/* NAME : mmc_selectsdcard */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine selects specific SD card. */
+/* PARAMETERS : */
+/* IN : u8 SD card to select. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_selectsdcard(u8 cardno)
+{
+ t_mmc_error error;
+
+ if (cardno < 16)
+ {
+ t_mmc0->mmc_SelectSD = cardno;
+ error = MMC_OK;
+ }
+ else
+ error = MMC_REQUEST_NOT_APPLICABLE;
+
+ return error;
+
+}
+
+/****************************************************************************/
+/* NAME : mmc_Poweron */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine enquires cards about their operating voltage */
+/* and sets optimal value to supply output voltage. Sends out */
+/* of range cards to inactive states. Also configures */
+/* clock controls. */
+/* PARAMETERS : */
+/* IN : */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_poweron(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 response, one_msec, count = 0, delay;
+ t_bool validvoltage, flag = FALSE;
+ u32 address_mode = Byte_Mode;
+
+ validvoltage = FALSE;
+ selected_card = 0;
+ no_of_cards = 5;
+
+ t_mmc[card_num]->mmc_Power = 0x43; //PowerOn | OpenDrain;
+
+ t_mmc[card_num]->mmc_Clock = 0x41FF; //ClkDivInit| ClkEnable | Hwfc_en;//setting clk freq just less than 400KHz
+ clockfreq = MCLK / (2 * (ClkDivInit + 1));
+ t_mmc[card_num]->mmc_Mask0 &= ~AllInterrupts;
+ one_msec = 52000 / ((t_mmc[card_num]->mmc_Power & 0xFF) + 2);
+
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = (GO_IDLE_STATE & ~RespExpected) | CmdPathEnable;
+ error = mmc_cmderror(card_num);
+ if (error != MMC_OK)
+ return error;
+
+ /* send CMD8 to verify SD card interface operating condition */
+ t_mmc[card_num]->mmc_Argument = Check_Pattern;
+ t_mmc[card_num]->mmc_Command = SD_SEND_IF_COND | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp7error(card_num);
+ /* IF ERROR IS COMMAND TIMEOUT IT IS MMC CARD */
+ if (error == MMC_OK)
+ {
+ address_mode = Sector_Mode;
+ }
+ else
+ {
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = (GO_IDLE_STATE & ~RespExpected) | CmdPathEnable;
+ error = mmc_cmderror(card_num);
+ if (error != MMC_OK)
+ return error;
+ }
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = APP_CMD | RespExpected | CmdPathEnable;
+
+ for (delay = 0; delay < (one_msec * 27); delay++) ;
+ error = mmc_cmdresp145error(APP_CMD, card_num);
+
+ /* IF ERROR IS COMMAND TIMEOUT IT IS MMC CARD */
+ if (MMC_OK == error)
+ {
+ /*SD CARD */
+ /*Send CMD41 SD_APP_APP_OP_COND WITH ARGUMENT 0x00FFC000 */
+ printf(" initcard:: Set the SD voltage \n");
+ while ((!validvoltage) && (count < 0xFFFF))
+ {
+ if (flag)
+ {
+ /*SEND CMD55 APP_CMD with RCA as 0*/
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = APP_CMD | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(APP_CMD, card_num);
+ if (error != MMC_OK)
+ {
+ return (error);
+ }
+ }
+
+ t_mmc[card_num]->mmc_Argument = VoltageWindowSD | address_mode; /* voltage window */
+ t_mmc[card_num]->mmc_Command = SD_APP_OP_COND | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp3error(card_num);
+ if (MMC_OK != error)
+ {
+ return (error);
+ }
+
+ response = t_mmc[card_num]->mmc_Response0;
+ validvoltage = (t_bool) (((response >> 31) == 1) ? 1 : 0);
+ flag = TRUE;
+ count++;
+ }
+
+ if (count >= 0xFFFF)
+ {
+ error = MMC_INVALID_VOLTRANGE;
+ return (error);
+ }
+
+ if (Sector_Mode == address_mode)
+ {
+ printf(" SD high capacity card detected \n");
+ }
+ else
+ {
+ printf(" SD card detected \n");
+ }
+ sd_card = 1;
+ }
+ else if (MMC_CMD_RSP_TIMEOUT == error)
+ {
+ /*Send CMD0 GO_IDLE_STATE*/
+ printf(" initcard:: Set the MMC voltage \n");
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = (GO_IDLE_STATE & ~RespExpected) | CmdPathEnable;
+
+ error = mmc_cmderror(card_num);
+ if (MMC_OK != error)
+ {
+ return (error);
+ }
+ address_mode = Byte_Mode;
+ validvoltage = FALSE;
+ response = 0;
+
+ /* MMC_CARD */
+ while ((!validvoltage) && (count < 0xFFFF))
+ {
+ t_mmc[card_num]->mmc_Argument = 0xc0ff8000; //VoltageWindowMMC | address_mode;
+ t_mmc[card_num]->mmc_Command = SEND_OP_COND | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp3error(card_num);
+ if (MMC_OK != error)
+ {
+ return (error);
+ }
+
+ for (delay = 0; delay < 1; delay++) ;
+
+ response = t_mmc[card_num]->mmc_Response0;
+ validvoltage = (t_bool) (((response >> 31) == 1) ? 1 : 0);
+ count++;
+ }
+
+ if (count >= 0xFFFF)
+ {
+ error = MMC_INVALID_VOLTRANGE;
+ return (error);
+ }
+
+ if (response & Sector_Mode)
+ {
+ printf(" MMC high capacity card detected \n");
+ }
+ else
+ {
+ printf(" EMMC card detected \n");
+ }
+ mmc_card = 1;
+ error = MMC_OK;
+ }
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_Poweroff */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine turns the supply output voltage off. */
+/* PARAMETERS : */
+/* IN : */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+t_mmc_error mmc_poweroff(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ t_mmc[card_num]->mmc_Power &= ~PowerOn;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_initializeCards */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine initializes all cards. All cards come into */
+/* standby state. */
+/* PARAMETERS : */
+/* IN : */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_initializeCards(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u16 rca = emmc_rel_addr;
+ t_bool card_initialized = FALSE;
+
+ if ((t_mmc[card_num]->mmc_Power & PowerOn) == 0x00)
+ {
+ printf("emmc power failed \n");
+ error = MMC_REQUEST_NOT_APPLICABLE;
+ return error;
+ }
+ while (!card_initialized)
+ {
+ t_mmc[card_num]->mmc_Argument = 0x00000000;
+ t_mmc[card_num]->mmc_Command = ALL_SEND_CID | RespExpected | LongResponse | CmdPathEnable;
+
+ error = mmc_cmdresp2error(card_num);
+ if (MMC_OK != error)
+ {
+ return (error);
+ }
+
+ card_array[card_num].CID[0] = t_mmc[card_num]->mmc_Response3;
+ card_array[card_num].CID[1] = t_mmc[card_num]->mmc_Response2;
+ card_array[card_num].CID[2] = t_mmc[card_num]->mmc_Response1;
+ card_array[card_num].CID[3] = t_mmc[card_num]->mmc_Response0;
+ if (mmc_card == 1)
+ {
+ printf("init the MMC Card\n");
+ t_mmc[card_num]->mmc_Argument = rca;//rca << 16;
+ t_mmc[card_num]->mmc_Command = SET_REL_ADDR | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(SET_REL_ADDR, card_num);
+ if (error != MMC_OK)
+ {
+ printf ("emmc card init response for CMD3 error \n");
+ return error;
+ }
+ }
+ else if (sd_card == 1)
+ {
+ printf("init the SD Card\n");
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = SET_REL_ADDR | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp6error(SET_REL_ADDR, &rca, card_num);
+ if (error != MMC_OK)
+ {
+ printf ("emmc card init response for CMD6 error \n");
+ return error;
+ }
+ }
+ card_array[card_num].RCA = rca;
+ t_mmc[card_num]->mmc_Argument = rca;//(u32) rca << 16;
+ t_mmc[card_num]->mmc_Command = SEND_CSD | RespExpected | LongResponse | CmdPathEnable;
+
+ error = mmc_cmdresp2error(card_num);
+ if (error != MMC_OK)
+ {
+ printf("emmc card init response for CMD9 error \n");
+ return error;
+ }
+ card_array[card_num].CSD[0] = t_mmc[card_num]->mmc_Response3;
+ card_array[card_num].CSD[1] = t_mmc[card_num]->mmc_Response2;
+ card_array[card_num].CSD[2] = t_mmc[card_num]->mmc_Response1;
+ card_array[card_num].CSD[3] = t_mmc[card_num]->mmc_Response0;
+
+ //rca++;
+ error = MMC_OK; //All cards get intialized
+ card_initialized = TRUE;
+ /*
+ t_mmc[card_num]->mmc_Argument = (u32) 0x03B70100;
+ t_mmc[card_num]->mmc_Command =
+ APP_SD_SET_BUSWIDTH | RespExpected | LongResponse | CmdPathEnable;
+
+ error = mmc_cmdresp2error(card_num);
+ if (error != MMC_OK)
+ {
+ printf("emmc card init response for CMD6 error \n");
+ return error;
+ }
+ */
+ }
+ t_mmc[card_num]->mmc_Power = 0x3; /* PUSHPULL mode after intialization */
+ t_mmc[card_num]->mmc_Clock = 0x4100; //(t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x00000002;
+
+ return error;
+
+}
+
+/****************************************************************************/
+/* NAME : mmc_setdevicemode */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine sets device mode whether to operate in Polling,*/
+/* Interrupt, dma mode. */
+/* PARAMETERS : */
+/* IN : t_mmc_device_mode mode to for further transmission. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_setdevicemode(t_mmc_device_mode mode)
+{
+ t_mmc_error error;
+
+ switch (mode)
+ {
+ case POLLING_MODE:
+ device_mode = POLLING_MODE;
+ break;
+ case INTERRUPT_MODE:
+ device_mode = INTERRUPT_MODE;
+ break;
+ case DMA_MODE:
+ device_mode = DMA_MODE;
+ break;
+ default:
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_readbytes */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine allows to read bytes from specified address */
+/* in a card */
+/* PARAMETERS : */
+/* IN : u8 cardno: card to access */
+/* u32 addr : address from where to start reading */
+/* u16 no_of_bytes: no. of bytes to read */
+/* OUT : u32* readbuff: buffer to store data */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_readbytes(u8 card_num, u32 addr, u32 * readbuff,u16 no_of_bytes)
+{
+ t_mmc_error error = MMC_OK;
+ u32 i;
+ u32 timeout = 0;
+ u32 *tempbuff = readbuff;
+
+ total_no_of_bytes = 0;
+
+ t_mmc0->mmc_DataCtrl = AllZero;
+
+ if ((card_num > no_of_cards) || (card_num == 0))
+ {
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+
+ /* send command for selecting the card */
+ if (card_num != selected_card)
+ {
+ t_mmc0->mmc_Argument = card_array[card_num].RCA;//card_array[card_num - 1].RCA << 16;
+ t_mmc0->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_REL_ADDR, card_num);
+ if (error != MMC_OK)
+ return error;
+ else
+ selected_card = card_num;
+ }
+
+ /* now depending on parameter no_of_bytes, send command READ_DAT_UNTIL_STOP */
+
+ if (no_of_bytes == 0) // this means open-ended stream read,until STOP_TRANSMISSION follows
+ {
+ if (device_mode != INTERRUPT_MODE)
+ return MMC_REQUEST_NOT_APPLICABLE;
+
+ total_no_of_bytes = 65532;
+
+ t_mmc0->mmc_DataLength = 65532;
+
+ t_mmc0->mmc_DataTimer = 0xefffffff;
+
+ t_mmc0->mmc_DataCtrl = ReadDir | StreamMode | DataPathEnable;
+
+ dest_buffer = readbuff;
+
+ t_mmc0->mmc_Clock = (t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x0000000B;
+
+ t_mmc0->mmc_Argument = addr >> 9;
+ t_mmc0->mmc_Command = READ_DAT_UNTIL_STOP | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(READ_DAT_UNTIL_STOP, card_num);
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | RxFifoHalfFull | RxOverrun;
+ }
+ else if (no_of_bytes > 0)
+ {
+ total_no_of_bytes = no_of_bytes;
+
+ t_mmc0->mmc_DataLength = no_of_bytes;
+
+ t_mmc0->mmc_DataTimer = 0xefffffff;
+
+ t_mmc0->mmc_DataCtrl = ReadDir | StreamMode | DataPathEnable;
+
+ dest_buffer = readbuff;
+
+ t_mmc0->mmc_Clock = (t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x0000000B;
+
+ t_mmc0->mmc_Argument = addr >> 9;
+ t_mmc0->mmc_Command = READ_DAT_UNTIL_STOP | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(READ_DAT_UNTIL_STOP, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ if (device_mode == POLLING_MODE)
+ {
+
+ timeout = 0xffffffff;
+
+ while ((timeout > 0) && !(t_mmc0->mmc_Status & (DataCrcFail | DataTimeOut | DataEnd)))
+ {
+ timeout--;
+ if (t_mmc0->mmc_Status & RxFifoHalfFull)
+ {
+ for (i = 0; i < 8; i++)
+ *(tempbuff + i) = t_mmc0->mmc_Fifo;
+ tempbuff += 8;
+ }
+
+ }
+
+ if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut))
+ {
+ t_mmc0->mmc_Clear |= DataTimeOut;
+ error = MMC_DATA_TIMEOUT;
+ transfer_error = MMC_DATA_TIMEOUT;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & DataCrcFail)
+ {
+ t_mmc0->mmc_Clear |= DataCrcFail;
+ error = MMC_DATA_CRC_FAIL;
+ transfer_error = MMC_DATA_CRC_FAIL;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+
+ while (t_mmc0->mmc_Status & RxDataAvlbl)
+ {
+ *tempbuff = t_mmc0->mmc_Fifo;
+ tempbuff++;
+ }
+
+ t_mmc0->mmc_Argument = 0x00000000;
+ t_mmc0->mmc_Command = STOP_TRANSMISSION | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(STOP_TRANSMISSION, card_num);
+
+ transfer_error = error;
+ if (error != MMC_OK)
+ return error;
+
+ }
+
+ else if (device_mode == INTERRUPT_MODE)
+ t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxFifoHalfFull | RxOverrun;
+
+ else if (device_mode == DMA_MODE)
+ {
+ t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxOverrun;
+ t_mmc0->mmc_DataCtrl |= DMAEnab;
+ }
+ }
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_writebytes */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine allows to write bytes starting from a specified*/
+/* address in a card */
+/* PARAMETERS : */
+/* IN : u8 cardno: card to access */
+/* u32 addr : address where to start writing */
+/* u16 no_of_bytes: no. of bytes to write */
+/* OUT : u32* writebuff: source buffer */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_writebytes(u8 card_num, u32 addr, u32 * writebuff, u16 no_of_bytes)
+{
+ t_mmc_error error;
+ u32 timeout = 0;
+ u32 *tempbuff = writebuff;
+ u32 i, j, bytes_transferred = 0;
+ u8 cardstate;
+
+ total_no_of_bytes = 0;
+
+ t_mmc0->mmc_DataCtrl = AllZero;
+
+ if ((card_num > no_of_cards) || (card_num == 0))
+ {
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+ /* send command for selecting the card */
+
+ if (card_num != selected_card)
+ {
+ t_mmc0->mmc_Argument = card_array[card_num].RCA;//card_array[card_num - 1].RCA << 16;
+ t_mmc0->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num);
+
+ if (error != MMC_OK)
+ return error;
+ else
+ selected_card = card_num;
+ }
+
+ /* now depending on parameter no_of_bytes, send command WRITE_DAT_UNTIL_STOP */
+
+ if (no_of_bytes == 0) // this means open-ended stream read,until STOP_TRANSMISSION follows
+ {
+ if (device_mode != INTERRUPT_MODE)
+ return MMC_REQUEST_NOT_APPLICABLE;
+
+ t_mmc0->mmc_DataTimer = 0xefffffff;
+
+ total_no_of_bytes = 65532;
+
+ t_mmc0->mmc_DataLength = 65532;
+
+ source_buffer = writebuff;
+
+ t_mmc0->mmc_Clock = (t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x00000031;
+
+ t_mmc0->mmc_Argument = addr >> 9;
+ t_mmc0->mmc_Command = WRITE_DAT_UNTIL_STOP | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(WRITE_DAT_UNTIL_STOP, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc0->mmc_DataCtrl = (StreamMode & ~ReadDir) | DataPathEnable;
+
+ t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | TxFifoHalfEmpty | TxUnderrun;
+
+ /*Now the card will send data thru DMA to the destination buffer.CRC/TimeOut error will
+ be handled in the interrupt handler*/
+ }
+ else if (no_of_bytes > 0)
+ {
+ total_no_of_bytes = no_of_bytes;
+
+ t_mmc0->mmc_DataLength = no_of_bytes;
+
+ t_mmc0->mmc_DataTimer = 0xefffffff;
+
+ source_buffer = writebuff;
+
+ t_mmc0->mmc_Argument = addr >> 9;
+ t_mmc0->mmc_Command = WRITE_DAT_UNTIL_STOP | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(WRITE_DAT_UNTIL_STOP, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc0->mmc_DataCtrl = (StreamMode & ~ReadDir) | DataPathEnable;
+
+ if (device_mode == POLLING_MODE)
+ {
+ timeout = 0xefffffff;
+
+ while ((timeout > 0) && !(t_mmc0->mmc_Status & (DataCrcFail | DataTimeOut | DataEnd)))
+ {
+ timeout--;
+ if (t_mmc0->mmc_Status & TxFifoHalfEmpty)
+ {
+ if ((total_no_of_bytes - bytes_transferred) < 32)
+ {
+ j = ((total_no_of_bytes - bytes_transferred) % 4 == 0) ?
+ ((total_no_of_bytes - bytes_transferred) / 4)
+ : ((total_no_of_bytes - bytes_transferred) / 4 +1);
+
+ for (i = 0; i < j; i++, tempbuff++,bytes_transferred += 4)
+ t_mmc0->mmc_Fifo = *tempbuff;
+
+ }
+ else
+ {
+ for (i = 0; i < 8; i++)
+ t_mmc0->mmc_Fifo = *(tempbuff + i);
+ tempbuff += 8;
+ bytes_transferred += 32;
+ }
+ }
+ }
+
+ if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut))
+ {
+ t_mmc0->mmc_Clear |= DataTimeOut;
+ transfer_error = error = MMC_DATA_TIMEOUT;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & DataCrcFail)
+ {
+ t_mmc0->mmc_Clear |= DataCrcFail;
+ transfer_error = error = MMC_DATA_CRC_FAIL;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+
+ mmc_iscardprogramming(card_num, &cardstate);
+ while ((cardstate == 7) || (cardstate == 6))
+ mmc_iscardprogramming(card_num, &cardstate);
+
+ t_mmc0->mmc_Argument = 0x00000000;
+ t_mmc0->mmc_Command = STOP_TRANSMISSION | RespExpected | CmdPathEnable;
+
+ transfer_error = error = mmc_cmdresp145error(STOP_TRANSMISSION, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ }
+
+ else if (device_mode == INTERRUPT_MODE)
+
+ t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxFifoHalfEmpty | TxUnderrun;
+
+ else if (device_mode == DMA_MODE)
+ {
+ t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxUnderrun;
+ t_mmc0->mmc_DataCtrl |= DMAEnab;
+ }
+
+ }
+ error = MMC_OK;
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_readblocks */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine allows to read blocks from a specified */
+/* address in a card */
+/* PARAMETERS : */
+/* IN : u8 cardno: card to access */
+/* u32 addr : address from where to start reading */
+/* u16 blocksize : size of block in bytes */
+/* u16 no_of_blocks: no. of blocks to read */
+/* OUT : u32* readbuff: source buffer */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_readblocks(u8 card_num, u32 addr, u32 * readbuff, u16 blocksize, u16 no_of_blocks)
+{
+ t_mmc_error error = MMC_OK;
+ u32 i;
+ u32 timeout = 0;
+ u8 power;
+ u32 *tempbuff = readbuff;
+
+ total_no_of_bytes = 0;
+
+ t_mmc[card_num]->mmc_DataCtrl = AllZero;
+
+ /* send command for selecting the card */
+ if ((card_num > no_of_cards) || (card_num == 0))
+ {
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+ if (card_num != selected_card)
+ {
+ t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA;//0x1 << 16; //card_array[cardno - 1].RCA << 16;
+ t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num);
+
+ if (error != MMC_OK)
+ {
+ printf("SEL_DESEL_CARD ::error=0x%x \n", error);
+ return error;
+ }
+ else
+ selected_card = card_num;
+ }
+
+ if (t_mmc[card_num]->mmc_Response0 & 0x02000000)
+ return MMC_LOCK_UNLOCK_FAILED;
+
+ /* now depending on parameter no_of_blocks, send command READ_DAT_UNTIL_STOP */
+
+ //set the block size,both on controller and card
+
+ if ((blocksize > 0) && (blocksize <= 2048) && ((blocksize & (blocksize - 1)) == 0))
+ {
+
+ power = convert_from_bytes_to_power_of_two(blocksize);
+ t_mmc[card_num]->mmc_DataCtrl = power << 4;
+
+ t_mmc[card_num]->mmc_Argument = (u32) blocksize;
+ t_mmc[card_num]->mmc_Command = SET_BLOCKLEN | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_BLOCKLEN, card_num);
+
+ if (error != MMC_OK)
+ {
+ printf("SET_BLOCKLEN ::error=0x%x \n", error);
+ return error;
+ }
+ }
+ else
+ {
+ printf("SET_BLOCKLEN ::error set proper block len\n");
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+
+ if (no_of_blocks == 0) // this means open-ended block read,until STOP_TRANSMISSION follows
+ {
+
+ if (device_mode != INTERRUPT_MODE)
+ return MMC_REQUEST_NOT_APPLICABLE;
+
+ t_mmc[card_num]->mmc_DataTimer = 0xefffffff;
+
+ t_mmc[card_num]->mmc_DataLength = (65535 / blocksize) * blocksize;
+
+ total_no_of_bytes = (65535 / blocksize) * blocksize;
+
+ t_mmc[card_num]->mmc_Argument = (65535 / blocksize);
+ t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc[card_num]->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable;
+
+ dest_buffer = readbuff;
+
+ t_mmc[card_num]->mmc_Argument = addr >> 9;
+ t_mmc[card_num]->mmc_Command = READ_MULT_BLOCK | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(READ_MULT_BLOCK, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | RxFifoHalfFull | RxOverrun;
+
+ /*Now the card will send data thru DMA to the destination buffer.CRC/TimeOut error will
+ be handled in the interrupt handler*/
+
+ }
+ else if (no_of_blocks == 1)
+ {
+ total_no_of_bytes = blocksize;
+
+ t_mmc[card_num]->mmc_DataLength = blocksize;
+
+ t_mmc[card_num]->mmc_DataTimer = 0x0fffffff;
+
+ t_mmc[card_num]->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable;
+
+ dest_buffer = readbuff;
+
+ t_mmc[card_num]->mmc_Argument = addr >> 9;
+ t_mmc[card_num]->mmc_Command = READ_SINGLE_BLOCK | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(READ_SINGLE_BLOCK, card_num);
+
+ if (error != MMC_OK)
+ {
+ printf("READ_SINGLE_BLOCK ::error=0x%x \n", error);
+ return error;
+ }
+ if (device_mode == POLLING_MODE)
+ {
+
+ timeout = 0xefffffff;
+
+ while ((timeout > 0) && !(t_mmc[card_num]->mmc_Status & (RxOverrun | DataCrcFail |
+ DataTimeOut | DataBlockEnd)))
+ {
+ timeout--;
+ if (t_mmc[card_num]->mmc_Status & RxFifoHalfFull)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ *(tempbuff + i) = t_mmc[card_num]->mmc_Fifo;
+ }
+ tempbuff += 8;
+ }
+
+ }
+
+ if ((timeout == 0)|| (t_mmc[card_num]->mmc_Status & DataTimeOut))
+ {
+ t_mmc[card_num]->mmc_Clear |= DataTimeOut;
+ transfer_error = error = MMC_DATA_TIMEOUT;
+ printf("mmc_readblocks::1 MMC_DATA_TIMEOUT \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & DataCrcFail)
+ {
+ t_mmc[card_num]->mmc_Clear |= DataCrcFail;
+ transfer_error = error = MMC_DATA_CRC_FAIL;
+ printf("mmc_readblocks::1 MMC_DATA_CRC_FAIL \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & RxOverrun)
+ {
+ t_mmc[card_num]->mmc_Clear |= RxOverrun;
+ transfer_error = error = MMC_RX_OVERRUN;
+ printf("mmc_readblocks::1 MMC_RX_OVERRUN \n");
+ return error;
+ }
+
+ while (t_mmc[card_num]->mmc_Status & RxDataAvlbl)
+ {
+ *tempbuff = t_mmc[card_num]->mmc_Fifo;
+ tempbuff++;
+ }
+ transfer_error = error;
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+ }
+
+ else if (device_mode == INTERRUPT_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxFifoHalfFull | RxOverrun;
+ }
+ else if (device_mode == DMA_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxOverrun;
+ t_mmc[card_num]->mmc_DataCtrl |= DMAEnab;
+ }
+
+ }
+ else if (no_of_blocks > 1)
+ {
+ // set the block count,both for the controller and the card
+ total_no_of_bytes = no_of_blocks * blocksize;
+
+ t_mmc[card_num]->mmc_DataLength = no_of_blocks * blocksize;
+
+ t_mmc[card_num]->mmc_Argument = (u32) no_of_blocks;
+ t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc[card_num]->mmc_DataTimer = 0xefffffff;
+
+ t_mmc[card_num]->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable;
+
+ dest_buffer = readbuff;
+
+ t_mmc[card_num]->mmc_Argument = addr >> 9;
+ t_mmc[card_num]->mmc_Command = READ_MULT_BLOCK | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(READ_MULT_BLOCK, card_num);
+ if (error != MMC_OK)
+ return error;
+
+ if (device_mode == POLLING_MODE)
+ {
+ timeout = 0xefffffff;
+ while ((timeout > 0)&& !(t_mmc[card_num]->mmc_Status & (RxOverrun | DataCrcFail |DataTimeOut | DataEnd)))
+ {
+ timeout--;
+ if (t_mmc[card_num]->mmc_Status & RxFifoHalfFull)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ *(tempbuff + i) = t_mmc[card_num]->mmc_Fifo;
+ }
+ tempbuff += 8;
+ }
+ }
+
+ if ((timeout == 0) || (t_mmc[card_num]->mmc_Status & DataTimeOut))
+ {
+ t_mmc[card_num]->mmc_Clear |= DataTimeOut;
+ transfer_error = error = MMC_DATA_TIMEOUT;
+ return error;
+
+ }
+ else if (t_mmc[card_num]->mmc_Status & DataCrcFail)
+ {
+ t_mmc[card_num]->mmc_Clear |= DataCrcFail;
+ transfer_error = error = MMC_DATA_CRC_FAIL;
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & RxOverrun)
+ {
+ t_mmc[card_num]->mmc_Clear |= RxOverrun;
+ transfer_error = error = MMC_RX_OVERRUN;
+ return error;
+ }
+
+ while (t_mmc[card_num]->mmc_Status & RxDataAvlbl)
+ {
+ *tempbuff = t_mmc[card_num]->mmc_Fifo;
+ tempbuff++;
+ }
+ transfer_error = error;
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+ }
+
+ else if (device_mode == INTERRUPT_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxFifoHalfFull | RxOverrun;
+ }
+ else if (device_mode == DMA_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxOverrun;
+ t_mmc[card_num]->mmc_DataCtrl |= DMAEnab;
+ }
+ }
+
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_writeblocks */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine allows to write blocks starting from a */
+/* specified address in a card */
+/* PARAMETERS : */
+/* IN : u8 cardno: card to access */
+/* u32 addr : address from where to start writing */
+/* u16 blocksize : size of block in bytes */
+/* u16 no_of_blocks: no. of blocks to write */
+/* OUT : u32* writebuff: source buffer */
+/* */
+/* RETURN : t_mmc_error */
+/****************************************************************************/
+
+t_mmc_error mmc_writeblocks(u8 card_num, u32 addr, u32 * writebuff,
+ u16 blocksize, u16 no_of_blocks)
+{
+ t_mmc_error error = MMC_OK;
+ u32 count, rest_words;
+ u8 power, cardstate;
+ u32 timeout = 0;
+ u32 *tempbuff = writebuff;
+ u32 bytes_transferred = 0;
+ u32 card_status;
+
+ if (NULL == writebuff)
+ {
+ error = MMC_INVALID_PARAMETER;
+ return (error);
+ }
+
+ total_no_of_bytes = 0;
+
+ t_mmc[card_num]->mmc_DataCtrl = AllZero;
+
+ /* send command for selecting the card */
+ if ((card_num > no_of_cards) || (card_num == 0))
+ {
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+ if (card_num != selected_card)
+ {
+ t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; //card_array[cardno - 1].RCA << 16;
+ t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num);
+
+ if (error != MMC_OK)
+ return error;
+ else
+ selected_card = card_num;
+ }
+
+ if (t_mmc[card_num]->mmc_Response0 & R1_CARD_IS_LOCKED)
+ return MMC_LOCK_UNLOCK_FAILED;
+
+ /* now depending on parameter no_of_blocks, send command READ_DAT_UNTIL_STOP */
+
+ //set the block size,both on controller and card
+
+ if ((blocksize > 0) && (blocksize <= 2048)
+ && (((blocksize & (blocksize - 1)) == 0)))
+ {
+ power = convert_from_bytes_to_power_of_two(blocksize);
+ t_mmc[card_num]->mmc_DataCtrl = power << 4;
+
+ t_mmc[card_num]->mmc_Argument = (u32) blocksize;
+ t_mmc[card_num]->mmc_Command = SET_BLOCKLEN | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_BLOCKLEN, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ }
+ else
+ {
+ printf(" mmc_writeblocks::bad block size \n");
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+
+ if (no_of_blocks == 0) // this means open-ended block read,until STOP_TRANSMISSION follows
+ {
+ if (device_mode != INTERRUPT_MODE)
+ return MMC_REQUEST_NOT_APPLICABLE;
+
+ t_mmc[card_num]->mmc_DataTimer = 0xefffffff;
+
+ t_mmc[card_num]->mmc_DataLength = (65535 / blocksize) * blocksize;
+
+ total_no_of_bytes = (65535 / blocksize) * blocksize;
+
+ t_mmc[card_num]->mmc_Argument = (65535 / blocksize);
+ t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ source_buffer = writebuff;
+
+ t_mmc[card_num]->mmc_Argument = addr >> 9;
+ t_mmc[card_num]->mmc_Command = WRITE_MULT_BLOCK | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(WRITE_MULT_BLOCK, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc[card_num]->mmc_DataCtrl |= DataPathEnable & ~(ReadDir | StreamMode);
+
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | TxFifoHalfEmpty | TxUnderrun;
+
+ /*Now the card will send data thru DMA to the destination buffer.CRC/TimeOut error will
+ be handled in the interrupt handler*/
+
+ }
+ else if (no_of_blocks == 1)
+ {
+ total_no_of_bytes = blocksize;
+
+ t_mmc[card_num]->mmc_DataLength = blocksize;
+
+ t_mmc[card_num]->mmc_DataTimer = 0xefffffff;
+
+ source_buffer = writebuff;
+
+ /*Wait till card is ready for data Added*/
+ t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; //card_array[cardno - 1].RCA << 16;
+ t_mmc[card_num]->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(SEND_STATUS, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ card_status = t_mmc[card_num]->mmc_Response0;
+ timeout = 0xefffffff;
+
+ while ((0 == (card_status & 0x00000100)) && (timeout > 0))
+ {
+ timeout--;
+ t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA;//0x1 << 16;
+ t_mmc[card_num]->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SEND_STATUS, card_num);
+
+ if (error != MMC_OK)
+ return error;
+ card_status = t_mmc[card_num]->mmc_Response0;
+ }
+ if (timeout == 0)
+ {
+ return (MMC_DATA_TIMEOUT);
+ }
+
+ /*Till here*/
+ /*SEND CMD24 WRITE_SINGLE_BLOCK */
+ t_mmc[card_num]->mmc_Argument = addr >> 9;
+ t_mmc[card_num]->mmc_Command = WRITE_SINGLE_BLOCK | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(WRITE_SINGLE_BLOCK, card_num);
+ if (error != MMC_OK)
+ return error;
+ t_mmc[card_num]->mmc_DataCtrl |= DataPathEnable & ~(ReadDir | StreamMode);
+
+ if (device_mode == POLLING_MODE)
+ {
+
+ while (!(t_mmc[card_num]->mmc_Status & (DataBlockEnd | TxUnderrun | DataCrcFail | DataTimeOut)))
+ {
+
+ if (t_mmc[card_num]-> mmc_Status & TxFifoHalfEmpty)
+ {
+ if ((total_no_of_bytes - bytes_transferred) < 32)
+ {
+ rest_words = ((total_no_of_bytes - bytes_transferred) % 4 == 0) ?
+ ((total_no_of_bytes - bytes_transferred) / 4)
+ : ((total_no_of_bytes - bytes_transferred) / 4 +1);
+
+ for (count = 0; count < rest_words; count++, tempbuff++, bytes_transferred += 4)
+ t_mmc[card_num]-> mmc_Fifo = *tempbuff;
+
+ }
+ else
+ {
+ for (count = 0; count < 8; count++)
+ {
+ t_mmc[card_num]->mmc_Fifo = *(tempbuff + count);
+ }
+ tempbuff += 8;
+ bytes_transferred += 32;
+ }
+ }
+ }
+
+ if ((timeout == 0) || (t_mmc[card_num]->mmc_Status & DataTimeOut))
+ {
+ t_mmc[card_num]->mmc_Clear |= DataTimeOut;
+ transfer_error = error = MMC_DATA_TIMEOUT;
+ printf(" MMC_DATA_TIMEOUT error \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & DataCrcFail)
+ {
+ t_mmc[card_num]->mmc_Clear |= DataCrcFail;
+ transfer_error = error = MMC_DATA_CRC_FAIL;
+ printf(" MMC_DATA_CRC_FAIL error \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & TxUnderrun)
+ {
+ t_mmc[card_num]->mmc_Clear |= TxUnderrun;
+ transfer_error = error = MMC_TX_UNDERRUN;
+ printf(" MMC_TX_UNDERRUN underrun error \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & StartBitError)
+ {
+ t_mmc[card_num]->mmc_Clear |= StartBitError;
+ transfer_error = error = MMC_START_BIT_ERR;
+ printf(" MMC_START_BIT_ERR start bit error \n");
+ return error;
+ }
+ //clear all the static status flags
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags;
+ transfer_error = error;
+
+ error = mmc_iscardprogramming(card_num, &cardstate);
+ while (error == MMC_OK && ((cardstate == 7) || (cardstate == 6)))
+ error = mmc_iscardprogramming(card_num, &cardstate);
+ }
+
+ else if (device_mode == INTERRUPT_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxFifoHalfEmpty | TxUnderrun;
+ }
+ else if (device_mode == DMA_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxUnderrun;
+ t_mmc[card_num]->mmc_DataCtrl |= DMAEnab;
+ }
+
+ }
+ else if (no_of_blocks > 1)
+ {
+ // set the block count,both for the controller and the card
+ if (no_of_blocks * blocksize > 0x01FFFFFF)
+ {
+ error = MMC_INVALID_PARAMETER;
+ return (error);
+ }
+
+ total_no_of_bytes = no_of_blocks * blocksize;
+
+ t_mmc[card_num]->mmc_DataLength = (u32) (no_of_blocks * blocksize);
+
+ t_mmc[card_num]->mmc_Argument = (u32) no_of_blocks;
+ t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc[card_num]->mmc_DataTimer = 0xefffffff;
+
+ source_buffer = writebuff;
+
+ /*SEND CMD25 WRITE_MULT_BLOCK with argument data address*/
+ t_mmc[card_num]->mmc_Argument = addr >> 9;
+ t_mmc[card_num]->mmc_Command = WRITE_MULT_BLOCK | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(WRITE_MULT_BLOCK, card_num);
+
+ if (error != MMC_OK)
+ return error;
+
+ t_mmc[card_num]->mmc_DataCtrl |= DataPathEnable & ~(ReadDir | StreamMode);
+
+ if (device_mode == POLLING_MODE)
+ {
+ timeout = 0xefffffff;
+
+ while ((timeout > 0) && !(t_mmc[card_num]->mmc_Status & (TxUnderrun | DataCrcFail |
+ DataTimeOut | DataEnd | StartBitError)))
+ {
+ timeout--;
+ if (t_mmc[card_num]-> mmc_Status & TxFifoHalfEmpty)
+ {
+ if ((total_no_of_bytes - bytes_transferred) < 32)
+ {
+ rest_words = ((total_no_of_bytes - bytes_transferred) % 4 == 0) ?
+ ((total_no_of_bytes - bytes_transferred) /4)
+ : ((total_no_of_bytes - bytes_transferred) / 4 +1);
+
+ for (count = 0; count < rest_words; count++, tempbuff++,bytes_transferred += 4)
+ t_mmc[card_num]-> mmc_Fifo = *tempbuff;
+
+ }
+ else
+ {
+ for (count = 0; count < 8; count++)
+ {
+ t_mmc[card_num]-> mmc_Fifo = *(tempbuff + count);
+ }
+ tempbuff += 8;
+ bytes_transferred += 32;
+ }
+ }
+
+ }
+
+ if ((timeout == 0) || (t_mmc[card_num]->mmc_Status & DataTimeOut))
+ {
+ t_mmc[card_num]->mmc_Clear |= DataTimeOut;
+ transfer_error = error = MMC_DATA_TIMEOUT;
+ printf(" MMC_DATA_TIMEOUT start bit error \n");
+ return error;
+
+ }
+ else if (t_mmc[card_num]->mmc_Status & DataCrcFail)
+ {
+ t_mmc[card_num]->mmc_Clear |= DataCrcFail;
+ transfer_error = error = MMC_DATA_CRC_FAIL;
+ printf(" MMC_DATA_CRC_FAIL start bit error \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & TxUnderrun)
+ {
+ t_mmc[card_num]->mmc_Clear |= TxUnderrun;
+ transfer_error = error = MMC_TX_UNDERRUN;
+ printf(" MMC_TX_UNDERRUN start bit error \n");
+ return error;
+ }
+ else if (t_mmc[card_num]->mmc_Status & StartBitError)
+ {
+ t_mmc[card_num]->mmc_Clear |= StartBitError;
+ transfer_error = error = MMC_START_BIT_ERR;
+ printf(" MMC_START_BIT_ERR start bit error \n");
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+ transfer_error = error;
+ error = mmc_iscardprogramming(card_num, &cardstate);
+ while ((MMC_OK == error) && ((cardstate == 7) || (cardstate == 6)))
+ error = mmc_iscardprogramming(card_num, &cardstate);
+ }
+ else if (device_mode == INTERRUPT_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd |TxFifoHalfEmpty | TxUnderrun;
+ }
+ else if (device_mode == DMA_MODE)
+ {
+ t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxUnderrun;
+ t_mmc[card_num]->mmc_DataCtrl |= DMAEnab;
+ }
+
+ }
+
+ return error;
+}
+
+/****************************************************************************/
+/* NAME : mmc_gettransferstate() */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine */
+/* PARAMETERS : */
+/* */
+/* RETURN : t_mmc_transfer_state */
+/****************************************************************************/
+
+t_mmc_transfer_state mmc_gettransferstate()
+{
+ if (t_mmc0->mmc_Status & (TxActive | RxActive))
+ return TRANSFER_IN_PROGRESS;
+ else
+ return NO_TRANSFER;
+}
+
+/****************************************************************************/
+/* NAME : mmc_erase */
+/*--------------------------------------------------------------------------*/
+/* DESCRIPTION: This routine allows to erase memory area specified for the */
+/* given card. */
+/* PARAMETERS : */
+/* IN : u8 Cardno. to access */
+/* u32 start address for erase. */
+/* u32 Last address for erase. */
+/* OUT : */
+/* */
+/* RETURN : t_mmc_error */
+
+/****************************************************************************/
+
+t_mmc_error mmc_erase(u8 card_num, u32 StartAddr, u32 EndAddr)
+{
+ t_mmc_error error;
+ u32 response;
+ u8 cardstate;
+ u32 delay, max_delay;
+
+ if ((card_num > no_of_cards) || (card_num == 0))
+ {
+ printf("mmc_erase:: card no=%d no_of_cards=%d failed \n",card_num, no_of_cards);
+ error = MMC_INVALID_PARAMETER;
+ return error;
+ }
+ max_delay = 52000 / ((t_mmc[card_num]->mmc_Clock & 0xFF) + 2);
+
+ /* send command for selecting the card */
+
+ if (card_num != selected_card)
+ {
+ t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; //card_array[cardno - 1].RCA << 16;
+ t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num);
+ if (error != MMC_OK)
+ return error;
+ else
+ selected_card = card_num;
+ }
+
+ if (t_mmc[card_num]->mmc_Response0 & R1_CARD_IS_LOCKED)
+ {
+ error = MMC_LOCK_UNLOCK_FAILED;
+ return (error);
+ }
+
+ t_mmc[card_num]->mmc_Argument = StartAddr >> 9;
+ t_mmc[card_num]->mmc_Command = ERASE_GRP_START | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(ERASE_GRP_START, card_num);
+ if (error != MMC_OK)
+ {
+ printf("mmc_erase:: erase start CMD35 failed \n");
+ return error;
+ }
+ response = t_mmc[card_num]->mmc_Response0;
+
+ if (response & (R1_OUT_OF_RANGE | R1_ERASE_PARAM))
+ {
+ printf("mmc_erase:: erase start CMD35 R1_OUT_OF_RANGE \n");
+ error = MMC_BAD_ERASE_PARAM;
+ return error;
+ }
+
+ if (response & R1_ERASE_SEQ_ERROR)
+ {
+ printf("mmc_erase:: erase start CMD35 R1_ERASE_SEQ_ERROR \n");
+ error = MMC_ERASE_SEQ_ERR;
+ return error;
+ }
+
+ if (response & (R1_CARD_IS_LOCKED | R1_LOCK_UNLOCK_FAILED))
+ {
+ printf("mmc_erase:: erase start CMD35 R1_CARD_IS_LOCKED \n");
+ error = MMC_LOCK_UNLOCK_FAILED;
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Argument = EndAddr >> 9;
+ t_mmc[card_num]->mmc_Command = ERASE_GRP_END | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(ERASE_GRP_END, card_num);
+ if (error != MMC_OK)
+ {
+ printf("mmc_erase:: erase end CMD36 failed \n");
+ return error;
+ }
+ response = t_mmc[card_num]->mmc_Response0;
+
+ if (response & (R1_OUT_OF_RANGE | R1_ERASE_PARAM))
+ {
+ printf("mmc_erase:: erase end R1_OUT_OF_RANGE \n");
+ error = MMC_BAD_ERASE_PARAM;
+ return error;
+ }
+
+ if (response & R1_ERASE_SEQ_ERROR)
+ {
+ printf("mmc_erase:: erase end R1_ERASE_SEQ_ERROR \n");
+ error = MMC_ERASE_SEQ_ERR;
+ return error;
+ }
+
+ if (response & (R1_CARD_IS_LOCKED | R1_LOCK_UNLOCK_FAILED))
+ {
+ printf("mmc_erase:: erase end R1_CARD_IS_LOCKED\n");
+ error = MMC_LOCK_UNLOCK_FAILED;
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Argument = 0;
+ t_mmc[card_num]->mmc_Command = ERASE | RespExpected | CmdPathEnable;
+ error = mmc_cmdresp145error(ERASE, card_num);
+ if (error != MMC_OK)
+ {
+ printf("mmc_erase:: erase CMD38 failed \n");
+ return error;
+ }
+ response = t_mmc[card_num]->mmc_Response0;
+ if (response & R1_ERASE_SEQ_ERROR)
+ {
+ printf("mmc_erase:: erase R1_ERASE_SEQ_ERROR \n");
+ error = MMC_ERASE_SEQ_ERR;
+ return error;
+ }
+
+ if (response & (R1_CARD_IS_LOCKED | R1_LOCK_UNLOCK_FAILED))
+ {
+ printf("mmc_erase:: erase R1_CARD_IS_LOCKED \n");
+ error = MMC_LOCK_UNLOCK_FAILED;
+ return error;
+ }
+
+ if (response & R1_WP_ERASE_SKIP)
+ {
+ printf("mmc_erase:: erase R1_WP_ERASE_SKIP \n");
+ error = MMC_WRITE_PROT_VIOLATION;
+ return error;
+ }
+ for (delay = 0; delay < (max_delay * 3); delay++) ;
+
+ mmc_iscardprogramming(card_num, &cardstate);
+ while ((MMC_OK == error) && ((cardstate == 7) || (cardstate == 6)))
+ mmc_iscardprogramming(card_num, &cardstate);
+
+ error = MMC_OK;
+ return error;
+}
+
+t_mmc_error mmc_cmderror(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 timeout;
+
+ timeout = 100000;
+ while ((timeout > 0) && !(t_mmc[card_num]->mmc_Status & CmdSent))
+ timeout--;
+
+ if (timeout == 0) {
+ error = MMC_CMD_RSP_TIMEOUT;
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static flags
+
+ return error;
+}
+
+t_mmc_error mmc_cmdresp145error(u8 cmd, u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 100000;
+ status = t_mmc[card_num]->mmc_Status;
+ while ((timeout > 0) && !(status & (CmdCrcFail | CmdRespEnd | CmdTimeOut)))
+ {
+ timeout--;
+ status = t_mmc[card_num]->mmc_Status;
+ }
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc[card_num]->mmc_Clear |= CmdTimeOut;
+ return error;
+ }
+ else if (status & CmdCrcFail)
+ {
+ error = MMC_CMD_CRC_FAIL;
+ t_mmc[card_num]->mmc_Clear |= CmdCrcFail;
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags; /*Clear Static flags */
+ if (t_mmc[card_num]->mmc_RespCommand != cmd)
+ {
+ /* check response received for CMD7*/
+ error = MMC_ILLEGAL_CMD;
+ return error;
+ }
+ return error;
+}
+
+t_mmc_error mmc_cmdresp2error(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 100000;
+ status = t_mmc[card_num]->mmc_Status;
+ while ((timeout > 0) && !(status & (CmdCrcFail | CmdTimeOut | CmdRespEnd)))
+ {
+ timeout--;
+ status = t_mmc[card_num]->mmc_Status;
+ }
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc[card_num]->mmc_Clear |= CmdTimeOut;
+ return error;
+ }
+ else if (status & CmdCrcFail)
+ {
+ error = MMC_CMD_CRC_FAIL;
+ t_mmc[card_num]->mmc_Clear |= CmdCrcFail;
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags; /*Clear Static flags */
+
+ return error;
+}
+
+t_mmc_error mmc_cmdresp3error(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 0x100000;
+ status = t_mmc[card_num]->mmc_Status;
+ while ((timeout > 0) && !(status & (CmdRespEnd | CmdTimeOut | CmdCrcFail)))
+ {
+ timeout--;
+ status = t_mmc[card_num]->mmc_Status;
+ }
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc[card_num]->mmc_Clear |= CmdTimeOut;
+ return error;
+ }
+
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags;
+ return error;
+}
+
+t_mmc_error mmc_cmdresp6error(u8 cmd, u16 * p_rca, u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status;
+ u32 response_r1;
+
+ status = t_mmc[card_num]->mmc_Status;
+ while (!(status & (CmdRespEnd | CmdTimeOut | CmdCrcFail)))
+ {
+ status = t_mmc[card_num]->mmc_Status;
+ }
+
+ if (status & CmdTimeOut)
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc[card_num]->mmc_Clear |= CmdTimeOut;
+ return (error);
+ }
+ else if (status & CmdCrcFail)
+ {
+ error = MMC_CMD_CRC_FAIL;
+ t_mmc[card_num]->mmc_Clear |= CmdCrcFail;
+ return (error);
+ }
+
+ /* CHECK RESPONSE RECEIVED IS OF DESIRED COMMAND */
+ if (t_mmc[card_num]->mmc_RespCommand != cmd)
+ {
+ error = MMC_ILLEGAL_CMD;
+ return (error);
+ }
+
+ /*Clear Static flags*/
+ t_mmc[card_num]->mmc_Clear = ClrStaticFlags;
+
+ /* WE HAVE RECEIVED RESPONSE, RETRIEVE IT. */
+ response_r1 = t_mmc[card_num]->mmc_Response0;
+
+ if (AllZero == (response_r1 & (R6_GEN_UNKNOWN_ERROR | R6_ILLEGAL_CMD | R6_COM_CRC_FAILED)))
+ {
+ *p_rca = (u16) (response_r1 >> 16);
+ return (error);
+ }
+
+ if (response_r1 & R6_GEN_UNKNOWN_ERROR)
+ {
+ return (MMC_GENERAL_UNKNOWN_ERROR);
+ }
+
+ if (response_r1 & R6_ILLEGAL_CMD)
+ {
+ return (MMC_ILLEGAL_CMD);
+ }
+
+ if (response_r1 & R6_COM_CRC_FAILED)
+ {
+ return (MMC_COM_CRC_FAILED);
+ }
+
+ return (error);
+}
+
+t_mmc_error mmc_cmdresp7error(u8 card_num)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status;
+ u32 timeout = 10000;
+
+ status = t_mmc[card_num]->mmc_Status;
+ while (!(status & (CmdCrcFail | CmdRespEnd | CmdTimeOut)) && (timeout > 0))
+ {
+ timeout--;
+ status = t_mmc[card_num]->mmc_Status;
+ }
+
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ /* Card is not V2.0 complient or card does not support the set voltage range */
+ error = MMC_CMD_RSP_TIMEOUT;
+ return (error);
+ }
+
+ if (status & CmdRespEnd)
+ {
+ /* Card is V2.0 complient */
+ error = MMC_OK;
+ return (error);
+ }
+
+ return (error);
+}
+
+t_mmc_error mmc_iscardprogramming(u8 card_num, u8 * status)
+{
+ t_mmc_error error;
+ u32 response;
+
+ t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA;//0x1 << 16; //RCA
+ t_mmc[card_num]->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(SEND_STATUS, card_num);
+ if (error != MMC_OK)
+ return error;
+
+ response = t_mmc[card_num]->mmc_Response0;
+ *status = (response >> 9) & 0x0000000f;
+
+ return error;
+
+}
+
+t_mmc_error mmc_sendstatus(u8 cardno, u32 * status)
+{
+ t_mmc_error error = MMC_OK;
+
+ t_mmc0->mmc_Argument = card_array[cardno].RCA;//card_array[cardno - 1].RCA << 16; //RCA
+ t_mmc0->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable;
+
+ error = mmc_cmdresp145error(SEND_STATUS, cardno);
+ if (error != MMC_OK)
+ return error;
+
+ *status = t_mmc0->mmc_Response0;
+
+ return error;
+}
+
+t_mmc_error mmc_cmderror_2(void)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 0xefffffff;
+ status = t_mmc0->mmc_Status;
+ while ((timeout > 0) && !(status & (CmdSent| CmdCrcFail | CmdTimeOut | CmdRespEnd)))
+ {
+ timeout--;
+ status = t_mmc0->mmc_Status;
+ }
+
+ if (timeout == 0)
+ {
+ printf(" cmd1 timeout error\n");
+ error = MMC_CMD_RSP_TIMEOUT;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static flags
+
+ return error;
+}
+
+t_mmc_error mmc_cmdresp2error_2(void)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 0xefffffff; //(u32)((float)(64/(float)clockfreq )/ ((float)(1/(float)MCLK) + 8*(float)(1/(float)PROCESSOR_CLK)));
+ status = t_mmc0->mmc_Status;
+
+ while ((timeout > 0) && !(status & (CmdCrcFail | CmdTimeOut | CmdRespEnd)))
+ {
+ timeout--;
+ status = t_mmc0->mmc_Status;
+ }
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc0->mmc_Clear |= CmdTimeOut;
+ return error;
+ }
+ if (status & CmdCrcFail)
+ {
+ error = MMC_CMD_CRC_FAIL;
+ t_mmc0->mmc_Clear |= CmdCrcFail;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; /*Clear Static flags */
+
+ return error;
+}
+
+t_mmc_error mmc_cmdresp3error_2(void)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 0xefffffff;
+ status = t_mmc0->mmc_Status;
+
+ while ((timeout > 0) && !(status & (CmdRespEnd | CmdTimeOut | CmdCrcFail)))
+ {
+ timeout--;
+ status = t_mmc0->mmc_Status;
+ }
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc0->mmc_Clear |= CmdTimeOut;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags;
+
+ return error;
+}
+
+t_mmc_error mmc_cmdresp145error_2(u8 cmd)
+{
+ t_mmc_error error = MMC_OK;
+ u32 status, timeout;
+
+ timeout = 0xefffffff;
+ status = t_mmc0->mmc_Status;
+
+ while ((timeout > 0) && !(status & (CmdCrcFail | CmdRespEnd | CmdTimeOut)))
+ {
+ timeout--;
+ status = t_mmc0->mmc_Status;
+ }
+ if ((timeout == 0) || (status & CmdTimeOut))
+ {
+ error = MMC_CMD_RSP_TIMEOUT;
+ t_mmc0->mmc_Clear |= CmdTimeOut;
+ return error;
+ }
+ else if (status & CmdCrcFail)
+ {
+ error = MMC_CMD_CRC_FAIL;
+ t_mmc0->mmc_Clear |= CmdCrcFail;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; /*Clear Static flags */
+ if (t_mmc0->mmc_RespCommand != cmd)
+ {
+ /* check response received for CMD7*/
+ error = MMC_ILLEGAL_CMD;
+ return error;
+ }
+
+ return error;
+}
+
+t_mmc_error mmc_cmdreadresp(u32 * tempbuff)
+{
+ t_mmc_error error = MMC_OK;
+ u32 i;
+ u32 timeout = 0;
+
+ timeout = 0xefffffff;
+
+ while ((timeout > 0) && !(t_mmc0-> mmc_Status & (RxOverrun | DataCrcFail | DataTimeOut |DataBlockEnd)))
+ {
+ timeout--;
+ if (t_mmc0->mmc_Status & RxFifoHalfFull)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ *(tempbuff + i) = t_mmc0->mmc_Fifo;
+ }
+ tempbuff += 8;
+ }
+ }
+ if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut))
+ {
+ t_mmc0->mmc_Clear |= DataTimeOut;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & DataCrcFail)
+ {
+ t_mmc0->mmc_Clear |= DataCrcFail;
+ error = MMC_DATA_CRC_FAIL;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & RxOverrun)
+ {
+ t_mmc0->mmc_Clear |= RxOverrun;
+ error = MMC_RX_OVERRUN;
+ return error;
+ }
+
+ while (t_mmc0->mmc_Status & RxDataAvlbl)
+ {
+ *tempbuff = t_mmc0->mmc_Fifo;
+ tempbuff++;
+ }
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+
+ return error;
+}
+
+t_mmc_error mmc_waitcmdreadresp(void)
+{
+ t_mmc_error error = MMC_OK;
+ u32 timeout = 0;
+
+ timeout = 0xefffffff;
+
+ while (!(t_mmc0->mmc_Status & (RxOverrun | DataCrcFail | DataTimeOut | DataBlockEnd)))
+ {
+
+ }
+
+ if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut))
+ {
+ t_mmc0->mmc_Clear |= DataTimeOut;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & DataCrcFail)
+ {
+ t_mmc0->mmc_Clear |= DataCrcFail;
+ error = MMC_DATA_CRC_FAIL;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & RxOverrun)
+ {
+ t_mmc0->mmc_Clear |= RxOverrun;
+ error = MMC_RX_OVERRUN;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+
+ return error;
+}
+
+t_mmc_error mmc_iscardprogramming_2(u8 * status)
+{
+ t_mmc_error error;
+ u32 response;
+ t_mmc_command_control commcontrol;
+
+ commcontrol.IsRespExpected = TRUE;
+ commcontrol.IsLongResp = FALSE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_sendcommand(MMC_SEND_STATUS, t_mmc_rel_addr, commcontrol);
+ error = mmc_cmdresp145error_2(MMC_SEND_STATUS);
+
+ if (error != MMC_OK)
+ return error;
+
+ response = t_mmc0->mmc_Response0;
+ *status = (response >> 9) & 0x0000000f;
+
+ return error;
+}
+
+t_mmc_error mmc_cmdwriteresp(u8 cardno, u32 * tempbuff, u16 total_num_of_bytes)
+{
+ u32 timeout = 0;
+ t_mmc_error error = MMC_OK;
+ u32 bytes_transferred = 0;
+ u32 i, j;
+ u8 cardstate;
+
+ timeout = 0xefffffff;
+
+ while ((timeout > 0) && !(t_mmc0-> mmc_Status & (DataBlockEnd | TxUnderrun | DataCrcFail | DataTimeOut)))
+ {
+ timeout--;
+ if (t_mmc0->mmc_Status & TxFifoHalfEmpty)
+ {
+ if ((total_num_of_bytes - bytes_transferred) < 32)
+ {
+ j = ((total_num_of_bytes - bytes_transferred) % 4 ==0) ?
+ ((total_num_of_bytes - bytes_transferred) / 4) :
+ ((total_num_of_bytes - bytes_transferred) / 4 + 1);
+
+ for (i = 0; i < j; i++, tempbuff++, bytes_transferred += 4)
+ t_mmc0->mmc_Fifo = *tempbuff;
+ }
+ else
+ {
+ for (i = 0; i < 8; i++)
+ t_mmc0->mmc_Fifo = *(tempbuff + i);
+ tempbuff += 8;
+ bytes_transferred += 32;
+ }
+ }
+ }
+
+ if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut))
+ {
+ t_mmc0->mmc_Clear |= DataTimeOut;
+ error = MMC_DATA_TIMEOUT;
+ printf(" mmc_cmdwriteresp timeout error \n");
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & DataCrcFail)
+ {
+ t_mmc0->mmc_Clear |= DataCrcFail;
+ error = MMC_DATA_CRC_FAIL;
+ printf(" mmc_cmdwriteresp CRC error \n");
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & TxUnderrun)
+ {
+ t_mmc0->mmc_Clear |= TxUnderrun;
+ error = MMC_TX_UNDERRUN;
+ printf(" mmc_cmdwriteresp underrun error \n");
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+
+ error = mmc_iscardprogramming_2(&cardstate);
+ while (error == MMC_OK && cardstate == 7)
+ error = mmc_iscardprogramming_2(&cardstate);
+
+ return error;
+}
+
+t_mmc_error mmc_waitcmdwriteresp(u8 cardno, u32 * tempbuff, u16 total_num_of_bytes)
+{
+ u32 timeout = 0;
+ t_mmc_error error = MMC_OK;
+ u8 cardstate;
+
+ timeout = 0xefffffff;
+
+ while ((timeout > 0) && !(t_mmc0-> mmc_Status & (DataBlockEnd | TxUnderrun | DataCrcFail | DataTimeOut)))
+ {
+
+ }
+
+ if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut))
+ {
+ t_mmc0->mmc_Clear |= DataTimeOut;
+ error = MMC_DATA_TIMEOUT;
+ return error;
+
+ }
+ else if (t_mmc0->mmc_Status & DataCrcFail)
+ {
+ t_mmc0->mmc_Clear |= DataCrcFail;
+ error = MMC_DATA_CRC_FAIL;
+ return error;
+ }
+ else if (t_mmc0->mmc_Status & TxUnderrun)
+ {
+ t_mmc0->mmc_Clear |= TxUnderrun;
+ error = MMC_TX_UNDERRUN;
+ return error;
+ }
+
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags
+
+ error = mmc_iscardprogramming_2(&cardstate);
+ while (error == MMC_OK && cardstate == 7)
+ error = mmc_iscardprogramming_2(&cardstate);
+
+ return error;
+}
diff --git a/board/st/u8500/mmc.h b/board/st/u8500/mmc.h
new file mode 100755
index 000000000..c114ffab8
--- /dev/null
+++ b/board/st/u8500/mmc.h
@@ -0,0 +1,263 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _MMC_H_
+#define _MMC_H_
+
+#include <common.h>
+#include "asm-arm/arch-stw8500/mmc.h"
+
+/*---------------------------------------------------------------------------
+ * Enums
+ *---------------------------------------------------------------------------*/
+
+extern char *mmc_error_name[];
+
+#define t_mmc_irq_src u32
+
+typedef enum {
+ MMC_CMD_CRC_FAIL_INT = 0x00000001,
+ MMC_DATA_CRC_FAIL_INT = 0x00000002,
+ MMC_CMD_TIMEOUT_INT = 0x00000004,
+ MMC_DATA_TIMEOUT_INT = 0x00000008,
+ MMC_TX_UNDERRUN_INT = 0x00000010,
+ MMC_RX_OVERRUN_INT = 0x00000020,
+ MMC_CMD_RESP_OK_INT = 0x00000040,
+ MMC_CMD_SENT_INT = 0x00000080,
+ MMC_DATA_END_INT = 0x00000100,
+ MMC_DATA_BLOCK_OK_INT = 0x00000400,
+ MMC_CMD_ACTIVE_INT = 0x00000800,
+ MMC_TX_ACTIVE_INT = 0x00001000,
+ MMC_RX_ACTIVE_INT = 0x00002000,
+ MMC_TX_FIFO_HALF_EMPTY_INT = 0x00004000,
+ MMC_RX_FIFO_HALF_FULL_INT = 0x00008000,
+ MMC_TX_FIFO_FULL_INT = 0x00010000,
+ MMC_RX_FIFO_FULL_INT = 0x00020000,
+ MMC_TX_FIFO_EMPTY_INT = 0x00040000,
+ MMC_RX_FIFO_EMPTY_INT = 0x00080000,
+ MMC_TX_DATA_AVLBL_INT = 0x00100000,
+ MMC_RX_DATA_AVLBL_INT = 0x00200000,
+ MMC_ALL_STATIC_IT = 0x000005FF,
+ MMC_ALL_IT = 0x003FFDFF
+
+} t_mmc_interrupt;
+
+typedef enum {
+ MMC_DISABLE = 0,
+ MMC_ENABLE
+} t_mmc_state;
+
+
+typedef enum {
+ MMC_POWER_OFF = 0x0,
+ MMC_POWER_UP = 0x2,
+ MMC_POWER_ON = 0x3
+} t_mmc_power_state;
+
+typedef enum {
+ MMC_PUSH_PULL = 0,
+ MMC_OPEN_DRAIN
+} t_mmc_bus_mode;
+
+typedef enum {
+ MMC_GO_IDLE_STATE = 0,
+ MMC_SEND_OP_COND = 1,
+ MMC_ALL_SEND_CID = 2,
+ MMC_SET_REL_ADDR = 3,
+ MMC_SET_DSR = 4,
+ MMC_SEL_DESEL_CARD = 7,
+ MMC_SEND_CSD = 9,
+ MMC_SEND_CID = 10,
+ MMC_READ_DAT_UNTIL_STOP = 11,
+ MMC_STOP_TRANSMISSION = 12,
+ MMC_SEND_STATUS = 13,
+ MMC_GO_INACTIVE_STATE = 15,
+ MMC_SET_BLOCKLEN = 16,
+ MMC_READ_SINGLE_BLOCK = 17,
+ MMC_READ_MULT_BLOCK = 18,
+ MMC_WRITE_DAT_UNTIL_STOP = 20,
+ MMC_SET_BLOCK_COUNT = 23,
+ MMC_WRITE_SINGLE_BLOCK = 24,
+ MMC_WRITE_MULT_BLOCK = 25,
+ MMC_PROG_CID = 26,
+ MMC_PROG_CSD = 27,
+ MMC_SET_WRITE_PROT = 28,
+ MMC_CLR_WRITE_PROT = 29,
+ MMC_SEND_WRITE_PROT = 30,
+ MMC_ERASE_GRP_START = 35,
+ MMC_ERASE_GRP_END = 36,
+ MMC_ERASE = 38,
+ MMC_FAST_IO = 39,
+ MMC_GO_IRQ_STATE = 40,
+ SD_SEND_OP_COND = 41,
+ MMC_LOCK_UNLOCK = 42,
+ MMC_APP_CMD = 55,
+ MMC_GEN_CMD = 56,
+ MMC_NO_CMD = 64
+} t_mmc_command_index;
+
+typedef enum {
+ MMC_SHORT_RESP = 0,
+ MMC_LONG_RESP
+} t_mmc_response_type;
+
+
+typedef enum {
+ MMC_WRITE= 0,
+ MMC_READ
+} t_mmc_transfer_direction;
+
+typedef enum {
+ MMC_BLOCK = 0,
+ MMC_STREAM
+} t_mmc_transfer_type;
+
+typedef enum {
+ POLLING_MODE = 0,
+ INTERRUPT_MODE,
+ DMA_MODE
+} t_mmc_device_mode;
+
+/*---------------------------------------------------------------------------
+ * Structures
+ *---------------------------------------------------------------------------*/
+
+typedef struct {
+ t_mmc_bus_mode mode;
+ t_mmc_state rodctrl;
+} t_mmc_bus_configuration;
+
+typedef struct {
+ t_mmc_state pwrsave;
+ t_mmc_state bypass;
+ t_mmc_state widebus;
+} t_mmc_clock_control;
+
+typedef struct {
+ t_bool IsRespExpected;
+ t_bool IsLongResp;
+ t_bool IsInterruptMode;
+ t_bool IsPending;
+ t_mmc_state cmdpath;
+} t_mmc_command_control;
+
+
+#define t_mmc_event u32
+
+#define t_mmc_filter_mode u32
+#define NO_FILTER_MODE 0
+
+typedef enum
+{
+ MMC_NEW = 0,
+ MMC_OLD
+} t_mmc_irq_status_usage;
+
+typedef struct
+{
+ t_mmc_irq_status_usage usage;
+ u32 IRQStatus;
+ u32 EventStatus;
+} t_mmc_irq_status;
+
+typedef enum {
+
+ MMC_MULTIMEDIA_CARD,
+ MMC_SECURE_DIGITAL_CARD,
+ MMC_SECURE_DIGITAL_IO_CARD,
+ MMC_HIGH_SPEED_MULTIMEDIA_CARD,
+ MMC_SECURE_DIGITAL_IO_COMBO_CARD
+
+} t_mmc_card_type;
+
+typedef struct {
+ u32 CID[4];
+ u32 CSD[4];
+ u16 RCA;
+ t_mmc_card_type card_type;
+ u8 padding;
+ u8 sdio_cccr[4]; /* I/O ready, CCCR/SDIO revision, SD Specification revision, and Card Capability registers */
+} t_mmc_card_info;
+
+typedef struct {
+ t_mmc_error error;
+ u16 transferred_bytes;
+} t_mmc_last_transfer_info;
+
+typedef enum {
+ NO_TRANSFER = 0,
+ TRANSFER_IN_PROGRESS
+} t_mmc_transfer_state;
+
+typedef enum {
+ WRITE_PROT_WHOLE_CARD_TEMP = 0,
+ WRITE_PROT_WHOLE_CARD_PERM,
+ WRITE_PROT_SINGLE_GROUP
+} t_mmc_write_protect_type;
+
+/*---------------------------------------------------------------------------
+ * Functions Prototype
+ *---------------------------------------------------------------------------*/
+
+
+t_mmc_error mmc_init (u8,t_logical_address) ;
+
+t_mmc_error mmc_setpowerstate(t_mmc_power_state);
+t_mmc_power_state mmc_getpowerstate(void);
+t_mmc_error mmc_setoperatingvoltage(u8);
+u8 mmc_getoperatingvoltage (void);
+t_mmc_error mmc_configbus(t_mmc_bus_configuration);
+
+t_mmc_error mmc_setclock(t_mmc_state);
+t_mmc_error mmc_configclockcontrol(t_mmc_clock_control);
+t_mmc_error mmc_setclockfrequency(u8);
+t_mmc_error mmc_sendcommand(t_mmc_command_index, u32,t_mmc_command_control) ;
+t_mmc_command_index mmc_getcommandresponse(void) ;
+t_mmc_error mmc_getresponse(t_mmc_response_type, u32*) ;
+t_mmc_error mmc_setdatapath(t_mmc_state);
+t_mmc_error mmc_setdatatimeout(u32);
+t_mmc_error mmc_setdatalength(u16);
+t_mmc_error mmc_setdatablocklength(u8);
+t_mmc_error mmc_settransferdirection(t_mmc_transfer_direction) ;
+t_mmc_error mmc_settransfertype(t_mmc_transfer_type);
+t_mmc_error mmc_handledma(t_mmc_state);
+u16 mmc_getdatacounter(void);
+
+t_mmc_error mmc_selectsdcard(u8);
+t_mmc_error mmc_poweron(u8) ;
+t_mmc_error mmc_poweroff(u8);
+t_mmc_error mmc_initializeCards(u8);
+t_mmc_error mmc_getcardinfo(u8, t_mmc_card_info *) ;
+t_mmc_error mmc_setdevicemode(t_mmc_device_mode);
+t_mmc_error mmc_readbytes(u8, u32, u32*, u16) ;
+t_mmc_error mmc_readblocks(u8, u32, u32*, u16, u16) ;
+t_mmc_error mmc_writebytes(u8, u32, u32* , u16) ;
+t_mmc_error mmc_writeblocks(u8, u32, u32*, u16, u16) ;
+t_mmc_transfer_state mmc_gettransferstate(void);
+t_mmc_error mmc_erase(u8, u32, u32) ;
+
+u8 convert_from_bytes_to_power_of_two (u16 no_of_bytes);
+
+/*New Interrupt strategy(M1 functions)*/
+void mmc_acknowledgementevent(t_mmc_event *);
+
+#endif /* _MMC_H_ */
diff --git a/board/st/u8500/mmc_p.h b/board/st/u8500/mmc_p.h
new file mode 100755
index 000000000..26b4b7795
--- /dev/null
+++ b/board/st/u8500/mmc_p.h
@@ -0,0 +1,316 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _MMC_P_H_
+#define _MMC_P_H_
+
+#define BIT31 0x80000000
+#define PROCESSOR_CLK 200000000
+#define MAXBSIZEPOWER 11
+
+#define MCLK 26000000
+
+#define MMC_PERIPHERAL_ID0 0x81
+#define MMC_PERIPHERAL_ID1 0x11
+#define MMC_PERIPHERAL_ID2 0x04
+#define MMC_PERIPHERAL_ID3 0x00
+
+
+#define MMC_PCELL_ID0 0x0D
+#define MMC_PCELL_ID1 0xF0
+#define MMC_PCELL_ID2 0x05
+#define MMC_PCELL_ID3 0xB1
+
+
+typedef volatile struct {
+ u32 mmc_Power; // 0x00
+ u32 mmc_Clock; // 0x04
+ u32 mmc_Argument; // 0x08
+ u32 mmc_Command; // 0x0c
+ u32 mmc_RespCommand; // 0x10
+ u32 mmc_Response0; // 0x14
+ u32 mmc_Response1; // 0x18
+ u32 mmc_Response2; // 0x1c
+ u32 mmc_Response3; // 0x20
+ u32 mmc_DataTimer; // 0x24
+ u32 mmc_DataLength; // 0x28
+ u32 mmc_DataCtrl; // 0x2c
+ u32 mmc_DataCnt; // 0x30
+ u32 mmc_Status; // 0x34
+ u32 mmc_Clear; // 0x38
+ u32 mmc_Mask0; // 0x3c
+ u32 mmc_Mask1; // 0x40
+ u32 mmc_SelectSD; // 0x44
+ u32 mmc_FifoCnt; // 0x48
+ u32 mmc_unused1[(0x80-0x4C)>>2];
+ u32 mmc_Fifo; // 0x80
+ u32 mmc_unused2[(0xFE0-0x84)>>2];
+ u32 mmc_PeriphId0; // 0xFE0 mmc Peripheral Identi.cation Register
+ u32 mmc_PeriphId1; // 0xFE4
+ u32 mmc_PeriphId2; // 0xFE8
+ u32 mmc_PeriphId3; // 0xFEC
+
+ u32 mmc_PCellId0; // 0xFF0 mmc PCell Identi.cation Register
+ u32 mmc_PCellId1; // 0xFF4
+ u32 mmc_PCellId2; // 0xFF8
+ u32 mmc_PCellId3; // 0xFFc
+}t_mmc_register;
+
+
+// Elementary layer
+#define BIT_MASK(__bws) ((u32)(((wb ## __bws)==32)?0xFFFFFFFF:\
+ ((1U << (wb ## __bws)) - 1)) << (sb ## __bws))
+
+#define MMC_WRITE_BITS(reg,val,mask,sb) ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask))))
+#define MMC_READ_BITS(reg,mask,sb) ((reg & mask)>>sb)
+
+#define wbMMC_Power_CTRL 2
+#define sbMMC_Power_CTRL 0
+#define MMC_Power_MASK_CTRL BIT_MASK(MMC_Power_CTRL)
+
+#define wbMMC_Power_VOLT 4
+#define sbMMC_Power_VOLT 2
+#define MMC_Power_MASK_VOLT BIT_MASK(MMC_Power_VOLT)
+
+#define wbMMC_Power_OPEND 1
+#define sbMMC_Power_OPEND 6
+#define MMC_Power_MASK_OPEND BIT_MASK(MMC_Power_OPEND)
+
+#define wbMMC_Power_ROD 1
+#define sbMMC_Power_ROD 7
+#define MMC_Power_MASK_ROD BIT_MASK(MMC_Power_ROD)
+
+#define wbMMC_Clock_CLKDIV 8
+#define sbMMC_Clock_CLKDIV 0
+#define MMC_Clock_MASK_CLKDIV BIT_MASK(MMC_Clock_CLKDIV)
+
+#define wbMMC_Clock_ENABLE 1
+#define sbMMC_Clock_ENABLE 8
+#define MMC_Clock_MASK_ENABLE BIT_MASK(MMC_Clock_ENABLE)
+
+#define wbMMC_Clock_PWRSAVE 1
+#define sbMMC_Clock_PWRSAVE 9
+#define MMC_Clock_MASK_PWRSAVE BIT_MASK(MMC_Clock_PWRSAVE)
+
+#define wbMMC_Clock_BYPASS 1
+#define sbMMC_Clock_BYPASS 10
+#define MMC_Clock_MASK_BYPASS BIT_MASK(MMC_Clock_BYPASS)
+
+#define wbMMC_Clock_WIDEBUS 1
+#define sbMMC_Clock_WIDEBUS 11
+#define MMC_Clock_MASK_WIDEBUS BIT_MASK(MMC_Clock_WIDEBUS)
+#define MMC_SET_WIDEBUS(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_WIDEBUS,sbMMC_Clock_WIDEBUS)
+
+#define wbMMC_DataPath_ENABLE 1
+#define sbMMC_DataPath_ENABLE 0
+#define MMC_DataPath_MASK_ENABLE BIT_MASK(MMC_DataPath_ENABLE)
+
+#define wbMMC_DataPath_BLOCKSIZE 4
+#define sbMMC_DataPath_BLOCKSIZE 4
+#define MMC_DataPath_MASK_BLOCKSIZE BIT_MASK(MMC_DataPath_BLOCKSIZE)
+
+#define wbMMC_DataPath_DIRECTION 1
+#define sbMMC_DataPath_DIRECTION 1
+#define MMC_DataPath_MASK_DIRECTION BIT_MASK(MMC_DataPath_DIRECTION)
+
+#define wbMMC_DataPath_MODE 1
+#define sbMMC_DataPath_MODE 2
+#define MMC_DataPath_MASK_MODE BIT_MASK(MMC_DataPath_MODE)
+
+#define wbMMC_DataPath_DMA 1
+#define sbMMC_DataPath_DMA 3
+#define MMC_DataPath_MASK_DMA BIT_MASK(MMC_DataPath_DMA)
+
+#define MMC_SET_CTRL(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_CTRL,sbMMC_Power_CTRL)
+#define MMC_SET_VOLT(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_VOLT,sbMMC_Power_VOLT)
+#define MMC_SET_OPEND(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_OPEND,sbMMC_Power_OPEND)
+#define MMC_SET_ROD(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_ROD,sbMMC_Power_ROD)
+#define MMC_SET_CENABLE(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_ENABLE,sbMMC_Clock_ENABLE)
+#define MMC_SET_PWRSAVE(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_PWRSAVE,sbMMC_Clock_PWRSAVE)
+#define MMC_SET_BYPASS(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_BYPASS,sbMMC_Clock_BYPASS)
+
+#define MMC_SET_CLKDIV(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_CLKDIV,sbMMC_Clock_CLKDIV)
+#define MMC_SET_DATAPATH(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_ENABLE,sbMMC_DataPath_ENABLE)
+#define MMC_SET_BLOCKSIZE(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_BLOCKSIZE,sbMMC_DataPath_BLOCKSIZE)
+#define MMC_SET_DATADIR(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_DIRECTION,sbMMC_DataPath_DIRECTION)
+#define MMC_SET_MODE(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_MODE,sbMMC_DataPath_MODE)
+#define MMC_SET_DMA(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_DMA,sbMMC_DataPath_DMA)
+
+
+
+// Functional layer
+#define R1_OUT_OF_RANGE 0x80000000
+#define R1_ADDRESS_ERROR 0x40000000
+#define R1_BLOCK_LEN_ERROR 0x20000000
+#define R1_ERASE_SEQ_ERROR 0x10000000
+#define R1_ERASE_PARAM 0x08000000
+#define R1_WP_VIOLATION 0x04000000
+#define R1_CARD_IS_LOCKED 0x02000000
+#define R1_LOCK_UNLOCK_FAILED 0x01000000
+#define R1_COM_CRC_ERROR 0x00800000
+#define R1_ILLEGAL_COMMAND 0x00400000
+#define R1_CARD_ECC_FAILED 0x00200000
+#define R1_CC_ERROR 0x00100000
+#define R1_UNKNOWN_ERROR 0x00080000
+#define R1_STREAM_READ_UNDERRUN 0x00040000
+#define R1_STREAM_WRITE_OVERRUN 0x00020000
+#define R1_CID_CSD_OVERWRITE 0x00010000
+#define R1_WP_ERASE_SKIP 0x00008000
+#define R1_CARD_ECC_DISABLED 0x00004000
+#define R1_ERASE_RESET 0x00002000
+#define R1_AKE_SEQ_ERROR 0x00000008
+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA 0x000000100
+#define R1_APP_CMD 0x000000020
+
+/* DEFINES FOR R6 RESPONSE */
+#define R6_GEN_UNKNOWN_ERROR 0x00002000
+#define R6_ILLEGAL_CMD 0x00004000
+#define R6_COM_CRC_FAILED 0x00008000
+
+#define AllOne (0xffffffff)
+#define AllZero (0x00000000)
+
+
+//Power Control register
+
+#define PowerOn (0x00000003)
+#define OpenDrain (0x00000040)
+#define CmdDatEn (0x0000003C)
+#define VoltageWindowMMC (0x80FFC000)
+#define VoltageWindowSD (0x80010000)
+#define StuffBits0To32 (0xFFFFFFFF)
+#define StuffBits0To15 (0xFFFF)
+#define Sector_Mode (0x40000000)
+#define Byte_Mode (0x00000000)
+#define Check_Pattern (0x000001AA)
+
+//Clock Control register
+
+#define ClkDivInit (0x00000076)
+#define ClkDivTrans (0x00000001)
+#define ClkEnable (0x00000100)
+#define PwrSave (0x00000200)
+#define Enab_Bypass (0x00000400)
+#define Widebus_4 (0x00000800)
+#define Widebus_8 (0x00001000)
+#define Hwfc_en (0x00004000)
+
+//Command register
+
+//all commands
+
+#define GO_IDLE_STATE (0)
+#define SEND_OP_COND (1)
+#define ALL_SEND_CID (2)
+#define SET_REL_ADDR (3)
+#define SET_DSR (4)
+#define SEL_DESEL_CARD (7)
+#define SEND_EXT_CSD (8)
+#define SEND_CSD (9)
+#define SEND_CID (10)
+#define READ_DAT_UNTIL_STOP (11)
+#define STOP_TRANSMISSION (12)
+#define SEND_STATUS (13)
+#define GO_INACTIVE_STATE (15)
+#define SET_BLOCKLEN (16)
+#define READ_SINGLE_BLOCK (17)
+#define READ_MULT_BLOCK (18)
+#define WRITE_DAT_UNTIL_STOP (20)
+#define SET_BLOCK_COUNT (23)
+#define WRITE_SINGLE_BLOCK (24)
+#define WRITE_MULT_BLOCK (25)
+#define PROG_CID (26)
+#define PROG_CSD (27)
+#define SET_WRITE_PROT (28)
+#define CLR_WRITE_PROT (29)
+#define SEND_WRITE_PROT (30)
+#define ERASE_GRP_START (35)
+#define ERASE_GRP_END (36)
+#define ERASE (38)
+#define FAST_IO (39)
+#define GO_IRQ_STATE (40)
+#define LOCK_UNLOCK (42)
+#define APP_CMD (55)
+#define GEN_CMD (56)
+
+/*Following commands are SD Card Specific commands. MMC_APP_CMD should be sent before sending these commands.*/
+#define APP_SD_SET_BUSWIDTH (6)
+#define SD_APP_STAUS (13)
+#define SD_APP_SEND_NUM_WRITE_BLOCKS (22)
+#define SD_APP_OP_COND (41)
+#define SD_APP_SET_CLR_CARD_DETECT (42)
+#define SD_APP_SEND_SCR (51)
+#define SD_SEND_IF_COND (8)
+
+//Command control register
+
+#define RespExpected (0x00000040)
+#define LongResponse (0x00000080)
+#define EnabIntrReq (0x00000100)
+#define EnabCmdPend (0x00000200)
+#define CmdPathEnable (0x00000400)
+
+
+//Data Control register
+
+#define DataPathEnable (0x00000001)
+#define ReadDir (0x00000002)
+#define StreamMode (0x00000004)
+#define DMAEnab (0x00000008)
+#define BlockSize (0x000000F0)
+
+//Status register
+
+#define CmdCrcFail (0x00000001)
+#define DataCrcFail (0x00000002)
+#define CmdTimeOut (0x00000004)
+#define DataTimeOut (0x00000008)
+#define TxUnderrun (0x00000010)
+#define RxOverrun (0x00000020)
+#define CmdRespEnd (0x00000040)
+#define CmdSent (0x00000080)
+#define DataEnd (0x00000100)
+#define StartBitError (0x00000200)
+#define DataBlockEnd (0x00000400)
+#define CmdActive (0x00000800)
+#define TxActive (0x00001000)
+#define RxActive (0x00002000)
+#define TxFifoHalfEmpty (0x00004000)
+#define RxFifoHalfFull (0x00008000)
+#define TxFifoFull (0x00010000)
+#define RxFifoFull (0x00020000)
+#define TxFifoEmpty (0x00040000)
+#define RxFifoEmpty (0x00080000)
+#define TxDataAvlbl (0x00100000)
+#define RxDataAvlbl (0x00200000)
+#define AllInterrupts (0x003FFDFF)
+#define ErrorBits (0xFDFFE008)
+
+#define ClrStaticFlags (0x00C007FF)
+
+/* COMMAND CLASS SUPPORTED */
+#define CCCC_LOCK_UNLOCK (0x80)
+#define CCCC_WRITE_PROT (0x40)
+#define CCCC_ERASE (0x20)
+
+#endif /*MMCP*/
diff --git a/board/st/u8500/mmc_utils.c b/board/st/u8500/mmc_utils.c
new file mode 100755
index 000000000..b7d4e7085
--- /dev/null
+++ b/board/st/u8500/mmc_utils.c
@@ -0,0 +1,956 @@
+/*
+ * (C) Copyright 2009
+ * ST-Ericsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <linux/ctype.h>
+
+#include <common.h>
+#include <command.h>
+#include "gpio.h"
+#include "mmc.h" // MMC api
+#include "mmc_utils.h" // to access MMC
+#include "mmc_p.h" // t_mmc_register definition
+
+u32 MMCBuffer[1024] ;
+static int IS_SD_CARD;
+
+/* --- exported from other modules ---------------------------------------- */
+static u8 selected_card = 0;
+extern t_mmc_error mmc_cmderror_2 (void);
+extern t_mmc_error mmc_cmdresp2error_2 (void);
+extern t_mmc_error mmc_cmdresp3error_2 (void);
+extern t_mmc_error mmc_cmdresp145error_2 (u8 cmd);
+extern t_mmc_error mmc_cmdreadresp (u32 * tempbuff);
+extern t_mmc_error mmc_waitcmdreadresp (void);
+extern t_mmc_error mmc_cmdwriteresp (u8 cardno, u32 * tempbuff, u16 total_num_of_bytes);
+extern t_mmc_error mmc_waitcmdwriteresp (u8 cardno, u32 * tempbuff, u16 total_num_of_bytes);
+
+extern t_mmc_register *t_mmc0;
+extern u32 t_mmc_rel_addr;
+
+t_mmc_boot_record mmc_boot_record;
+
+void mmc_copyByteH (u8 * sourceAddr, u8 * destAddress, int size)
+{
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ *(destAddress + i) = *(sourceAddr + i);
+ }
+}
+
+void mmc_shift_memH (int num_of_words, u32 * start_address, u32 * dest_address, u32 shift)
+{
+ u32 *address;
+ int word = 0;
+ u32 high;
+ int i, word_offset, bit_offset;
+
+ word_offset = (int) (shift / 32);
+ bit_offset = (int) (shift % 32);
+ for (i = 0; i < num_of_words; i++)
+ {
+ *(dest_address + i) = 0;
+ }
+ for (i = word_offset; i < num_of_words; i++)
+ {
+ *(dest_address + i - word_offset) = *(start_address + i);
+ }
+ address = dest_address;
+ for (word = 0; word < num_of_words - 1; word++)
+ {
+ *address = (*address) >> bit_offset;
+ address++;
+ high = (*address << (32 - bit_offset));
+ *(address - 1) |= high;
+ }
+ *address = (*address) >> bit_offset;
+}
+
+u8 convert_from_bytes_to_power_of_two (u16 no_of_bytes)
+{
+ u8 count = 0;
+ while (no_of_bytes != 1)
+ {
+ no_of_bytes >>= 1;
+ count++;
+ }
+ return count;
+}
+
+t_mmc_error mmc_enable ()
+{
+ t_mmc_error error = MMC_OK;
+ t_mmc_command_control commcontrol;
+ t_bool validvoltage = FALSE;
+ u32 arg, response;
+ int i;
+
+ IS_SD_CARD = 0;
+
+ selected_card = 0;
+
+ t_mmc0->mmc_Power = 0x1BF;
+ t_mmc0->mmc_Clock = 0x41FF;
+
+ commcontrol.IsRespExpected = FALSE;
+ commcontrol.IsLongResp = FALSE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_sendcommand (MMC_GO_IDLE_STATE, 0x00000000, commcontrol);
+
+ error = mmc_cmderror_2 ();
+
+ //// Added by Chris Sebastian for SD Card support:
+ //// Send ACMD41. If we do not get a response, it is not an SD card.
+ //// If we do get a response, loop until card is not busy.
+
+ commcontrol.IsRespExpected = TRUE;
+ commcontrol.IsLongResp = FALSE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ for(i = 200; i; i--) {
+ error = mmc_sendcommand (MMC_APP_CMD, 0x00000000, commcontrol); // Let the card know that the next command is an app-cmd.
+ error = mmc_cmdresp145error_2(MMC_APP_CMD);
+ error = mmc_sendcommand (SD_SEND_OP_COND, 0x00060000, commcontrol); // I got the 0x00060000 from Linux kernel source.
+ error = mmc_cmdresp3error_2 ();
+ t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags. CmdResp3Error_2 leaves some bits set.
+ if (t_mmc0->mmc_Response0 & 0x80000000) {
+ printf("SD card detected \n");
+ IS_SD_CARD = 1;
+ return MMC_OK; // SD CARD DETECTED. Do not continue with MMC init logic. Quick escape!
+ }
+ }
+
+ commcontrol.IsRespExpected = FALSE;
+ commcontrol.IsLongResp = FALSE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_sendcommand (MMC_GO_IDLE_STATE, 0x00000000, commcontrol);
+ error = mmc_cmderror_2 ();
+
+ arg = 0x00060000; // High Voltage MMC, byte mode. Was 0x00FFC000, but that writes to reserved bits...
+ while (!validvoltage)
+ {
+ // send CMD1 (SEND_OP_COND)
+ commcontrol.IsRespExpected = TRUE;
+ error = mmc_sendcommand (MMC_SEND_OP_COND, arg, commcontrol);
+
+ error = mmc_cmdresp3error_2 ();
+
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ mmc_getresponse (MMC_SHORT_RESP, &response);
+
+ arg = response;
+ validvoltage = (t_bool) (((response >> 31) == 1) ? 1 : 0);
+
+ }
+end:
+ return error;
+}
+
+t_mmc_error mmc_disable ()
+{
+ t_mmc_error error = MMC_OK;
+ t_mmc_power_state powerstate = MMC_POWER_OFF;
+
+ error = mmc_setpowerstate (powerstate);
+ return error;
+}
+
+t_mmc_error mmc_initCard ()
+{
+ t_mmc_error error = MMC_OK;
+ t_mmc_command_control commcontrol;
+ t_mmc_bus_configuration busconfig;
+ t_mmc_clock_control clockcontrol;
+
+ // send CMD2 (ALL_SEND_CID)
+ commcontrol.IsRespExpected = TRUE;
+ commcontrol.IsLongResp = TRUE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_sendcommand (MMC_ALL_SEND_CID, 0x00000000, commcontrol);
+ error = mmc_cmdresp2error_2 ();
+ // error is MMC_CMD_CRC_FAIL on COB board ?!
+ // if( error != MMC_OK)
+ // goto end;
+
+ // send CMD3 (SET_RELATIVE_ADDR)
+
+ commcontrol.IsLongResp = FALSE;
+ error = mmc_sendcommand (MMC_SET_REL_ADDR, t_mmc_rel_addr, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_SET_REL_ADDR);
+ if(IS_SD_CARD) {
+ t_mmc_rel_addr = t_mmc0->mmc_Response0 & 0xFFFF0000;
+ }
+
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ busconfig.mode = MMC_PUSH_PULL;
+ busconfig.rodctrl = MMC_DISABLE;
+ error = mmc_configbus (busconfig);
+ clockcontrol.pwrsave= MMC_DISABLE;
+ clockcontrol.bypass = MMC_DISABLE;
+ clockcontrol.widebus= MMC_DISABLE;
+ error = mmc_setclockfrequency (0x0A); // 12MHz
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ error = mmc_configclockcontrol (clockcontrol);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+end:
+ return error;
+}
+
+t_mmc_error mmc_readblock (u8 cardno, u32 addr, u32 * readbuff, u16 blocksize, t_mmc_transfer_mode mmc_transfer_mode)
+{
+ t_mmc_error error = MMC_OK;
+ u8 power;
+ t_mmc_command_control commcontrol;
+ u32 response;
+
+ commcontrol.IsRespExpected = TRUE ;
+ commcontrol.IsLongResp = FALSE ;
+ commcontrol.IsInterruptMode = FALSE ;
+ commcontrol.IsPending = FALSE ;
+ commcontrol.cmdpath = MMC_ENABLE ;
+ error = mmc_setdatapath (MMC_DISABLE);
+ error = mmc_handledma (MMC_DISABLE);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ // send command for selecting the card
+ if (cardno != selected_card)
+ {
+ error = mmc_sendcommand (MMC_SEL_DESEL_CARD, t_mmc_rel_addr, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_SEL_DESEL_CARD);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ else
+ {
+ selected_card = cardno;
+ }
+ }
+ error = mmc_getresponse (MMC_SHORT_RESP, &response);
+ if (response & 0x02000000)
+ {
+ return MMC_LOCK_UNLOCK_FAILED;
+ }
+ // set the block size,both on controller and card
+ if ((blocksize > 0) && (blocksize <= 2048) && ((blocksize & (blocksize - 1)) == 0))
+ {
+ power = convert_from_bytes_to_power_of_two (blocksize);
+ error = mmc_setdatablocklength (power);
+ error = mmc_sendcommand (MMC_SET_BLOCKLEN, (u32) blocksize, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_SET_BLOCKLEN);
+ if (error != MMC_OK)
+ {
+ return error;
+ }
+ }
+ else
+ {
+ error = MMC_INVALID_PARAMETER;
+ goto end;
+ }
+ error = mmc_setdatalength (blocksize );
+ error = mmc_setdatatimeout (0xefffffff );
+ error = mmc_settransferdirection (MMC_READ );
+ error = mmc_settransfertype (MMC_BLOCK );
+ error = mmc_setdatapath (MMC_ENABLE);
+ //t_mmc0->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable;
+ error = mmc_sendcommand (MMC_READ_SINGLE_BLOCK, addr, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_READ_SINGLE_BLOCK);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ if (mmc_transfer_mode == MMCDMA)
+ {
+ error = mmc_waitcmdreadresp ();
+ }
+ else
+ {
+ error = mmc_cmdreadresp (readbuff);
+ }
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+end:
+ return error;
+}
+
+t_mmc_error mmc_writeblock (u8 cardno, u32 addr, u32 * writebuff, u16 blocksize, t_mmc_transfer_mode mmc_transfer_mode)
+{
+ t_mmc_error error = MMC_OK;
+ u8 power;
+ t_mmc_command_control commcontrol;
+ u32 response;
+
+ commcontrol.IsRespExpected = TRUE;
+ commcontrol.IsLongResp = FALSE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_setdatapath (MMC_DISABLE);
+ error = mmc_handledma (MMC_DISABLE);
+ error = mmc_settransferdirection(MMC_WRITE);
+ error = mmc_settransfertype (MMC_BLOCK);
+
+ if (cardno != selected_card)
+ {
+ error = mmc_sendcommand (MMC_SEL_DESEL_CARD, t_mmc_rel_addr, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_SEL_DESEL_CARD);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ else
+ {
+ selected_card = cardno;
+ }
+ }
+
+ mmc_getresponse (MMC_SHORT_RESP, &response);
+ if (response & 0x02000000)
+ {
+ return MMC_LOCK_UNLOCK_FAILED;
+ }
+ // set the block size,both on controller and card
+ if ((blocksize > 0) && (blocksize <= 2048) && (((blocksize & (blocksize - 1)) == 0)))
+ {
+ power = convert_from_bytes_to_power_of_two (blocksize);
+ error = mmc_setdatablocklength (power);
+ error = mmc_sendcommand (MMC_SET_BLOCKLEN, (u32) blocksize, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_SET_BLOCKLEN);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ }
+ else
+ {
+ error = MMC_INVALID_PARAMETER;
+ goto end;
+ }
+
+ error = mmc_setdatalength (blocksize);
+ error = mmc_setdatatimeout (0xefffffff);
+ error = mmc_settransferdirection (MMC_WRITE);
+ error = mmc_settransfertype (MMC_BLOCK);
+ error = mmc_setdatapath (MMC_ENABLE);
+ error = mmc_sendcommand (MMC_WRITE_SINGLE_BLOCK, addr, commcontrol);
+ error = mmc_cmdresp145error_2 (MMC_WRITE_SINGLE_BLOCK);
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ if (mmc_transfer_mode == MMCDMA)
+ {
+ error = mmc_waitcmdwriteresp (cardno, writebuff, blocksize);
+ }
+ else
+ {
+ error = mmc_cmdwriteresp (cardno, writebuff, blocksize);
+ }
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+end:
+ return error;
+}
+
+t_mmc_error mmc_readcsd (u32 * CSD)
+{
+ t_mmc_error error = MMC_OK;
+ t_mmc_command_control commcontrol;
+ u32 buf[4];
+
+ // send CMD9 (SEND CSD)
+ commcontrol.IsRespExpected = TRUE;
+ commcontrol.IsLongResp = TRUE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_sendcommand (MMC_SEND_CSD, t_mmc_rel_addr, commcontrol);
+ error = mmc_cmdresp2error_2 ();
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ error = mmc_getresponse (MMC_LONG_RESP, buf);
+ CSD[0] = buf[3];
+ CSD[1] = buf[2];
+ CSD[2] = buf[1];
+ CSD[3] = buf[0];
+end:
+ return error;
+}
+
+t_mmc_error mmc_readcid (u32 * CID)
+{
+ t_mmc_error error = MMC_OK;
+ t_mmc_command_control commcontrol;
+ u32 buf[4];
+
+ // send CMD9 (SEND CSD)
+ commcontrol.IsRespExpected = TRUE;
+ commcontrol.IsLongResp = TRUE;
+ commcontrol.IsInterruptMode = FALSE;
+ commcontrol.IsPending = FALSE;
+ commcontrol.cmdpath = MMC_ENABLE;
+
+ error = mmc_sendcommand (MMC_SEND_CID, t_mmc_rel_addr, commcontrol);
+ error = mmc_cmdresp2error_2 ();
+ if (error != MMC_OK)
+ {
+ goto end;
+ }
+ error = mmc_getresponse (MMC_LONG_RESP, buf);
+ CID[0] = buf[3];
+ CID[1] = buf[2];
+ CID[2] = buf[1];
+ CID[3] = buf[0];
+end:
+ return error;
+}
+
+t_mmc_error mmc_read_file (char *filename, u32 address, u32 * FileSize)
+{
+ u8 *mem_address = (u8 *) address;
+ u8 sector[512];
+ u16 BytesPerSector;
+ u32 BRStartSector;
+ u32 FATStartSector;
+ u32 DataStartSector;
+ u32 FileStartSector;
+ u16 SectorsPerFAT;
+ u8 SectorsPerCluster;
+ u8 k;
+ u16 MaxRDEntries;
+ u16 ReservedSectors;
+ u32 RDStartSector, j;
+ char nomefile[12] = " ";
+ int filelength;
+ u16 FileStartCluster = 0;
+ t_mmc_error response, response2;
+ int i, goout, found, result = PASS;
+ u32 CSD[4];
+ char mmcfilename[] = " ";
+ char *dotpos;
+
+ /////////// Attention please: /////////////////////
+ // //
+ // if other Alternate function apart from MMCI //
+ // are selected, the MMCI I/F has some problems //
+ // //
+ ////////////////////////////////////////////////////
+
+ gpio_altfuncenable(GPIO_ALT_SD_CARD0, "MMC");
+ // Power-on the controller
+ response = mmc_enable ();
+
+ if (response != MMC_OK)
+ {
+
+ response = mmc_enable (); // This actually IS necessary because it takes time for newly-inserted cards initialize. ~Chris S.
+ if (response != MMC_OK)
+ {
+ printf ("Error in card power on\n");
+ result = FAIL;
+ goto end;
+ }
+ }
+ // Initialise the cards on the bus, if any
+ response = mmc_initCard ();
+
+ if (response != MMC_OK)
+ {
+ printf ("Error in card initialization\n");
+ result = FAIL;
+ goto end;
+ }
+ // Get card info: CID, CSD, RCA registers
+ response = mmc_readcsd (CSD);
+
+ if (response != MMC_OK)
+ {
+ printf ("Error while fetching card info\n");
+ result = FAIL;
+ goto end;
+ }
+ // Read the MBR
+ response = mmc_readblock (1, 0, (u32 *) sector, 512, MMCPOLLING);
+
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading boot record\n");
+ result = FAIL;
+ goto end;
+ }
+ if (sector[446] == 0x00 || sector[446] == 0x80)
+ { // found a MBR at the beginning of card
+ BRStartSector = sector[454];
+ }
+ else
+ { // BR at the beginning of card
+ BRStartSector = 0x00;
+ }
+ // Read the BR
+ response = mmc_readblock (1, (u32) (512 * BRStartSector), (u32 *) & mmc_boot_record, 512, MMCPOLLING);
+
+ k = 0;
+ while (response == MMC_DATA_CRC_FAIL && (k < 2))
+ {
+ response = mmc_readblock (1, (u32) (512 * BRStartSector), (u32 *) & mmc_boot_record, 512, MMCPOLLING);
+ k++;
+ }
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading boot record\n");
+ result = FAIL;
+ goto end;
+ }
+ mmc_copyByteH (mmc_boot_record.BytesPerSector, (u8 *) & BytesPerSector, 2);
+ mmc_copyByteH (mmc_boot_record.ReservedSectors, (u8 *) & ReservedSectors, 2);
+ FATStartSector = BRStartSector + ReservedSectors; // the field at offset 15 contains the number of reserved sectors at
+ // the beginning of the media including the boot sector
+ mmc_copyByteH (mmc_boot_record.SectorsPerFat, (u8 *) & SectorsPerFAT, 2);
+ SectorsPerCluster = mmc_boot_record.SectorsPerCluster[0];
+ mmc_copyByteH (mmc_boot_record.NumOfRootEntries, (u8 *) & MaxRDEntries, 2);
+ FATStartSector += SectorsPerFAT;
+ RDStartSector = FATStartSector + SectorsPerFAT;
+ DataStartSector = RDStartSector + (u32) ((MaxRDEntries * 32) / 512);
+
+
+
+ // convert filename into mmc compatible file name (upper case , <= 8+3 char, no dot, no extension)
+ filelength = strlen (filename);
+ dotpos = strchr (filename, '.');
+ if (dotpos == NULL)
+ {
+ // no dot
+ if (filelength <= 8)
+ {
+ for (j = 0; j < filelength; j++)
+ {
+ mmcfilename[j] = (char) toupper (filename[j]);
+ }
+ }
+ else
+ {
+ for (j = 0; j < 6; j++)
+ {
+ mmcfilename[j] = (char) toupper (filename[j]);
+ }
+ mmcfilename[7] = '~';
+ mmcfilename[8] = '1';
+ filelength = 8;
+ }
+ }
+ else
+ {
+ // dot
+ if ((dotpos - filename) <= 8)
+ {
+ for (j = 0; j < (dotpos - filename); j++)
+ {
+ mmcfilename[j] = (char) toupper (filename[j]);
+ }
+ for (; j < 8; j++)
+ {
+ mmcfilename[j] = ' ';
+ }
+ // copy 3 char after .
+ mmcfilename[j++] = (char) toupper (dotpos[1]);
+ mmcfilename[j++] = (char) toupper (dotpos[2]);
+ mmcfilename[j++] = (char) toupper (dotpos[3]);
+
+ }
+ else
+ {
+ for (j = 0; j < 6; j++)
+ {
+ mmcfilename[j] = (char) toupper (filename[j]);
+ }
+ mmcfilename[6] = '~';
+ mmcfilename[7] = '1';
+ // copy 3 char after .
+ mmcfilename[8] = (char) toupper (dotpos[1]);
+ mmcfilename[9] = (char) toupper (dotpos[2]);
+ mmcfilename[10] = (char) toupper (dotpos[3]);
+ }
+ filelength = 11;
+ }
+ mmcfilename[11] = '\0';
+
+
+ // search Root Directory for entry filename
+ goout = 0;
+ found = 0;
+ for (j = 0; j < (DataStartSector - RDStartSector); j++)
+ {
+ if (goout == 1)
+ break;
+ response = mmc_readblock (1, (u32) ((RDStartSector + j) * 512), (u32 *) sector, 512, MMCPOLLING);
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading root directory\n");
+ result = FAIL;
+ goto end;
+ }
+
+ for (i = 0; i < 512; i += 32)
+ {
+ strncpy (nomefile, (char *) &sector[i], filelength);
+ if (strcmp (nomefile, mmcfilename) == 0)
+ {
+ mmc_copyByteH (&sector[i + 26], (u8 *) & FileStartCluster, 2);
+ mmc_copyByteH (&sector[i + 28], (u8 *) FileSize, 4);
+ FileStartCluster -= 2;
+ goout = 1;
+ found = 1;
+ break;
+ }
+ if (nomefile[0] == 0)
+ { // end of Root Directory
+ goout = 1;
+ break;
+ }
+ }
+ }
+
+ // size of file : *FileSize ( 32 bits quantum)
+ // number of bytes per sector : BytesPerSector
+ // Beginning of file : FileStartSector
+
+ printf ("Bytes per sector : %d \n", BytesPerSector );
+ printf ("Sectors per cluster : %d \n", SectorsPerCluster );
+ if (found)
+ {
+ u32 remaining = *FileSize ;
+ u32 count;
+ u32 burstsize = BytesPerSector ;
+
+ FileStartSector = ( DataStartSector + (u32)(FileStartCluster * SectorsPerCluster)) ;
+ printf ("Reading file %s from MMC ..., start sector = %d, address 0x%x \n",filename,FileStartSector,address);
+ count = SectorsPerCluster - (FileStartSector % SectorsPerCluster) ;
+ FileStartSector = FileStartSector * BytesPerSector; // the first burst might be different to align of clusters
+
+ do
+ {
+ if ( remaining >= burstsize )
+ { // read straight burst
+
+ k = 0;
+ do
+ {
+ response = mmc_readblock (1, (u32) FileStartSector , (u32 *) mem_address, burstsize , MMCPOLLING);
+ k++;
+
+ } while ((response==MMC_DATA_CRC_FAIL)&&(k<4));
+ if ( k != 1) printf ("!");
+ FileStartSector += burstsize;
+ mem_address += burstsize;
+ remaining -= burstsize;
+ }
+ else
+ { // read burst +1 and perform memcpy
+
+ burstsize = ((remaining + (BytesPerSector-1))/BytesPerSector) * BytesPerSector ;
+ k = 0;
+ do
+ {
+ response = mmc_readblock (1, (u32) FileStartSector , (u32 *) MMCBuffer , burstsize , MMCPOLLING);
+ k++;
+ } while ((response==MMC_DATA_CRC_FAIL)&&(k<4));
+ if ( k != 1) printf ("!");
+ memcpy ((char *) mem_address, (char *)MMCBuffer,remaining);
+ remaining = 0;
+ }
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading file %s\n", filename);
+ result = FAIL;
+ goto end;
+ }
+ } while ( remaining );
+
+ }
+ else
+ {
+ printf ("Unable to find %s on Multi Media Card\n", filename);
+ response = MMC_INVALID_PARAMETER;
+ result = FAIL;
+ goto end;
+ }
+
+end:
+ gpio_altfuncdisable(GPIO_ALT_SD_CARD0, "MMC");
+ response2 = mmc_disable ();
+
+ return response;
+}
+
+t_mmc_error display_file_list (char *extension)
+{
+ u32 i, j, k, goout;
+ u32 FATStartSector;
+ u8 SectorsPerCluster;
+ u32 RDStartSector;
+ u32 DataStartSector;
+ u16 BytesPerSector;
+ u32 BRStartSector;
+ u16 SectorsPerFAT;
+ u16 MaxRDEntries;
+ u16 ReservedSectors;
+ u8 sector[512];
+ t_mmc_error response;
+ t_mmc_error response2;
+ u32 CSD[4];
+ char nomefile[12] = " ";
+ char name[9] = " ";
+ char extent[4] = " ";
+ u32 FileSize;
+
+ //printf("disp:: start\n");
+ gpio_altfuncenable(GPIO_ALT_SD_CARD0, "MMC");
+
+ // Power-on the controller
+ response = mmc_enable ();
+
+ if (response != MMC_OK)
+ {
+ response = mmc_enable (); // This actually IS necessary because it takes time for newly-inserted cards initialize. ~Chris S.
+ if (response != MMC_OK)
+ {
+ printf ("Error in card power on, response is %d\n", response);
+ goto end;
+ }
+ }
+ // Initialise the cards on the bus, if any
+
+ response = mmc_initCard ();
+
+ if (response != MMC_OK)
+ {
+ printf ("1. Error in card initialization\n");
+ goto end;
+ }
+ // Get card info: CID, CSD, RCA registers
+
+ response = mmc_readcsd (CSD);
+
+ if (response != MMC_OK) {
+ printf ("Error while fetching card info\n");
+ goto end;
+ }
+ // Read the MBR
+
+ response = mmc_readblock (1, 0, (u32 *) sector, 512, MMCPOLLING);
+
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading boot record\n");
+ goto end;
+ }
+ if (sector[446] == 0x00 || sector[446] == 0x80)
+ { // found a MBR at the beginning of card
+
+ BRStartSector = sector[454];
+ }
+ else
+ { // BR at the beginning of card
+
+ BRStartSector = 0x00;
+ }
+ // Read the BR
+ response = mmc_readblock (1, (u32) (512 * BRStartSector), (u32 *) & mmc_boot_record, 512, MMCPOLLING);
+
+ k = 0;
+ while (response == MMC_DATA_CRC_FAIL && (k < 2))
+ {
+ response = mmc_readblock (1, (u32) (512 * BRStartSector), (u32 *) & mmc_boot_record, 512, MMCPOLLING);
+ k++;
+ }
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading boot record\n");
+ goto end;
+ }
+ mmc_copyByteH (mmc_boot_record.BytesPerSector, (u8 *) & BytesPerSector, 2);
+ mmc_copyByteH (mmc_boot_record.ReservedSectors, (u8 *) & ReservedSectors, 2);
+ FATStartSector = BRStartSector + ReservedSectors; // the field at offset 15 contains the number of reserved sectors at
+ // the beginning of the media including the boot sector
+
+ mmc_copyByteH (mmc_boot_record.SectorsPerFat, (u8 *) & SectorsPerFAT, 2);
+ SectorsPerCluster = mmc_boot_record.SectorsPerCluster[0];
+ mmc_copyByteH (mmc_boot_record.NumOfRootEntries, (u8 *) & MaxRDEntries, 2);
+
+ FATStartSector += SectorsPerFAT;
+ RDStartSector = FATStartSector + SectorsPerFAT;
+ DataStartSector = RDStartSector + (u32) ((MaxRDEntries * 32) / 512);
+ // search Root Directory for entry filename
+ goout = 0;
+ printf ("file \t\t size\n");
+
+ for (j = 0; j < (DataStartSector - RDStartSector); j++)
+ {
+ printf(" disp:: data start \n");
+ if (goout == 1)
+ {
+ break;
+ }
+ response = mmc_readblock (1, (u32) ((RDStartSector + j) * 512), (u32 *) sector, 512, MMCPOLLING);
+ k = 0;
+ while (response == MMC_DATA_CRC_FAIL && (k < 2))
+ {
+ response = mmc_readblock (1, (u32) ((RDStartSector + j) * 512), (u32 *) sector, 512, MMCPOLLING);
+ k++;
+ }
+ if (response != MMC_OK)
+ {
+ printf ("Error while reading root directory\n");
+ goto end;
+ }
+ for (i = 0; i < 512; i += 32)
+ {
+ strncpy (nomefile, (char *) &sector[i], 11);
+ if (nomefile[0] == 0) // end of Root Directory
+ {
+ goout = 1;
+ break;
+ }
+ if (nomefile[0] != 0xE5) // not deleted file only
+ {
+ for (k = 0; k < 3; k++)
+ {
+ extent[k] = (char) toupper (extension[k]);
+ }
+ if ((strncmp (&nomefile[8], extent, strlen (extension)) == 0) || (*extension == '*'))
+ {
+ mmc_copyByteH (&sector[i + 28], (u8 *) & FileSize, 4);
+ k = 0;
+ while ((nomefile[k] != 0x20) && (k < 8))
+ {
+ name[k] = (char) tolower (nomefile[k]);
+ k++;
+ }
+ name[k] = '\0';
+ for (k = 0; k < 3; k++)
+ {
+ extent[k] = (char) tolower (nomefile[k + 8]);
+ }
+ printf ("%s.%s \t %10ld\n", name, extent, FileSize);
+ }
+ }
+ }
+ }
+end:
+ gpio_altfuncdisable(GPIO_ALT_SD_CARD0, "MMC");
+ response2 = mmc_disable ();
+ //printf("disp:: done \n");
+ return response;
+}
+
+/*
+ * command line commands
+ */
+
+static char mmc_cmdbuffer[1024] ;
+
+int copy_file_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ unsigned long address;
+ unsigned long filesize;
+ int load_result;
+ char filename[30];
+
+ strcpy(filename , argv[1]);
+ address = simple_strtoul (argv[2], 0, 16);
+
+ printf("copy_file_mmc : filename = %s\n", filename);
+ printf("copy_file_mmc : address = %x\n", address);
+
+ load_result = mmc_read_file(filename, address, &filesize);
+ if (load_result != 0)
+ {
+ printf("copy_file_mmc error : in loading file \n");
+ }
+ return(load_result);
+}
+
+int mmc_read_cmd_file (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ unsigned long filesize;
+ int load_result;
+
+ load_result = mmc_read_file("command.txt",
+ (unsigned long)&mmc_cmdbuffer, &filesize);
+ if (load_result != 0) {
+ printf("mmc_read_cmd_file error : in loading file \n");
+ } else {
+ setenv ("bootcmd", mmc_cmdbuffer);
+ }
+ return(load_result);
+}
+
+
+U_BOOT_CMD(
+ copy_file_mmc, 3, 0, copy_file_mmc,
+ "- copy file from mmc card\n",
+ "filename address\n"
+ " - load binary file from the MMC/SD card to a memory address\n"
+);
+
+
+U_BOOT_CMD(
+ mmc_read_cmd_file, 1, 0, mmc_read_cmd_file,
+ "- copy command file from mmc card\n",
+ NULL
+);
+
+/* ------------------------------- End of file ---------------------------- */
diff --git a/board/st/u8500/mmc_utils.h b/board/st/u8500/mmc_utils.h
new file mode 100755
index 000000000..b998814c5
--- /dev/null
+++ b/board/st/u8500/mmc_utils.h
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __MMC_UTILS_H
+#define __MMC_UTILS_H
+
+#include <common.h>
+
+typedef struct
+{
+ u8 jump [3];
+ u8 OEMname [8];
+ u8 BytesPerSector [2];
+ u8 SectorsPerCluster [1];
+ u8 ReservedSectors [2];
+ u8 NumOfFAT [1];
+ u8 NumOfRootEntries [2];
+ u8 NumOfSectors [2];
+ u8 MediaDesc [1];
+ u8 SectorsPerFat [2];
+ u8 SectorsPerTrack [2];
+ u8 NumOfHeads [2];
+ u8 NumOfHiddenSectors [4];
+ u8 NumOfTotSectors [4];
+ u8 DriveNumber [1];
+ u8 reserved [1];
+ u8 ExtBootSig [1];
+ u8 VolumeID [4];
+ u8 VolumeLabel [11];
+ u8 FSType [8];
+ u8 LoadProg [448];
+ u8 Signature [2];
+} t_mmc_boot_record;
+
+typedef struct
+{
+ u8 filename [8];
+ u8 extension [3];
+ u8 attrib ;
+ u8 reserved [10];
+ u8 hour [2];
+ u8 date [2];
+ u8 startCluster [2];
+ u8 dimension [4];
+} t_mmc_root_entry;
+
+typedef struct s_root_elem
+{
+ char name[8];
+ char ext[3];
+ char nulll[0xf];
+ short offset;
+ unsigned sizee;
+} s_root_elem;
+
+typedef struct s_root
+{
+ s_root_elem elem[16];
+} s_root;
+
+typedef struct s_file_elem
+{
+ char filename [8] ;
+} s_file_elem;
+
+typedef struct s_file_list
+{
+ s_file_elem elem [30];
+} s_file_list ;
+
+typedef enum
+{
+ MMCPOLLING,
+ MMCDMA
+}t_mmc_transfer_mode;
+
+
+t_mmc_error mmc_readblock (u8 cardno, u32 addr, u32* readbuff, u16 blocksize, t_mmc_transfer_mode transfer_mode);
+t_mmc_error mmc_writeblock (u8 cardno, u32 addr, u32* writebuff, u16 blocksize, t_mmc_transfer_mode transfer_mode);
+t_mmc_error mmc_enable (void);
+t_mmc_error mmc_disable (void);
+t_mmc_error mmc_initCard (void);
+t_mmc_error mmc_readcsd (u32 *response);
+t_mmc_error mmc_readcid (u32 *response) ;
+t_mmc_error display_file_list(char *extension);
+
+#endif /* !defined(__MMC_UTILS_H) */
+
+
diff --git a/board/st/u8500/u8500.c b/board/st/u8500/u8500.c
new file mode 100755
index 000000000..0cca76cf3
--- /dev/null
+++ b/board/st/u8500/u8500.c
@@ -0,0 +1,140 @@
+/*
+* (C) Copyright 2009
+* STEricsson, <www.stericsson.com>
+*
+* See file CREDITS for list of people who contributed to this
+* project.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+* MA 02111-1307 USA
+*/
+
+#include <config.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include "common.h"
+
+void init_regs(void);
+#if 0
+void *memcopy(void *dest, const void *src, size_t count)
+{
+ u16 *tmp = (u16 *) dest, *s = (u16 *) src;
+
+ count = count / 2;
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+#endif
+#if defined(CONFIG_SHOW_BOOT_PROGRESS)
+void show_boot_progress(int progress)
+{
+ printf("Boot reached stage %d\n", progress);
+}
+#endif
+
+static inline void delay(unsigned long loops)
+{
+ __asm__ volatile ("1:\n"
+ "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0"(loops));
+}
+
+/*
+* Miscellaneous platform dependent initialisations
+*/
+
+int board_init(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ gd->bd->bi_arch_number = 0x1A4;
+ gd->bd->bi_boot_params = 0x00000100;
+ //enable the timers in PRCMU reg
+ *((volatile unsigned int *)(CFG_PRCMU_BASE + 0x1C8)) = 0x20000;
+ icache_enable();
+ gpio_init();
+
+ init_regs();
+ return 0;
+}
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+ setenv("verify", "n");
+ return (0);
+}
+#endif
+
+/******************************
+Routine:
+Description:
+******************************/
+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_SIZE_1;
+ gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+ gd->bd->bi_dram[1].size = PHYS_SDRAM_SIZE_2;
+
+ return 0;
+}
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+unsigned int addr_vall_arr[] = {
+0x8011F000, 0x0000FFFF, // Clocks for HSI TODO Enable reqd only
+0x8011F008, 0x00001C44, // Clocks for HSI TODO Enable reqd only
+0x8000F000, 0x00007FFF, // Clocks for I2C TODO Enable reqd only
+0x8000F008, 0x00007FFF, // Clocks for I2C TODO Enable reqd only
+0x8000E120, 0x003C0000, // GPIO for I2C/SD
+0x8000E124, 0x00000000, // GPIO for I2C/SD
+0x8012F000, 0x00007FFF, // Clocks for SD TODO Enable reqd only
+0x8012F008, 0x00007FFF, // Clocks for SD TODO Enable reqd only
+0xA03DF000, 0x0000000D, // Clock for MTU Timers
+0x8011E00C, 0x00000000, // GPIO ALT FUNC for EMMC
+0x8011E004, 0x0000FFE0, // GPIO ALT FUNC for EMMC
+0x8011E020, 0x0000FFE0, // GPIO ALT FUNC for EMMC
+0x8011E024, 0x00000000, // GPIO ALT FUNC for EMMC
+0x8012E00C, 0x00000000, // GPIO ALT FUNC for SD
+0x8012E004, 0x0FFC0000, // GPIO ALT FUNC for SD
+0x8012E020, 0x60000000, // GPIO ALT FUNC for SD
+0x8012E024, 0x60000000, // GPIO ALT FUNC for SD
+0x801571E4, 0x0000000C, // PRCMU settings for B2R2
+0x80157024, 0x00000130, // PRCMU settings for EMMC/SD
+0xA03FF000, 0x00000003, // USB
+0xA03FF008, 0x00000001, // USB
+0xA03FE00C, 0x00000000, // USB
+0xA03FE020, 0x00000FFF, // USB
+0xA03FE024, 0x00000000 // USB
+};
+#ifdef BOARD_LATE_INIT
+int board_late_init(void)
+{
+ return (0);
+}
+#endif
+void init_regs(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(addr_vall_arr)/2; i++)
+ {
+
+ *((volatile unsigned int *)(addr_vall_arr[2 * i]))
+ = addr_vall_arr[(2 * i) + 1];
+ }
+}
diff --git a/common/env_emmc.c b/common/env_emmc.c
new file mode 100755
index 000000000..c46e18aa6
--- /dev/null
+++ b/common/env_emmc.c
@@ -0,0 +1,224 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/* #define DEBUG */
+
+#include <common.h>
+
+#if defined(CONFIG_ENV_IS_IN_EMMC) /* Environment is in EMMC Flash */
+
+#include <command.h>
+#include <environment.h>
+#include <linux/stddef.h>
+#include <malloc.h>
+#include <asm/arch/emmc.h>
+
+#if defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_EMMC)
+#define CMD_SAVEENV
+#elif defined(CONFIG_ENV_OFFSET_REDUND)
+#error Cannot use CONFIG_ENV_OFFSET_REDUND without CONFIG_CMD_ENV & CONFIG_CMD_EMMC
+#endif
+
+#if defined(CONFIG_ENV_SIZE_REDUND) && (CONFIG_ENV_SIZE_REDUND != CONFIG_ENV_SIZE)
+#error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE
+#endif
+
+#ifdef CONFIG_INFERNO
+#error CONFIG_INFERNO not supported yet
+#endif
+
+/* references to names in env_common.c */
+extern uchar default_environment[];
+extern int default_environment_size;
+
+char * env_name_spec = "EMMC";
+
+
+#ifdef ENV_IS_EMBEDDED
+extern uchar environment[];
+env_t *env_ptr = (env_t *)(&environment[0]);
+#else /* ! ENV_IS_EMBEDDED */
+env_t *env_ptr = 0;
+#endif /* ENV_IS_EMBEDDED */
+
+
+DECLARE_GLOBAL_DATA_PTR;
+
+uchar env_get_char_spec (int index)
+{
+ return ( *((uchar *)(gd->env_addr + index)) );
+}
+
+
+/* this is called before nand_init()
+ * so we can't read Nand to validate env data.
+ * Mark it OK for now. env_relocate() in env_common.c
+ * will call our relocate function which will does
+ * the real validation.
+ *
+ * When using a eMMC boot image (like sequoia_nand), the environment
+ * can be embedded or attached to the U-Boot image in eMMC flash. This way
+ * the SPL loads not only the U-Boot image from eMMC but also the
+ * environment.
+ */
+int env_init(void)
+{
+#if defined(ENV_IS_EMBEDDED)
+ ulong total;
+ int crc1_ok = 0, crc2_ok = 0;
+ env_t *tmp_env1, *tmp_env2;
+
+ total = CONFIG_ENV_SIZE;
+
+ tmp_env1 = env_ptr;
+ tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE);
+
+ crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
+ crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
+
+ if (!crc1_ok && !crc2_ok)
+ gd->env_valid = 0;
+ else if(crc1_ok && !crc2_ok)
+ gd->env_valid = 1;
+ else if(!crc1_ok && crc2_ok)
+ gd->env_valid = 2;
+ else {
+ #ifdef CONFIG_REDUNDAND_ENVIRONMENT
+ /* both ok - check serial */
+ if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
+ gd->env_valid = 2;
+ else if(tmp_env2->flags == 255 && tmp_env1->flags == 0)
+ gd->env_valid = 1;
+ else if(tmp_env1->flags > tmp_env2->flags)
+ gd->env_valid = 1;
+ else if(tmp_env2->flags > tmp_env1->flags)
+ gd->env_valid = 2;
+ else /* flags are equal - almost impossible */
+ #endif
+ gd->env_valid = 1;
+ }
+
+ if (gd->env_valid == 1)
+ env_ptr = tmp_env1;
+ else if (gd->env_valid == 2)
+ env_ptr = tmp_env2;
+#else /* ENV_IS_EMBEDDED */
+ gd->env_addr = (ulong)&default_environment[0];
+ gd->env_valid = 1;
+#endif /* ENV_IS_EMBEDDED */
+
+ return (0);
+}
+
+#ifdef CMD_SAVEENV
+int saveenv(void)
+{
+ ulong total;
+ int ret = 0;
+
+ puts ("Erasing eMMC...");
+ if (emmc_erase(CONFIG_ENV_OFFSET_START, CONFIG_ENV_OFFSET_END))
+ return 1;
+
+ puts ("Writing to EMMC... ");
+ total = CONFIG_ENV_SIZE;
+ ret = emmc_write(CONFIG_ENV_OFFSET_START, (u32 *) env_ptr,
+ CONFIG_ENV_SIZE);
+ //if (ret || total != CONFIG_ENV_SIZE)
+ //return 1;
+
+ puts ("done\n");
+ return ret;
+}
+#endif /* CMD_SAVEENV */
+#ifdef CONFIG_ENV_OFFSET_REDUND
+void env_relocate_spec (void)
+{
+#if !defined(ENV_IS_EMBEDDED)
+ ulong total;
+ int crc1_ok = 0, crc2_ok = 0;
+ env_t *tmp_env1, *tmp_env2;
+
+ total = CONFIG_ENV_SIZE;
+
+ tmp_env1 = (env_t *) malloc(CONFIG_ENV_SIZE);
+ tmp_env2 = (env_t *) malloc(CONFIG_ENV_SIZE);
+
+ emmc_read(CONFIG_ENV_OFFSET_START,(u32 *) tmp_env1, total);
+ emmc_read(CONFIG_ENV_OFFSET_START,(u32 *) tmp_env2, total);
+
+ crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
+ crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
+
+ if(!crc1_ok && !crc2_ok)
+ return set_default_env();
+ else if(crc1_ok && !crc2_ok)
+ gd->env_valid = 1;
+ else if(!crc1_ok && crc2_ok)
+ gd->env_valid = 2;
+ else {
+ /* both ok - check serial */
+ if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
+ gd->env_valid = 2;
+ else if(tmp_env2->flags == 255 && tmp_env1->flags == 0)
+ gd->env_valid = 1;
+ else if(tmp_env1->flags > tmp_env2->flags)
+ gd->env_valid = 1;
+ else if(tmp_env2->flags > tmp_env1->flags)
+ gd->env_valid = 2;
+ else /* flags are equal - almost impossible */
+ gd->env_valid = 1;
+
+ }
+
+ free(env_ptr);
+ if(gd->env_valid == 1) {
+ env_ptr = tmp_env1;
+ free(tmp_env2);
+ } else {
+ env_ptr = tmp_env2;
+ free(tmp_env1);
+ }
+
+#endif /* ! ENV_IS_EMBEDDED */
+}
+#else /* ! CONFIG_ENV_OFFSET_REDUND */
+void env_relocate_spec (void)
+{
+#if !defined(ENV_IS_EMBEDDED)
+ ulong total;
+ int ret;
+
+ total = CONFIG_ENV_SIZE;
+ printf("env_relocate_spec start\n");
+ emmc_init(4);
+ ret = emmc_read(CONFIG_ENV_OFFSET_START, (u_char*)env_ptr, total);
+ if (ret || total != CONFIG_ENV_SIZE)
+ return set_default_env();
+
+ if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
+ return set_default_env();
+#endif /* ! ENV_IS_EMBEDDED */
+}
+#endif /* CONFIG_ENV_OFFSET_REDUND */
+
+#endif /* CONFIG_ENV_IS_IN_EMMC */
diff --git a/cpu/arm_cortexa9/Makefile b/cpu/arm_cortexa9/Makefile
new file mode 100755
index 000000000..ae20299db
--- /dev/null
+++ b/cpu/arm_cortexa9/Makefile
@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2000-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 $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).a
+
+START := start.o
+COBJS := cpu.o
+
+SRCS := $(START:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+######################################################################### \ No newline at end of file
diff --git a/cpu/arm_cortexa9/config.mk b/cpu/arm_cortexa9/config.mk
new file mode 100755
index 000000000..3036fa624
--- /dev/null
+++ b/cpu/arm_cortexa9/config.mk
@@ -0,0 +1,36 @@
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <gj@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
+#
+PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
+ -msoft-float
+
+# Make ARMv5 to allow more compilers to work, even though its v7a.
+PLATFORM_CPPFLAGS += -march=armv7-a -mcpu=cortex-a9
+# =========================================================================
+#
+# Supply options according to compiler version
+#
+# =========================================================================
+PLATFORM_CPPFLAGS +=$(call cc-option)
+PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,)
+PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\
+ $(call cc-option,-malignment-traps,))
diff --git a/cpu/arm_cortexa9/cpu.c b/cpu/arm_cortexa9/cpu.c
new file mode 100755
index 000000000..02e716b6d
--- /dev/null
+++ b/cpu/arm_cortexa9/cpu.c
@@ -0,0 +1,249 @@
+/*
+ * (C) Copyright 2008 Texas Insturments
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+
+#ifdef CONFIG_USE_IRQ
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+#ifndef CONFIG_L2_OFF
+void l2cache_enable(void);
+void l2cache_disable(void);
+#endif
+
+static void cache_flush(void);
+
+/* read co-processor 15, register #1 (control register) */
+static unsigned long read_p15_c1(void)
+{
+ unsigned long value;
+
+ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 0\
+ @ read control reg\n":"=r"(value)
+ ::"memory");
+ return value;
+}
+
+/* write to co-processor 15, register #1 (control register) */
+static void write_p15_c1(unsigned long value)
+{
+ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 0\
+ @ write it back\n"::"r"(value)
+ : "memory");
+
+ read_p15_c1();
+}
+
+static void cp_delay(void)
+{
+ /* Many OMAP regs need at least 2 nops */
+ asm("nop");
+ asm("nop");
+}
+
+/* See also ARM Ref. Man. */
+#define C1_MMU (1<<0) /* mmu off/on */
+#define C1_ALIGN (1<<1) /* alignment faults off/on */
+#define C1_DC (1<<2) /* dcache off/on */
+#define C1_WB (1<<3) /* merging write buffer on/off */
+#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */
+#define C1_SYS_PROT (1<<8) /* system protection */
+#define C1_ROM_PROT (1<<9) /* ROM protection */
+#define C1_IC (1<<12) /* icache off/on */
+#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */
+#define RESERVED_1 (0xf << 3) /* must be 111b for R/W */
+
+int cpu_init(void)
+{
+ /*
+ * setup up stacks if necessary
+ */
+#ifdef CONFIG_USE_IRQ
+ IRQ_STACK_START =
+ _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4;
+ FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
+#endif
+ return 0;
+}
+
+int cleanup_before_linux(void)
+{
+ unsigned int i;
+
+ /*
+ * this function is called just before we call linux
+ * it prepares the processor for linux
+ *
+ * we turn off caches etc ...
+ */
+ disable_interrupts();
+
+ /* turn off I/D-cache */
+ icache_disable();
+ dcache_disable();
+
+ /* invalidate I-cache */
+ cache_flush();
+
+#ifndef CONFIG_L2_OFF
+ /* turn off L2 cache */
+ l2cache_disable();
+ /* invalidate L2 cache also */
+ v7_flush_dcache_all(get_device_type());
+#endif
+ i = 0;
+ /* mem barrier to sync up things */
+ asm("mcr p15, 0, %0, c7, c10, 4": :"r"(i));
+
+#ifndef CONFIG_L2_OFF
+ l2cache_enable();
+#endif
+#ifdef CONFIG_U8500
+ *((volatile unsigned int *)(0xA04127CC)) = 0xFF;
+ while (*((volatile unsigned int *)(0xA04127CC)) & 0xFF);
+ *((volatile unsigned int *)(0xA0412900)) = 0xFF;
+ *((volatile unsigned int *)(0xA0412904)) = 0xFF;
+#endif
+ return 0;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ disable_interrupts();
+ reset_cpu(0);
+
+ /* NOTREACHED */
+ return 0;
+}
+
+void icache_enable(void)
+{
+ ulong reg;
+
+ reg = read_p15_c1(); /* get control reg. */
+ cp_delay();
+ write_p15_c1(reg | C1_IC);
+}
+
+void icache_disable(void)
+{
+ ulong reg;
+
+ reg = read_p15_c1();
+ cp_delay();
+ write_p15_c1(reg & ~C1_IC);
+}
+
+void dcache_disable (void)
+{
+ ulong reg;
+
+ reg = read_p15_c1 ();
+ cp_delay ();
+ write_p15_c1 (reg & ~C1_DC);
+}
+
+#ifndef CONFIG_U8500
+void l2cache_enable()
+{
+ unsigned long i;
+ volatile unsigned int j;
+
+ /* ES2 onwards we can disable/enable L2 ourselves */
+ if (get_cpu_rev() == CPU_3430_ES2) {
+ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i));
+ __asm__ __volatile__("orr %0, %0, #0x2":"=r"(i));
+ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i));
+ } else {
+ /* Save r0, r12 and restore them after usage */
+ __asm__ __volatile__("mov %0, r12":"=r"(j));
+ __asm__ __volatile__("mov %0, r0":"=r"(i));
+
+ /*
+ * GP Device ROM code API usage here
+ * r12 = AUXCR Write function and r0 value
+ */
+ __asm__ __volatile__("mov r12, #0x3");
+ __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1");
+ __asm__ __volatile__("orr r0, r0, #0x2");
+ /* SMI instruction to call ROM Code API */
+ __asm__ __volatile__(".word 0xE1600070");
+ __asm__ __volatile__("mov r0, %0":"=r"(i));
+ __asm__ __volatile__("mov r12, %0":"=r"(j));
+ }
+}
+#endif
+
+void l2cache_disable()
+{
+#ifndef CONFIG_U8500
+ unsigned long i;
+ volatile unsigned int j;
+
+ /* ES2 onwards we can disable/enable L2 ourselves */
+ if (get_cpu_rev() == CPU_3430_ES2) {
+ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i));
+ __asm__ __volatile__("bic %0, %0, #0x2":"=r"(i));
+ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i));
+ } else {
+ /* Save r0, r12 and restore them after usage */
+ __asm__ __volatile__("mov %0, r12":"=r"(j));
+ __asm__ __volatile__("mov %0, r0":"=r"(i));
+
+ /*
+ * GP Device ROM code API usage here
+ * r12 = AUXCR Write function and r0 value
+ */
+ __asm__ __volatile__("mov r12, #0x3");
+ __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1");
+ __asm__ __volatile__("bic r0, r0, #0x2");
+ /* SMI instruction to call ROM Code API */
+ __asm__ __volatile__(".word 0xE1600070");
+ __asm__ __volatile__("mov r0, %0":"=r"(i));
+ __asm__ __volatile__("mov r12, %0":"=r"(j));
+ }
+#endif
+}
+
+int icache_status(void)
+{
+ return (read_p15_c1() & C1_IC) != 0;
+}
+
+static void cache_flush(void)
+{
+ asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
+}
+
diff --git a/cpu/arm_cortexa9/start.S b/cpu/arm_cortexa9/start.S
new file mode 100755
index 000000000..62c9e5a53
--- /dev/null
+++ b/cpu/arm_cortexa9/start.S
@@ -0,0 +1,524 @@
+/*
+ * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
+ *
+ * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
+ *
+ * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
+ * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
+ * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
+ * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
+ * Copyright (c) 2003 Kshitij <kshitij@ti.com>
+ * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <version.h>
+
+.globl _start
+_start: b reset
+ ldr pc, _undefined_instruction
+ ldr pc, _software_interrupt
+ ldr pc, _prefetch_abort
+ ldr pc, _data_abort
+ ldr pc, _not_used
+ ldr pc, _irq
+ ldr pc, _fiq
+
+_undefined_instruction: .word undefined_instruction
+_software_interrupt: .word software_interrupt
+_prefetch_abort: .word prefetch_abort
+_data_abort: .word data_abort
+_not_used: .word not_used
+_irq: .word irq
+_fiq: .word fiq
+_pad: .word 0x12345678 /* now 16*4=64 */
+.global _end_vect
+_end_vect:
+
+ .balignl 16,0xdeadbeef
+/*************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************/
+
+_TEXT_BASE:
+ .word TEXT_BASE
+
+.globl _armboot_start
+_armboot_start:
+ .word _start
+
+/*
+ * These are defined in the board-specific linker script.
+ */
+.globl _bss_start
+_bss_start:
+ .word __bss_start
+
+.globl _bss_end
+_bss_end:
+ .word _end
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+ .word 0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+ .word 0x0badc0de
+#endif
+
+/*
+ * the actual reset code
+ */
+
+reset:
+ /*
+ * set the cpu to SVC32 mode
+ */
+ mrs r0, cpsr
+ bic r0, r0, #0x1f
+ orr r0, r0, #0xd3
+ msr cpsr,r0
+
+#if (CONFIG_OMAP34XX)
+ /* Copy vectors to mask ROM indirect addr */
+ adr r0, _start @ r0 <- current position of code
+ add r0, r0, #4 @ skip reset vector
+ mov r2, #64 @ r2 <- size to copy
+ add r2, r0, r2 @ r2 <- source end address
+ mov r1, #SRAM_OFFSET0 @ build vect addr
+ mov r3, #SRAM_OFFSET1
+ add r1, r1, r3
+ mov r3, #SRAM_OFFSET2
+ add r1, r1, r3
+next:
+ ldmia r0!, {r3 - r10} @ copy from source address [r0]
+ stmia r1!, {r3 - r10} @ copy to target address [r1]
+ cmp r0, r2 @ until source end address [r2]
+ bne next @ loop until equal */
+#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
+ /* No need to copy/exec the clock code - DPLL adjust already done
+ * in NAND/oneNAND Boot.
+ */
+ bl cpy_clk_code @ put dpll adjust code behind vectors
+#endif /* NAND Boot */
+#endif
+ /* the mask ROM code should have PLL and others stable */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ bl cpu_init_crit
+#endif
+
+#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+relocate: @ relocate U-Boot to RAM
+ adr r0, _start @ r0 <- current position of code
+ ldr r1, _TEXT_BASE @ test if we run from flash or RAM
+ cmp r0, r1 @ don't reloc during debug
+ beq stack_setup
+
+ ldr r2, _armboot_start
+ ldr r3, _bss_start
+ sub r2, r3, r2 @ r2 <- size of armboot
+ add r2, r0, r2 @ r2 <- source end address
+
+copy_loop: @ copy 32 bytes at a time
+ ldmia r0!, {r3 - r10} @ copy from source address [r0]
+ stmia r1!, {r3 - r10} @ copy to target address [r1]
+ cmp r0, r2 @ until source end addreee [r2]
+ ble copy_loop
+#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
+
+ /* Set up the stack */
+stack_setup:
+ ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot
+ sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
+ sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
+#ifdef CONFIG_USE_IRQ
+ sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
+#endif
+ sub sp, r0, #12 @ leave 3 words for abort-stack
+ and sp, sp, #~7 @ 8 byte alinged for (ldr/str)d
+
+ /* Clear BSS (if any). Is below tx (watch load addr - need space) */
+clear_bss:
+ ldr r0, _bss_start @ find start of bss segment
+ ldr r1, _bss_end @ stop here
+ mov r2, #0x00000000 @ clear value
+clbss_l:
+ str r2, [r0] @ clear BSS location
+ cmp r0, r1 @ are we at the end yet
+ add r0, r0, #4 @ increment clear index pointer
+ bne clbss_l @ keep clearing till at end
+
+ ldr pc, _start_armboot @ jump to C code
+
+_start_armboot: .word start_armboot
+
+
+/*************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************/
+cpu_init_crit:
+ /*
+ * Invalidate L1 I/D
+ */
+ mov r0, #0 @ set up for MCR
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
+
+ /*
+ * disable MMU stuff and caches
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
+ bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
+ orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
+ orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
+ mcr p15, 0, r0, c1, c0, 0
+
+ /*
+ * Jump to board specific initialization...
+ * The Mask ROM will have already initialized
+ * basic memory. Go here to bump up clock rate and handle
+ * wake up conditions.
+ */
+ mov ip, lr @ persevere link reg across call
+#ifndef CONFIG_U8500
+ bl lowlevel_init @ go setup pll,mux,memory
+#endif
+ mov lr, ip @ restore link
+ mov pc, lr @ back to my caller
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE 72
+
+#define S_OLD_R0 68
+#define S_PSR 64
+#define S_PC 60
+#define S_LR 56
+#define S_SP 52
+
+#define S_IP 48
+#define S_FP 44
+#define S_R10 40
+#define S_R9 36
+#define S_R8 32
+#define S_R7 28
+#define S_R6 24
+#define S_R5 20
+#define S_R4 16
+#define S_R3 12
+#define S_R2 8
+#define S_R1 4
+#define S_R0 0
+
+#define MODE_SVC 0x13
+#define I_BIT 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+ .macro bad_save_user_regs
+ sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current
+ @ user stack
+ stmia sp, {r0 - r12} @ Save user registers (now in
+ @ svc mode) r0-r12
+
+ ldr r2, _armboot_start
+ sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
+ sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort
+ @ stack
+ ldmia r2, {r2 - r3} @ get values for "aborted" pc
+ @ and cpsr (into parm regs)
+ add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
+
+ add r5, sp, #S_SP
+ mov r1, lr
+ stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
+ mov r0, sp @ save current stack into r0
+ @ (param register)
+ .endm
+
+ .macro irq_save_user_regs
+ sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ Calling r0-r12
+ add r8, sp, #S_PC @ !! R8 NEEDS to be saved !!
+ @ a reserved stack spot would
+ @ be good.
+ stmdb r8, {sp, lr}^ @ Calling SP, LR
+ str lr, [r8, #0] @ Save calling PC
+ mrs r6, spsr
+ str r6, [r8, #4] @ Save CPSR
+ str r0, [r8, #8] @ Save OLD_R0
+ mov r0, sp
+ .endm
+
+ .macro irq_restore_user_regs
+ ldmia sp, {r0 - lr}^ @ Calling r0 - lr
+ mov r0, r0
+ ldr lr, [sp, #S_PC] @ Get PC
+ add sp, sp, #S_FRAME_SIZE
+ subs pc, lr, #4 @ return & move spsr_svc into
+ @ cpsr
+ .endm
+
+ .macro get_bad_stack
+ ldr r13, _armboot_start @ setup our mode stack (enter
+ @ in banked mode)
+ sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool
+ sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple
+ @ spots for abort stack
+
+ str lr, [r13] @ save caller lr in position 0
+ @ of saved stack
+ mrs lr, spsr @ get the spsr
+ str lr, [r13, #4] @ save spsr in position 1 of
+ @ saved stack
+
+ mov r13, #MODE_SVC @ prepare SVC-Mode
+ @ msr spsr_c, r13
+ msr spsr, r13 @ switch modes, make sure
+ @ moves will execute
+ mov lr, pc @ capture return pc
+ movs pc, lr @ jump to next instruction &
+ @ switch modes.
+ .endm
+
+ .macro get_bad_stack_swi
+ sub r13, r13, #4 @ space on current stack for
+ @ scratch reg.
+ str r0, [r13] @ save R0's value.
+ ldr r0, _armboot_start @ get data regions start
+ sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool
+ sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple
+ @ spots for abort stack
+ str lr, [r0] @ save caller lr in position 0
+ @ of saved stack
+ mrs r0, spsr @ get the spsr
+ str lr, [r0, #4] @ save spsr in position 1 of
+ @ saved stack
+ ldr r0, [r13] @ restore r0
+ add r13, r13, #4 @ pop stack entry
+ .endm
+
+ .macro get_irq_stack @ setup IRQ stack
+ ldr sp, IRQ_STACK_START
+ .endm
+
+ .macro get_fiq_stack @ setup FIQ stack
+ ldr sp, FIQ_STACK_START
+ .endm
+
+/*
+ * exception handlers
+ */
+ .align 5
+undefined_instruction:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_undefined_instruction
+
+ .align 5
+software_interrupt:
+ get_bad_stack_swi
+ bad_save_user_regs
+ bl do_software_interrupt
+
+ .align 5
+prefetch_abort:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_prefetch_abort
+
+ .align 5
+data_abort:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_data_abort
+
+ .align 5
+not_used:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+ .align 5
+irq:
+ get_irq_stack
+ irq_save_user_regs
+ bl do_irq
+ irq_restore_user_regs
+
+ .align 5
+fiq:
+ get_fiq_stack
+ /* someone ought to write a more effective fiq_save_user_regs */
+ irq_save_user_regs
+ bl do_fiq
+ irq_restore_user_regs
+
+#else
+
+ .align 5
+irq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_irq
+
+ .align 5
+fiq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_fiq
+
+#endif
+
+/*
+ * v7_flush_dcache_all()
+ *
+ * Flush the whole D-cache.
+ *
+ * Corrupted registers: r0-r5, r7, r9-r11
+ *
+ * - mm - mm_struct describing address space
+ */
+ .align 5
+.global v7_flush_dcache_all
+v7_flush_dcache_all:
+ stmfd r13!, {r0 - r5, r7, r9 - r12, r14}
+
+ mov r7, r0 @ take a backup of device type
+ cmp r0, #0x3 @ check if the device type is
+ @ GP
+ moveq r12, #0x1 @ set up to invalide L2
+smi: .word 0x01600070 @ Call SMI monitor (smieq)
+ cmp r7, #0x3 @ compare again in case its
+ @ lost
+ beq finished_inval @ if GP device, inval done
+ @ above
+
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished_inval @ if loc is 0, then no need to
+ @ clean
+ mov r10, #0 @ start clean at cache level 0
+inval_loop1:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache
+ @ level
+ mov r1, r0, lsr r2 @ extract cache type bits from
+ @ clidr
+ and r1, r1, #7 @ mask of the bits for current
+ @ cache only
+ cmp r1, #2 @ see what cache we have at
+ @ this level
+ blt skip_inval @ skip if no cache, or just
+ @ i-cache
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level
+ @ in cssr
+ mov r2, #0 @ operand for mcr SBZ
+ mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to
+ @ sych the new cssr&csidr,
+ @ with armv7 this is 'isb',
+ @ but we compile with armv5
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ and r2, r1, #7 @ extract the length of the
+ @ cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the
+ @ way size
+ clz r5, r4 @ find bit position of way
+ @ size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the
+ @ index size
+inval_loop2:
+ mov r9, r4 @ create working copy of max
+ @ way size
+inval_loop3:
+ orr r11, r10, r9, lsl r5 @ factor way and cache number
+ @ into r11
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way
+ subs r9, r9, #1 @ decrement the way
+ bge inval_loop3
+ subs r7, r7, #1 @ decrement the index
+ bge inval_loop2
+skip_inval:
+ add r10, r10, #2 @ increment cache number
+ cmp r3, r10
+ bgt inval_loop1
+finished_inval:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level
+ @ in cssr
+ mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer,
+ @ with armv7 this is 'isb',
+ @ but we compile with armv5
+
+ ldmfd r13!, {r0 - r5, r7, r9 - r12, pc}
+
+
+ .align 5
+.global reset_cpu
+reset_cpu:
+#if defined CONFIG_U8500
+ ldr r0, =CFG_PRCMU_BASE
+ ldr r1, =0x1
+ str r1, [r0, #0x1F0]
+#else
+ ldr r1, rstctl @ get addr for global reset
+ @ reg
+ mov r3, #0x2 @ full reset pll + mpu
+ str r3, [r1] @ force reset
+ mov r0, r0
+#endif
+_loop_forever:
+ b _loop_forever
+rstctl:
+ .word 0x48307250
diff --git a/cpu/arm_cortexa9/start.S.bak b/cpu/arm_cortexa9/start.S.bak
new file mode 100755
index 000000000..6bd65521b
--- /dev/null
+++ b/cpu/arm_cortexa9/start.S.bak
@@ -0,0 +1,502 @@
+/*
+ * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
+ *
+ * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
+ *
+ * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
+ * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
+ * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
+ * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
+ * Copyright (c) 2003 Kshitij <kshitij@ti.com>
+ * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <version.h>
+
+.globl _start
+_start: b reset
+ ldr pc, _undefined_instruction
+ ldr pc, _software_interrupt
+ ldr pc, _prefetch_abort
+ ldr pc, _data_abort
+ ldr pc, _not_used
+ ldr pc, _irq
+ ldr pc, _fiq
+
+_undefined_instruction: .word undefined_instruction
+_software_interrupt: .word software_interrupt
+_prefetch_abort: .word prefetch_abort
+_data_abort: .word data_abort
+_not_used: .word not_used
+_irq: .word irq
+_fiq: .word fiq
+_pad: .word 0x12345678 /* now 16*4=64 */
+.global _end_vect
+_end_vect:
+
+ .balignl 16,0xdeadbeef
+/*************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************/
+
+_TEXT_BASE:
+ .word TEXT_BASE
+
+.globl _armboot_start
+_armboot_start:
+ .word _start
+
+/*
+ * These are defined in the board-specific linker script.
+ */
+.globl _bss_start
+_bss_start:
+ .word __bss_start
+
+.globl _bss_end
+_bss_end:
+ .word _end
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+ .word 0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+ .word 0x0badc0de
+#endif
+
+/*
+ * the actual reset code
+ */
+
+reset:
+ /*
+ * set the cpu to SVC32 mode
+ */
+ mrs r0, cpsr
+ bic r0, r0, #0x1f
+ orr r0, r0, #0xd3
+ msr cpsr,r0
+
+#if (CONFIG_OMAP34XX)
+ /* Copy vectors to mask ROM indirect addr */
+ adr r0, _start @ r0 <- current position of code
+ add r0, r0, #4 @ skip reset vector
+ mov r2, #64 @ r2 <- size to copy
+ add r2, r0, r2 @ r2 <- source end address
+ mov r1, #SRAM_OFFSET0 @ build vect addr
+ mov r3, #SRAM_OFFSET1
+ add r1, r1, r3
+ mov r3, #SRAM_OFFSET2
+ add r1, r1, r3
+next:
+ ldmia r0!, {r3 - r10} @ copy from source address [r0]
+ stmia r1!, {r3 - r10} @ copy to target address [r1]
+ cmp r0, r2 @ until source end address [r2]
+ bne next @ loop until equal */
+#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
+ /* No need to copy/exec the clock code - DPLL adjust already done
+ * in NAND/oneNAND Boot.
+ */
+ bl cpy_clk_code @ put dpll adjust code behind vectors
+#endif /* NAND Boot */
+#endif
+ /* the mask ROM code should have PLL and others stable */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ bl cpu_init_crit
+#endif
+
+#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+relocate: @ relocate U-Boot to RAM
+ adr r0, _start @ r0 <- current position of code
+ ldr r1, _TEXT_BASE @ test if we run from flash or RAM
+ cmp r0, r1 @ don't reloc during debug
+ beq stack_setup
+
+ ldr r2, _armboot_start
+ ldr r3, _bss_start
+ sub r2, r3, r2 @ r2 <- size of armboot
+ add r2, r0, r2 @ r2 <- source end address
+
+copy_loop: @ copy 32 bytes at a time
+ ldmia r0!, {r3 - r10} @ copy from source address [r0]
+ stmia r1!, {r3 - r10} @ copy to target address [r1]
+ cmp r0, r2 @ until source end addreee [r2]
+ ble copy_loop
+#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
+
+ /* Set up the stack */
+stack_setup:
+ ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot
+ sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
+ sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
+#ifdef CONFIG_USE_IRQ
+ sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
+#endif
+ sub sp, r0, #12 @ leave 3 words for abort-stack
+ and sp, sp, #~7 @ 8 byte alinged for (ldr/str)d
+
+ /* Clear BSS (if any). Is below tx (watch load addr - need space) */
+clear_bss:
+ ldr r0, _bss_start @ find start of bss segment
+ ldr r1, _bss_end @ stop here
+ mov r2, #0x00000000 @ clear value
+clbss_l:
+ str r2, [r0] @ clear BSS location
+ cmp r0, r1 @ are we at the end yet
+ add r0, r0, #4 @ increment clear index pointer
+ bne clbss_l @ keep clearing till at end
+
+ ldr pc, _start_armboot @ jump to C code
+
+_start_armboot: .word start_armboot
+
+
+/*************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************/
+cpu_init_crit:
+ /*
+ * Invalidate L1 I/D
+ */
+ mov r0, #0 @ set up for MCR
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
+
+ /*
+ * disable MMU stuff and caches
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
+ bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
+ orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
+ orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
+ mcr p15, 0, r0, c1, c0, 0
+
+ /*
+ * Jump to board specific initialization...
+ * The Mask ROM will have already initialized
+ * basic memory. Go here to bump up clock rate and handle
+ * wake up conditions.
+ */
+ mov ip, lr @ persevere link reg across call
+ bl lowlevel_init @ go setup pll,mux,memory
+ mov lr, ip @ restore link
+ mov pc, lr @ back to my caller
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE 72
+
+#define S_OLD_R0 68
+#define S_PSR 64
+#define S_PC 60
+#define S_LR 56
+#define S_SP 52
+
+#define S_IP 48
+#define S_FP 44
+#define S_R10 40
+#define S_R9 36
+#define S_R8 32
+#define S_R7 28
+#define S_R6 24
+#define S_R5 20
+#define S_R4 16
+#define S_R3 12
+#define S_R2 8
+#define S_R1 4
+#define S_R0 0
+
+#define MODE_SVC 0x13
+#define I_BIT 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+ .macro bad_save_user_regs
+ sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current
+ @ user stack
+ stmia sp, {r0 - r12} @ Save user registers (now in
+ @ svc mode) r0-r12
+
+ ldr r2, _armboot_start
+ sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
+ sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort
+ @ stack
+ ldmia r2, {r2 - r3} @ get values for "aborted" pc
+ @ and cpsr (into parm regs)
+ add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
+
+ add r5, sp, #S_SP
+ mov r1, lr
+ stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
+ mov r0, sp @ save current stack into r0
+ @ (param register)
+ .endm
+
+ .macro irq_save_user_regs
+ sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ Calling r0-r12
+ add r8, sp, #S_PC @ !! R8 NEEDS to be saved !!
+ @ a reserved stack spot would
+ @ be good.
+ stmdb r8, {sp, lr}^ @ Calling SP, LR
+ str lr, [r8, #0] @ Save calling PC
+ mrs r6, spsr
+ str r6, [r8, #4] @ Save CPSR
+ str r0, [r8, #8] @ Save OLD_R0
+ mov r0, sp
+ .endm
+
+ .macro irq_restore_user_regs
+ ldmia sp, {r0 - lr}^ @ Calling r0 - lr
+ mov r0, r0
+ ldr lr, [sp, #S_PC] @ Get PC
+ add sp, sp, #S_FRAME_SIZE
+ subs pc, lr, #4 @ return & move spsr_svc into
+ @ cpsr
+ .endm
+
+ .macro get_bad_stack
+ ldr r13, _armboot_start @ setup our mode stack (enter
+ @ in banked mode)
+ sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool
+ sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple
+ @ spots for abort stack
+
+ str lr, [r13] @ save caller lr in position 0
+ @ of saved stack
+ mrs lr, spsr @ get the spsr
+ str lr, [r13, #4] @ save spsr in position 1 of
+ @ saved stack
+
+ mov r13, #MODE_SVC @ prepare SVC-Mode
+ @ msr spsr_c, r13
+ msr spsr, r13 @ switch modes, make sure
+ @ moves will execute
+ mov lr, pc @ capture return pc
+ movs pc, lr @ jump to next instruction &
+ @ switch modes.
+ .endm
+
+ .macro get_bad_stack_swi
+ sub r13, r13, #4 @ space on current stack for
+ @ scratch reg.
+ str r0, [r13] @ save R0's value.
+ ldr r0, _armboot_start @ get data regions start
+ sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool
+ sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple
+ @ spots for abort stack
+ str lr, [r0] @ save caller lr in position 0
+ @ of saved stack
+ mrs r0, spsr @ get the spsr
+ str lr, [r0, #4] @ save spsr in position 1 of
+ @ saved stack
+ ldr r0, [r13] @ restore r0
+ add r13, r13, #4 @ pop stack entry
+ .endm
+
+ .macro get_irq_stack @ setup IRQ stack
+ ldr sp, IRQ_STACK_START
+ .endm
+
+ .macro get_fiq_stack @ setup FIQ stack
+ ldr sp, FIQ_STACK_START
+ .endm
+
+/*
+ * exception handlers
+ */
+ .align 5
+undefined_instruction:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_undefined_instruction
+
+ .align 5
+software_interrupt:
+ get_bad_stack_swi
+ bad_save_user_regs
+ bl do_software_interrupt
+
+ .align 5
+prefetch_abort:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_prefetch_abort
+
+ .align 5
+data_abort:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_data_abort
+
+ .align 5
+not_used:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+ .align 5
+irq:
+ get_irq_stack
+ irq_save_user_regs
+ bl do_irq
+ irq_restore_user_regs
+
+ .align 5
+fiq:
+ get_fiq_stack
+ /* someone ought to write a more effective fiq_save_user_regs */
+ irq_save_user_regs
+ bl do_fiq
+ irq_restore_user_regs
+
+#else
+
+ .align 5
+irq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_irq
+
+ .align 5
+fiq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_fiq
+
+#endif
+
+/*
+ * v7_flush_dcache_all()
+ *
+ * Flush the whole D-cache.
+ *
+ * Corrupted registers: r0-r5, r7, r9-r11
+ *
+ * - mm - mm_struct describing address space
+ */
+ .align 5
+.global v7_flush_dcache_all
+v7_flush_dcache_all:
+ stmfd r13!, {r0 - r5, r7, r9 - r12, r14}
+
+ mov r7, r0 @ take a backup of device type
+ cmp r0, #0x3 @ check if the device type is
+ @ GP
+ moveq r12, #0x1 @ set up to invalide L2
+smi: .word 0x01600070 @ Call SMI monitor (smieq)
+ cmp r7, #0x3 @ compare again in case its
+ @ lost
+ beq finished_inval @ if GP device, inval done
+ @ above
+
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished_inval @ if loc is 0, then no need to
+ @ clean
+ mov r10, #0 @ start clean at cache level 0
+inval_loop1:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache
+ @ level
+ mov r1, r0, lsr r2 @ extract cache type bits from
+ @ clidr
+ and r1, r1, #7 @ mask of the bits for current
+ @ cache only
+ cmp r1, #2 @ see what cache we have at
+ @ this level
+ blt skip_inval @ skip if no cache, or just
+ @ i-cache
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level
+ @ in cssr
+ mov r2, #0 @ operand for mcr SBZ
+ mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to
+ @ sych the new cssr&csidr,
+ @ with armv7 this is 'isb',
+ @ but we compile with armv5
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ and r2, r1, #7 @ extract the length of the
+ @ cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the
+ @ way size
+ clz r5, r4 @ find bit position of way
+ @ size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the
+ @ index size
+inval_loop2:
+ mov r9, r4 @ create working copy of max
+ @ way size
+inval_loop3:
+ orr r11, r10, r9, lsl r5 @ factor way and cache number
+ @ into r11
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way
+ subs r9, r9, #1 @ decrement the way
+ bge inval_loop3
+ subs r7, r7, #1 @ decrement the index
+ bge inval_loop2
+skip_inval:
+ add r10, r10, #2 @ increment cache number
+ cmp r3, r10
+ bgt inval_loop1
+finished_inval:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level
+ @ in cssr
+ mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer,
+ @ with armv7 this is 'isb',
+ @ but we compile with armv5
+
+ ldmfd r13!, {r0 - r5, r7, r9 - r12, pc}
diff --git a/cpu/arm_cortexa9/stw8500/Makefile b/cpu/arm_cortexa9/stw8500/Makefile
new file mode 100755
index 000000000..6e0fe8af4
--- /dev/null
+++ b/cpu/arm_cortexa9/stw8500/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# 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 $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(SOC).a
+
+COBJS = timer.o interrupts.o
+
+SRCS := $(START:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/arm_cortexa9/stw8500/interrupts.c b/cpu/arm_cortexa9/stw8500/interrupts.c
new file mode 100755
index 000000000..4357ede39
--- /dev/null
+++ b/cpu/arm_cortexa9/stw8500/interrupts.c
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2006, NXP BV
+ * Jean-Paul Saman
+ *
+ * (C) Copyright 2004
+ * Texas Instruments
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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 <asm/arch/bits.h>
+#include <asm/proc-armv/ptrace.h>
+
+extern void reset_cpu(ulong addr);
+
+#ifdef CONFIG_USE_IRQ
+/* enable IRQ interrupts */
+void enable_interrupts (void)
+{
+ unsigned long temp;
+ __asm__ __volatile__("mrs %0, cpsr\n"
+ "bic %0, %0, #0x80\n"
+ "msr cpsr_c, %0"
+ : "=r" (temp)
+ :
+ : "memory");
+}
+
+/*
+ * disable IRQ/FIQ interrupts
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts (void)
+{
+ unsigned long old,temp;
+ __asm__ __volatile__("mrs %0, cpsr\n"
+ "orr %1, %0, #0xc0\n"
+ "msr cpsr_c, %1"
+ : "=r" (old), "=r" (temp)
+ :
+ : "memory");
+ return(old & 0x80) == 0;
+}
+#else
+void enable_interrupts (void)
+{
+ return;
+}
+int disable_interrupts (void)
+{
+ return 0;
+}
+#endif
+
+
+void bad_mode (void)
+{
+ panic ("Resetting CPU ...\n");
+ reset_cpu (0);
+}
+
+void show_regs (struct pt_regs *regs)
+{
+ unsigned long flags;
+ const char *processor_modes[] = {
+ "USER_26", "FIQ_26", "IRQ_26", "SVC_26",
+ "UK4_26", "UK5_26", "UK6_26", "UK7_26",
+ "UK8_26", "UK9_26", "UK10_26", "UK11_26",
+ "UK12_26", "UK13_26", "UK14_26", "UK15_26",
+ "USER_32", "FIQ_32", "IRQ_32", "SVC_32",
+ "UK4_32", "UK5_32", "UK6_32", "ABT_32",
+ "UK8_32", "UK9_32", "UK10_32", "UND_32",
+ "UK12_32", "UK13_32", "UK14_32", "SYS_32",
+ };
+
+ flags = condition_codes (regs);
+
+ printf ("pc : [<%08lx>] lr : [<%08lx>]\n"
+ "sp : %08lx ip : %08lx fp : %08lx\n",
+ instruction_pointer (regs),
+ regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+ printf ("r10: %08lx r9 : %08lx r8 : %08lx\n",
+ regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
+ printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
+ regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
+ printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
+ regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
+ printf ("Flags: %c%c%c%c",
+ flags & CC_N_BIT ? 'N' : 'n',
+ flags & CC_Z_BIT ? 'Z' : 'z',
+ flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
+ printf (" IRQs %s FIQs %s Mode %s%s\n",
+ interrupts_enabled (regs) ? "on" : "off",
+ fast_interrupts_enabled (regs) ? "on" : "off",
+ processor_modes[processor_mode (regs)],
+ thumb_mode (regs) ? " (T)" : "");
+}
+
+void do_undefined_instruction (struct pt_regs *pt_regs)
+{
+ printf ("undefined instruction\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+void do_software_interrupt (struct pt_regs *pt_regs)
+{
+ printf ("software interrupt\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+void do_prefetch_abort (struct pt_regs *pt_regs)
+{
+ printf ("prefetch abort\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+void do_data_abort (struct pt_regs *pt_regs)
+{
+ printf ("data abort\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+void do_not_used (struct pt_regs *pt_regs)
+{
+ printf ("not used\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+void do_fiq (struct pt_regs *pt_regs)
+{
+ printf ("fast interrupt request\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+void do_irq (struct pt_regs *pt_regs)
+{
+ printf ("interrupt request\n");
+ show_regs (pt_regs);
+ bad_mode ();
+}
+
+/* nothing really to do with interrupts, just starts up a counter. */
+int interrupt_init (void)
+{
+
+ (void) timer_init();
+
+ return(0);
+}
diff --git a/cpu/arm_cortexa9/stw8500/timer.c b/cpu/arm_cortexa9/stw8500/timer.c
new file mode 100755
index 000000000..16067c900
--- /dev/null
+++ b/cpu/arm_cortexa9/stw8500/timer.c
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2009 Alessandro Rubini
+ *
+ * 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/mtu.h>
+
+/*
+ * The timer is a decrementer, we'll left it free running at 2.4MHz.
+ * We have 2.4 ticks per microsecond and an overflow in almost 30min
+ */
+#define TIMER_CLOCK (24 * 100 * 1000)
+#define COUNT_TO_USEC(x) ((x) * 5 / 12) /* overflows at 6min */
+#define USEC_TO_COUNT(x) ((x) * 12 / 5) /* overflows at 6min */
+#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ)
+#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ)
+
+/* macro to read the 32 bit timer: since it decrements, we invert read value */
+#define READ_TIMER() (~readl(CONFIG_SYS_TIMERBASE + MTU_VAL(0)))
+
+/* Configure a free-running, auto-wrap counter with no prescaler */
+int timer_init(void)
+{
+ writel(MTU_CRn_ENA | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS,
+ CONFIG_SYS_TIMERBASE + MTU_CR(0));
+ reset_timer();
+ return 0;
+}
+
+/* Restart counting from 0 */
+void reset_timer(void)
+{
+ writel(0, CONFIG_SYS_TIMERBASE + MTU_LR(0)); /* Immediate effect */
+}
+
+/* Return how many HZ passed since "base" */
+ulong get_timer(ulong base)
+{
+ return TICKS_TO_HZ(READ_TIMER()) - base;
+}
+
+/* Delay x useconds */
+void udelay(unsigned long usec)
+{
+ ulong ini, end;
+
+ ini = READ_TIMER();
+ end = ini + USEC_TO_COUNT(usec);
+ while ((signed)(end - READ_TIMER()) > 0)
+ ;
+}
diff --git a/cpu/arm_cortexa9/u-boot.lds b/cpu/arm_cortexa9/u-boot.lds
new file mode 100755
index 000000000..fc787cd5d
--- /dev/null
+++ b/cpu/arm_cortexa9/u-boot.lds
@@ -0,0 +1,58 @@
+/*
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/arm_cortexa9/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ . = ALIGN(4);
+ __bss_start = .;
+ .bss : { *(.bss) }
+ _end = .;
+}
diff --git a/include/asm-arm/arch-stw8500/bits.h b/include/asm-arm/arch-stw8500/bits.h
new file mode 100755
index 000000000..08e16a2a8
--- /dev/null
+++ b/include/asm-arm/arch-stw8500/bits.h
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __bits_h
+#define __bits_h 1
+
+#define BIT0 (1<<0)
+#define BIT1 (1<<1)
+#define BIT2 (1<<2)
+#define BIT3 (1<<3)
+#define BIT4 (1<<4)
+#define BIT5 (1<<5)
+#define BIT6 (1<<6)
+#define BIT7 (1<<7)
+#define BIT8 (1<<8)
+#define BIT9 (1<<9)
+#define BIT10 (1<<10)
+#define BIT11 (1<<11)
+#define BIT12 (1<<12)
+#define BIT13 (1<<13)
+#define BIT14 (1<<14)
+#define BIT15 (1<<15)
+#define BIT16 (1<<16)
+#define BIT17 (1<<17)
+#define BIT18 (1<<18)
+#define BIT19 (1<<19)
+#define BIT20 (1<<20)
+#define BIT21 (1<<21)
+#define BIT22 (1<<22)
+#define BIT23 (1<<23)
+#define BIT24 (1<<24)
+#define BIT25 (1<<25)
+#define BIT26 (1<<26)
+#define BIT27 (1<<27)
+#define BIT28 (1<<28)
+#define BIT29 (1<<29)
+#define BIT30 (1<<30)
+#define BIT31 (1<<31)
+
+#endif
diff --git a/include/asm-arm/arch-stw8500/common.h b/include/asm-arm/arch-stw8500/common.h
new file mode 100755
index 000000000..b6185081a
--- /dev/null
+++ b/include/asm-arm/arch-stw8500/common.h
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+#include <common.h>
+
+#define PASS (1)
+#define FAIL (0)
+
+#define IO(addr) (*((u32*) (addr)))
+#define HIO(addr) (*((u16*) (addr)))
+#define BIO(addr) (*((u8*) (addr)))
+
+/*
+ * macro to get at IO space
+ */
+#define IO_ADDRESS(x) (x)
+
+#define REG_WRITE_BITS(reg,val,mask,sb) (writel(((readl(reg) & ~(mask)) | (((val)<<(sb)) & (mask))), reg))
+
+#define nmdk_error(format, arg...) printf(": " format "\n" , ## arg)
+
+#if !defined(FALSE) && !defined(TRUE)
+typedef enum {FALSE, TRUE} t_bool;
+#else /* FALSE & TRUE already defined */
+typedef enum {BOOL_FALSE, BOOL_TRUE} t_bool;
+#endif /* !defined(FALSE) && !defined(TRUE) */
+
+/*-----------------------------------------------------------------------------
+ * Bit mask definition
+ *---------------------------------------------------------------------------*/
+#define MASK_NULL8 0x00
+#define MASK_NULL16 0x0000
+#define MASK_NULL32 0x00000000
+#define MASK_ALL8 0xFF
+#define MASK_ALL16 0xFFFF
+#define MASK_ALL32 0xFFFFFFFF
+
+#define MASK_BIT0 (1UL<<0)
+#define MASK_BIT1 (1UL<<1)
+#define MASK_BIT2 (1UL<<2)
+#define MASK_BIT3 (1UL<<3)
+#define MASK_BIT4 (1UL<<4)
+#define MASK_BIT5 (1UL<<5)
+#define MASK_BIT6 (1UL<<6)
+#define MASK_BIT7 (1UL<<7)
+#define MASK_BIT8 (1UL<<8)
+#define MASK_BIT9 (1UL<<9)
+#define MASK_BIT10 (1UL<<10)
+#define MASK_BIT11 (1UL<<11)
+#define MASK_BIT12 (1UL<<12)
+#define MASK_BIT13 (1UL<<13)
+#define MASK_BIT14 (1UL<<14)
+#define MASK_BIT15 (1UL<<15)
+#define MASK_BIT16 (1UL<<16)
+#define MASK_BIT17 (1UL<<17)
+#define MASK_BIT18 (1UL<<18)
+#define MASK_BIT19 (1UL<<19)
+#define MASK_BIT20 (1UL<<20)
+#define MASK_BIT21 (1UL<<21)
+#define MASK_BIT22 (1UL<<22)
+#define MASK_BIT23 (1UL<<23)
+#define MASK_BIT24 (1UL<<24)
+#define MASK_BIT25 (1UL<<25)
+#define MASK_BIT26 (1UL<<26)
+#define MASK_BIT27 (1UL<<27)
+#define MASK_BIT28 (1UL<<28)
+#define MASK_BIT29 (1UL<<29)
+#define MASK_BIT30 (1UL<<30)
+#define MASK_BIT31 (1UL<<31)
+
+#define NOMADIK_INTERNAL_ERROR (-8)
+#define NOMADIK_NOT_CONFIGURED (-7)
+#define NOMADIK_REQUEST_PENDING (-6)
+#define NOMADIK_REQUEST_NOT_APPLICABLE (-5)
+#define NOMADIK_INVALID_PARAMETER (-4)
+#define NOMADIK_UNSUPPORTED_FEATURE (-3)
+#define NOMADIK_UNSUPPORTED_HW (-2)
+#define NOMADIK_ERROR (-1)
+#define NOMADIK_OK ( 0)
+#define NOMADIK_INTERNAL_EVENT ( 1)
+#define NOMADIK_REMAINING_PENDING_EVENTS ( 2)
+#define NOMADIK_REMAINING_FILTER_PENDING_EVENTS ( 3)
+#define NOMADIK_NO_MORE_PENDING_EVENT ( 4)
+#define NOMADIK_NO_MORE_FILTER_PENDING_EVENT ( 5)
+#define NOMADIK_NO_PENDING_EVENT_ERROR ( 7)
+
+
+#define NOMADIK_MAX_ERROR_VALUE (-65) /* HW specific error codes
+ * should start from this offset
+ */
+/*-----------------------------------------------------------------------------
+ * Bit setting or clearing
+ *---------------------------------------------------------------------------*/
+#define NOMADIK_SET_BITS(reg,mask) ((reg) |= (mask))
+#define NOMADIK_CLEAR_BITS(reg,mask) ((reg) &= ~(mask))
+#define NOMADIK_READ_BITS(reg,mask) ((reg) & (mask))
+#define NOMADIK_WRITE_BITS(reg,val,mask) ((reg) = (((reg) & ~(mask)) | ((val) & (mask))))
+#define NOMADIK_READ_REG(reg) (reg)
+#define NOMADIK_WRITE_REG(reg,val) ((reg) = (val))
+
+/*
+ * Definition of the different kind of addresses manipulated into a system with MMU
+ * (handle physical AND logical addresses)
+ */
+
+typedef u32 t_physical_address;
+typedef u32 t_logical_address;
+
+/*function prototypes*/
+void gpio_init(void);
+int emmc_init (u8);
+
+#endif /* _COMMON_H_ */
diff --git a/include/asm-arm/arch-stw8500/emmc.h b/include/asm-arm/arch-stw8500/emmc.h
new file mode 100755
index 000000000..aa4b48df0
--- /dev/null
+++ b/include/asm-arm/arch-stw8500/emmc.h
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _STM_EMMC_H
+#define _STM_EMMC_H
+
+
+#include <common.h>
+
+extern int emmc_init (u8);
+int emmc_erase(u32, u32);
+int emmc_read (u32,u32,u32);
+int emmc_write(u32,u32,u32);
+int emmc_write_pib(void);
+
+
+#endif /* !defined(_STM_EMMC_H) */
diff --git a/include/asm-arm/arch-stw8500/gpio.h b/include/asm-arm/arch-stw8500/gpio.h
new file mode 100755
index 000000000..26e14d04c
--- /dev/null
+++ b/include/asm-arm/arch-stw8500/gpio.h
@@ -0,0 +1,524 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _MOP500_GPIO_h
+#define _MOP500_GPIO_h
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include "common.h"
+#include <configs/u8500.h>
+
+#define GPIO_TOTAL_PINS 268
+
+#define GPIO_PINS_PER_BLOCK 32
+#define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK +1)
+#define GPIO_BLOCK(pin) ( ( ( pin + GPIO_PINS_PER_BLOCK ) >> 5) - 1 )
+
+
+struct gpio_register {
+ u32 gpio_dat; /* GPIO data register *//*0x000 */
+ u32 gpio_dats; /* GPIO data Set register *//*0x004 */
+ u32 gpio_datc; /* GPIO data Clear register *//*0x008 */
+ u32 gpio_pdis; /* GPIO Pull disable register *//*0x00C */
+ u32 gpio_dir; /* GPIO data direction register *//*0x010 */
+ u32 gpio_dirs; /* GPIO data dir Set register *//*0x014 */
+ u32 gpio_dirc; /* GPIO data dir Clear register *//*0x018 */
+ u32 gpio_slpm; /* GPIO Sleep mode register *//*0x01C */
+ u32 gpio_afsa; /* GPIO AltFun A Select reg *//*0x020 */
+ u32 gpio_afsb; /* GPIO AltFun B Select reg *//*0x024 */
+ u32 gpio_lowemi; /* GPIO low EMI Select reg *//*0x028 */
+ u32 reserved_1[(0x040 - 0x02C) >> 2]; /*0x028-0x3C Reserved*/
+ u32 gpio_rimsc; /* GPIO rising edge intr set/clear *//*0x040 */
+ u32 gpio_fimsc; /* GPIO falling edge interrupt set/clear register *//*0x044 */
+ u32 gpio_mis; /* GPIO masked interrupt status register *//*0x048 */
+ u32 gpio_ic; /* GPIO Interrupt Clear register *//*0x04C */
+ u32 gpio_rwimsc; /* GPIO Rising-edge Wakeup IMSC register *//*0x050 */
+ u32 gpio_fwimsc; /* GPIO Falling-edge Wakeup IMSC register *//*0x054 */
+ u32 gpio_wks; /* GPIO Wakeup Status register *//*0x058 */
+};
+
+/* Error values returned by functions */
+typedef enum {
+ GPIO_OK = 0, /* (0) */
+ GPIO_UNSUPPORTED_HW = -2, /* NOMADIK_UNSUPPORTED_HW, (-2) */
+ GPIO_UNSUPPORTED_FEATURE = -3, /* NOMADIK_UNSUPPORTED_FEATURE, (-3) */
+ GPIO_INVALID_PARAMETER = -4, /* NOMADIK_INVALID_PARAMETER, (-4) */
+ GPIO_REQUEST_NOT_APPLICABLE = -5, /* NOMADIK_REQUEST_NOT_APPLICABLE, (-5) */
+ GPIO_REQUEST_PENDING = -6, /* NOMADIK_REQUEST_PENDING, (-6) */
+ GPIO_NOT_CONFIGURED = -7, /* NOMADIK_NOT_CONFIGURED, (-7) */
+ GPIO_INTERNAL_ERROR = -8, /* NOMADIK_INTERNAL_ERROR, (-8) */
+ GPIO_INTERNAL_EVENT = 1, /* NOMADIK_INTERNAL_EVENT,*/
+ GPIO_REMAINING_EVENT = 2, /* NOMADIK_REMAINING_PENDING_EVENTS,*/
+ GPIO_NO_MORE_PENDING_EVENT = 3, /* NOMADIK_NO_MORE_PENDING_EVENT,*/
+ GPIO_INVALID_CLIENT = -25,
+ GPIO_INVALID_PIN = -26,
+ GPIO_PIN_BUSY = -27,
+ GPIO_PIN_NOT_ALLOCATED = -28,
+ GPIO_WRONG_CLIENT = -29,
+ GPIO_UNSUPPORTED_ALTFUNC = -30,
+
+} gpio_error;
+
+/*GPIO DEVICE ID */
+typedef enum {
+ GPIO_DEVICE_ID_0,
+ GPIO_DEVICE_ID_1,
+ GPIO_DEVICE_ID_2,
+ GPIO_DEVICE_ID_3,
+ GPIO_DEVICE_ID_INVALID
+} gpio_device_id;
+
+/*
+ * Pin description To be used in SOFTWARE mode: refers to a pin.
+ */
+typedef enum {
+ GPIO_PIN_0,
+ GPIO_PIN_1,
+ GPIO_PIN_2,
+ GPIO_PIN_3,
+ GPIO_PIN_4,
+ GPIO_PIN_5,
+ GPIO_PIN_6,
+ GPIO_PIN_7,
+ GPIO_PIN_8,
+ GPIO_PIN_9,
+ GPIO_PIN_10,
+ GPIO_PIN_11,
+ GPIO_PIN_12,
+ GPIO_PIN_13,
+ GPIO_PIN_14,
+ GPIO_PIN_15,
+ GPIO_PIN_16,
+ GPIO_PIN_17,
+ GPIO_PIN_18,
+ GPIO_PIN_19,
+ GPIO_PIN_20,
+ GPIO_PIN_21,
+ GPIO_PIN_22,
+ GPIO_PIN_23,
+ GPIO_PIN_24,
+ GPIO_PIN_25,
+ GPIO_PIN_26,
+ GPIO_PIN_27,
+ GPIO_PIN_28,
+ GPIO_PIN_29,
+ GPIO_PIN_30,
+ GPIO_PIN_31,
+ GPIO_PIN_32,
+ GPIO_PIN_33,
+ GPIO_PIN_34,
+ GPIO_PIN_35,
+ GPIO_PIN_36,
+ GPIO_PIN_37,
+ GPIO_PIN_38,
+ GPIO_PIN_39,
+ GPIO_PIN_40,
+ GPIO_PIN_41,
+ GPIO_PIN_42,
+ GPIO_PIN_43,
+ GPIO_PIN_44,
+ GPIO_PIN_45,
+ GPIO_PIN_46,
+ GPIO_PIN_47,
+ GPIO_PIN_48,
+ GPIO_PIN_49,
+ GPIO_PIN_50,
+ GPIO_PIN_51,
+ GPIO_PIN_52,
+ GPIO_PIN_53,
+ GPIO_PIN_54,
+ GPIO_PIN_55,
+ GPIO_PIN_56,
+ GPIO_PIN_57,
+ GPIO_PIN_58,
+ GPIO_PIN_59,
+ GPIO_PIN_60,
+ GPIO_PIN_61,
+ GPIO_PIN_62,
+ GPIO_PIN_63,
+ GPIO_PIN_64,
+ GPIO_PIN_65,
+ GPIO_PIN_66,
+ GPIO_PIN_67,
+ GPIO_PIN_68,
+ GPIO_PIN_69,
+ GPIO_PIN_70,
+ GPIO_PIN_71,
+ GPIO_PIN_72,
+ GPIO_PIN_73,
+ GPIO_PIN_74,
+ GPIO_PIN_75,
+ GPIO_PIN_76,
+ GPIO_PIN_77,
+ GPIO_PIN_78,
+ GPIO_PIN_79,
+ GPIO_PIN_80,
+ GPIO_PIN_81,
+ GPIO_PIN_82,
+ GPIO_PIN_83,
+ GPIO_PIN_84,
+ GPIO_PIN_85,
+ GPIO_PIN_86,
+ GPIO_PIN_87,
+ GPIO_PIN_88,
+ GPIO_PIN_89,
+ GPIO_PIN_90,
+ GPIO_PIN_91,
+ GPIO_PIN_92,
+ GPIO_PIN_93,
+ GPIO_PIN_94,
+ GPIO_PIN_95,
+ GPIO_PIN_96,
+ GPIO_PIN_97,
+ GPIO_PIN_98,
+ GPIO_PIN_99,
+ GPIO_PIN_100,
+ GPIO_PIN_101,
+ GPIO_PIN_102,
+ GPIO_PIN_103,
+ GPIO_PIN_104,
+ GPIO_PIN_105,
+ GPIO_PIN_106,
+ GPIO_PIN_107,
+ GPIO_PIN_108,
+ GPIO_PIN_109,
+ GPIO_PIN_110,
+ GPIO_PIN_111,
+ GPIO_PIN_112,
+ GPIO_PIN_113,
+ GPIO_PIN_114,
+ GPIO_PIN_115,
+ GPIO_PIN_116,
+ GPIO_PIN_117,
+ GPIO_PIN_118,
+ GPIO_PIN_119,
+ GPIO_PIN_120,
+ GPIO_PIN_121,
+ GPIO_PIN_122,
+ GPIO_PIN_123,
+ GPIO_PIN_124,
+ GPIO_PIN_125,
+ GPIO_PIN_126,
+ GPIO_PIN_127,
+ GPIO_PIN_128,
+ GPIO_PIN_129,
+ GPIO_PIN_130,
+ GPIO_PIN_131,
+ GPIO_PIN_132,
+ GPIO_PIN_133,
+ GPIO_PIN_134,
+ GPIO_PIN_135,
+ GPIO_PIN_136,
+ GPIO_PIN_137,
+ GPIO_PIN_138,
+ GPIO_PIN_139,
+ GPIO_PIN_140,
+ GPIO_PIN_141,
+ GPIO_PIN_142,
+ GPIO_PIN_143,
+ GPIO_PIN_144,
+ GPIO_PIN_145,
+ GPIO_PIN_146,
+ GPIO_PIN_147,
+ GPIO_PIN_148,
+ GPIO_PIN_149,
+ GPIO_PIN_150,
+ GPIO_PIN_151,
+ GPIO_PIN_152,
+ GPIO_PIN_153,
+ GPIO_PIN_154,
+ GPIO_PIN_155,
+ GPIO_PIN_156,
+ GPIO_PIN_157,
+ GPIO_PIN_158,
+ GPIO_PIN_159,
+ GPIO_PIN_160,
+ GPIO_PIN_161,
+ GPIO_PIN_162,
+ GPIO_PIN_163,
+ GPIO_PIN_164,
+ GPIO_PIN_165,
+ GPIO_PIN_166,
+ GPIO_PIN_167,
+ GPIO_PIN_168,
+ GPIO_PIN_169,
+ GPIO_PIN_170,
+ GPIO_PIN_171,
+ GPIO_PIN_172,
+ GPIO_PIN_173,
+ GPIO_PIN_174,
+ GPIO_PIN_175,
+ GPIO_PIN_176,
+ GPIO_PIN_177,
+ GPIO_PIN_178,
+ GPIO_PIN_179,
+ GPIO_PIN_180,
+ GPIO_PIN_181,
+ GPIO_PIN_182,
+ GPIO_PIN_183,
+ GPIO_PIN_184,
+ GPIO_PIN_185,
+ GPIO_PIN_186,
+ GPIO_PIN_187,
+ GPIO_PIN_188,
+ GPIO_PIN_189,
+ GPIO_PIN_190,
+ GPIO_PIN_191,
+ GPIO_PIN_192,
+ GPIO_PIN_193,
+ GPIO_PIN_194,
+ GPIO_PIN_195,
+ GPIO_PIN_196,
+ GPIO_PIN_197,
+ GPIO_PIN_198,
+ GPIO_PIN_199,
+ GPIO_PIN_200,
+ GPIO_PIN_201,
+ GPIO_PIN_202,
+ GPIO_PIN_203,
+ GPIO_PIN_204,
+ GPIO_PIN_205,
+ GPIO_PIN_206,
+ GPIO_PIN_207,
+ GPIO_PIN_208,
+ GPIO_PIN_209,
+ GPIO_PIN_210,
+ GPIO_PIN_211,
+ GPIO_PIN_212,
+ GPIO_PIN_213,
+ GPIO_PIN_214,
+ GPIO_PIN_215,
+ GPIO_PIN_216,
+ GPIO_PIN_217,
+ GPIO_PIN_218,
+ GPIO_PIN_219,
+ GPIO_PIN_220,
+ GPIO_PIN_221,
+ GPIO_PIN_222,
+ GPIO_PIN_223,
+ GPIO_PIN_224,
+ GPIO_PIN_225,
+ GPIO_PIN_226,
+ GPIO_PIN_227,
+ GPIO_PIN_228,
+ GPIO_PIN_229,
+ GPIO_PIN_230,
+ GPIO_PIN_231,
+ GPIO_PIN_232,
+ GPIO_PIN_233,
+ GPIO_PIN_234,
+ GPIO_PIN_235,
+ GPIO_PIN_236,
+ GPIO_PIN_237,
+ GPIO_PIN_238,
+ GPIO_PIN_239,
+ GPIO_PIN_240,
+ GPIO_PIN_241,
+ GPIO_PIN_242,
+ GPIO_PIN_243,
+ GPIO_PIN_244,
+ GPIO_PIN_245,
+ GPIO_PIN_246,
+ GPIO_PIN_247,
+ GPIO_PIN_248,
+ GPIO_PIN_249,
+ GPIO_PIN_250,
+ GPIO_PIN_251,
+ GPIO_PIN_252,
+ GPIO_PIN_253,
+ GPIO_PIN_254,
+ GPIO_PIN_255,
+ GPIO_PIN_256,
+ GPIO_PIN_257,
+ GPIO_PIN_258,
+ GPIO_PIN_259,
+ GPIO_PIN_260,
+ GPIO_PIN_261,
+ GPIO_PIN_262,
+ GPIO_PIN_263,
+ GPIO_PIN_264,
+ GPIO_PIN_265,
+ GPIO_PIN_266,
+ GPIO_PIN_267
+} gpio_pin;
+
+/*
+ * Alternate Function:
+ * refered in altfun_table to pointout particular altfun to be enabled
+ * when using GPIO_ALT_FUNCTION A/B/C enable/disable operation
+ */
+typedef enum {
+ GPIO_ALT_UART_0_MODEM,
+ GPIO_ALT_UART_0_NO_MODEM,
+ GPIO_ALT_UART_1,
+ GPIO_ALT_UART_2,
+ GPIO_ALT_I2C_0,
+ GPIO_ALT_I2C_1,
+ GPIO_ALT_MSP_0,
+ GPIO_ALT_MSP_1,
+ GPIO_ALT_MSP_2,
+ GPIO_ALT_MSP_3,
+ GPIO_ALT_MSP_4,
+ GPIO_ALT_MSP_5,
+ GPIO_ALT_SSP_0,
+ GPIO_ALT_SSP_1,
+ GPIO_ALT_MM_CARD0,
+ GPIO_ALT_SD_CARD0,
+ GPIO_ALT_DMA_0,
+ GPIO_ALT_DMA_1,
+ GPIO_ALT_HSI0,
+ GPIO_ALT_CCIR656_INPUT,
+ GPIO_ALT_CCIR656_OUTPUT,
+ GPIO_ALT_LCD_PANEL,
+ GPIO_ALT_MDIF,
+ GPIO_ALT_SDRAM,
+ GPIO_ALT_HAMAC_AUDIO_DBG,
+ GPIO_ALT_HAMAC_VIDEO_DBG,
+ GPIO_ALT_CLOCK_RESET,
+ GPIO_ALT_TSP,
+ GPIO_ALT_IRDA,
+ GPIO_ALT_USB_MINIMUM,
+ GPIO_ALT_USB_I2C,
+ GPIO_ALT_OWM,
+ GPIO_ALT_PWL,
+ GPIO_ALT_FSMC,
+ GPIO_ALT_COMP_FLASH,
+ GPIO_ALT_SRAM_NOR_FLASH,
+ GPIO_ALT_FSMC_ADDLINE_0_TO_15,
+ GPIO_ALT_SCROLL_KEY,
+ GPIO_ALT_MSHC,
+ GPIO_ALT_HPI,
+ GPIO_ALT_USB_OTG,
+ GPIO_ALT_SDIO,
+ GPIO_ALT_HSMMC,
+ GPIO_ALT_FSMC_ADD_DATA_0_TO_25,
+ GPIO_ALT_HSI1,
+ GPIO_ALT_NOR,
+ GPIO_ALT_NAND,
+ GPIO_ALT_KEYPAD,
+ GPIO_ALT_VPIP,
+ GPIO_ALT_CAM,
+ GPIO_ALT_CCP1,
+ GPIO_ALT_EMMC,
+#ifdef CONFIG_NOMADIK_8500_V1
+ GPIO_ALT_POP_EMMC,
+#endif
+ GPIO_ALT_FUNMAX /* Add new alt func before this */
+} gpio_alt_function;
+
+/* Defines pin assignment(Software mode or Alternate mode) */
+typedef enum {
+ GPIO_MODE_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_MODE_SOFTWARE, /* Pin connected to GPIO (SW controlled) */
+ GPIO_ALTF_A, /* Pin connected to alternate function 1 (HW periph 1) */
+ GPIO_ALTF_B, /* Pin connected to alternate function 2 (HW periph 2) */
+ GPIO_ALTF_C, /* Pin connected to alternate function 3 (HW periph 3) */
+ GPIO_ALTF_FIND, /* Pin connected to alternate function 3 (HW periph 3) */
+ GPIO_ALTF_DISABLE /* Pin connected to alternate function 3 (HW periph 3) */
+} gpio_mode;
+
+/* Defines GPIO pin direction */
+typedef enum {
+ GPIO_DIR_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_DIR_INPUT, /* GPIO set as input */
+ GPIO_DIR_OUTPUT /* GPIO set as output */
+} gpio_direction;
+
+/* Interrupt trigger mode */
+typedef enum {
+ GPIO_TRIG_LEAVE_UNCHANGED, /* Parameter will be ignored by the function */
+ GPIO_TRIG_DISABLE, /* Triggers no IT */
+ GPIO_TRIG_RISING_EDGE, /* Triggers an IT on a rising edge */
+ GPIO_TRIG_FALLING_EDGE, /* Triggers an IT on a falling edge */
+ GPIO_TRIG_BOTH_EDGES, /* Triggers an IT on a rising and a falling edge */
+ GPIO_TRIG_HIGH_LEVEL, /* Triggers an IT on a high level */
+ GPIO_TRIG_LOW_LEVEL /* Triggers an IT on a low level */
+} gpio_trig; /* Interrupt trigger mode, or disable */
+
+/* Configuration parameters for one GPIO pin.*/
+typedef struct {
+ gpio_mode mode; /* Defines mode (SOFTWARE or Alternate). */
+ gpio_direction direction; /* Define pin direction (in SOFTWARE mode only). */
+ gpio_trig trig; /* Interrupt trigger (in SOFTWARE mode only) */
+ char *dev_name; /* Name of client driver who owns the gpio pin */
+} gpio_config;
+
+/* GPIO pin data*/
+typedef enum {
+ GPIO_DATA_LOW, /* GPIO pin status is low. */
+ GPIO_DATA_HIGH /* GPIO pin status is high. */
+} gpio_data;
+
+/* GPIO behaviour in sleep mode */
+typedef enum {
+ GPIO_SLEEP_MODE_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_SLEEP_MODE_INPUT_DEFAULTVOLT, /* GPIO is an input with pull up/down enabled
+ when in sleep mode. */
+ GPIO_SLEEP_MODE_CONTROLLED_BY_GPIO /* GPIO pin is controlled by GPIO IP. So mode,
+ direction and data values for GPIO pin in
+ sleep mode are determined by configuration
+ set to GPIO pin before entering to sleep mode. */
+} gpio_sleep_mode;
+
+/* GPIO ability to wake the system up from sleep mode.*/
+typedef enum {
+ GPIO_WAKE_LEAVE_UNCHANGED, /* Parameter will be ignored by the function. */
+ GPIO_WAKE_DISABLE, /* GPIO will not wake the system from sleep mode. */
+ GPIO_WAKE_LOW_LEVEL, /* GPIO will wake the system up on a LOW level. */
+ GPIO_WAKE_HIGH_LEVEL, /* GPIO will wake the system up on a HIGH level. */
+ GPIO_WAKE_RISING_EDGE, /* GPIO will wake the system up on a RISING edge. */
+ GPIO_WAKE_FALLING_EDGE, /* GPIO will wake the system up on a FALLING edge. */
+ GPIO_WAKE_BOTH_EDGES /* GPIO will wake the system up on both RISING and FALLING edge. */
+} gpio_wake;
+
+/* Configuration parameters for one GPIO pin in sleep mode.*/
+typedef struct {
+ gpio_sleep_mode sleep_mode; /* GPIO behaviour in sleep mode. */
+ gpio_wake wake; /* GPIO ability to wake up the system. */
+} gpio_sleep_config;
+
+/*------------------------------------------------------------------------
+ * Functions declaration
+ * refer ./Documentation/arm/STM-Nomadik/gpio_user_guide.txt
+ *----------------------------------------------------------------------*/
+
+extern int gpio_setpinconfig(gpio_pin pin_id, gpio_config * pin_config);
+extern int gpio_resetpinconfig(gpio_pin pin_id, char *dev_name);
+extern int gpio_writepin(gpio_pin pin_id, gpio_data value, char *dev_name);
+extern int gpio_readpin(gpio_pin pin_id, gpio_data * value);
+extern int gpio_altfuncenable(gpio_alt_function altfunc,
+ char *dev_name);
+extern int gpio_altfuncdisable(gpio_alt_function altfunc,
+ char *dev_name);
+
+struct gpio_altfun_data {
+ u16 altfun;
+ u16 start;
+ u16 end;
+ t_bool cont;
+ u8 type;
+};
+
+#endif /* __INC_GPIO_H */
diff --git a/include/asm-arm/arch-stw8500/mmc.h b/include/asm-arm/arch-stw8500/mmc.h
new file mode 100755
index 000000000..c8aa4d71c
--- /dev/null
+++ b/include/asm-arm/arch-stw8500/mmc.h
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __MMC_NOMADIK_P_H__
+#define __MMC_NOMADIK_P_H__
+
+#define MAX_ERROR_VALUE -65
+typedef enum
+{
+ /* MMC specific error defines */
+ MMC_CMD_CRC_FAIL = (MAX_ERROR_VALUE - 1), /* Command response received (but CRC check failed) */
+ MMC_DATA_CRC_FAIL = (MAX_ERROR_VALUE - 2), /* Data bock sent/received (CRC check Failed) */
+ MMC_CMD_RSP_TIMEOUT = (MAX_ERROR_VALUE - 3), /* Command response timeout */
+ MMC_DATA_TIMEOUT = (MAX_ERROR_VALUE - 4), /* Data time out*/
+ MMC_TX_UNDERRUN = (MAX_ERROR_VALUE - 5), /* Transmit FIFO under-run */
+ MMC_RX_OVERRUN = (MAX_ERROR_VALUE - 6), /* Receive FIFO over-run */
+ MMC_START_BIT_ERR = (MAX_ERROR_VALUE - 7), /* Start bit not detected on all data signals in widE bus mode */
+ MMC_CMD_OUT_OF_RANGE = (MAX_ERROR_VALUE - 8), /* CMD's argument was out of range.*/
+ MMC_ADDR_MISALIGNED = (MAX_ERROR_VALUE - 9), /* Misaligned address */
+ MMC_BLOCK_LEN_ERR = (MAX_ERROR_VALUE - 10), /* Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
+ MMC_ERASE_SEQ_ERR = (MAX_ERROR_VALUE - 11), /* An error in the sequence of erase command occurs.*/
+ MMC_BAD_ERASE_PARAM = (MAX_ERROR_VALUE - 12), /* An Invalid selection for erase groups */
+ MMC_WRITE_PROT_VIOLATION = (MAX_ERROR_VALUE - 13), /* Attempt to program a write protect block */
+ MMC_LOCK_UNLOCK_FAILED = (MAX_ERROR_VALUE - 14), /* Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
+ MMC_COM_CRC_FAILED = (MAX_ERROR_VALUE - 15), /* CRC check of the previous command failed */
+ MMC_ILLEGAL_CMD = (MAX_ERROR_VALUE - 16), /* Command is not legal for the card state */
+ MMC_CARD_ECC_FAILED = (MAX_ERROR_VALUE - 17), /* Card internal ECC was applied but failed to correct the data */
+ MMC_CC_ERROR = (MAX_ERROR_VALUE - 18), /* Internal card controller error */
+ MMC_GENERAL_UNKNOWN_ERROR = (MAX_ERROR_VALUE - 19), /* General or Unknown error */
+ MMC_STREAM_READ_UNDERRUN = (MAX_ERROR_VALUE - 20), /* The card could not sustain data transfer in stream read operation. */
+ MMC_STREAM_WRITE_OVERRUN = (MAX_ERROR_VALUE - 21), /* The card could not sustain data programming in stream mode */
+ MMC_CID_CSD_OVERWRITE = (MAX_ERROR_VALUE - 22), /* CID/CSD overwrite error */
+ MMC_WP_ERASE_SKIP = (MAX_ERROR_VALUE - 23), /* only partial address space was erased */
+ MMC_CARD_ECC_DISABLED = (MAX_ERROR_VALUE - 24), /* Command has been executed without using internal ECC */
+ MMC_ERASE_RESET = (MAX_ERROR_VALUE - 25), /* Erase sequence was cleared before executing because an out of erase sequence command was received */
+ MMC_AKE_SEQ_ERROR = (MAX_ERROR_VALUE - 26), /* Error in sequence of authentication. */
+ MMC_INVALID_VOLTRANGE = (MAX_ERROR_VALUE - 27),
+ MMC_ADDR_OUT_OF_RANGE = (MAX_ERROR_VALUE - 28),
+ MMC_SWITCH_ERROR = (MAX_ERROR_VALUE - 29),
+ MMC_SDIO_DISABLED = (MAX_ERROR_VALUE - 30),
+ MMC_SDIO_FUNCTION_BUSY = (MAX_ERROR_VALUE - 31),
+ MMC_SDIO_FUNCTION_FAILED = (MAX_ERROR_VALUE - 32),
+ MMC_SDIO_UNKNOWN_FUNCTION = MAX_ERROR_VALUE,
+
+ /* standard error defines */
+ MMC_INTERNAL_ERROR = -8,
+ MMC_NOT_CONFIGURED = -7,
+ MMC_REQUEST_PENDING = -6,
+ MMC_REQUEST_NOT_APPLICABLE = -5,
+ MMC_INVALID_PARAMETER = -4,
+ MMC_UNSUPPORTED_FEATURE = -3,
+ MMC_UNSUPPORTED_HW = -2,
+ MMC_ERROR = -1,
+ MMC_OK = 0,
+ MMC_INTERNAL_EVENT = 1,
+ MMC_REMAINING_PENDING_EVENTS = 2,
+ MMC_REMAINING_FILTER_PENDING_EVENTS = 3,
+ MMC_NO_MORE_PENDING_EVENT = 4,
+ MMC_NO_MORE_FILTER_PENDING_EVENT = 5,
+ MMC_NO_PENDING_EVENT_ERROR = 7,
+} t_mmc_error;
+
+int init_mmc_card(void);
+
+#endif
+
diff --git a/include/asm-arm/arch-stw8500/mtu.h b/include/asm-arm/arch-stw8500/mtu.h
new file mode 100755
index 000000000..a87be9ef4
--- /dev/null
+++ b/include/asm-arm/arch-stw8500/mtu.h
@@ -0,0 +1,66 @@
+/*
+ * (C) Copyright 2009 Alessandro Rubini
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_MTU_H
+#define __ASM_ARCH_MTU_H
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
+#define MTU_RIS 0x04 /* Raw interrupt status */
+#define MTU_MIS 0x08 /* Masked interrupt status */
+#define MTU_ICR 0x0C /* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
+#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
+#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
+#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA 0x80
+#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK 0x0c
+#define MTU_CRn_PRESCALE_1 0x00
+#define MTU_CRn_PRESCALE_16 0x04
+#define MTU_CRn_PRESCALE_256 0x08
+#define MTU_CRn_32BITS 0x02
+#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR 0xff0
+#define MTU_ITOP 0xff4
+
+#define MTU_PERIPH_ID0 0xfe0
+#define MTU_PERIPH_ID1 0xfe4
+#define MTU_PERIPH_ID2 0xfe8
+#define MTU_PERIPH_ID3 0xfeC
+
+#define MTU_PCELL0 0xff0
+#define MTU_PCELL1 0xff4
+#define MTU_PCELL2 0xff8
+#define MTU_PCELL3 0xffC
+
+#endif /* __ASM_ARCH_MTU_H */
diff --git a/include/configs/u8500.h b/include/configs/u8500.h
new file mode 100755
index 000000000..331258d18
--- /dev/null
+++ b/include/configs/u8500.h
@@ -0,0 +1,226 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*-----------------------------------------------------------------------
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_U8500 1
+#define CONFIG_U8500_ED 1
+#define CONFIG_L2_OFF 1
+
+#define PCI_IO_VADDR 0xee000000
+
+#define __io(a) ((void __iomem *)(PCI_IO_VADDR + (a)))
+
+#define CONFIG_SYS_MEMTEST_START 0x00000000
+#define CONFIG_SYS_MEMTEST_END 0x1FFFFFFF
+#define CONFIG_SYS_HZ 1000//(2400000 / 128) /* Timer0 is clocked at 2.4Mhz with 256 divider */
+
+#ifndef CONFIG_U8500_V1
+#define CONFIG_SYS_TIMERBASE 0xA03DA000 /* MTU0 timer */
+#else
+#define CONFIG_SYS_TIMERBASE 0xA03C6000 /* MTU0 timer */
+#endif
+
+#define CONFIG_MISC_INIT_R 1 /* call misc_init_r during start up */
+
+#define BOARD_LATE_INIT 1
+#define LITTLEENDIAN
+
+/*-----------------------------------------------------------------------
+ * Size of malloc() pool
+ */
+#define CONFIG_ENV_SIZE 128*1024
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 256*1024)
+#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
+
+/*-----------------------------------------------------------------------
+ * PL011 Configuration
+ */
+
+#define CONFIG_PL011_SERIAL
+/*
+ * U8500 UART registers base for 3 serial devices
+ */
+#define CFG_UART0_BASE 0x80120000
+#define CFG_UART1_BASE 0x80121000
+#define CFG_UART2_BASE 0x80007000
+#define CFG_SERIAL0 CFG_UART0_BASE
+#define CFG_SERIAL1 CFG_UART1_BASE
+#define CFG_SERIAL2 CFG_UART2_BASE
+#define CONFIG_PL011_CLOCK 38400000
+#define CONFIG_PL01x_PORTS { (void *) (CFG_SERIAL0), (void *) (CFG_SERIAL1), (void *) (CFG_SERIAL2) }
+#define CONFIG_CONS_INDEX 2
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+// do_fat_read will loop (insane timeout), e.g. fail, if this is defined
+#define CONFIG_MMC 1
+#define CONFIG_DOS_PARTITION 1
+
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_IMI
+#define CONFIG_CMD_MISC
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_ECHO
+#define CONFIG_CMD_CONSOLE
+#define CONFIG_CMD_LOADS
+#define CONFIG_CMD_LOADB
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EMMC
+
+#define CONFIG_BOOTDELAY 5
+#define CONFIG_BOOTARGS "cachepolicy=writealloc root=/dev/ram0 initrd=0x800000,20M init=linuxrc rw console=ttyAMA2,115200n8 mem=256M board_id=0"
+#define CONFIG_BOOTCOMMAND "emmc_read 0x100000 0x280000 0x200000; bootm 0x100000"
+
+#ifndef CONFIG_USB_TTY
+#define CONFIG_PREBOOT "mmc init;mmc_read_cmd_file"
+#endif
+/*-----------------------------------------------------------------------
+ * Miscellaneous configurable options
+ */
+
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_PROMPT "U8500 $ " /* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+ + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Arg Buffer Size */
+
+#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
+#define CONFIG_SYS_LOAD_ADDR 0x800000 /* default load address */
+#define CONFIG_SYS_LOADS_BAUD_CHANGE 1
+
+#define CONFIG_SYS_HUSH_PARSER 1
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+#define CONFIG_CMDLINE_EDITING
+
+
+#define CONFIG_SETUP_MEMORY_TAGS 2
+#define CONFIG_INITRD_TAG 1
+#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+
+#define CONFIG_STACKSIZE (128*1024) /* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS 2 /* we have dual bank of DRAM */
+#define PHYS_SDRAM_1 0x00000000 /* DDR-SDRAM Bank #1 */
+#define PHYS_SDRAM_SIZE_1 0x10000000 /* 256 MB */
+#define PHYS_SDRAM_2 0x20000000 /* DDR-SDRAM Bank #2 */
+#define PHYS_SDRAM_SIZE_2 0x10000000 /* 256 MB */
+
+/*-----------------------------------------------------------------------
+ * MMC related configs
+ */
+#define MMC_BLOCK_SIZE 512
+#define CFG_MMC_BASE 0x80126000 /* MMC base for 8500 */
+
+/*-----------------------------------------------------------------------
+ * EMMC related configs
+ */
+#define CFG_EMMC_BASE 0x80114000 /* EMMC base of size 2GB for 8500 */
+#define CONFIG_CMD_ENV
+#define CONFIG_ENV_IS_IN_EMMC 1
+#define CONFIG_ENV_OFFSET_START 0x260000
+#define CONFIG_ENV_OFFSET_END 0x27F000
+
+/*-----------------------------------------------------------------------
+ * USB related configs
+ */
+#define CONFIG_USB_BASE 0xA03E0000
+
+#ifdef CONFIG_USB_TTY
+#define CONFIG_ARM
+#define CONFIG_USBTTY "cdc_acm"
+#define CONFIG_USB_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define __LITTLE_ENDIAN 1
+#define CONFIG_SYS_CONSOLE_ENV_OVERWRITE
+#endif
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#ifndef CONFIG_U8500_V1
+
+#define CONFIG_SYS_MAX_FLASH_SECT 512
+#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
+
+#else
+
+#define CFG_POP_EMMC_BASE 0x80005000 /*POP EMMC base of size 256MB for 8500 cut1.0 */
+
+#endif
+
+/*------------------------------------------------------------------------------
+ * base register values for U8500
+ */
+#define CFG_PRCMU_BASE 0x80157000 /* Power, reset and clock Management Unit */
+#define CFG_SDRAMC_BASE 0x903CF000 /* SDRAMC cnf registers */
+#define CFG_FSMC_BASE 0x80000000 /* FSMC Controller */
+
+/*
+ * U8500 GPIO register base for 9 banks
+ */
+#define CFG_GPIO_0_BASE 0x8012E000
+#define CFG_GPIO_1_BASE 0x8012E080
+#define CFG_GPIO_2_BASE 0x8000E000
+#define CFG_GPIO_3_BASE 0x8000E080
+#define CFG_GPIO_4_BASE 0x8000E100
+#define CFG_GPIO_5_BASE 0x8000E180
+#define CFG_GPIO_6_BASE 0x8011E000
+#define CFG_GPIO_7_BASE 0x8011E080
+#define CFG_GPIO_8_BASE 0xA03FE000
+
+/*
+ * U8500 I2C0 register base for SD card
+ */
+#define CFG_I2C0_BASE 0x80004000
+
+/*
+ * U8500 RTC register base
+ */
+#define CFG_RTC_BASE 0x80154000 /* Real time clock */
+
+#endif /* __CONFIG_H */