]> git.karo-electronics.de Git - karo-tx-redboot.git/commitdiff
Initial revision
authorlothar <lothar>
Fri, 13 Feb 2009 19:19:53 +0000 (19:19 +0000)
committerlothar <lothar>
Fri, 13 Feb 2009 19:19:53 +0000 (19:19 +0000)
52 files changed:
packages/devs/eth/arm/imx_3stack/v2_0/cdl/board_eth_drivers.cdl [new file with mode: 0644]
packages/devs/eth/arm/imx_3stack/v2_0/include/devs_eth_arm_board.inl [new file with mode: 0644]
packages/devs/eth/smsc/lan92xx/v2_0/cdl/smsc_lan92xx_eth_drivers.cdl [new file with mode: 0644]
packages/devs/eth/smsc/lan92xx/v2_0/include/smsc_lan92xx.h [new file with mode: 0644]
packages/devs/eth/smsc/lan92xx/v2_0/src/if_lan92xx.c [new file with mode: 0644]
packages/devs/flash/arm/imx_3stack/v2_0/cdl/flash_board_spansion.cdl [new file with mode: 0644]
packages/devs/flash/arm/imx_3stack/v2_0/src/board_spansionflash.c [new file with mode: 0644]
packages/devs/flash/arm/mx35evb/v2_0/cdl/flash_board_spansion.cdl [new file with mode: 0644]
packages/devs/flash/arm/mx35evb/v2_0/cdl/flash_board_strata.cdl [new file with mode: 0644]
packages/devs/flash/arm/mx35evb/v2_0/include/board_strataflash.inl [new file with mode: 0644]
packages/devs/flash/arm/mx35evb/v2_0/src/board_spansionflash.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/card_mx32.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/imx_nfc.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/imx_spi_nor.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/mxc_ata.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/mxc_mmc.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/mxc_nfc_v3.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/mxcmci_core.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/mxcmci_host.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/mxcmci_mmc.h [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/include/spi_nor_parts.inl [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/card_mx32.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/mxc_ata.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/mxc_mmc.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/mxcmci_core.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/mxcmci_host.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/mxcmci_mmc.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/mxcmci_sd.c [new file with mode: 0644]
packages/devs/flash/arm/mxc/v2_0/src/spi_nor.c [new file with mode: 0644]
packages/devs/i2c/arm/mxc/v2_0/cdl/mxc_i2c.cdl [new file with mode: 0644]
packages/devs/i2c/arm/mxc/v2_0/include/mxc_i2c.h [new file with mode: 0644]
packages/devs/i2c/arm/mxc/v2_0/src/mxc_i2c.c [new file with mode: 0644]
packages/devs/pmic/arm/mx25_3stack/v2_0/cdl/mc34704.cdl [new file with mode: 0644]
packages/devs/pmic/arm/mx25_3stack/v2_0/include/mc34704.h [new file with mode: 0644]
packages/devs/pmic/arm/mx25_3stack/v2_0/src/mc34704.c [new file with mode: 0644]
packages/devs/pmic/arm/mx35_3stack/v2_0/cdl/mc9s08dz.cdl [new file with mode: 0644]
packages/devs/pmic/arm/mx35_3stack/v2_0/include/mc9s08dz.h [new file with mode: 0644]
packages/devs/pmic/arm/mx35_3stack/v2_0/src/mc9s08dz.c [new file with mode: 0644]
packages/devs/spi/arm/imx/v2_0/cdl/spi.cdl [new file with mode: 0644]
packages/devs/spi/arm/imx/v2_0/include/imx_spi.h [new file with mode: 0644]
packages/devs/spi/arm/imx/v2_0/src/imx_spi.c [new file with mode: 0644]
packages/devs/usb/imx/v2_0/cdl/usbs_imx.cdl [new file with mode: 0644]
packages/devs/usb/imx/v2_0/include/usbs_imx.h [new file with mode: 0644]
packages/devs/usb/imx/v2_0/src/usbs_imx.c [new file with mode: 0644]
packages/services/diagnosis/v2_0/cdl/diagnosis.cdl [new file with mode: 0644]
packages/services/diagnosis/v2_0/include/diagnosis.h [new file with mode: 0644]
packages/services/diagnosis/v2_0/include/memory.h [new file with mode: 0644]
packages/services/diagnosis/v2_0/src/core.c [new file with mode: 0644]
packages/services/diagnosis/v2_0/src/memory/ram_pm.c [new file with mode: 0644]
packages/services/diagnosis/v2_0/src/memory/ram_rw.c [new file with mode: 0644]
packages/services/diagnosis/v2_0/src/memory/routine.S [new file with mode: 0644]
packages/services/diagnosis/v2_0/src/wdt/wdt.c [new file with mode: 0644]

diff --git a/packages/devs/eth/arm/imx_3stack/v2_0/cdl/board_eth_drivers.cdl b/packages/devs/eth/arm/imx_3stack/v2_0/cdl/board_eth_drivers.cdl
new file mode 100644 (file)
index 0000000..886425f
--- /dev/null
@@ -0,0 +1,95 @@
+# ====================================================================
+#
+#      board_eth_drivers.cdl
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+
+cdl_package CYGPKG_DEVS_ETH_ARM_IMX_3STACK {
+    display       "Ethernet driver for Freescale MXC Board development board"
+
+    parent        CYGPKG_IO_ETH_DRIVERS
+    active_if    CYGPKG_IO_ETH_DRIVERS
+
+    include_dir   cyg/io
+
+    # FIXME: This really belongs in the SMSC LAN92xx package
+    cdl_interface CYGINT_DEVS_ETH_SMSC_LAN92XX_REQUIRED {
+        display   "SMSC LAN92XX ethernet driver required"
+    }
+
+    define_proc {
+        puts $::cdl_system_header "/***** ethernet driver proc output start *****/"
+        puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN92XX_INL <cyg/io/devs_eth_arm_board.inl>"
+        puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN92XX_CFG <pkgconf/devs_eth_arm_imx_3stack.h>"
+        puts $::cdl_system_header "/*****  ethernet driver proc output end  *****/"
+    }
+
+    cdl_component CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0 {
+        display       "MXC Board ethernet port driver"
+        flavor        bool
+        default_value 1
+        description   "
+            This option includes the ethernet device driver for the
+            MXC Board port."
+
+        implements CYGHWR_NET_DRIVER_ETH0
+        implements CYGINT_DEVS_ETH_SMSC_LAN92XX_REQUIRED
+
+        cdl_option CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME {
+            display       "Device name for the ETH0 ethernet driver"
+            flavor        data
+            default_value {"\"eth0\""}
+            description   "
+                This option sets the name of the ethernet device."
+        }
+
+        cdl_component CYGSEM_DEVS_ETH_ARM_MXCBOARD_ETH0_SET_ESA {
+            display       "Set the ethernet station address"
+            flavor        bool
+            default_value 0
+            description   "Enabling this option will allow the ethernet
+            station address to be forced to the value set by the
+            configuration.  This may be required if the hardware does
+            not include a serial EEPROM for the ESA."
+
+            cdl_option CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_ESA {
+                display       "The ethernet station address"
+                flavor        data
+                default_value {"{0x08, 0x88, 0x12, 0x34, 0x56, 0x78}"}
+                description   "The ethernet station address"
+            }
+        }
+    }
+}
diff --git a/packages/devs/eth/arm/imx_3stack/v2_0/include/devs_eth_arm_board.inl b/packages/devs/eth/arm/imx_3stack/v2_0/include/devs_eth_arm_board.inl
new file mode 100644 (file)
index 0000000..3820473
--- /dev/null
@@ -0,0 +1,101 @@
+//==========================================================================
+//
+//      devs_eth_arm_board.inl
+//
+//      Board ethernet I/O definitions.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+
+#include <cyg/hal/hal_intr.h>           // CYGNUM_HAL_INTERRUPT_ETHR
+#include <cyg/hal/hal_if.h>
+
+#ifdef CYGPKG_REDBOOT
+#include <pkgconf/redboot.h>
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+#include <redboot.h>
+#include <flash_config.h>
+#endif
+#endif
+
+extern unsigned int sys_ver;
+
+#ifdef __WANT_DEVS
+
+#ifdef CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
+#if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
+RedBoot_config_option("Set " CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME " network hardware address [MAC]",
+                      eth0_esa,
+                      ALWAYS_ENABLED, true,
+                      CONFIG_BOOL, false
+                     );
+RedBoot_config_option(CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME " network hardware address [MAC]",
+                      eth0_esa_data,
+                      "eth0_esa", true,
+                      CONFIG_ESA, 0
+                     );
+#endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG
+
+#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+// Note that this section *is* active in an application, outside RedBoot,
+// where the above section is not included.
+
+#include <cyg/hal/hal_if.h>
+
+#ifndef CONFIG_ESA
+#define CONFIG_ESA (6)
+#endif
+#ifndef CONFIG_BOOL
+#define CONFIG_BOOL (1)
+#endif
+
+cyg_bool _board_provide_eth0_esa(unsigned char * mac)
+{
+    cyg_bool set_esa;
+    int ok;
+    ok = CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                      "eth0_esa", &set_esa, CONFIG_BOOL);
+    if (ok && set_esa) {
+        ok = CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                          "eth0_esa_data", mac, CONFIG_ESA);
+    }
+
+    return ok && set_esa;
+}
+#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+
+#endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
+
+#endif // __WANT_DEVS
diff --git a/packages/devs/eth/smsc/lan92xx/v2_0/cdl/smsc_lan92xx_eth_drivers.cdl b/packages/devs/eth/smsc/lan92xx/v2_0/cdl/smsc_lan92xx_eth_drivers.cdl
new file mode 100644 (file)
index 0000000..fcbeb5c
--- /dev/null
@@ -0,0 +1,88 @@
+# ====================================================================
+#
+#      smsc_lan92xx_eth_drivers.cdl
+#
+#      Ethernet drivers - support for LAN92XX compatible ethernet controllers
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2007 Fred Fan
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Fred Fan
+# Contributors:   Fred Fan
+# Date:           2007-9-27
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_ETH_SMSC_LAN92XX {
+    display       "SMSC LAN92XX compatible ethernet driver"
+    description   "Ethernet driver for SMSC LAN92XX compatible controllers."
+
+    parent        CYGPKG_IO_ETH_DRIVERS
+    active_if    CYGPKG_IO_ETH_DRIVERS
+
+    implements    CYGHWR_NET_DRIVERS
+    implements    CYGINT_IO_ETH_MULTICAST
+
+    active_if     CYGINT_DEVS_ETH_SMSC_LAN92XX_REQUIRED
+
+    include_dir   cyg/io
+    compile       -library=libextras.a if_lan92xx.c
+
+    define_proc { 
+        puts $::cdl_header "#include <pkgconf/system.h>";
+        puts $::cdl_header "#include CYGDAT_DEVS_ETH_SMSC_LAN92XX_CFG";
+    }
+
+    cdl_component CYGPKG_DEVS_ETH_SMSC_LAN92XX_OPTIONS {
+        display "LAN92XX ethernet driver build options"
+        flavor  none
+       no_define
+
+        cdl_option CYGPKG_DEVS_ETH_SMSC_LAN91CXX_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "-D_KERNEL -D__ECOS" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the LAN91CXX ethernet driver package.
+                These flags are used in addition
+                to the set of global flags."
+        }
+    }
+}
diff --git a/packages/devs/eth/smsc/lan92xx/v2_0/include/smsc_lan92xx.h b/packages/devs/eth/smsc/lan92xx/v2_0/include/smsc_lan92xx.h
new file mode 100644 (file)
index 0000000..edab0b4
--- /dev/null
@@ -0,0 +1,187 @@
+#ifndef CYGONCE_DEVS_ETH_SMSC_LAN92XX_LAN92XX_H
+#define CYGONCE_DEVS_ETH_SMSC_LAN92XX_LAN92XX_H
+//==========================================================================
+//
+//      lan92xx.h
+//
+//      SMCS LAN9217 (LAN92XX compatible) Ethernet chip
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Nick Garnett 
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources,
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_endian.h>
+
+#define __WANT_CONFIG
+#include CYGDAT_DEVS_ETH_SMSC_LAN92XX_CFG
+#undef __WANT_CONFIG
+
+typedef struct
+{
+    unsigned short id;
+    unsigned short ver;
+    char *id_name;
+}smsc_lan92xx_id_t;
+
+// LAN92xx register offset
+#define LAN92XX_RX_DATA         0x00
+#define LAN92XX_TX_DATA         0x20
+#define LAN92XX_RX_STATUS1      0x40
+#define LAN92XX_RX_STATUS2      0x44
+#define LAN92XX_TX_STATUS1      0x48
+#define LAN92XX_TX_STATUS2      0x4C
+#define LAN92XX_ID_REV          0x50
+#define LAN92XX_IRQ_CFG         0x54
+#define LAN92XX_INT_STS         0x58
+#define LAN92XX_INT_EN          0x5C
+#define LAN92XX_RESERVED1       0x60
+#define LAN92XX_BYTE_TEST       0x64
+#define LAN92XX_FIFO_INT        0x68
+#define LAN92XX_RX_CFG          0x6C
+#define LAN92XX_TX_CFG          0x70
+#define LAN92XX_HW_CFG          0x74
+#define LAN92XX_RX_DP_CTRL      0x78
+#define LAN92XX_RX_FIFO_INF     0x7C
+#define LAN92XX_TX_FIFO_INF     0x80
+#define LAN92XX_PMT_CTRL        0x84
+#define LAN92XX_GPIO_CFG        0x88
+#define LAN92XX_GPT_CFG         0x8C
+#define LAN92XX_GPT_CNT         0x90
+#define LAN92XX_RESERVED2       0x94
+#define LAN92XX_WORD_SWAP       0x98
+#define LAN92XX_FREE_RUN        0x9C
+#define LAN92XX_RX_DROP         0xA0
+#define LAN92XX_MAC_CMD         0xA4
+#define LAN92XX_MAC_DATA        0xA8
+#define LAN92XX_AFC_CFG         0xAC
+#define LAN92XX_E2P_CMD         0xB0
+#define LAN92XX_E2P_DATA        0xB4
+
+// Access these MAC registers indirectly through MAC_CMD and MAC_DATA
+// registers. 
+#define MAC_MAC_CR         1
+#define MAC_ADDRH          2
+#define MAC_ADDRL          3
+#define MAC_HASHH          4
+#define MAC_HASHL          5
+#define MAC_MII_ACC     6
+#define MAC_MII_DATA    7
+#define MAC_FLOW        8
+#define MAC_VLAN1       9
+#define MAC_VLAN2       10
+#define MAC_WUFF        11
+#define MAC_WUCSR       12
+
+// These PHY registers are accessed indirectly through the MAC via the 
+// MII interface using the MII_ACC and MII_DATA registers. PHY controls
+// the 802.3 physical layer such as 10/100Mbps, full/half mode.
+#define PHY_BCR         0
+#define PHY_BSR         1
+#define PHY_ID1         2
+#define PHY_ID2         3
+#define PHY_ANAR        4
+#define PHY_ANLPAR      5
+#define PHY_ANER        6
+#define PHY_MCSR        17
+#define PHY_SMR         18
+#define PHY_SCSI        27
+#define PHY_ISR         29
+#define PHY_IMR         30
+#define PHY_SCSR        31
+
+#define PHY_100TX_FD    0x4000
+#define PHY_100TX_HD    0x2000
+#define PHY_10T_RD      0x1000
+#define PHY_10T_HD      0x0800
+#define PHY_LINK_ON     0x0004
+
+#define IS_DUPLEX(x)   ((x) & (PHY_100TX_FD | PHY_10T_RD))
+
+#define MAC_TIMEOUT     (1000 * 100)
+#define MAC_TICKET      2
+
+#define E2P_CMD_SHIFT  28
+#define E2P_CMD_BUSY   0x80000000
+#define E2P_CMD_TIMEOUT        0x00000200
+#define E2P_CMD_LOADED 0x00000100
+
+enum epc_cmd {
+    E2P_CMD_READ    = 0 << E2P_CMD_SHIFT,
+    E2P_CMD_EWDS    = 1 << E2P_CMD_SHIFT,
+    E2P_CMD_EWEN    = 2 << E2P_CMD_SHIFT,
+    E2P_CMD_WRITE   = 3 << E2P_CMD_SHIFT,
+    E2P_CMD_WRAL    = 4 << E2P_CMD_SHIFT,
+    E2P_CMD_ERASE   = 5 << E2P_CMD_SHIFT,
+    E2P_CMD_ERAL    = 6 << E2P_CMD_SHIFT,
+    E2P_CMD_Reload  = 7 << E2P_CMD_SHIFT,
+};
+#define E2P_CMD(cmd, addr) (E2P_CMD_BUSY | (cmd) | (addr))
+
+#define E2P_CONTEXT_ID  0xA5
+
+typedef struct
+{
+    unsigned int base;
+    int status;
+    int tx_busy;
+    int tx_key;
+    unsigned char mac_addr[6];
+} smsc_lan92xx_t;
+
+#ifndef LAN92XX_REG_BASE
+#define LAN92XX_REG_BASE    PBC_BASE
+#endif
+
+#ifndef LAN92XX_REG_READ
+#define LAN92XX_REG_READ(reg_offset)  \
+    (*(volatile unsigned int *)(LAN92XX_REG_BASE + reg_offset))
+#endif    
+
+#ifndef LAN92XX_REG_WRITE
+#define LAN92XX_REG_WRITE(reg_offset, val)  \
+    (*(volatile unsigned int *)(LAN92XX_REG_BASE + reg_offset) = (val))
+#endif
+
+#endif // CYGONCE_DEVS_ETH_SMSC_MAC_MAC_H
diff --git a/packages/devs/eth/smsc/lan92xx/v2_0/src/if_lan92xx.c b/packages/devs/eth/smsc/lan92xx/v2_0/src/if_lan92xx.c
new file mode 100644 (file)
index 0000000..9b0de14
--- /dev/null
@@ -0,0 +1,702 @@
+//==========================================================================
+//
+//      dev/if_lan92xx.c
+//
+//      Ethernet device driver for SMSC LAN92XX compatible controllers
+//
+//==========================================================================
+//==========================================================================
+
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Fred Fan
+// Contributors:
+// Date:         2007-10-16
+// Purpose:
+// Description:  Driver for SMSC LAN92xx ethernet controller
+//
+// Note:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_eth_drivers.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_diag.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/eth/netdev.h>
+#include <cyg/io/eth/eth_drv.h>
+#include <cyg/io/smsc_lan92xx.h>
+
+
+#ifdef CYGPKG_NET
+#include <pkgconf/net.h>
+#include <cyg/kernel/kapi.h>
+#include <net/if.h>  /* Needed for struct ifnet */
+#endif
+
+//#define LAN92XX_DEBUG
+#ifdef LAN92XX_DEBUG
+#define PDEBUG(fmt, args...) diag_printf(fmt, ##args)
+#else
+#define PDEBUG(fmt, args...)
+#endif /*LAN92XX_DEBUG*/
+
+#define __WANT_DEVS
+#include CYGDAT_DEVS_ETH_SMSC_LAN92XX_INL
+#undef __WANT_DEVS
+
+#define LAN_92XX_DRV_VER    "1.1"
+
+#define MAX_RX_NUM (CYGNUM_IO_ETH_DRIVERS_NUM_PKT - 1)
+static smsc_lan92xx_id_t smsc_lan92xx_id_table[] =
+{
+    {0x117A, 0x0000, "SMSC LAN9217"},
+    {0x9220, 0x0000, "SMSC LAN9220"},
+    {0},
+};
+
+static int lan92xx_eeprom_present = 1;
+
+static smsc_lan92xx_t lan92xx_dev;
+static inline void
+lan92xx_set_mac_addr(struct eth_drv_sc *sc, unsigned char *enaddr);
+static void lan92xx_soft_reset(struct eth_drv_sc *sc);
+static inline unsigned int
+lan92xx_mac_read(struct eth_drv_sc *sc, unsigned char reg);
+static inline void
+lan92xx_mac_write(struct eth_drv_sc *sc, unsigned char reg, unsigned long val);
+static inline unsigned int
+lan92xx_mii_read(struct eth_drv_sc *sc, unsigned char addr);
+static inline void
+lan92xx_mii_write(struct eth_drv_sc *sc, unsigned char addr, unsigned int val);
+
+/*!
+ * This function set the value of PHY registers by MII interface
+ */
+static void
+lan92xx_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
+{
+    unsigned int val;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+
+    lan92xx_set_mac_addr(sc, enaddr);
+
+    pdev->tx_busy = 0;
+
+    val = lan92xx_mac_read(sc, MAC_MAC_CR)& (~0x800);
+    val |= 0x0010080C;
+    lan92xx_mac_write(sc, MAC_MAC_CR, val);
+    val = lan92xx_mac_read(sc, MAC_MAC_CR);
+}
+
+/*!
+ * This function pauses the FEC controller.
+ */
+static void
+lan92xx_stop(struct eth_drv_sc *sc)
+{
+    unsigned int val;
+
+    val = lan92xx_mac_read(sc, MAC_MAC_CR);
+    val &= ~(0x0000000C);
+    lan92xx_mac_write(sc, MAC_MAC_CR, val);
+}
+
+static int
+lan92xx_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length)
+{
+    /*TODO:: Add support */
+    PDEBUG("%s: key=0x%x, data=0x%x, data_len=0x%x\n",
+           __FUNCTION__, key, (unsigned long)data, (unsigned long)data_length);
+    return 0;
+}
+
+/*!
+ * This function checks the status of FEC control.
+ */
+static int
+lan92xx_can_send(struct eth_drv_sc *sc)
+{
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+
+    if (!(pdev->status & PHY_LINK_ON)) return 0;
+    if (pdev->tx_busy) return 0;
+
+    return 1;
+}
+
+/*!
+ * This function transmits a frame.
+ */
+static void
+lan92xx_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total, unsigned long key)
+{
+    int i, j, len, freespace;
+    unsigned int tx_cmd1, tx_cmd2, data, *pdata;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+    freespace = LAN92XX_REG_READ(LAN92XX_TX_FIFO_INF) & 0xFFFF;
+
+    if (freespace < total + 16 ) {
+        sc->funs->eth_drv->tx_done(sc, key, -1);
+        return;
+    }
+    for (i = 0; i < sg_len; i++) {
+        len = (sg_list[i].len + 3) >> 2;
+        if (i == (sg_len - 1))
+            tx_cmd1 = 0x1000;
+        else if (i)
+            tx_cmd1 = 0x0000;
+        else
+            tx_cmd1 = 0x2000;
+
+        tx_cmd1 |= sg_list[i].len;
+        tx_cmd2 = (total << 16) + total;
+        LAN92XX_REG_WRITE(LAN92XX_TX_DATA, tx_cmd1);
+
+        LAN92XX_REG_WRITE(LAN92XX_TX_DATA, tx_cmd2);
+        pdata = (unsigned int *)sg_list[i].buf;
+
+        for (j=0; j<len; j++) {
+            data = *(pdata++);
+            LAN92XX_REG_WRITE(LAN92XX_TX_DATA, data);
+            for (data=0; data<2; data++) {
+                asm volatile("nop");
+                asm volatile("nop");
+                asm volatile("nop");
+                asm volatile("nop");
+            }
+        }
+    }
+    pdev->tx_busy = 1;
+    pdev->tx_key = key;
+}
+
+static void
+lan92xx_drop_packet(struct eth_drv_sc *sc, int count)
+{
+    unsigned int data;
+    if (count >= 4) {
+        LAN92XX_REG_WRITE(LAN92XX_RX_DP_CTRL, 0x80000000);
+        while (LAN92XX_REG_READ(LAN92XX_RX_DP_CTRL) & 0x80000000) {
+        }
+    } else {
+        while (count--)
+            data = LAN92XX_REG_READ(LAN92XX_RX_DATA);
+    }
+}
+
+/*!
+ * This function receives ready Frame in DB.
+ */
+static void
+lan92xx_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
+{
+    unsigned int i, rlen;
+    unsigned int *pdata = (unsigned int *)(sg_list->buf);
+
+    rlen = (sg_list->len + 3) >> 2;
+    if ((void *)(sg_list->buf) == NULL) {
+        goto Drop;
+    }
+
+    for (i = 0; i < rlen; i++) {
+        *(pdata++) = LAN92XX_REG_READ(LAN92XX_RX_DATA);
+    }
+    return;
+Drop:
+    lan92xx_drop_packet(sc, rlen);
+}
+
+static void
+lan92xx_deliver(struct eth_drv_sc *sc)
+{
+    /*TODO::When redboot support thread ,
+     *      the polling function will be called at here
+     */
+    return;
+}
+
+static void
+lan92xx_link_status(struct eth_drv_sc *sc)
+{
+    unsigned int val;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+    val = lan92xx_mii_read(sc, PHY_ISR);
+    if (val&0x50) {
+        val = lan92xx_mii_read(sc, PHY_BSR);
+        if (val != pdev->status) {
+            pdev->status = val;
+            val = lan92xx_mac_read(sc, MAC_MAC_CR) & (~0x802F0800);
+            if ( IS_DUPLEX(pdev->status)) {
+                val |= 0x00100000;
+            }
+            lan92xx_mac_write(sc, MAC_MAC_CR, val);
+        }
+    }
+}
+/*!
+ * This function checks the event of FEC controller
+ */
+static void
+lan92xx_poll(struct eth_drv_sc *sc)
+{
+    unsigned int val, reg;
+    int rx_num = 0;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+
+    reg = LAN92XX_REG_READ(LAN92XX_INT_STS);
+    LAN92XX_REG_WRITE(LAN92XX_INT_STS, reg);
+
+    //diag_printf("INT_STS: %x\n", reg);
+    if (reg & 0x40000) {
+        lan92xx_link_status(sc);
+    }
+
+    if (reg & 0xE000) {
+        diag_printf("%s:: TX or RX error [0x%x]\n", __FUNCTION__, reg);
+        lan92xx_soft_reset(sc);
+        return;
+    }
+
+    while (1) {
+        reg = LAN92XX_REG_READ(LAN92XX_RX_FIFO_INF);
+        if (!(reg & 0xFF0000))
+            break;
+        reg = LAN92XX_REG_READ(LAN92XX_RX_STATUS1);
+
+        if (reg & 0x4000909A) {
+            val = (reg >> 16) & 0x3FFF;
+            val = (val + 3) >> 2;
+            lan92xx_drop_packet(sc, val);
+        } else {
+            val = (reg >> 16) & 0x3FFF;
+            sc->funs->eth_drv->recv(sc, val);
+            rx_num++;
+        }
+
+        if ( rx_num >= MAX_RX_NUM) break;
+    }
+
+    while (1) {
+        reg = LAN92XX_REG_READ(LAN92XX_TX_FIFO_INF);
+        if (!(reg & 0xFF0000)) break;
+
+        if (!LAN92XX_REG_READ(LAN92XX_TX_STATUS2)) {
+            diag_printf("***FIFO %x, wrong status =%x: int_sts=%x\n",
+                        reg, LAN92XX_REG_READ(LAN92XX_TX_STATUS2),
+                        LAN92XX_REG_READ(LAN92XX_INT_STS));
+            continue;
+        }
+        reg = LAN92XX_REG_READ(LAN92XX_TX_STATUS1);
+        if (reg & 0x8000) {
+            sc->funs->eth_drv->tx_done(sc, pdev->tx_key, -1);
+        } else {
+            sc->funs->eth_drv->tx_done(sc, pdev->tx_key, 0);
+        }
+        pdev->tx_busy = 0;
+    }
+}
+
+static int
+lan92xx_int_vector(struct eth_drv_sc *sc)
+{
+    PDEBUG("%s::\n", __FUNCTION__);
+
+    /*TODO::
+     *      get FEC interrupt number
+     */
+    return -1;
+}
+
+static smsc_lan92xx_id_t *lan92xx_probe(unsigned long id)
+{
+    smsc_lan92xx_id_t *p = smsc_lan92xx_id_table;
+    while (p->id) {
+        if (id == p->id)
+            return p;
+        p++;
+    }
+    return NULL;
+}
+
+static inline unsigned int
+lan92xx_mac_read(struct eth_drv_sc *sc, unsigned char reg)
+{
+    unsigned int cmd;
+
+    if (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000) {
+        diag_printf("Error: %d. MAC is busy\n", __LINE__);
+        return 0xFFFFFFFF;
+    }
+
+    cmd = 0xC0000000 | (reg & 0xFF);
+    LAN92XX_REG_WRITE(LAN92XX_MAC_CMD, cmd);
+
+    /* Workaround for hardware read-after-write */
+    LAN92XX_REG_READ(LAN92XX_BYTE_TEST);
+
+    while (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000);
+
+    return LAN92XX_REG_READ(LAN92XX_MAC_DATA);
+}
+
+static inline void
+lan92xx_mac_write(struct eth_drv_sc *sc, unsigned char reg, unsigned long val)
+{
+    unsigned int cmd;
+
+    if (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000) {
+        diag_printf("Error: %d. MAC is busy\n", __LINE__);
+        return;
+    }
+
+    LAN92XX_REG_WRITE(LAN92XX_MAC_DATA, val);
+    cmd = 0x80000000 | (reg & 0xFF);
+    LAN92XX_REG_WRITE(LAN92XX_MAC_CMD, cmd);
+
+    /* Workaround for hardware read-after-write */
+    LAN92XX_REG_READ(LAN92XX_BYTE_TEST);
+
+    while (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000);
+}
+
+static inline void
+lan92xx_set_mac_addr(struct eth_drv_sc *sc, unsigned char *enaddr)
+{
+    unsigned int val;
+    val = enaddr[3];
+    val = (val << 8) | enaddr[2];
+    val = (val << 8) | enaddr[1];
+    val = (val << 8) | enaddr[0];
+    lan92xx_mac_write(sc, MAC_ADDRL, val);
+
+    val = lan92xx_mac_read(sc, MAC_ADDRH) >> 16;
+    val = (val << 8) | enaddr[5];
+    val = (val << 8) | enaddr[4];
+    lan92xx_mac_write(sc, MAC_ADDRH, val);
+}
+
+static inline unsigned int
+lan92xx_mii_read(struct eth_drv_sc *sc, unsigned char addr)
+{
+    unsigned int cmd;
+
+    cmd = (0x1 << 11 ) | (addr << 6) | 1;
+    lan92xx_mac_write(sc, MAC_MII_ACC, cmd);
+    while (lan92xx_mac_read(sc, MAC_MII_ACC) & 1);
+
+    return lan92xx_mac_read(sc, MAC_MII_DATA)&0xFFFF;
+}
+
+static inline void
+lan92xx_mii_write(struct eth_drv_sc *sc, unsigned char addr, unsigned int val)
+{
+    unsigned int cmd;
+
+    cmd = (0x1 << 11 ) | (addr << 6) | 3;
+    lan92xx_mac_write(sc, MAC_MII_DATA, val);
+    lan92xx_mac_read(sc, MAC_MII_DATA);
+    lan92xx_mac_write(sc, MAC_MII_ACC, cmd);
+
+    while (lan92xx_mac_read(sc, MAC_MII_ACC) & 1);
+}
+
+static int lan92xx_phy_init(struct eth_drv_sc *sc)
+{
+    int val;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+
+    lan92xx_mii_write(sc, PHY_BCR, 0x8000);
+
+    while (lan92xx_mii_read(sc, PHY_BCR) & 0x8000);
+
+    for (val = 0; val < 2500; val++)
+        hal_delay_us(4);
+
+    val = lan92xx_mii_read(sc, PHY_ANAR);
+    val |= 0x01E1;
+    lan92xx_mii_write(sc, PHY_ANAR, val);
+    lan92xx_mii_write(sc, PHY_SMR, 0x00E1);
+    lan92xx_mii_write(sc, PHY_SCSI, 0x400B);
+    lan92xx_mii_write(sc, PHY_IMR, 0x00F0);
+    lan92xx_mii_write(sc, PHY_BCR, 0x1200);
+
+    while ((lan92xx_mii_read(sc, PHY_BCR) & 0x200));
+
+    pdev->status = lan92xx_mii_read(sc, PHY_BSR);
+
+    return 0;
+}
+
+static int lan92xx_mac_init(struct eth_drv_sc *sc)
+{
+    static int mac_init = 0;
+    unsigned int val;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+
+    val = lan92xx_mac_read(sc, MAC_MAC_CR) & (~0x802F0800);
+    if (IS_DUPLEX(pdev->status)) {
+        val |= 0x00100000;
+    }
+    lan92xx_mac_write(sc, MAC_MAC_CR, val);
+
+    lan92xx_mac_write(sc, MAC_HASHH, 0);
+    lan92xx_mac_write(sc, MAC_HASHL, 0);
+
+    if (mac_init)
+        return 0;
+
+    mac_init = 1;
+
+#if CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+    if (!_board_provide_eth0_esa(pdev->mac_addr))
+#endif
+    {
+        // make sure EPC not busy
+        while ((val = LAN92XX_REG_READ(LAN92XX_E2P_CMD)) & E2P_CMD_BUSY);
+
+        if (val & E2P_CMD_TIMEOUT) {
+            lan92xx_eeprom_present = 0;
+            diag_printf("LAN9217: NO EEPROM\n");
+            return -1;
+        }
+
+        if (!(LAN92XX_REG_READ(LAN92XX_E2P_CMD) & E2P_CMD_LOADED)) {
+            diag_printf("LAN9217:EEPROM is empty\n");
+        }
+        val = lan92xx_mac_read(sc, MAC_ADDRH);
+        pdev->mac_addr[5] = (val >> 8) & 0xFF;
+        pdev->mac_addr[4] = val&0xFF;
+        val = lan92xx_mac_read(sc, MAC_ADDRL);
+        pdev->mac_addr[3] = (val >> 24) & 0xFF;
+        pdev->mac_addr[2] = (val >> 16) & 0xFF;
+        pdev->mac_addr[1] = (val >> 8) & 0xFF;
+        pdev->mac_addr[0] = val & 0xFF;
+    }
+    return 0;
+}
+
+/*
+ * This function reset LAN9219 .
+ */
+static void
+lan92xx_soft_reset(struct eth_drv_sc *sc)
+{
+    unsigned int timeout = MAC_TIMEOUT;
+
+    LAN92XX_REG_WRITE(LAN92XX_HW_CFG, 1);
+    while ((LAN92XX_REG_READ(LAN92XX_HW_CFG) & 1) && (--timeout)) {
+        hal_delay_us(MAC_TICKET);
+    }
+
+    if (!timeout) {
+        diag_printf("LAN92XX: Reset fail \n");
+        return ;
+    }
+
+    LAN92XX_REG_WRITE(LAN92XX_INT_EN, 0);
+    LAN92XX_REG_WRITE(LAN92XX_HW_CFG, 0x150000);
+    LAN92XX_REG_WRITE(LAN92XX_AFC_CFG, 0x6E3740);
+    LAN92XX_REG_WRITE(LAN92XX_TX_CFG, 0x2);
+
+    timeout = MAC_TIMEOUT;
+
+    while ((LAN92XX_REG_READ(LAN92XX_E2P_CMD) & 0x80000000) && (--timeout)) {
+        hal_delay_us(MAC_TICKET);
+    }
+
+    LAN92XX_REG_WRITE(LAN92XX_GPIO_CFG, 0x70070000);
+    LAN92XX_REG_WRITE(LAN92XX_INT_STS, 0xFFFFFFFF);
+    lan92xx_mac_init(sc);
+}
+
+/*!
+ * This function initializes the LAN92xx driver.
+ * It is called by net_init in net module of RedBoot during RedBoot init
+ */
+static bool
+lan92xx_init(struct cyg_netdevtab_entry *tab)
+{
+    unsigned int reg, timeout;
+    smsc_lan92xx_id_t *id;
+    struct eth_drv_sc *sc = tab ? tab->device_instance : NULL;
+    smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
+
+    diag_printf("\nLAN92xx Driver version %s\n", LAN_92XX_DRV_VER);
+    if (!pdev) {
+        diag_printf("LAN92xx:: Driver don't attach with device\n");
+        return false;
+    }
+    reg = LAN92XX_REG_READ(LAN92XX_ID_REV);
+    id = lan92xx_probe(reg >> 16);
+    if (id) {
+        diag_printf("%s: ID = 0x%x REV = 0x%x\n", id->id_name, id->id, id->ver);
+    } else {
+        diag_printf("LAN92XX: unknow chip ID = %x\n", reg);
+        return false;
+    }
+
+    timeout = MAC_TIMEOUT;
+    while ((!(LAN92XX_REG_READ(LAN92XX_PMT_CTRL) & 1)) && (--timeout)) {
+        hal_delay_us(MAC_TICKET);
+    }
+    if (timeout == 0) {
+        diag_printf("LAN92XX: is not ready to access\n");
+        return false;
+    }
+
+    lan92xx_phy_init(sc);
+
+    lan92xx_soft_reset(sc);
+    (sc->funs->eth_drv->init)(sc, pdev->mac_addr);
+    return true;
+}
+
+/*!
+ * Global variable which defines the LAN92xx driver,
+ */
+ETH_DRV_SC(lan92xx_sc,
+           &lan92xx_dev, // Driver specific data
+           CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME,
+           lan92xx_start,
+           lan92xx_stop,
+           lan92xx_control,
+           lan92xx_can_send,
+           lan92xx_send,
+           lan92xx_recv,
+           lan92xx_deliver,     // "pseudoDSR" called from fast net thread
+           lan92xx_poll,        // poll function, encapsulates ISR and DSR
+           lan92xx_int_vector);
+
+/*!
+ * Global variable which defines the FEC device
+ */
+NETDEVTAB_ENTRY(lan92xx_netdev,
+                "lan92xx_" CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME,
+                lan92xx_init,
+                &lan92xx_sc);
+
+// Low level function to issue a command to the eeprom controller.
+// return 0 on success and -1 on failure
+static inline int
+_lan92xx_e2p_do_cmd(unsigned int cmd)
+{
+    unsigned int v;
+    LAN92XX_REG_WRITE(LAN92XX_E2P_CMD, cmd);
+    while ((v = LAN92XX_REG_READ(LAN92XX_E2P_CMD)) & E2P_CMD_BUSY);
+    if (v & E2P_CMD_TIMEOUT) {
+        diag_printf("%s:: EEPROM timeout\n", __FUNCTION__);
+        // clear the timeout status bit
+        LAN92XX_REG_WRITE(LAN92XX_E2P_CMD, E2P_CMD_TIMEOUT);
+        while ((v = LAN92XX_REG_READ(LAN92XX_E2P_CMD)) & E2P_CMD_BUSY);
+        return -1;
+    }
+    return 0;
+}
+
+// for all the 7 EEPROM operations
+// return 0 on success and -1 on failure
+static int
+lan92xx_e2p_op(enum epc_cmd cmd, unsigned char addr, unsigned char *data)
+{
+    switch (cmd) {
+    case E2P_CMD_READ:
+        if (_lan92xx_e2p_do_cmd(E2P_CMD(cmd, addr)) != 0)
+            return -1;
+        *data = (unsigned char)LAN92XX_REG_READ(LAN92XX_E2P_DATA);
+        return 0;
+        break;
+    case E2P_CMD_WRAL:
+    case E2P_CMD_WRITE:
+        LAN92XX_REG_WRITE(LAN92XX_E2P_DATA, *data);
+        break;
+    default:
+        break;
+    }
+
+    if (_lan92xx_e2p_do_cmd(E2P_CMD(cmd, addr)) != 0)
+        return -1;
+
+    return 0;
+}
+
+static void setMac(int argc, char *argv[])
+{
+    int i;
+    unsigned char data[7];
+    unsigned long temp;
+
+    if (!lan92xx_eeprom_present) {
+        diag_printf("NO EEPROM present\n\n");
+        return;
+    }
+
+    if (argc == 1) {
+        for (i = 0; i < 7 ; i++) {
+            if (lan92xx_e2p_op(E2P_CMD_READ, i, &data[i]) != 0) {
+                diag_printf("read MAC %d address fail\n\n", i);
+                return;
+            }
+        }
+
+        if (data[0] != E2P_CONTEXT_ID) {
+            diag_printf("Warning: Unprogrammed MAC address: 0x%x\n", data[0]);
+            return;
+        }
+
+        diag_printf("MAC address: ");
+        diag_printf("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n\n",
+                    data[1], data[2], data[3],
+                    data[4], data[5], data[6]);
+        return;
+    }
+
+    if (argc != 2) {
+        diag_printf("Error: Wrong argument\n");
+        return;
+    }
+
+    data[0] = E2P_CONTEXT_ID;
+    for (i = 1;  i < 7;  i++) {
+        if (!parse_num(*(&argv[1]), &temp, &argv[1], ":")) {
+            diag_printf("Error: failed to parse command: %d\n", __LINE__);
+            return;
+        }
+        if (temp > 0xFF) {
+            diag_printf("Error: invalid valie: 0x%x\n", (unsigned int)temp);
+            return;
+        }
+        data[i] = temp;
+    }
+
+    // enable erase/write
+    if (lan92xx_e2p_op(E2P_CMD_EWEN, 0, data) != 0) {
+        diag_printf("%s:: Enable write/erase fail\n", __FUNCTION__);
+        return;
+    }
+    for (i = 0; i < 7; i++) {
+        if (lan92xx_e2p_op(E2P_CMD_ERASE, i, &data[i]) != 0 ||
+            lan92xx_e2p_op(E2P_CMD_WRITE, i, &data[i]) != 0) {
+            diag_printf("Error: failed to program eeprom at %d\n", i);
+            return;
+        }
+    }
+
+    // disable erase/write
+    if (lan92xx_e2p_op(E2P_CMD_EWDS, 0, data) != 0) {
+        diag_printf("%s:: Enable write/erase fail\n", __FUNCTION__);
+    }
+}
+
+RedBoot_cmd("setmac",
+            "Set Ethernet MAC address in EEPROM",
+            "[0x##:0x##:0x##:0x##:0x##:0x##]",
+            setMac
+           );
diff --git a/packages/devs/flash/arm/imx_3stack/v2_0/cdl/flash_board_spansion.cdl b/packages/devs/flash/arm/imx_3stack/v2_0/cdl/flash_board_spansion.cdl
new file mode 100644 (file)
index 0000000..6f2a22c
--- /dev/null
@@ -0,0 +1,71 @@
+# ====================================================================
+#
+#      flash_board_spansion.cdl
+#
+#      FLASH memory - Hardware support
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      gthomas
+# Original data:  gthomas
+# Contributors:
+# Date:           2000-07-26
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_FLASH_IMX_3STACK_SPANSION {
+    display       "Freescale Spansion FLASH memory support"
+
+    parent        CYGPKG_IO_FLASH
+    active_if    CYGPKG_IO_FLASH
+
+    implements    CYGHWR_IO_FLASH_DEVICE
+
+    compile       board_spansionflash.c
+
+    # Arguably this should do in the generic package
+    # but then there is a logic loop so you can never enable it.
+    cdl_interface CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED {
+        display   "Generic AMD FlashFile driver required"
+    }
+
+    implements    CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED
+
+    requires      CYGHWR_DEVS_FLASH_AMD_S29GL512N
+}
diff --git a/packages/devs/flash/arm/imx_3stack/v2_0/src/board_spansionflash.c b/packages/devs/flash/arm/imx_3stack/v2_0/src/board_spansionflash.c
new file mode 100644 (file)
index 0000000..9743dbf
--- /dev/null
@@ -0,0 +1,73 @@
+//==========================================================================
+//
+//      board_spansionflash.c
+//
+//      Flash programming for AMD Flash devices
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Patrick Doyle <wpd@delcomsys.com>
+// Contributors: Patrick Doyle <wpd@delcomsys.com>
+// Date:         2002-11-26
+// Purpose:      
+// Description:  
+//              
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/hal/hal_soc.h>
+
+//--------------------------------------------------------------------------
+// Device properties
+
+// We use the one SPANSION S29WS256N part on the EVB.
+#define CYGNUM_FLASH_INTERLEAVE (1)
+#define CYGNUM_FLASH_SERIES     (1)
+#define CYGNUM_FLASH_WIDTH      (16)
+#define CYGNUM_FLASH_BASE       (CS0_BASE_ADDR)
+
+#define CYGNUM_FLASH_TIMEOUT_QUERY 5000000
+#define CYGNUM_FLASH_TIMEOUT_ERASE_TIMER       100000000
+#define CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE    100000000
+#define CYGNUM_FLASH_TIMEOUT_PROGRAM           100000000
+//--------------------------------------------------------------------------
+// Platform specific extras
+
+//--------------------------------------------------------------------------
+// Now include the driver code.
+#include "cyg/io/flash_am29xxxxx.inl"
diff --git a/packages/devs/flash/arm/mx35evb/v2_0/cdl/flash_board_spansion.cdl b/packages/devs/flash/arm/mx35evb/v2_0/cdl/flash_board_spansion.cdl
new file mode 100644 (file)
index 0000000..6b03903
--- /dev/null
@@ -0,0 +1,71 @@
+# ====================================================================
+#
+#      flash_board_spansion.cdl
+#
+#      FLASH memory - Hardware support
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      gthomas
+# Original data:  gthomas
+# Contributors:
+# Date:           2000-07-26
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_FLASH_MX35EVB_SPANSION {
+    display       "Freescale Spansion FLASH memory support"
+
+    parent        CYGPKG_IO_FLASH
+    active_if    CYGPKG_IO_FLASH
+
+    implements    CYGHWR_IO_FLASH_DEVICE
+
+    compile       board_spansionflash.c
+
+    # Arguably this should do in the generic package
+    # but then there is a logic loop so you can never enable it.
+    cdl_interface CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED {
+        display   "Generic AMD FlashFile driver required"
+    }
+
+    implements    CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED
+
+    requires      CYGHWR_DEVS_FLASH_S29WS256N
+}
diff --git a/packages/devs/flash/arm/mx35evb/v2_0/cdl/flash_board_strata.cdl b/packages/devs/flash/arm/mx35evb/v2_0/cdl/flash_board_strata.cdl
new file mode 100644 (file)
index 0000000..070f8b3
--- /dev/null
@@ -0,0 +1,80 @@
+# ====================================================================
+#
+#      flash_board_strata.cdl
+#
+#      FLASH memory - Hardware support
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      gthomas
+# Original data:  gthomas
+# Contributors:
+# Date:           2000-07-26
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_FLASH_MX35EVB_STRATA {
+    display       "Freescale FLASH memory support"
+
+    parent        CYGPKG_IO_FLASH
+    active_if    CYGPKG_IO_FLASH
+
+    requires      CYGPKG_DEVS_FLASH_STRATA
+    requires      CYGNUM_DEVS_FLASH_STRATA_MAX_BLOCKS == 256
+
+    implements    CYGHWR_IO_FLASH_BLOCK_LOCKING
+
+    include_dir   cyg/io
+
+    # Arguably this should do in the generic package
+    # but then there is a logic loop so you can never enable it.
+    cdl_interface CYGINT_DEVS_FLASH_STRATA_REQUIRED {
+        display   "Generic StrataFLASH driver required"
+    }
+
+    implements    CYGINT_DEVS_FLASH_STRATA_REQUIRED
+
+    define_proc {
+        puts $::cdl_system_header "/***** strataflash driver proc output start *****/"
+        puts $::cdl_system_header "#define CYGDAT_DEVS_FLASH_STRATA_INL <cyg/io/board_strataflash.inl>"
+        puts $::cdl_system_header "#define CYGDAT_DEVS_FLASH_STRATA_CFG <pkgconf/devs_flash_board_strata.h>"
+        puts $::cdl_system_header "/*****  strataflash driver proc output end  *****/"
+    }
+}
+
diff --git a/packages/devs/flash/arm/mx35evb/v2_0/include/board_strataflash.inl b/packages/devs/flash/arm/mx35evb/v2_0/include/board_strataflash.inl
new file mode 100644 (file)
index 0000000..ee8a1c5
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef CYGONCE_DEVS_FLASH_BOARD_STRATAFLASH_INL
+#define CYGONCE_DEVS_FLASH_BOARD_STRATAFLASH_INL
+//==========================================================================
+//
+//      board_strataflash.inl
+//
+//      Flash programming - device constants, etc.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    gthomas, hmt
+// Contributors: gthomas
+// Date:         2001-02-24
+// Purpose:      
+// Description:  
+//              
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+// The system has one 16-bit devices.
+// a StrataFlash 28F256L18. The 256 means 256Mbit, so 32Mbyte with 16bit width.
+
+#define CYGNUM_FLASH_DEVICES   (1)
+#define CYGNUM_FLASH_BASE      (0xA0000000u)
+#define CYGNUM_FLASH_BASE_MASK  (0xFE000000u) // 32MB devices (size=0x02000000 -> mask=0xFE000000)
+#define CYGNUM_FLASH_WIDTH     (16)
+#define CYGNUM_FLASH_BLANK      (1)
+
+#endif  // CYGONCE_DEVS_FLASH_BOARD_STRATAFLASH_INL
\ No newline at end of file
diff --git a/packages/devs/flash/arm/mx35evb/v2_0/src/board_spansionflash.c b/packages/devs/flash/arm/mx35evb/v2_0/src/board_spansionflash.c
new file mode 100644 (file)
index 0000000..9743dbf
--- /dev/null
@@ -0,0 +1,73 @@
+//==========================================================================
+//
+//      board_spansionflash.c
+//
+//      Flash programming for AMD Flash devices
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Patrick Doyle <wpd@delcomsys.com>
+// Contributors: Patrick Doyle <wpd@delcomsys.com>
+// Date:         2002-11-26
+// Purpose:      
+// Description:  
+//              
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/hal/hal_soc.h>
+
+//--------------------------------------------------------------------------
+// Device properties
+
+// We use the one SPANSION S29WS256N part on the EVB.
+#define CYGNUM_FLASH_INTERLEAVE (1)
+#define CYGNUM_FLASH_SERIES     (1)
+#define CYGNUM_FLASH_WIDTH      (16)
+#define CYGNUM_FLASH_BASE       (CS0_BASE_ADDR)
+
+#define CYGNUM_FLASH_TIMEOUT_QUERY 5000000
+#define CYGNUM_FLASH_TIMEOUT_ERASE_TIMER       100000000
+#define CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE    100000000
+#define CYGNUM_FLASH_TIMEOUT_PROGRAM           100000000
+//--------------------------------------------------------------------------
+// Platform specific extras
+
+//--------------------------------------------------------------------------
+// Now include the driver code.
+#include "cyg/io/flash_am29xxxxx.inl"
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/card_mx32.h b/packages/devs/flash/arm/mxc/v2_0/include/card_mx32.h
new file mode 100644 (file)
index 0000000..0da935d
--- /dev/null
@@ -0,0 +1,314 @@
+#ifndef CARD_MX32_H
+#define CARD_MX32_H
+
+#include <cyg/infra/cyg_type.h>
+
+/*sdhc memory map*/
+typedef struct _sdhc
+{
+    cyg_uint32 sdhc_clk;
+    cyg_uint32 sdhc_status;
+    cyg_uint32 sdhc_clk_rate;
+    cyg_uint32 sdhc_dat_cont;
+    cyg_uint32 sdhc_response_to;
+    cyg_uint32 sdhc_read_to;
+    cyg_uint32 sdhc_blk_len;
+    cyg_uint32 sdhc_nob;
+    cyg_uint32 sdhc_rev_no;
+    cyg_uint32 sdhc_int_cntr;
+    cyg_uint32 sdhc_cmd;
+    cyg_uint32 sdhc_arg;
+    cyg_uint32 sdhc_reserved;
+    cyg_uint32 sdhc_res_fifo;
+    cyg_uint32 sdhc_buffer_access;
+}sdhc_t, *psdhc_t;
+
+/* Defines for card types */
+typedef enum
+{
+       TYPE_NONE,
+       SD_CSD_1_0,
+       SD_CSD_2_0,
+       MMC_CSD_1_0,
+       MMC_CSD_1_1,
+       MMC_CSD_1_2,
+       MMC_UNKNOWN
+}card_type;
+
+typedef struct _card_specific_data
+{
+       cyg_uint32 csd0;
+       cyg_uint32 csd1;
+       cyg_uint32 csd2;
+       cyg_uint32 csd3;
+}CARD_SPECIFIC_DATA;
+
+/* Defines for card types */
+typedef struct _card_id
+{
+       cyg_uint32 cid0;
+       cyg_uint32 cid1;
+       cyg_uint32 cid2;
+       cyg_uint32 cid3;
+}CARD_ID;
+
+enum sdhc_clk_val
+{
+    SDHC_CLK_START = 0x2,
+    SDHC_CLK_STOP = 0x1,
+    SDHC_CLK_RESET = 0x8
+};
+
+typedef enum frequency_mode
+{
+       iden_mode = 0x1,
+       trans_mode = 0x2
+} frequency_mode_t;
+
+typedef struct command
+{
+       cyg_uint32 index;
+       cyg_uint32 data_control;
+       cyg_uint32 arg;
+}command_t;
+
+
+#define NO_ARG 0
+#define ENABLE 1
+#define DISABLE 0
+#define PASS 0
+#define SUCCESS 0
+#define FAIL 1
+
+#define CARD_STATE 0x1E00
+#define CARD_STATE_SHIFT 9
+
+/*Defines of CSD data*/
+#define CSD_STRUCT_MSK 0x00C00000
+#define CSD_STRUCT_SHIFT       22
+
+
+/* Define the states of the card*/
+enum states
+{
+       IDLE,
+       READY,
+       IDENT,
+       STBY,
+       TRAN,
+       DATA,
+       RCV,
+       PRG,
+       DIS
+};
+
+
+/* SDHC Response */
+typedef struct _response
+{
+    cyg_uint32 rsp0;
+    cyg_uint32 rsp1;
+    cyg_uint32 rsp2;
+    cyg_uint32 rsp3;
+}response_t;
+
+
+typedef enum card_mode
+{
+       NONE = 0,
+       SD = 1,
+       MMC = 2
+}card_mode_t;
+
+enum RW
+{
+       READ = 0,
+       WRITE = 1
+};
+
+enum cmd_response
+{
+       RESPONSE_NO = 0x0,
+       RESPONSE_48_CRC = 0x1,
+       RESPONSE_136 = 0x2,
+       RESPONSE_48_WITHOUT_CRC = 0x3
+};
+
+enum status_bus_width
+{
+       ONE = 0x0,
+       FOUR = 0x2
+};
+
+
+#define SDHC_INT                  0xc015
+
+#define OCR_VALUE 0x80ff8000
+#define OCR_VALUE_MASK 0x00ff8000
+#define CARD_BUSY 0x80000000
+#define SD_R1_APP_CMD_MSK 0x20
+
+#define BLOCK_LEN 0x200
+
+
+
+/* Status regsiter Masks */
+#define SDHC_STATUS_END_CMD_RESP_MSK          0x2000
+#define SDHC_STATUS_WRITE_OP_DONE_MSK         0x1000
+#define SDHC_STATUS_READ_OP_DONE_MSK          0x800
+#define SDHC_STATUS_WR_CRC_ERR_CODE_MSK       0x600
+#define SDHC_STATUS_CARD_BUS_CLK_RUN_MSK               0x100
+#define SDHC_STATUS_RESP_CRC_ERR_MSK          0x20
+#define SDHC_STATUS_BUF_READ_RDY_MSK          0x80
+#define SDHC_STATUS_BUF_WRITE_RDY_MSK         0x40
+#define SDHC_STATUS_READ_CRC_ERR_MSK          0x8
+#define SDHC_STATUS_WRITE_CRC_ERR_MSK         0x4
+#define SDHC_STATUS_TIME_OUT_RESP_MSK         0x2
+#define SDHC_STATUS_TIME_OUT_READ             0x1
+
+#define SDHC_STATUS_CLEAR                     ((cyg_uint32)(0xC0007E2F))
+
+
+
+/* Command (data control) masks */
+#define SDHC_CMD_FROMAT_OF_RESP      0x00000007
+#define SDHC_CMD_DATA_ENABLE         0x00000008
+#define SDHC_CMD_WRITE_READ          0x00000010
+#define SDHC_CMD_INIT                0x00000080
+#define SDHC_CMD_BUS_WIDTH           0x00000300
+#define SDHC_CMD_START_READWAIT     0x00000400
+#define SDHC_CMD_STOP_READWAIT      0x00000800
+#define SDHC_CMD_DATA_CTRL_CMD_RESP_LONG_OFF   0x00001000
+
+/* Command (data control) shift */
+#define SDHC_CMD_FROMAT_OF_RESP_SHIFT     0x0
+#define SDHC_CMD_DATA_ENABLE_SHIFT        0x3
+#define SDHC_CMD_BUS_WIDTH_SHIFT          0x8
+#define SDHC_CMD_WRITE_READ_SHIFT         0x4
+#define SDHC_CMD_INIT_SHIFT               0x7
+
+//#define SDHC_CMD_FROMAT_OF_RESP_NONE      0x0
+//#define SDHC_CMD_DATA_CTRL_FROMAT_OF_RESP_48        0x1
+//#define SDHC_CMD_DATA_CTRL_FROMAT_OF_RESP_136       0x2
+//#define SDHC_CMD_DATA_CTRL_FROMAT_OF_RESP_48_N0_CRC 0x3
+//#define SDHC_CMD_DATA_CTRL_BUS_WIDTH_1_BIT          0x0
+//#define SDHC_CMD_DATA_CTRL_BUS_WIDTH_4_BIT          0x2
+
+/* Define  each command */
+enum commands
+{
+       CMD0= 0,
+       CMD1= 1,
+       CMD2= 2,
+       CMD3= 3,
+       CMD5= 5,
+       CMD6=6,
+       ACMD6= 6,
+       CMD7= 7,
+       CMD8 = 8,
+       CMD9=9,
+       CMD12   = 12,
+       CMD13   = 13,
+       CMD16   = 16,
+       CMD17   = 17,
+       CMD18   = 18,
+       CMD24   = 24,
+       CMD25   = 25,
+       CMD26   = 26,
+       CMD32   = 32,
+       CMD33   = 33,
+       CMD35   = 35,
+       CMD36   = 36,
+       CMD38   = 38,
+       ACMD41  = 41,
+       ACMD51  = 51,
+       CMD55   = 55
+};
+
+extern cyg_uint32 CCC; /* Card Command Class */
+
+extern cyg_uint32 mxcmci_init (cyg_uint32 bus_width, cyg_uint32 base_address);
+extern cyg_uint32 mmc_data_write (cyg_uint32 *src_ptr,cyg_uint32 length,cyg_uint32 offset);
+extern cyg_uint32 mmc_data_erase (cyg_uint32 offset, cyg_uint32 size);
+extern cyg_uint32 mmc_data_read (cyg_uint32 *,cyg_uint32 ,cyg_uint32);
+extern cyg_uint32 card_flash_query(void* data);
+extern cyg_uint32 card_get_capacity_size (void);
+
+struct csd_v1_0 {
+       cyg_uint32 rsv3:1,
+        crc:7,
+        rsv2:2,
+        file_format:2,
+        tmp_write_protect:1,
+        perm_write_protect:1,
+        copy:1,
+        file_format_grp:1,
+        rsv1:5,
+        write_bl_partial:1,
+        write_bl_len:4,
+        r2w_factor:3,
+        rsv0:2,
+        wp_grp_enable:1;
+       cyg_uint32 wp_grp_size:7,
+        sector_size:7,
+        erase_blk_en:1,
+        c_size_mult:3,
+        vdd_w_curr_max:3,
+        vdd_w_curr_min:3,
+        vdd_r_curr_max:3,
+        vdd_r_curr_min:3,
+        c_size_lo:2;
+    cyg_uint32 c_size_up:10,
+        rsv4:2,
+        dsr_imp:1,
+        read_blk_misalign:1,
+        write_blk_misalign:1,
+        read_bl_partial:1,
+        read_bl_len:4,
+        ccc:12;
+    cyg_uint32 tran_speed:8,
+        nsac:8,
+        taac:8,
+        rsv5:6,
+        csd_structure:2;
+} __attribute__ ((packed));
+
+struct csd_v2_0 {
+       cyg_uint32
+        rsv3:1,
+        crc:7,
+        rsv2:2,
+        file_format:2,
+        tmp_write_protect:1,
+        perm_write_protect:1,
+        copy:1,
+        file_format_grp:1,
+        rsv1:5,
+        write_bl_partial:1,
+        write_bl_len:4,
+        r2w_factor:3,
+        rsv0:2,
+        wp_grp_enable:1;
+       cyg_uint32
+        wp_grp_size:7,
+        sector_size:7,
+        erase_blk_en:1,
+        rsv9:1,
+        c_size_lo:16;
+    cyg_uint32
+        c_size_up:6,
+        rsv4:6,
+        dsr_imp:1,
+        read_blk_misalign:1,
+        write_blk_misalign:1,
+        read_bl_partial:1,
+        read_bl_len:4,
+        ccc:12;
+    cyg_uint32 tran_speed:8,
+        nsac:8,
+        taac:8,
+        rsv5:6,
+        csd_structure:2;
+} __attribute__ ((packed));
+
+#endif
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/imx_nfc.h b/packages/devs/flash/arm/mxc/v2_0/include/imx_nfc.h
new file mode 100644 (file)
index 0000000..d8f5704
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef _IMX_NFC_H_
+#define _IMX_NFC_H_
+//==========================================================================
+//
+//      imx_nfc.h
+//
+//      Flash programming to support NAND flash on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Kevin Zhang <k.zhang@freescale.com>
+// Contributors: Kevin Zhang <k.zhang@freescale.com>
+// Date:         2008-06-02
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#define NFC_DEBUG_MIN   1
+#define NFC_DEBUG_MED   2
+#define NFC_DEBUG_MAX   3
+#define NFC_DEBUG_DEF   NFC_DEBUG_MED
+
+extern int _mxc_boot;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned char u8;
+
+//----------------------------------------------------------------------------
+// Common device details.
+#define FLASH_Read_ID                   (0x90)
+#ifdef CYGHWR_DEVS_FLASH_MXC_NAND_RESET_WORKAROUND
+#define FLASH_Reset                     0xFFFF
+#else
+#define FLASH_Reset                     (0xFF)
+#endif
+#define FLASH_Read_Mode1                (0x00)
+#define FLASH_Read_Mode1_LG             (0x30)
+#define FLASH_Read_Mode2                (0x01)
+#define FLASH_Read_Mode3                (0x50)
+#define FLASH_Program                   (0x10)
+#define FLASH_Send_Data                 (0x80)
+#define FLASH_Status                    (0x70)
+#define FLASH_Block_Erase               (0x60)
+#define FLASH_Start_Erase               (0xD0)
+
+enum nfc_page_area {
+    NFC_SPARE_ONLY,
+    NFC_MAIN_ONLY,
+};
+
+enum {
+    MXC_NAND_8_BIT = 8,
+    MXC_NAND_16_BIT =  16,
+};
+
+enum {
+    NAND_SLC = 0,
+    NAND_MLC = 1,
+};
+
+// read column 464-465 byte but only 464 for bad block marker
+#define BAD_BLK_MARKER_464          (NAND_MAIN_BUF3 + 464)
+// read column 4-5 byte, but only 5 is used for swapped main area data
+#define BAD_BLK_MARKER_SP_5         (NAND_SPAR_BUF3 + 4)
+
+typedef void nfc_iomuxsetup_func_t(void);
+
+#endif // _IMX_NFC_H_
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/imx_spi_nor.h b/packages/devs/flash/arm/mxc/v2_0/include/imx_spi_nor.h
new file mode 100644 (file)
index 0000000..a6433b3
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef _IMX_SPI_NOR_H_
+#define _IMX_SPI_NOR_H_
+//==========================================================================
+//
+//      imx_nfc.h
+//
+//      Flash programming to support NAND flash on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Kevin Zhang <k.zhang@freescale.com>
+// Contributors: Kevin Zhang <k.zhang@freescale.com>
+// Date:         2008-11-14
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+// dummy defines - not used
+#define CYGNUM_FLASH_INTERLEAVE         1
+#define CYGNUM_FLASH_SERIES             1
+#define CYGNUM_FLASH_WIDTH              8
+#define CYGNUM_FLASH_BASE               0
+#define CYGNUM_FLASH_BLANK              1
+
+#define READ        0x03    // tx: 1 byte cmd + 3 byte addr; rx: variable bytes
+#define READ_HS     0x0B    // tx: 1 byte cmd + 3 byte addr + 1 byte dummy; rx: variable bytes
+#define RDSR        0x05    // read status register 1 byte tx cmd + 1 byte rx status
+    #define RDSR_BUSY       (1 << 0)    // 1=write-in-progress (default 0)
+    #define RDSR_WEL        (1 << 1)    // 1=write enable (default 0)
+    #define RDSR_BP0        (1 << 2)    // block write prot level (default 1)
+    #define RDSR_BP1        (1 << 3)    // block write prot level (default 1)
+    #define RDSR_BP2        (1 << 4)    // block write prot level (default 1)
+    #define RDSR_BP3        (1 << 5)    // block write prot level (default 1)
+    #define RDSR_AAI        (1 << 6)    // 1=AAI prog mode; 0=byte prog (default 0)
+    #define RDSR_BPL        (1 << 7)    // 1=BP3,BP2,BP1,BP0 RO; 0=R/W (default 0)    
+#define WREN        0x06    // write enable. 1 byte tx cmd
+#define WRDI        0x04    // write disable. 1 byte tx cmd
+#define EWSR        0x50    // Enable write status. 1 byte tx cmd
+#define WRSR        0x01    // Write status register. 1 byte tx cmd + 1 byte tx value
+#define ERASE_4K    0x20    // sector erase. 1 byte cmd + 3 byte addr
+#define ERASE_32K   0x52    // 32K block erase. 1 byte cmd + 3 byte addr
+#define ERASE_64K   0xD8    // 64K block erase. 1 byte cmd + 3 byte addr
+#define ERASE_CHIP  0x60    // whole chip erase
+#define BYTE_PROG   0x02    // all tx: 1 cmd + 3 addr + 1 data
+#define AAI_PROG    0xAD    // all tx: [1 cmd + 3 addr + 2 data] + RDSR
+                            //   + [1cmd + 2 data] + .. + [WRDI] + [RDSR]
+#define JEDEC_ID    0x9F    // read JEDEC ID. tx: 1 byte cmd; rx: 3 byte ID
+
+#define SZ_64K      0x10000
+#define SZ_32K      0x8000
+#define SZ_4K       0x1000
+
+extern imx_spi_init_func_t *spi_nor_init;
+extern imx_spi_xfer_func_t *spi_nor_xfer;
+extern struct imx_spi_dev imx_spi_nor;
+static int spi_nor_status(void);
+static int spi_nor_cmd_1byte(unsigned char cmd);
+int spi_nor_erase_block(void* block_addr, unsigned int block_size);
+static int spi_nor_write_status(unsigned char val);
+int spi_nor_program_buf(void *addr, void *data, int len);
+
+#endif // _IMX_SPI_NOR_H_
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/mxc_ata.h b/packages/devs/flash/arm/mxc/v2_0/include/mxc_ata.h
new file mode 100644 (file)
index 0000000..fe47544
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef _IMX_ATA_H_
+#define _IMX_ATA_H_
+//==========================================================================
+//
+//      mxc_ata.h
+//
+//   Support ATA on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
+// Contributors: Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
+// Date:         2008-11-18
+//
+//==========================================================================
+#define FSL_ATA_TIMING_REGS                             0x00
+#define FSL_ATA_FIFO_FILL                                   0x20
+#define FSL_ATA_CONTROL                                     0x24
+#define FSL_ATA_INT_PEND                                   0x28
+#define FSL_ATA_INT_EN                                       0x2C
+#define FSL_ATA_INT_CLEAR                                 0x30
+#define FSL_ATA_FIFO_ALARM                              0x34
+#define FSL_ATA_ADMA_ERROR_STATUS               0x38
+#define FSL_ATA_SYS_DMA_BADDR                       0x3C
+#define FSL_ATA_ADMA_SYS_ADDR                       0x40
+#define FSL_ATA_BLOCK_COUNT                            0x48
+#define FSL_ATA_BURST_LENGTH                          0x4C
+#define FSL_ATA_SECTOR_SIZE                             0x50
+#define FSL_ATA_DRIVE_DATA                              0xA0
+#define FSL_ATA_DFTR                                          0xA4
+#define FSL_ATA_DSCR                                          0xA8
+#define FSL_ATA_DSNR                                          0xAC
+#define FSL_ATA_DCLR                                           0xB0
+#define FSL_ATA_DCHR                                          0xB4
+#define FSL_ATA_DDHR                                          0xB8
+#define FSL_ATA_DCDR                                          0xBC
+#define FSL_ATA_DRIVE_CONTROL                         0xD8
+
+/* bits within FSL_ATA_CONTROL */
+#define FSL_ATA_CTRL_DMA_SRST                         0x1000
+#define FSL_ATA_CTRL_DMA_64ADMA                    0x800
+#define FSL_ATA_CTRL_DMA_32ADMA                    0x400
+#define FSL_ATA_CTRL_DMA_STAT_STOP               0x200
+#define FSL_ATA_CTRL_DMA_ENABLE                     0x100
+#define FSL_ATA_CTRL_FIFO_RST_B                       0x80
+#define FSL_ATA_CTRL_ATA_RST_B                        0x40
+#define FSL_ATA_CTRL_FIFO_TX_EN                      0x20
+#define FSL_ATA_CTRL_FIFO_RCV_EN                    0x10
+#define FSL_ATA_CTRL_DMA_PENDING                   0x08
+#define FSL_ATA_CTRL_DMA_ULTRA                       0x04
+#define FSL_ATA_CTRL_DMA_WRITE                       0x02
+#define FSL_ATA_CTRL_IORDY_EN                          0x01
+
+/* bits within the interrupt control registers */
+#define FSL_ATA_INTR_ATA_INTRQ1                      0x80
+#define FSL_ATA_INTR_FIFO_UNDERFLOW             0x40
+#define FSL_ATA_INTR_FIFO_OVERFLOW               0x20
+#define FSL_ATA_INTR_CTRL_IDLE                         0x10
+#define FSL_ATA_INTR_ATA_INTRQ2                      0x08
+#define FSL_ATA_INTR_DMA_ERR                           0x04
+#define FSL_ATA_INTR_DMA_TRANS_OVER            0x02
+
+/* ADMA Addr Descriptor Attribute Filed */
+#define FSL_ADMA_DES_ATTR_VALID                     0x01
+#define FSL_ADMA_DES_ATTR_END                        0x02
+#define FSL_ADMA_DES_ATTR_INT                         0x04
+#define FSL_ADMA_DES_ATTR_SET                         0x10
+#define FSL_ADMA_DES_ATTR_TRAN                      0x20
+#define FSL_ADMA_DES_ATTR_LINK                       0x30
+
+#define PIO_XFER_MODE_0                                     0
+#define PIO_XFER_MODE_1                                     1
+#define PIO_XFER_MODE_2                                     2
+#define PIO_XFER_MODE_3                                     3
+#define PIO_XFER_MODE_4                                     4
+
+#define ATA_ID_PROD                                             27
+#define ATA_ID_PROD_LEN                                     40
+
+#define ATA_BUSY                                                   (1 << 7)
+#define ATA_DRQ                                                     (1 << 3)
+#define ATA_ERR                                                     (1)
+
+#define ATA_IEN                                                     (1 << 1)
+#define ATA_SRST                                                   (1 << 2)
+
+#define ATA_CMD_READ                                          0x20
+#define ATA_CMD_WRITE                                        0x30
+#define ATA_CMD_READ_MULTI                              0xC4
+#define ATA_CMD_WRITE_MULTI                            0xC5
+#define ATA_CMD_ID_ATA                                      0xEC
+#define ATA_CMD_SET_FEATURES                          0xEF
+
+#define ATA_SECTOR_SIZE                                     512
+#define MAX_NUMBER_OF_SECTORS                       256
+#endif // _IMX_ATA_H_
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/mxc_mmc.h b/packages/devs/flash/arm/mxc/v2_0/include/mxc_mmc.h
new file mode 100644 (file)
index 0000000..42dc331
--- /dev/null
@@ -0,0 +1,47 @@
+/*=================================================================================
+
+    Module Name:  mxc_mmc.h
+
+    General Description: Limited Bootloader eSDHC Driver.
+
+===================================================================================
+                               Copyright: 2004,2005,2006,2007,2008 FREESCALE, INC.
+                   All Rights Reserved. This file contains copyrighted material.
+                   Use of this file is restricted by the provisions of a
+                   Freescale Software License Agreement, which has either
+                   accompanied the delivery of this software in shrink wrap
+                   form or been expressly executed between the parties.
+
+
+Revision History:
+                            Modification     Tracking
+Author (core ID)                Date          Number     Description of Changes
+-------------------------   ------------    ----------   --------------------------
+Lewis Liu                  18-Feb-2008
+
+
+Portability: Portable to other compilers or platforms.
+
+====================================================================================================*/
+
+#ifndef __MXC_MMC_H__
+#define __MXC_MMC_H__
+
+#include <pkgconf/system.h>
+
+#define FLASH_DEBUG_MIN 1
+#define FLASH_DEBUG_MED 2
+#define FLASH_DEBUG_MAX 3
+#define FLASH_DEBUG_LEVEL FLASH_DEBUG_MED
+#define flash_dprintf(level, args...)          \
+   do {                                \
+         if (FLASH_DEBUG_LEVEL >= level)     \
+            diag_printf(args);          \
+   } while(0)
+
+#define CHECK_RUN_TIMES(n) { \
+       static int count = 0;\
+       if(++count > n){\
+               diag_printf("%s: the loop gets the limitation, WRONG!\n", __FUNCTION__);break;}
+
+#endif //__MXC_MMC_H__
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/mxc_nfc_v3.h b/packages/devs/flash/arm/mxc/v2_0/include/mxc_nfc_v3.h
new file mode 100644 (file)
index 0000000..cacf665
--- /dev/null
@@ -0,0 +1,318 @@
+#ifndef _MXC_NFC_V3_H_
+#define _MXC_NFC_V3_H_
+//==========================================================================
+//
+//      mxc_nfc_v3.h
+//
+//      Flash programming to support NAND flash on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Kevin Zhang <k.zhang@freescale.com>
+// Contributors: Kevin Zhang <k.zhang@freescale.com>
+// Date:         2008-06-02
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/devs_flash_onmxc.h>
+#include "mxc_nand_specifics.h"
+
+#define PG_2K_DATA_OP_MULTI_CYCLES()        false
+#define ADDR_INPUT_SIZE                 8
+
+#define NAND_MAIN_BUF0                  (NFC_BASE + 0x000)
+#define NAND_MAIN_BUF1                  (NFC_BASE + 0x200)
+#define NAND_MAIN_BUF2                  (NFC_BASE + 0x400)
+#define NAND_MAIN_BUF3                  (NFC_BASE + 0x600)
+#define NAND_MAIN_BUF4                  (NFC_BASE + 0x800)
+#define NAND_MAIN_BUF5                  (NFC_BASE + 0xA00)
+#define NAND_MAIN_BUF6                  (NFC_BASE + 0xC00)
+#define NAND_MAIN_BUF7                  (NFC_BASE + 0xE00)
+#define NAND_SPAR_BUF0                  (NFC_BASE + 0x1000)
+#define NAND_SPAR_BUF1                  (NFC_BASE + 0x1040)
+#define NAND_SPAR_BUF2                  (NFC_BASE + 0x1080)
+#define NAND_SPAR_BUF3                  (NFC_BASE + 0x10C0)
+#define NAND_SPAR_BUF4                  (NFC_BASE + 0x1100)
+#define NAND_SPAR_BUF5                  (NFC_BASE + 0x1140)
+#define NAND_SPAR_BUF6                  (NFC_BASE + 0x1180)
+#define NAND_SPAR_BUF7                  (NFC_BASE + 0x11C0)
+
+// The following defines are not used. Just for compilation purpose
+#define ECC_STATUS_RESULT_REG     0xDEADFFFF
+#define NFC_DATA_INPUT(buf_no, earea, en)
+#define NFC_DATA_INPUT_2k(buf_no)
+// dummy function as it is not needed for automatic operations
+#define NFC_ADDR_INPUT(addr)
+#define NFC_ARCH_INIT()
+#define NUM_OF_CS_LINES                 8
+#define NFC_BUFSIZE                          4096
+
+enum nfc_internal_buf {
+    RAM_BUF_0 = 0x0 << 4,
+    RAM_BUF_1 = 0x1 << 4,
+    RAM_BUF_2 = 0x2 << 4,
+    RAM_BUF_3 = 0x3 << 4,
+    RAM_BUF_4 = 0x4 << 4,
+    RAM_BUF_5 = 0x5 << 4,
+    RAM_BUF_6 = 0x6 << 4,
+    RAM_BUF_7 = 0x7 << 4,
+};
+
+enum nfc_output_mode {
+    FDO_PAGE_SPARE      = 0x0008,
+    FDO_SPARE_ONLY      = 0x1008,  // LSB has to be 0x08
+    FDO_FLASH_ID        = 0x0010,
+    FDO_FLASH_STATUS    = 0x0020,
+};
+
+#define wait_for_auto_prog_done()                 \
+    do {                                                                            \
+        while ((readl(NFC_IPC_REG) & NFC_IPC_AUTO_DONE) == 0)  \
+            {} \
+        write_nfc_ip_reg((readl(NFC_IPC_REG) & ~NFC_IPC_AUTO_DONE), NFC_IPC_REG); \
+    } while (0)
+
+// Polls the NANDFC to wait for an operation to complete
+#define wait_op_done()                                                              \
+    do {                                                                            \
+        while ((readl(NFC_IPC_REG) & NFC_IPC_INT) == 0)  \
+            {} \
+        write_nfc_ip_reg(0, NFC_IPC_REG); \
+    } while (0)
+
+static void write_nfc_ip_reg(u32 val, u32 reg)
+{
+    writel(NFC_IPC_CREQ, NFC_IPC_REG);
+    while((readl(NFC_IPC_REG) & NFC_IPC_CACK) == 0);
+
+    writel(val, reg);
+    writel((readl(NFC_IPC_REG) & ~NFC_IPC_CREQ), NFC_IPC_REG);
+}
+
+/*!
+ * NAND flash data output operation (reading data from NAND flash)
+ * @param buf_no    internal ram buffer number that will contain data
+ *                  to be outputted from the NAND flash after operation done
+ * @param mode      one of the mode defined in enum nfc_output_mode
+ * @param ecc_en    1 - ecc enabled; 0 - ecc disabled
+ */
+static void NFC_DATA_OUTPUT(enum nfc_internal_buf buf_no, enum nfc_output_mode mode,
+                            int ecc_en)
+{
+    u32 v = readl(NFC_FLASH_CONFIG2_REG);
+
+    if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
+        write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
+    }
+    if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
+        write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
+    }
+
+    v = readl(NAND_CONFIGURATION1_REG);
+
+    if (mode == FDO_SPARE_ONLY) {
+        v = (v & ~0x71) | buf_no | NAND_CONFIGURATION1_SP_EN;
+    } else {
+        v = (v & ~0x71) | buf_no;
+    }
+
+    writel(v, NAND_CONFIGURATION1_REG);
+
+    writel(mode & 0xFF, NAND_LAUNCH_REG);
+    wait_op_done();
+}
+
+static void NFC_CMD_INPUT(u32 cmd)
+{
+    writel(cmd & 0xFFFF, NAND_CMD_REG);
+    writel(NAND_LAUNCH_FCMD, NAND_LAUNCH_REG);
+    wait_op_done();
+}
+
+static void NFC_SET_NFC_ACTIVE_CS(u32 cs_line)
+{
+    u32 v;
+
+    v = readl(NAND_CONFIGURATION1_REG) & (~0x7071);
+    v |= (cs_line << 12);
+    writel(v, NAND_CONFIGURATION1_REG);
+}
+
+static u16 NFC_STATUS_READ(void)
+{
+    u32 status;
+    u16 status_sum = 0;
+    int i;
+
+#ifdef IMX51_TO_2
+    return readl(NAND_STATUS_SUM_REG);
+#else
+    /* Cannot rely on STATUS_SUM register due to errata */
+    for (i = 0; i < num_of_nand_chips; i++) {
+        NFC_SET_NFC_ACTIVE_CS(i);
+        do {
+            writel(NAND_LAUNCH_AUTO_STAT, NAND_LAUNCH_REG);
+            status = (readl(NAND_CONFIGURATION1_REG) & 0x00FF0000) >> 16;
+        } while ((status & 0x40) == 0); // make sure I/O 6 == 1
+        /* Get Pass/Fail status */
+        status = (readl(NAND_CONFIGURATION1_REG) >> 16) & 0x1;
+        status_sum |= (status << i);
+    }
+    return status_sum;
+#endif
+}
+
+/* This function uses a global variable for the page size. It shouldn't be a big
+ * problem since we don't expect mixed page size nand flash parts on the same IC.
+ * Note for address 0, it will always be correct regardless the page size. So for
+ * ID read, it doesn't need to have the correct page size global variable first.
+ */
+static void start_nfc_addr_ops(u32 ops, u32 pg_no, u16 pg_off, u32 is_erase, u32 cs_line, u32 num_of_chips)
+{
+    u32 add0, add8, page_number;
+    int num_of_bits[] = {0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4};
+
+    if (ops == FLASH_Read_ID) {
+        // issue addr cycle
+        writel(0x0, NAND_ADD0_REG + (4 * cs_line));
+        writel(NAND_LAUNCH_FADD, NAND_LAUNCH_REG);
+        wait_op_done();
+        return;
+    }
+
+    if (num_of_chips >  1) {
+        page_number = (pg_no << num_of_bits[num_of_chips]) | (cs_line & (num_of_chips - 1));
+    } else {
+        page_number = pg_no;
+    }
+    if (is_erase) {
+        add0 = page_number;
+        add8 = 0;
+    } else {
+        // for both read and write
+        if (g_is_2k_page || g_is_4k_page) {
+            // the first two addr cycles are for column addr. Page number starts
+            // from the 3rd addr cycle.
+            add0 = pg_off | (page_number << 16);
+            add8 = page_number >> 16;
+        } else {
+            diag_printf("too bad, die\n");
+            asm("1: b 1b");
+            // For 512B page, the first addr cycle is for column addr. Page number
+            // starts from the 2nd addr cycle.
+            add0 = (pg_off & 0xFF) | (page_number << 8);
+            add8 = page_number >> 24;
+        }
+    }
+    writel(add0, NAND_ADD0_REG);
+    writel(add8, NAND_ADD8_REG);
+}
+
+/*
+ * Do a page read at random address
+ *
+ * @param pg_no             page number offset from 0
+ * @param pg_off             byte offset within the page
+ * @param ecc_force        can force ecc to be off. Otherwise, by default it is on
+ *                                    unless the page offset is non-zero
+ * @param cs_line            indicates which NAND of interleaved NAND devices is used
+ *
+ * @return  0 if successful; non-zero otherwise
+ */
+static int nfc_read_pg_random(u32 pg_no, u32 pg_off, u32 ecc_force, u32 cs_line, u32 num_of_chips)
+{
+    u32 ecc = NFC_FLASH_CONFIG2_ECC_EN;
+    u32 v, res = 0;
+
+    // clear the NAND_STATUS_SUM_REG register
+    writel(0, NAND_STATUS_SUM_REG);
+
+    // the 2nd condition is to test for unaligned page address -- ecc has to be off.
+    if (ecc_force == ECC_FORCE_OFF || pg_off != 0 ) {
+        ecc = 0;
+    }
+
+    // Take care of config1 for RBA and SP_EN
+    v = readl(NAND_CONFIGURATION1_REG) & (~0x71);
+    writel(v, NAND_CONFIGURATION1_REG);
+
+    // For ECC
+    v = readl(NFC_FLASH_CONFIG2_REG) & (~NFC_FLASH_CONFIG2_ECC_EN);
+    // setup config2 register for ECC enable or not
+    write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
+
+    start_nfc_addr_ops(FLASH_Read_Mode1, pg_no, pg_off, 0, cs_line, num_of_chips);
+
+    if (g_is_2k_page || g_is_4k_page) {
+        // combine the two commands for 2k/4k page read
+        writel((FLASH_Read_Mode1_LG << 8) | FLASH_Read_Mode1, NAND_CMD_REG);
+    } else {
+        // just one command is enough for 512 page
+        writel(FLASH_Read_Mode1, NAND_CMD_REG);
+    }
+
+    // start auto-read
+    writel(NAND_LAUNCH_AUTO_READ, NAND_LAUNCH_REG);
+    wait_op_done();
+
+    v = readl(NAND_STATUS_SUM_REG);
+    // test for CS0 ECC error from the STATUS_SUM register
+    if ((v & (0x0100 << cs_line)) != 0) {
+        // clear the status
+        writel((0x0100 << cs_line), NAND_STATUS_SUM_REG);
+        diag_printf("ECC error from NAND_STATUS_SUM_REG(0x%x) = 0x%x\n",
+                    NAND_STATUS_SUM_REG, v);
+        diag_printf("NAND_ECC_STATUS_RESULT_REG(0x%x) = 0x%x\n", NAND_ECC_STATUS_RESULT_REG,
+                    readl(NAND_ECC_STATUS_RESULT_REG));
+        res = -1;
+    }
+    return res;
+}
+
+/*!
+ * The NFC has to be preset before performing any operation
+ */
+static void NFC_PRESET(u32 max_block_count)
+{
+    // not needed. It is done in plf_hardware_init()
+}
+
+#endif // _MXC_NFC_V3_H_
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/mxcmci_core.h b/packages/devs/flash/arm/mxc/v2_0/include/mxcmci_core.h
new file mode 100644 (file)
index 0000000..04774da
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef _MXCMCI_CORE_H_
+#define _MXCMCI_CORE_H_
+
+/*=================================================================================
+
+    Module Name:  mxcmci_core.h
+
+    General Description: Limited Bootloader eSDHC Driver.
+
+===================================================================================
+                               Copyright: 2004,2005,2006,2007,2008 FREESCALE, INC.
+                   All Rights Reserved. This file contains copyrighted material.
+                   Use of this file is restricted by the provisions of a
+                   Freescale Software License Agreement, which has either
+                   accompanied the delivery of this software in shrink wrap
+                   form or been expressly executed between the parties.
+
+
+Revision History:
+                            Modification     Tracking
+Author (core ID)                Date          Number     Description of Changes
+-------------------------   ------------    ----------   --------------------------
+Lewis Liu                  18-June-2008
+
+
+Portability: Portable to other compilers or platforms.
+
+====================================================================================================*/
+
+#include "mxcmci_mmc.h"
+#include "mxcmci_host.h"
+
+#define SUCCESS 0
+#define FAIL 1
+#define NO_ARG 0
+#define RCA_SHIFT 16
+#define ONE 1
+#define FOUR 4
+#define EIGHT 8
+#define TWO_K_SIZE 2048
+#define MMCSD_READY_TIMEOUT    3000  /* ~(3s / (2 * 48 * 10us)) */
+#define ESDHC_ACMD41_TIMEOUT 48000 /* 1.5 sec =1500 msec delay for ACMD41 cmd */
+#define MMCSD_SUPPORT
+
+#define CURR_CARD_STATE(r) ((cyg_uint32) ((r) & 0x1E00) >> 9)
+
+/*Defines of CSD data*/
+#define CSD_STRUCT_MSK                       0x00C00000
+#define CSD_STRUCT_SHIFT                    22
+#define MMC_CSD_SPEC_VERS_MASK      0x003C0000
+#define MMC_CSD_SPEC_VERS_SHIFT     18
+
+extern cyg_uint32 Card_rca;
+extern cyg_uint32 address_mode;
+extern cyg_uint32 MMC_Spec_vers;
+extern card_specific_data csd;  /* Global variable for Card Specific Data */
+extern cyg_uint32 Card_capacity_size; /* Capacity size (C_SIZE) for card*/
+extern cyg_uint32 CCC; /* Card Command Class */
+
+
+/* Defines the id for each command */
+enum commands
+{
+       CMD0= 0,
+       CMD1= 1,
+       CMD2= 2,
+       CMD3= 3,
+       CMD5= 5,
+       CMD6=6,
+       ACMD6= 6,
+       CMD7= 7,
+       CMD8=8,
+       CMD9=9,
+       CMD12   = 12,
+       CMD13   = 13,
+       CMD16   = 16,
+       CMD17   = 17,
+       CMD18   = 18,
+       CMD24   = 24,
+       CMD25   = 25,
+       CMD26   = 26,
+       CMD32   = 32,
+       CMD33   = 33,
+       CMD35   = 35,
+       CMD36   = 36,
+       CMD37   = 37,
+       CMD38   = 38,
+       CMD39   = 39,
+       ACMD41  = 41,
+       CMD43   = 43,
+       ACMD51  = 51,
+       CMD55   = 55,
+       CMD60   = 60,
+       CMD61   = 61,
+       CMD62   = 62,
+};
+
+/* Defines for the states of the card*/
+enum states
+{
+       IDLE,
+       READY,
+       IDENT,
+       STBY,
+       TRAN,
+       DATA,
+       RCV,
+       PRG,
+       DIS
+};
+
+/* Defines for card types */
+typedef enum
+{
+       TYPE_NONE,
+       SD_CSD_1_0,
+       SD_CSD_2_0,
+       MMC_CSD_1_0,
+       MMC_CSD_1_1,
+       MMC_CSD_1_2,
+       MMC_UNKNOWN
+}card_type;
+
+typedef struct
+{
+       cyg_uint32 cid0;
+       cyg_uint32 cid1;
+       cyg_uint32 cid2;
+       cyg_uint32 cid3;
+}card_ident;
+
+
+/* CARD Flash Configuration Parameters Structure */
+typedef struct {
+    cyg_uint32  length;         /* Length of Card data to read */
+} CARD_FLASH_CFG_PARMS_T;
+
+/*==================================================================================================
+                                             ENUMS
+==================================================================================================*/
+
+/*==================================================================================================
+                                          Global Function
+==================================================================================================*/
+extern cyg_uint32 mxcmci_init (cyg_uint32 bus_width, cyg_uint32 base_address);
+extern cyg_uint32 mxcmci_data_read (cyg_uint32* dest_ptr,cyg_uint32 len,cyg_uint32 offset);
+extern cyg_uint32 mxcmci_software_reset (void);
+extern cyg_uint32 mxcmci_get_cid (void);
+extern cyg_uint32 mxcmci_trans_prepare(void);
+extern void   mxcmci_cmd_config (command_t *cmd_config,cyg_uint32 index,cyg_uint32 argument,xfer_type_t transfer,response_format_t format,
+                                  data_present_select data,crc_check_enable crc,cmdindex_check_enable cmdindex);
+
+
+#endif //_MXCMCI_CORE_H_
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/mxcmci_host.h b/packages/devs/flash/arm/mxc/v2_0/include/mxcmci_host.h
new file mode 100644 (file)
index 0000000..2006048
--- /dev/null
@@ -0,0 +1,257 @@
+#ifndef _MXCMCI_HOST_H_
+#define _MXCMCI_HOST_H_
+
+// ==========================================================================
+//
+//    Module Name:  mxcmci_host.h
+//
+//    General Description: Limited Bootloader eSDHC Driver.
+//
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//
+//
+//####DESCRIPTIONEND####
+//====================================================================================================
+
+#include <cyg/infra/cyg_type.h>
+
+
+#define ESDHC_SOFTWARE_RESET   0x01000000  /* RSTA bit of ESDHC system control register*/
+#define ESDHC_CMD_INHIBIT       0x00000003  /* Command inhibit bits*/
+#define ESDHC_SOFTWARE_INIT     0x08000000  /* INITA bit of ESDHC system control register */
+#define ESDHC_LITTLE_ENDIAN_MODE 0x00000020  /* Little Endian mode */
+#define ESDHC_HW_BIG_ENDIAN_MODE 0x00000010  /* Half Word Big Endian mode */
+#define ESDHC_BIG_ENDIAN_MODE    0x00000000  /* Big Endian mode */
+#define ESDHC_ONE_BIT_SUPPORT    0x00000000  /* 1 Bit Mode support */
+#define ESDHC_FOUR_BIT_SUPPORT   0x00000002  /* 4 Bit Mode support */
+#define ESDHC_EIGHT_BIT_SUPPORT  0x00000004  /* 8 Bit Mode support */
+#define ESDHC_CLOCK_ENABLE             0x00000007    /* Clock Enable */
+#define ESDHC_ENABLE                        0x00000008    /* Enable SD */
+
+#define ESDHC_FREQ_MASK 0xffff0007
+#define ESDHC_IDENT_FREQ 0x0000800e  /* SDCLKFS 0x08 ; DVS 0xe */
+#define ESDHC_OPERT_FREQ 0x00000200  /* SDCLKFS 0x02 ; DVS 0x0 */
+#define ESDHC_INTERRUPT_ENABLE         0x007f0123        /* Enable Interrupts */
+#define ESDHC_CONFIG_BLOCK 0x00010200             /* 512 byte block size*/
+#define ESDHC_CLEAR_INTERRUPT 0xffffffff
+
+#define ESDHC_CONFIG_BLOCK_512 0x00000200             /* 512 byte block size*/
+#define ESDHC_CONFIG_BLOCK_64  0x00000040             /* 64 byte block size*/
+#define ESDHC_BLOCK_SHIFT              16
+
+#define ESDHC_CLEAR_INTERRUPT 0xffffffff
+#define ESDHC_OPER_TIMEOUT 96 /* 3 msec time out */
+#define ESDHC_READ_TIMEOUT 3264 /* 102 msec read time out */
+#define ESDHC_ACMD41_TIMEOUT 48000 /* 1.5 sec =1500 msec delay for ACMD41 cmd */
+
+#define  ESDHCI_SPACE_AVAILABLE        0x00000400
+#define  ESDHCI_DATA_AVAILABLE 0x00000800
+
+/*==================================================================================================
+                                            DEFINES
+==================================================================================================*/
+#define DATA_TRANSFER_SHIFT 4
+#define RESPONSE_FORMAT_SHIFT 16
+#define DATA_PRESENT_SHIFT 21
+#define CRC_CHECK_SHIFT 19
+#define CMD_INDEX_CHECK_SHIFT 20
+#define CMD_INDEX_SHIFT 24
+#define BLOCK_COUNT_ENABLE_SHIFT 1
+#define MULTI_SINGLE_BLOCK_SELECT_SHIFT 5
+#define BLK_LEN 512
+#define SWITCH_BLK_LEN 64
+#define FIFO_SIZE 128
+#define WRITE_READ_WATER_MARK_LEVEL 0x00200020
+#define ESDHC3 2
+#define ESDHC2 1
+#define ONE 1
+#define ESDHC1 0
+/*==================================================================================================
+                                             ENUS
+==================================================================================================*/
+#define ESDHC_STATUS_END_CMD_RESP_MSK 0x1
+#define ESDHC_STATUS_END_CMD_RESP_TIME_MSK 0x00010001
+#define ESDHC_STATUS_TIME_OUT_RESP_MSK  0x10000
+#define ESDHC_STATUS_RESP_CRC_ERR_MSK 0x20000
+#define ESDHC_STATUS_RESP_INDEX_ERR_MSK 0x80000
+#define ESDHC_STATUS_BUF_READ_RDY_MSK 0x20
+#define ESDHC_STATUS_BUF_WRITE_RDY_MSK 0x10
+#define ESDHC_STATUS_TRANSFER_COMPLETE_MSK 0x2
+#define ESDHC_STATUS_TIME_OUT_READ 0x100000
+#define ESDHC_STATUS_READ_CRC_ERR_MSK 0x200000
+
+#define ESDHC_RESET_CMD_MSK 0x02000000
+#define ESDHC_RESET_DAT_MSK 0x04000000
+#define ESDHC_RESET_ALL_MSK 0x01000000
+
+typedef enum
+{
+    WRITE = 0,
+    READ = 1,
+}xfer_type_t;
+
+typedef enum
+{
+    RESPONSE_NONE,
+    RESPONSE_136,
+    RESPONSE_48,
+    RESPONSE_48_CHECK_BUSY
+}response_format_t;
+
+
+typedef enum
+{
+       DATA_PRESENT_NONE = 0,
+       DATA_PRESENT = 1
+}data_present_select;
+
+typedef enum
+{
+       DISABLE = 0,
+       ENABLE = 1
+}crc_check_enable,cmdindex_check_enable,block_count_enable;
+
+typedef enum
+{
+       SINGLE = 0,
+       MULTIPLE = 1
+}multi_single_block_select;
+
+typedef struct
+{
+    cyg_uint32 command;
+    cyg_uint32 arg;
+    xfer_type_t data_transfer;
+    response_format_t response_format;
+    data_present_select data_present;
+    crc_check_enable crc_check;
+    cmdindex_check_enable cmdindex_check;
+       block_count_enable block_count_enable_check;
+       multi_single_block_select multi_single_block;
+}command_t;
+
+typedef struct
+{
+    response_format_t format;
+    cyg_uint32 cmd_rsp0;
+    cyg_uint32 cmd_rsp1;
+    cyg_uint32 cmd_rsp2;
+    cyg_uint32 cmd_rsp3;
+}command_response_t;
+
+typedef enum
+{
+       BIG_ENDIAN,
+       HALF_WORD_BIG_ENDIAN,
+       LITTLE_ENDIAN
+}endian_mode_t;
+
+typedef enum
+{
+    OPERATING_FREQ = 20000,   /* in kHz */
+    IDENTIFICATION_FREQ = 400   /* in kHz */
+}sdhc_freq_t;
+
+
+enum esdhc_data_status
+{
+       ESDHC_DATA_ERR = 3,
+       ESDHC_DATA_OK = 4
+};
+
+enum esdhc_int_cntr_val
+{
+       ESDHC_INT_CNTR_END_CD_RESP = 0x4,
+       ESDHC_INT_CNTR_BUF_WR_RDY = 0x8
+};
+
+enum esdhc_reset_status
+{
+       ESDHC_WRONG_RESET = 0,
+       ESDHC_CORRECT_RESET = 1
+};
+
+typedef struct
+{
+    volatile cyg_uint32 dma_system_address;
+    volatile cyg_uint32 block_attributes;
+    volatile cyg_uint32 command_argument;
+    volatile cyg_uint32 command_transfer_type;
+    volatile cyg_uint32 command_response0;
+    volatile cyg_uint32 command_response1;
+    volatile cyg_uint32 command_response2;
+    volatile cyg_uint32 command_response3;
+    volatile cyg_uint32 data_buffer_access;
+    volatile cyg_uint32 present_state;
+    volatile cyg_uint32 protocol_control;
+    volatile cyg_uint32 system_control;
+    volatile cyg_uint32 interrupt_status;
+    volatile cyg_uint32 interrupt_status_enable;
+    volatile cyg_uint32 interrupt_signal_enable;
+    volatile cyg_uint32 autocmd12_status;
+    volatile cyg_uint32 host_controller_capabilities;
+    volatile cyg_uint32 watermark_level;
+    cyg_uint32 reserved1[2];
+    volatile cyg_uint32 force_event;
+    volatile cyg_uint32 adma_error_status_register;
+    volatile cyg_uint32 adma_system_address;
+    cyg_uint32 reserved[40];
+    volatile cyg_uint32 host_controller_version;
+}host_register, *host_register_ptr;
+
+
+extern host_register_ptr esdhc_base_pointer;
+//extern cyg_uint32 available_mask;
+
+extern void host_reset(cyg_uint32 data_transfer_width, cyg_uint32 endian_mode);
+extern void host_cfg_clock(sdhc_freq_t);
+extern void host_read_response(command_response_t *);
+extern cyg_uint32 host_send_cmd(command_t *cmd);
+extern cyg_uint32 host_data_read(cyg_uint32 *,cyg_uint32);
+extern cyg_uint32 host_data_write(cyg_uint32 *,cyg_uint32);
+extern void host_cfg_block(cyg_uint32 blk_len, cyg_uint32 nob);
+extern void host_init(cyg_uint32 base_address);
+extern void esdhc_softreset(cyg_uint32 mask);
+/*================================================================================================*/
+#endif  /* _MXCMCI_HOST_H_ */
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/mxcmci_mmc.h b/packages/devs/flash/arm/mxc/v2_0/include/mxcmci_mmc.h
new file mode 100644 (file)
index 0000000..697aa3d
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef _MXCMCI_MMC_H_
+#define _MXCMCI_MMC_H_
+
+// ========================================================================== 
+//                                                                           
+//    Module Name:  mxcmci_mmc.h
+//
+//    General Description: Limited Bootloader eSDHC Driver.
+//                                 
+//                                                                           
+// ========================================================================== 
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//     
+//
+//####DESCRIPTIONEND####
+//====================================================================================================
+
+
+#define MMC_OCR_VALUE 0x40FF8000
+#define MMC_OCR_VALUE_BAK 0x80FFC000
+#define MMC_OCR_HC_RES 0xC0FF8000
+#define MMC_OCR_LC_RES 0x80FF8000
+#define MMC_OCR_VALUE_MASK 0x00FF8000
+#define BYTE_MODE 0
+#define SECT_MODE 1
+#define CARD_BUSY_BIT 0x80000000
+#define CURR_STATE_SHIFT 9
+#define MMC_SPEC_VER 0x003C0000
+#define MMC_SPEC_VER_SHIFT 18  
+#define MMC_R1_SWITCH_ERROR_MASK 0x80
+#define SWITCH_ERROR_SHIFT 7
+#define BUS_SIZE_SHIFT 2
+#define BUS_WIDTH 0x3b700000
+
+
+extern cyg_uint32 mmc_init(cyg_uint32);
+extern cyg_uint32 mmc_data_read (cyg_uint32 *,cyg_uint32 ,cyg_uint32);
+extern cyg_uint32 mmc_data_write (cyg_uint32 *src_ptr,cyg_uint32 length,cyg_uint32 offset);
+extern cyg_uint32 mmc_data_erase (cyg_uint32 offset, cyg_uint32 size);
+extern cyg_uint32 mmc_voltage_validation (void);
+extern cyg_uint32 mmc_get_spec_ver (void);
+extern cyg_uint32 sd_voltage_validation (void);
+extern cyg_uint32 sd_init(cyg_uint32);
+extern cyg_uint32 card_flash_query(void* data);
+
+typedef struct 
+{
+       cyg_uint32 csd0;
+       cyg_uint32 csd1;
+       cyg_uint32 csd2;
+       cyg_uint32 csd3;
+}card_specific_data;
+
+#endif  /* _MXCMCI_MMC_H_ */
+
diff --git a/packages/devs/flash/arm/mxc/v2_0/include/spi_nor_parts.inl b/packages/devs/flash/arm/mxc/v2_0/include/spi_nor_parts.inl
new file mode 100644 (file)
index 0000000..cbae3bd
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef CYGONCE_DEVS_FLASH_SPI_NOR_PARTS_INL
+#define CYGONCE_DEVS_FLASH_SPI_NOR_PARTS_INL
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Kevin Zhang <k.zhang@freescale.com>
+// Contributors: Kevin Zhang <k.zhang@freescale.com>
+// Date:         2008-11-14
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+    {
+        device_id  : 0xbf, // Samsung K9F5608x0C (on EVB SDR memory card)
+        device_id2 : 0x25,
+        device_id3 : 0x41,
+        device_id4 : 0xFF,
+        block_size : SZ_64K,
+        block_count: 32,
+        device_size: SZ_64K * 32,
+        fis_start_addr: 0x80000,       // first 0.5MB reserved for Redboot
+        vendor_info: "SST25VF016B - 2MB ",
+    },
+#endif // CYGONCE_DEVS_FLASH_SPI_NOR_PARTS_INL
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/card_mx32.c b/packages/devs/flash/arm/mxc/v2_0/src/card_mx32.c
new file mode 100644 (file)
index 0000000..d9dd0c3
--- /dev/null
@@ -0,0 +1,1092 @@
+// ==========================================================================
+//
+//   card_mx32.c
+//   (c) 2008, Freescale
+//
+//   MMC card driver for MXC platform
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Ivan Xu <yu.xu@freescale.com>
+// Contributors: Ivan Xu <yu.xu@freescale.com>
+// Date:         2008-06-13 Initial version
+// Purpose:
+// Description:
+//     Support SD/MMC cards based on SDHC controller.
+//     only base functionality is implemented: Card init, read, write and erase.
+//     Write protection are not supported so far.
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/io/card_mx32.h>
+#include <cyg/hal/hal_io.h>
+#include <redboot.h>
+#include <stdlib.h>
+
+//#define diag_printf1    diag_printf
+#define diag_printf1(fmt,args...)
+
+volatile psdhc_t pSDHC;
+card_mode_t Card_Mode;
+cyg_uint32 HighCapacityCard = 0;
+cyg_uint32 card_address;
+card_type  Card_type;            /* Card Type*/
+CARD_ID card_id;
+CARD_SPECIFIC_DATA csd;          /* Global variable for Card Specific Data */
+cyg_uint32 CCC = 0;              /* Card Command Class */
+
+static struct csd_v1_0 g_csd_val;
+
+static void configure_cmd (command_t *cmd,cyg_uint32 index, cyg_uint32 argument,
+                                cyg_uint32 transfer,cyg_uint32 response_format, cyg_uint32 data_enable,
+                                cyg_uint32 bus_width )
+{
+       /* Configure Command index */
+       cmd->index = index;
+
+       /* Configure Command argument */
+       cmd->arg = argument;
+       /* workaround for CMD0, send 80 clock cycles before CMD0 */
+       if (cmd->index == 0)
+       {
+               cmd->data_control = (((transfer) << SDHC_CMD_WRITE_READ_SHIFT) |
+                       ((response_format) << SDHC_CMD_FROMAT_OF_RESP_SHIFT) |
+                       ((data_enable) << SDHC_CMD_DATA_ENABLE_SHIFT) |
+                       ((bus_width) << SDHC_CMD_BUS_WIDTH_SHIFT)) |
+                       (0x1 << SDHC_CMD_INIT_SHIFT );
+       } else {
+               cmd->data_control = (((transfer) << SDHC_CMD_WRITE_READ_SHIFT) |
+                       ((response_format) << SDHC_CMD_FROMAT_OF_RESP_SHIFT) |
+                       ((data_enable) << SDHC_CMD_DATA_ENABLE_SHIFT) |
+                       ((bus_width) << SDHC_CMD_BUS_WIDTH_SHIFT));
+       }
+}
+
+static void stop_clk(void)
+{
+       /* Stop the clock */
+//     pSDHC->sdhc_clk = SDHC_CLK_STOP;
+
+       /* Wait till the clock has stopped */
+//     while((pSDHC->sdhc_status & SDHC_STATUS_CARD_BUS_CLK_RUN_MSK));
+       return;
+}
+
+static void start_clk(void)
+{
+       /* Start the clock */
+       pSDHC->sdhc_clk = SDHC_CLK_START;
+
+       /* Wait till the clock has started */
+       while(!(pSDHC->sdhc_status & SDHC_STATUS_CARD_BUS_CLK_RUN_MSK));
+       return;
+}
+
+static void configure_clk(frequency_mode_t mode)
+{
+       if(mode == iden_mode)
+       {
+               /* Below 400 kHz  */
+               pSDHC->sdhc_clk_rate = 0x207;
+       }
+       else if(mode == trans_mode)
+       {
+               /* Below 20 MHz  */
+               pSDHC->sdhc_clk_rate = 0x3;
+       }
+
+    diag_printf1("pSDHC->sdhc_clk_rate=0x%x\n", pSDHC->sdhc_clk_rate);
+}
+
+static void read_response(cyg_uint32 response_mode, response_t*response)
+{
+       cyg_uint32 resp1=0;
+       cyg_uint32 resp2=0;
+       cyg_uint32 resp3=0;
+       cyg_uint32 count;
+
+       if(response_mode != 0)
+       {
+               if((response_mode == RESPONSE_48_CRC) || (response_mode == RESPONSE_48_WITHOUT_CRC))
+               {
+                       resp1 = readl(0x50004000 + 0x34) & 0xffff;
+                       resp2 = readl(0x50004000 + 0x34) & 0xffff;
+                       resp3 = readl(0x50004000 + 0x34) & 0xffff;
+
+                       response->rsp0 = (resp1 << 24) | (resp2 << 8) | (resp3 >> 8);
+               }
+               else if(response_mode == RESPONSE_136)
+               {
+                       resp1 = pSDHC->sdhc_res_fifo & 0xffff;
+                       resp2 = pSDHC->sdhc_res_fifo & 0xffff;
+                       response->rsp3 = (resp1 << 16) | resp2;
+                       resp1 = pSDHC->sdhc_res_fifo & 0xffff;
+                       resp2 = pSDHC->sdhc_res_fifo & 0xffff;
+                       response->rsp2 = (resp1 << 16) | resp2;
+
+                       resp1 = pSDHC->sdhc_res_fifo & 0xffff;
+                       resp2 = pSDHC->sdhc_res_fifo & 0xffff;
+                       response->rsp1 = (resp1 << 16) | resp2;
+
+                       resp1 = pSDHC->sdhc_res_fifo & 0xffff;
+                       resp2= pSDHC->sdhc_res_fifo & 0xffff;
+                       response->rsp0 = (resp1 << 16) | resp2;
+               }
+
+               /* Stop the clock */
+               stop_clk();
+               /* Clear w1c bits from STATUS register */
+               pSDHC->sdhc_status |= SDHC_STATUS_CLEAR;
+       }
+
+       //return status;
+}
+
+static cyg_uint32 check_response(void)
+{
+       cyg_uint32 status = PASS;
+
+       if((pSDHC->sdhc_status & SDHC_STATUS_END_CMD_RESP_MSK) &&
+          !(pSDHC->sdhc_status & SDHC_STATUS_TIME_OUT_RESP_MSK) &&
+          !(pSDHC->sdhc_status & SDHC_STATUS_RESP_CRC_ERR_MSK))
+       {
+               status = PASS;
+       }
+       else
+       {
+               status = FAIL;
+               diag_printf("response status:  %x Fail!\n", pSDHC->sdhc_status);
+       }
+       return status;
+}
+
+static cyg_uint32 send_cmd_and_wait_resp(command_t *cmd)
+{
+       /* Clear Interrupt status Register  and enable int*/
+       pSDHC->sdhc_status = 0xFFFFFFFF;
+       pSDHC->sdhc_int_cntr = SDHC_INT;
+
+       /* Write command index */
+       pSDHC->sdhc_cmd = cmd->index;
+
+       /* Write command arg */
+       pSDHC->sdhc_arg = cmd->arg;
+
+       /* Write command data control */
+       pSDHC->sdhc_dat_cont = cmd->data_control;
+
+       /* Start clock */
+       start_clk();
+
+       /* Wait for the response of command end */
+       while(!(pSDHC->sdhc_status & SDHC_STATUS_END_CMD_RESP_MSK) );
+
+       /* Mask all interrupts */
+       pSDHC->sdhc_int_cntr = 0;
+
+       /* Check if an error occured */
+       return check_response();
+}
+
+static cyg_uint32 card_get_csd (void)
+{
+       command_t cmd;
+       response_t response;
+       cyg_uint32 status = FAIL;
+       //cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+       /* Configure CMD9 for MMC/SD card */
+       /* 16bit card address is expected as Argument */
+       configure_cmd(&cmd,CMD9,card_address,READ,RESPONSE_136, DISABLE, ONE);
+
+       /* Send Command CMD9 to Extrace CSD register contents  */
+       if(send_cmd_and_wait_resp(&cmd) != FAIL)
+       {
+               /* Read Command response */
+               read_response (RESPONSE_136, &response);
+               /* Assign Response to CSD Strcuture */
+               csd.csd0 = response.rsp0;
+               csd.csd1 = response.rsp1;
+               csd.csd2 = response.rsp2;
+               csd.csd3 = response.rsp3;
+               diag_printf1("CSD:%x:%x:%x:%x\n", csd.csd0, csd.csd1, csd.csd2, csd.csd3);
+               status = SUCCESS;
+        // save csd
+        memcpy(&g_csd_val, &csd, sizeof(struct csd_v1_0));
+        diag_printf1("g_csd_val.c_size_mult=0x%x\n", g_csd_val.c_size_mult);
+        diag_printf1("g_csd_val addr=%p\n", &g_csd_val);
+       }
+
+       return status;
+}
+
+static cyg_uint32 csd_get_value(CARD_SPECIFIC_DATA * pcsd, cyg_uint32 start_bit, cyg_uint32 end_bit)
+{
+       cyg_uint32 value;
+    if (start_bit == 84) {
+        value = g_csd_val.ccc;
+    } else if (start_bit == 62) {
+        value = (g_csd_val.c_size_up << 2) | g_csd_val.c_size_lo;
+    } else if (start_bit == 47) {
+        value = g_csd_val.c_size_mult;
+    } else if (start_bit == 80) {
+        value = g_csd_val.read_bl_len;
+    } else if (start_bit == 48) {
+        struct csd_v2_0 *ptr = (struct csd_v2_0 *) &g_csd_val;
+        value = (ptr->c_size_up << 16) | ptr->c_size_lo;
+    } else {
+        diag_printf1("start_bit=%d is not supported\n", start_bit);
+        while (1) {}
+    }
+    diag_printf1("start_bit=%d, end_bit=%d, value=0x%x\n", start_bit, end_bit, value);
+    return value;
+}
+
+static cyg_uint32 mmc_init(void)
+{
+       cyg_uint32 status = FAIL;
+       command_t cmd;
+       response_t resp;
+
+       cyg_uint32 card_status = 0;
+
+
+       card_address = 0x1<<16;
+       /* get cid of MMC */
+       /* Configure CMD2 for card */
+       configure_cmd(&cmd,CMD2,NO_ARG,READ,RESPONSE_136,DISABLE,ONE);
+
+       /* Send CMD2 to card to determine CID contents */
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               return status;
+       }
+       else
+       {
+                /* Read Command response  */
+                read_response(RESPONSE_136, &resp);
+                /* Assign CID values to mmc_cid structures */
+               card_id.cid0 = resp.rsp0;
+               card_id.cid1 = resp.rsp1;
+               card_id.cid2 = resp.rsp2;
+               card_id.cid3 = resp.rsp3;
+
+               //status = PASS;
+       }
+
+       /* get rca of MMC */
+       /* Configure CMD3 for MMC card */
+       configure_cmd(&cmd,CMD3,card_address,READ,RESPONSE_48_CRC, DISABLE, ONE);
+
+       /* Assigns relative address to the card */
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               return status;
+       }
+       else
+       {
+                /* Read Command response */
+               read_response(RESPONSE_48_CRC, &resp);
+               card_status = resp.rsp0;
+               card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
+               if(card_status == IDENT)
+               {
+                       status = PASS;
+               }
+               else
+               {
+                       status = FAIL;
+                       return status;
+               }
+       }
+
+       card_get_csd();
+
+       configure_clk(trans_mode);
+
+       /*Send MMC to Transfer State */
+        /* Configure CMD7 for MMC card */
+       configure_cmd(&cmd,CMD7,card_address,READ,RESPONSE_48_CRC, DISABLE,ONE);
+
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               return status;
+       }
+       else
+       {
+               /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
+               configure_cmd(&cmd,CMD13,card_address,READ,RESPONSE_48_CRC,DISABLE,ONE);
+               if(send_cmd_and_wait_resp(&cmd) == FAIL)
+               {
+                       status = FAIL;
+                       return status;
+               }
+               else
+               {
+                       /* Read Command response */
+                       read_response (RESPONSE_48_CRC, &resp);
+                       card_status = resp.rsp0;
+                       card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
+
+                       if(card_status == TRAN)
+                       {
+                               status = PASS;
+                       }
+                       else
+                       {
+                               status= FAIL;
+                       }
+               }
+       }
+
+       return status;
+}
+
+static cyg_uint32 check_sd(void)
+{
+       command_t cmd;
+       //command_response_t response;
+       cyg_uint32 count =0;
+       cyg_uint32 default_rca = 0;
+       cyg_uint32 ocr_value=0;
+       cyg_uint32 status = FAIL;
+       response_t resp;
+
+       configure_cmd(&cmd,CMD8,0x1AA,READ,RESPONSE_48_CRC, DISABLE, ONE);
+       send_cmd_and_wait_resp(&cmd);
+
+       while((count < 3000) && (status != PASS))
+       {
+               /* Configure CMD55 for SD card */
+               configure_cmd(&cmd,CMD55,default_rca,READ,RESPONSE_48_CRC, DISABLE, ONE);
+
+               /* Send CMD55 to SD Memory card*/
+               if(send_cmd_and_wait_resp(&cmd) == FAIL)
+               {
+                       status = FAIL;
+                       //count++;
+                       diag_printf1("CMD55 FAIL!\n");
+                       break;
+                       //continue;
+               }
+               else
+               {
+                       ocr_value = ((cyg_uint32)(OCR_VALUE) & 0xFFFFFFFF);
+                       /* Configure ACMD41 for SD card */
+                       configure_cmd(&cmd,ACMD41,ocr_value,READ,RESPONSE_48_WITHOUT_CRC,DISABLE, ONE);
+                       /* SEND ACMD41 to SD Memory card to determine OCR value */
+                       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+                       {
+                               status = FAIL;
+                               diag_printf1("ACMD41 FAIL!\n");
+                               break;
+                       }
+                       else
+                       {
+                               /* Read Response from CMDRSP0 Register */
+                               read_response(RESPONSE_48_WITHOUT_CRC, &resp);
+                               ocr_value = resp.rsp0;
+                                diag_printf1("SD: response ocr value: 0x%x\n", ocr_value);
+                               /* Check if volatge lies in range or not*/
+                               if((ocr_value & OCR_VALUE_MASK) == OCR_VALUE_MASK)
+                               {
+                                       diag_printf1("response.cmd_rsp0: 0x%x\n", ocr_value);
+                                       /* Check if card busy bit is cleared or not */
+                                       if(ocr_value & CARD_BUSY)
+                                       {
+                                               status = PASS;
+                                       }
+                                       else
+                                       {
+                                               count++;
+                                               diag_printf1("SD: Busy! \n");
+                                       }
+                               }
+                               else
+                               {
+                                       count++;
+                                       diag_printf("SD: response ocr value: 0x%x  FAIL!\n", ocr_value);
+                               }
+                       }
+               }
+       }
+       return status;
+}
+
+
+static cyg_uint32 sd_init(cyg_uint32 bus_width)
+{
+       cyg_uint32 status = FAIL;
+       command_t cmd;
+       response_t resp;
+       cyg_uint32 card_status = 0;
+       cyg_uint32 read_resp = 0;
+
+       card_address = 0;
+
+       /* get cid of MMC */
+       /* Configure CMD2 for card */
+       configure_cmd(&cmd,CMD2,NO_ARG,READ,RESPONSE_136,DISABLE,ONE);
+
+       /* Send CMD2 to card to determine CID contents */
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               return status;
+       }
+       else
+       {
+                /* Read Command response  */
+                read_response(RESPONSE_136, &resp);
+                /* Assign CID values to mmc_cid structures */
+               card_id.cid0 = resp.rsp0;
+               card_id.cid1 = resp.rsp1;
+               card_id.cid2 = resp.rsp2;
+               card_id.cid3 = resp.rsp3;
+
+               //status = PASS;
+       }
+
+       /* get rca of card */
+       /* Configure CMD3 for card */
+       configure_cmd(&cmd,CMD3,NO_ARG,READ,RESPONSE_48_CRC, DISABLE, ONE);
+
+       /* Assigns relative address to the card */
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               return status;
+       }
+       else
+       {
+                /* Read Command response */
+               read_response(RESPONSE_48_CRC, &resp);
+                card_status = resp.rsp0;
+                card_address = ((cyg_uint32) (card_status & (0xffffff00)));
+               card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
+               if(card_status == IDENT)
+               {
+                       status = PASS;
+               }
+               else
+               {
+                       status = FAIL;
+                       return status;
+               }
+       }
+
+       card_get_csd();
+       configure_clk(trans_mode);
+
+       /*Send card to Transfer State */
+        /* Configure CMD7 for card */
+       configure_cmd(&cmd,CMD7,card_address,READ,RESPONSE_48_CRC, DISABLE,ONE);
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               return status;
+       }
+       else
+       {
+               /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
+               configure_cmd(&cmd,CMD13,card_address,READ,RESPONSE_48_CRC,
+                                   DISABLE,ONE);
+
+               if(send_cmd_and_wait_resp(&cmd) == FAIL)
+               {
+                       status = FAIL;
+                       return status;
+               }
+               else
+               {
+                       /* Read Command response */
+                       read_response (RESPONSE_48_CRC, &resp);
+                       card_status = resp.rsp0;
+                       card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
+                       if(card_status == TRAN)
+                       {
+                               status = PASS;
+                       }
+                       else
+                       {
+                               status = FAIL;
+                       }
+               }
+       }
+
+
+       /* set bus width */
+       if ((bus_width == FOUR ) || (bus_width == ONE))
+       {
+               /* Configure CMD55 for SD card */
+               configure_cmd(&cmd,CMD55,card_address,READ,RESPONSE_48_CRC, DISABLE, ONE);
+
+               /* Issue CMD55 to SD Memory card*/
+               if(send_cmd_and_wait_resp(&cmd) == FAIL)
+               {
+                       status = FAIL;
+                       return status;
+               }
+               else
+               {
+                       /* Read Command response */
+                       read_response(RESPONSE_48_CRC, &resp);
+                       read_resp = resp.rsp0;
+                       if(read_resp & SD_R1_APP_CMD_MSK)
+                       {
+                               bus_width = (bus_width>>ONE);
+
+                               /* Configure ACMD6 for SD card */
+                               configure_cmd(&cmd,ACMD6,bus_width,READ,RESPONSE_48_CRC, DISABLE, ONE);
+                               /* Send ACMD6 to SD Memory card*/
+                               if(send_cmd_and_wait_resp(&cmd) == FAIL)
+                               {
+                                       status = FAIL;
+                                       return status;
+                               }
+                               else
+                               {
+                                       status = PASS;
+                               }
+                       }
+               }
+       }
+
+       return status;
+}
+
+static cyg_uint32 check_mmc(void)
+{
+        command_t cmd;
+        response_t resp;
+       //cyg_uint32 response;
+       cyg_uint32 count=0;
+       cyg_uint32 ocr_value=0;
+       cyg_uint32 status = FAIL;
+
+
+       while((count < 10) && (status != PASS))
+       {
+       /* Configure CMD1 for MMC card */
+               configure_cmd(&cmd, CMD1, OCR_VALUE, READ, RESPONSE_48_WITHOUT_CRC,DISABLE, ONE);
+
+               /* Issue CMD1 to MMC card to determine OCR value */
+               if(send_cmd_and_wait_resp(&cmd) == FAIL)
+               {
+                       status = FAIL;
+                       count++;
+                       diag_printf1("CMD1 FAIL!\n");
+                       break;
+                       //continue;
+               }
+               else
+               {
+                       read_response(RESPONSE_48_WITHOUT_CRC, &resp);
+                       ocr_value = resp.rsp0;
+
+                       /* Mask OCR value against 0x00FF8000 and compare with response*/
+                       if ((ocr_value & OCR_VALUE_MASK) == OCR_VALUE_MASK)
+                       {
+                               /* Check if card busy bit is cleared or not */
+                               if(ocr_value & CARD_BUSY)
+                               {
+                                       status = PASS;
+                               }
+                               else
+                               {
+                                       count++;
+                               }
+                       }
+                       else
+                       {
+                               count++;
+                       }
+               }
+       }
+
+       return status;
+}
+
+static cyg_uint32 check_card(cyg_uint32 bus_width)
+{
+
+       cyg_uint32 status = FAIL;
+       Card_Mode = NONE;
+
+       //wait
+    hal_delay_us(2000);
+       diag_printf1("check SD\n");
+       if(check_sd() == PASS){
+               Card_Mode = SD;
+               diag_printf1("SD init\n");
+               status = sd_init(bus_width);
+               Card_type  = ((csd.csd3 & CSD_STRUCT_MSK)? SD_CSD_2_0: SD_CSD_1_0);
+
+               /* Card Command Class */
+               CCC  = csd_get_value(&csd, 84, 95);
+       }
+       else{
+               //wait
+        hal_delay_us(2000);
+               diag_printf1("check MMC\n");
+               if(check_mmc() == PASS){
+                       Card_Mode = MMC;
+
+                       status = mmc_init();
+                       Card_type = ((csd.csd3 & CSD_STRUCT_MSK) >> CSD_STRUCT_SHIFT) + SD_CSD_2_0;
+               /* Card Command Class */
+                       CCC  = csd_get_value(&csd, 84, 95);
+               }
+       }
+       return status;
+}
+
+static void sdhc_init(cyg_uint32 base_address)
+{
+       cyg_uint32 iomux_base  = 0x43FAC000;
+       cyg_uint32 gpio_base  = 0x53FA4000;
+       cyg_uint32 iomux_sw_mux_ctl1 = readl(iomux_base + 0x18);
+       cyg_uint32 iomux_sw_mux_ctl2 = readl(iomux_base + 0x1C);
+       unsigned long reg;
+
+       iomux_sw_mux_ctl1 &= 0x000000FF;
+       iomux_sw_mux_ctl1 |=  0x12121200;
+       writel(iomux_sw_mux_ctl1, iomux_base + 0x18);
+
+       iomux_sw_mux_ctl2 &= 0xFF000000;
+       iomux_sw_mux_ctl2 |=  0x00121012;
+       writel(iomux_sw_mux_ctl2, iomux_base + 0x1C);
+
+       writel(0x0A529485, iomux_base + 0x168);
+       writel(0x0A5294A5, iomux_base + 0x16c);
+
+       /* Initialize base address */
+       pSDHC = (psdhc_t)base_address;
+}
+
+static void sdhc_reset(void)
+{
+       pSDHC->sdhc_clk = SDHC_CLK_RESET;
+       pSDHC->sdhc_clk = SDHC_CLK_RESET | SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+       pSDHC->sdhc_clk = SDHC_CLK_STOP;
+}
+
+static cyg_uint32 card_reset(void)
+{
+       command_t  cmd;
+
+       configure_clk(iden_mode);
+
+       /*set size of read and response fifo */
+       //pSDHC->sdhc_read_to = 0xffff;
+       pSDHC->sdhc_read_to = 0x2DB4;
+       pSDHC->sdhc_response_to = 0xff;
+       hal_delay_us(20000);
+
+       /* CMD0 to reset SD/MMC cards */
+       configure_cmd(&cmd,CMD0,NO_ARG,READ, RESPONSE_NO, DISABLE, ONE);
+
+       return send_cmd_and_wait_resp(&cmd);
+}
+
+static void wait_transfer_done(cyg_uint32 mask)
+{
+       /* Wait interrupt (WRITE_OP_DONE/READ_OP_DONE) */
+       while(!(pSDHC->sdhc_status & mask));
+}
+
+static cyg_uint32 check_data(cyg_uint32 done_mask, cyg_uint32 crc_err_code_mask, cyg_uint32 crc_err_mask)
+{
+       cyg_uint32 status = FAIL;
+       /* Check whether the interrupt is an OP_DONE or a data time out or a CRC error  */
+       if((pSDHC->sdhc_status & done_mask) &&
+           !(pSDHC->sdhc_status & crc_err_code_mask) &&
+           !(pSDHC->sdhc_status & crc_err_mask))
+       {
+               status = PASS;
+       }
+       else
+       {
+               status = FAIL;
+       }
+       return status;
+}
+
+static cyg_uint32 check_card_status(void)
+{
+       command_t cmd;
+       cyg_uint32 status = PASS;
+       cyg_uint32 card_state;
+       cyg_uint32 read_resp;
+       response_t resp;
+       //cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+       configure_cmd(&cmd,CMD13,card_address,READ,RESPONSE_48_CRC, DISABLE, ONE);
+
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+       }
+       else
+       {
+               /* Read Command response */
+               read_response (RESPONSE_48_CRC, &resp);
+               read_resp = resp.rsp0;
+               card_state = ((cyg_uint32) (read_resp & CARD_STATE) >> CARD_STATE_SHIFT);
+
+               if(card_state == TRAN)
+               {
+                       status = PASS;
+               }
+               else
+               {
+                       status = FAIL;
+               }
+       }
+       return status;
+}
+
+
+
+/*==========================================================================
+FUNCTION: static cyg_uint32 card_get_capacity_size(void)
+DESCRIPTION:
+   this function will analize MMC/SD CSD register and return the capacity size (in unit of KB)
+
+ARGUMENTS PASSED:
+   None
+
+RETURN VALUE:
+   cyg_uint32
+
+PRE-CONDITIONS:
+   None
+
+POST-CONDITIONS:
+   None
+
+Detailed Description:
+==============================================================================*/
+cyg_uint32 card_get_capacity_size (void)
+{
+       cyg_uint32 capacity = 0;
+       cyg_uint32 c_size, c_size_mult, blk_len;
+
+       if(!csd.csd0  && !csd.csd1  && !csd.csd2 && !csd.csd3)
+               diag_printf("WARNINGS:card_init should be done first!\n");
+
+       switch(Card_type)
+       {
+               case SD_CSD_1_0:
+               case MMC_CSD_1_0:
+               case MMC_CSD_1_1:
+               case MMC_CSD_1_2:
+               case SD_CSD_2_0:
+                       c_size = csd_get_value(&csd, 62, 73);
+                       c_size_mult = csd_get_value(&csd, 47, 49);
+                       blk_len = csd_get_value(&csd, 80, 83);
+                       capacity = (((c_size+1) << (c_size_mult +2)) << blk_len) / 1024;
+                       diag_printf1("c_size=0x%x, c_size_mult=0x%x, blk_len=0x%x, capacity(KB)=0x%x\n",
+                                                 c_size, c_size_mult, blk_len, capacity);
+                       break;
+#if 0 // todo
+               case SD_CSD_2_0:
+                       //blk_len = csd_get_value(&csd, 80, 83);
+                       c_size = csd_get_value(&csd, 48, 69);
+                       capacity = (c_size + 1) * 512; // block length is fixed to 512B
+            diag_printf1("card capacity2=0x%x\n", capacity);
+                       break;
+#endif
+               default:
+                       break;
+       }
+       if (capacity > (0x80000000 / 1024))
+               HighCapacityCard = 1;
+       else
+               HighCapacityCard = 0;
+
+       return capacity;
+}
+
+cyg_uint32 mxcmci_init (cyg_uint32 bus_width, cyg_uint32 base_address)
+{
+       sdhc_init(base_address);
+
+       /* Software Reset to SDHC */
+       sdhc_reset();
+
+       /* Software Reset to card */
+       card_reset();
+
+       return check_card(bus_width);
+}
+
+cyg_uint32 mmc_data_read (cyg_uint32 *ram_ptr, cyg_uint32 length, cyg_uint32 offset)
+{
+       command_t cmd;
+       cyg_uint32 len, retry = 15;
+       cyg_uint32 status = PASS;
+       cyg_uint32 i, j, k = 0;
+
+       diag_printf1("\ncard_data_read !-- offset: %x, length: %x \n", offset, length);
+
+       len = (length + BLOCK_LEN - 1) & (~(BLOCK_LEN - 1));
+
+       if (HighCapacityCard)
+               offset = offset / 512;
+
+       /* Configure SDHC block and number of blocks */
+       pSDHC->sdhc_blk_len = BLOCK_LEN;
+       pSDHC->sdhc_nob = 0x1;
+
+       /* Configure CMD16 to set block length as 512 bytes.*/
+       configure_cmd(&cmd,CMD16,BLOCK_LEN,READ,RESPONSE_48_CRC, DISABLE, ONE);
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+               diag_printf1("CMD16 Fail!\n");
+       }
+       else
+       {
+               while(len != 0 && !status)
+               {
+                       //check card status whether it is in transfer mode, so as to start next transfer
+                       while((status = check_card_status())!=PASS);
+
+                       diag_printf1("length left: %x \n", len);
+
+                       /* Send CMD17 for single block read */
+                       configure_cmd(&cmd,CMD17,offset,READ,RESPONSE_48_CRC, ENABLE, ONE);
+                       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+                       {
+                               status= FAIL;
+                               diag_printf1("CMD17 Fail!\n");
+                       }
+                       else
+                       {
+                                /* Enable int */
+                               pSDHC->sdhc_int_cntr = SDHC_INT;
+                               for(i = 0; i < BLOCK_LEN/16; i++)
+                               {
+                                       /* Wait for BRR bit to be set */
+                                       while(!(pSDHC->sdhc_status & SDHC_STATUS_BUF_READ_RDY_MSK)) {
+                                               hal_delay_us(10);
+                                       }
+                                       for(j=0;j<4;j++)
+                                       {
+                                               /* Read 32 bit data from buffer access fifo */
+                                               *ram_ptr = pSDHC->sdhc_buffer_access;
+                                               ram_ptr++;
+                                       }
+                               }
+                               /* Wait for transfer complete  */
+                               wait_transfer_done(SDHC_STATUS_READ_OP_DONE_MSK);
+
+                               /* Check for status errors (crc or timeout)*/
+                               status = check_data(SDHC_STATUS_READ_OP_DONE_MSK, SDHC_STATUS_TIME_OUT_READ, SDHC_STATUS_READ_CRC_ERR_MSK);
+
+                               offset = offset + BLOCK_LEN;
+                               len = len - BLOCK_LEN;
+                               //ram_ptr= ram_ptr + (BLOCK_LEN/4);
+                               diag_printf1("length left3: %x \n", len);
+                       }
+               }
+       }
+       diag_printf1("End of card data read!\n");
+       return status;
+}
+
+cyg_uint32 mmc_data_write (cyg_uint32 *ram_ptr, cyg_uint32 length, cyg_uint32 offset)
+{
+       command_t cmd;
+       cyg_uint32 len;
+       cyg_uint32 status = PASS;
+       cyg_uint32 i, j = 0;
+
+       len = (length + BLOCK_LEN - 1) & (~(BLOCK_LEN - 1));
+
+       /* Configure SDHC block and number of blocks */
+       pSDHC->sdhc_blk_len = BLOCK_LEN;
+       pSDHC->sdhc_nob = 0x1;
+
+    /* high capacity card uses sector mode */
+       if (HighCapacityCard)
+               offset = offset / 512;
+
+       /* Send CMD16 to set block length as 512 bytes.*/
+       configure_cmd(&cmd,CMD16,BLOCK_LEN,READ,RESPONSE_48_CRC, DISABLE, ONE);
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+               status = FAIL;
+       }
+       else
+       {
+               while(len != 0 && !status)
+               {
+                       //check card status whether it is in transfer mode, so as to start next transfer
+                       while((status = check_card_status())!=PASS);
+                       /* Comfigure command CMD24 for block write--write address */
+                       configure_cmd(&cmd,CMD24,offset,WRITE,RESPONSE_48_CRC, ENABLE, ONE);
+                       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+                       {
+                               status = FAIL;
+                       }
+                       else
+                       {
+                                /* Enable int */
+                               pSDHC->sdhc_int_cntr = SDHC_INT;
+
+                               for(i = 0; i < (BLOCK_LEN)/4; i++)
+                               {
+                                       /* Wait for BWR bit to be set */
+                                       while(!(pSDHC->sdhc_status & SDHC_STATUS_BUF_WRITE_RDY_MSK));
+                                       //copy data from ram to sdhc buffer access fifo
+                                       pSDHC->sdhc_buffer_access = *ram_ptr;
+                                       ram_ptr++;
+                               }
+
+                               /* Wait for transfer done */
+                               wait_transfer_done(SDHC_STATUS_WRITE_OP_DONE_MSK);
+
+                               /* Check for status errors (crc or timeout)*/
+                               status = check_data(SDHC_STATUS_WRITE_OP_DONE_MSK, 0, SDHC_STATUS_WRITE_CRC_ERR_MSK);
+
+                               len = len - BLOCK_LEN;
+                               offset +=  BLOCK_LEN;
+                               //ram_ptr = ram_ptr + (BLOCK_LEN/4);
+                       }
+               }
+       }
+       return status;
+}
+
+cyg_uint32 mmc_data_erase (cyg_uint32 offset, cyg_uint32 size)
+{
+       command_t cmd;
+       cyg_uint32 startEraseBlockCmd;
+       cyg_uint32 endEraseBlockCmd;
+       cyg_uint32 startBlock = offset/BLOCK_LEN;
+       cyg_uint32 endBlock = (offset+size)/BLOCK_LEN;
+       cyg_uint32 status = FAIL;
+
+       /* Fix erase operation on MX31/32 */
+       return 0;
+       if(Card_Mode == MMC) {
+               startBlock *=BLOCK_LEN;
+               endBlock *= BLOCK_LEN;
+               startEraseBlockCmd = CMD35;
+               endEraseBlockCmd   = CMD36;
+       }
+       else if(Card_Mode == SD) {
+               startBlock *=BLOCK_LEN;
+               endBlock *= BLOCK_LEN;
+               startEraseBlockCmd = CMD32;
+               endEraseBlockCmd   = CMD33;
+       }
+       if (HighCapacityCard) {
+               startBlock /= BLOCK_LEN;
+               endBlock /= BLOCK_LEN;
+       }
+
+       /* Configure start erase command to set first block*/
+       configure_cmd(&cmd,startEraseBlockCmd,startBlock,READ,RESPONSE_48_CRC, DISABLE, ONE);
+       if((status = send_cmd_and_wait_resp(&cmd)) == PASS){
+
+               /* Configure end erase command to set end block*/
+               configure_cmd(&cmd,endEraseBlockCmd,endBlock,READ,RESPONSE_48_CRC, DISABLE, ONE);
+               if((status = send_cmd_and_wait_resp(&cmd)) == PASS){
+                       /* Comfigure command to start erase*/
+                       configure_cmd(&cmd,CMD38,0,READ,RESPONSE_48_CRC, DISABLE, ONE);
+                       if((status = send_cmd_and_wait_resp(&cmd)) == PASS){
+                               //wait for completion
+                               return status;
+                       }
+               }
+       }
+
+       return status;
+}
+
+cyg_uint32 card_flash_query(void* data)
+{
+       command_t cmd;
+       cyg_uint32 status = PASS;
+       response_t response;
+
+        // Configure CMD2 for card  No Argument is expected for CMD2
+       configure_cmd(&cmd,CMD2,NO_ARG,READ,RESPONSE_136, DISABLE, ONE);
+
+       // Send CMD2 to card to determine CID contents
+       if(send_cmd_and_wait_resp(&cmd) == FAIL)
+       {
+       status = FAIL;
+               diag_printf("%s: can't send query command\n", __FUNCTION__);
+       }
+       else
+       {
+               cyg_uint32* d = (cyg_uint32*)data;
+               // Read Command response
+               read_response (RESPONSE_136, &response);
+
+               // Assign CID values to mmc_cid structures
+               *d++ = response.rsp0;
+               *d++ = response.rsp1;
+               *d++= response.rsp2;
+               *d= response.rsp3;
+
+               // Assign cid_request as SUCCESS
+               status = PASS;
+       }
+       diag_printf( "%s(PASS?=%d):(ID=0x%x: 0x%x, 0x%x, 0x%x)\n",
+       __FUNCTION__, status,*(cyg_uint32*)(data), *(cyg_uint32*)((cyg_uint32)data+4),
+              *(cyg_uint8*)((cyg_uint32)data+8), *(cyg_uint8*)((cyg_uint32)data+12));
+       return;
+}
+
+
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxc_ata.c b/packages/devs/flash/arm/mxc/v2_0/src/mxc_ata.c
new file mode 100644 (file)
index 0000000..fea3e93
--- /dev/null
@@ -0,0 +1,490 @@
+//==========================================================================
+//
+//      mxc_ata.c
+//
+//      Flash programming to support ATA flash on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
+// Contributors: Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
+// Date:         2008-11-18 Initial version
+//
+//==========================================================================
+//
+
+#include <cyg/hal/hal_cache.h>
+#include <stdlib.h>
+#include <cyg/io/mxc_ata.h>
+#include <redboot.h>
+
+static struct fsl_ata_time_regs {
+    unsigned char time_off, time_on, time_1, time_2w;
+    unsigned char time_2r, time_ax, time_pio_rdx, time_4;
+    unsigned char time_9, time_m, time_jn, time_d;
+    unsigned char time_k, time_ack, time_env, time_rpx;
+    unsigned char time_zah, time_mlix, time_dvh, time_dzfs;
+    unsigned char time_dvs, time_cvh, time_ss, time_cyc;
+};
+extern void mxc_ata_iomux_setup(void);
+
+/*
+ * This structure contains the timing parameters for
+ * ATA bus timing in the 5 PIO modes.  The timings
+ * are in nanoseconds, and are converted to clock
+ * cycles before being stored in the ATA controller
+ * timing registers.
+ */
+static struct {
+    short t0, t1, t2_8, t2_16, t2i, t4, t9, tA;
+} pio_specs[] = {
+    [0] = {
+    .t0 = 600, .t1 = 70, .t2_8 = 290, .t2_16 = 165, .t2i = 40, .t4 =
+        30, .t9 = 20, .tA = 50,},
+    [1] = {
+    .t0 = 383, .t1 = 50, .t2_8 = 290, .t2_16 = 125, .t2i = 0, .t4 =
+        20, .t9 = 15, .tA = 50,},
+    [2] = {
+    .t0 = 240, .t1 = 30, .t2_8 = 290, .t2_16 = 100, .t2i = 0, .t4 =
+        15, .t9 = 10, .tA = 50,},
+    [3] = {
+    .t0 = 180, .t1 = 30, .t2_8 = 80, .t2_16 = 80, .t2i = 0, .t4 =
+        10, .t9 = 10, .tA = 50,},
+    [4] = {
+    .t0 = 120, .t1 = 25, .t2_8 = 70, .t2_16 = 70, .t2i = 0, .t4 =
+        10, .t9 = 10, .tA = 50,},
+    };
+
+#define NR_PIO_SPECS (sizeof pio_specs / sizeof pio_specs[0])
+
+static void update_timing_config(struct fsl_ata_time_regs *tp)
+{
+    unsigned int  *lp = (unsigned int  *) tp;
+    unsigned int  *ctlp = (unsigned int  *) ATA_BASE_ADDR;
+    int i;
+
+    for (i = 0; i < 5; i++) {
+        writel(*lp, ctlp);
+        lp++;
+        ctlp++;
+    }
+}
+
+static void set_ata_bus_timing(unsigned char xfer_mode)
+{
+    int speed = xfer_mode;
+    struct fsl_ata_time_regs tr = { 0 };
+    int T = 1 * 1000 * 1000 * 1000 / get_main_clock(IPG_CLK);
+
+    if (speed >= NR_PIO_SPECS)
+        return;
+    tr.time_off = 3;
+    tr.time_on = 3;
+
+    tr.time_1 = (pio_specs[speed].t1 + T) / T;
+    tr.time_2w = (pio_specs[speed].t2_8 + T) / T;
+
+    tr.time_2r = (pio_specs[speed].t2_8 + T) / T;
+    tr.time_ax = (pio_specs[speed].tA + T) / T + 2;
+    tr.time_pio_rdx = 1;
+    tr.time_4 = (pio_specs[speed].t4 + T) / T;
+
+    tr.time_9 = (pio_specs[speed].t9 + T) / T;
+
+    update_timing_config(&tr);
+}
+
+static unsigned char ata_sff_busy_wait(unsigned int bits, unsigned int max, unsigned int delay)
+{
+    unsigned char status;
+    unsigned int iterations = 1;
+
+    if (max != 0)
+        iterations = max;
+
+    do {
+        hal_delay_us(delay);
+        status = readb(ATA_BASE_ADDR + FSL_ATA_DCDR);
+        if (max != 0)
+            iterations--;
+    } while (status != 0xff && (status & bits) && (iterations > 0));
+
+    if (iterations == 0) {
+        diag_printf("ata_sff_busy_wait timeout status = %x\n", status);
+        return 0xff;
+    }
+
+    return status;
+}
+
+static void ata_sff_exec_command(unsigned short cmd)
+{
+    writeb(cmd, ATA_BASE_ADDR + FSL_ATA_DCDR);
+    readb(ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
+    hal_delay_us(4);
+}
+
+static int ata_dev_set_feature(unsigned int feature)
+{
+    unsigned char status;
+
+    writeb(feature, ATA_BASE_ADDR + FSL_ATA_DFTR);
+    //Issue Set feature command
+    ata_sff_exec_command(ATA_CMD_SET_FEATURES);
+    status = ata_sff_busy_wait(ATA_BUSY, 5000, 500);
+
+    if (status == 0xff)
+        return 1;
+    if (status & ATA_ERR) {
+        return 1;
+    }
+    return 0;
+}
+
+void ata_id_string(int *id, unsigned char *s,
+                                 unsigned int ofs, unsigned int len)
+{
+    unsigned int c;
+
+    while (len > 0) {
+        c = id[ofs] >> 8;
+        *s = c;
+        s++;
+
+        c = id[ofs] & 0xff;
+        *s = c;
+        s++;
+
+        ofs++;
+        len -= 2;
+    }
+}
+
+/**
+ *  ata_id_c_string - Convert IDENTIFY DEVICE page into C string
+ *  @id: IDENTIFY DEVICE results we will examine
+ *  @s: string into which data is output
+ *  @ofs: offset into identify device page
+ *  @len: length of string to return. must be an odd number.
+ *
+ *  This function is identical to ata_id_string except that it
+ *  trims trailing spaces and terminates the resulting string with
+ *  null.  @len must be actual maximum length (even number) + 1.
+ *
+ *  LOCKING:
+ *  caller.
+ */
+void ata_id_c_string(int *id)
+{
+    unsigned char model_num[ATA_ID_PROD_LEN + 1];
+
+    ata_id_string(id, model_num, ATA_ID_PROD, ATA_ID_PROD_LEN);
+
+    model_num[ATA_ID_PROD_LEN] = '\0';
+
+    diag_printf("ATA Model number = %s\n", model_num);
+}
+
+static int read_dev_id(void)
+{
+    int i, tried_spinup = 0;
+    int CIS[256], err_mask = 0;
+
+retry:
+
+    //identify device command
+    ata_sff_exec_command(ATA_CMD_ID_ATA);
+    if (ata_sff_busy_wait(ATA_BUSY, 5000, 500) == 0xff)
+        return 1;
+    memset((void *)CIS, 0, sizeof(int) * 256);
+
+    for (i=0 ; i < 256; i++ ) {
+        CIS[i] = readw(ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA);
+    }
+
+    if ((CIS[0] & (1 << 15)) == 0) {
+        if (!tried_spinup && (CIS[2] == 0x37c8 || CIS[2] == 0x738c)) {
+            tried_spinup = 1;
+            err_mask = ata_dev_set_feature(0x7);
+            if (err_mask && CIS[2] != 0x738c) {
+                diag_printf("ATA SPINUP Failed \n");
+                goto err_out;
+            }
+            if (CIS[2] == 0x37c8)
+                goto retry;
+        }
+        ata_id_c_string(CIS);
+        return 0;
+    } else {
+        diag_printf("ATA IDENTIFY DEVICE command Failed \n");
+    }
+err_out:
+    return 1;
+}
+
+static void write_sector_pio(unsigned int *addr, int num_of_sectors)
+{
+    int i, j;
+
+    for (i = 0; i < num_of_sectors; i++) {
+        for (j= 0; j < ATA_SECTOR_SIZE; j = j + 4) {
+            /* Write 4 bytes in each iteration */
+            writew((*addr & 0xFFFF), ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA) ;
+            writew(((*addr >> 16 ) & 0xFFFF), ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA) ;
+            addr++;
+        }
+        ata_sff_busy_wait(ATA_BUSY, 5000, 50);
+    }
+    readb(ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
+}
+
+static void read_sector_pio(unsigned int *addr, int num_of_sectors)
+{
+    int i, j;
+    unsigned int data[2];
+
+    for (i = 0; i < num_of_sectors; i++) {
+        for (j = 0; j < ATA_SECTOR_SIZE; j = j + 4) {
+            /* Read 4 bytes in each iteration */
+            data[0] = readw(ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA);
+            data[1] = readw(ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA);
+            *addr = ((data[1] << 16) & 0xFFFF0000) | (data[0] & 0xFFFF);
+            addr++;
+        }
+        ata_sff_busy_wait(ATA_BUSY, 5000, 10);
+    }
+    readb(ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
+}
+
+void ata_hwr_init(void)
+{
+    mxc_ata_iomux_setup();
+
+    /* Deassert the reset bit to enable the interface */
+    writel(FSL_ATA_CTRL_ATA_RST_B, ATA_BASE_ADDR + FSL_ATA_CONTROL);
+    writel(FSL_ATA_CTRL_ATA_RST_B | FSL_ATA_CTRL_FIFO_RST_B, ATA_BASE_ADDR + FSL_ATA_CONTROL);
+    /* Set initial timing and mode */
+    set_ata_bus_timing(PIO_XFER_MODE_4);
+    writeb(20, ATA_BASE_ADDR+ FSL_ATA_FIFO_ALARM) ; /* set fifo alarm to 20 halfwords, midway */
+
+    /* software reset */
+    writeb(ATA_IEN, ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
+    hal_delay_us(20);
+    writeb(ATA_IEN | ATA_SRST, ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
+    hal_delay_us(20);
+    writeb(ATA_IEN, ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
+
+    writeb(0, ATA_BASE_ADDR + FSL_ATA_DDHR);
+    if (ata_sff_busy_wait(ATA_BUSY | ATA_DRQ, 6000, 1000) == 0xff) {
+        diag_printf("Failed to initialize the ATA drive\n");
+        return;
+    }
+
+    /* Read the device ID */
+    if (read_dev_id())
+        diag_printf("Failed to initialize the ATA drive\n");
+}
+
+static void ata_read_buf(int argc, char *argv[]);
+RedBoot_cmd("ata_read",
+            "Read Ata",
+            "-f <flash_addr> -b <mem_base> -l <image_length>",
+            ata_read_buf
+           );
+
+static void ata_program_buf(int argc, char *argv[]);
+RedBoot_cmd("ata_write",
+            "Write Ata",
+            "-f <flash_addr> -b <mem_base> -l <image_length>",
+            ata_program_buf
+           );
+
+static void ata_read_buf(int argc, char *argv[])
+{
+    unsigned int total_sectors, num_of_sectors;
+    unsigned char lba_addr[4];
+    CYG_ADDRESS addr, data;
+    unsigned long sect_addr;
+    unsigned long len;
+    unsigned char status;
+    bool mem_addr_set = false;
+    bool flash_addr_set = false;
+    bool length_set = false;
+    struct option_info opts[3];
+
+    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
+              (void *)&data, (bool *)&mem_addr_set, "memory base address");
+    init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
+              (void *)&addr, (bool *)&flash_addr_set, "FLASH memory base address");
+    init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
+              (void *)&len, (bool *)&length_set, "image length [in FLASH]");
+
+    if (!scan_opts(argc, argv, 1, opts, 3, 0, 0, 0)) {
+        diag_printf("invalid arguments");
+        return;
+    }
+
+    if (!mem_addr_set || !flash_addr_set || !length_set) {
+        diag_printf("required parameter missing\n");
+        return;
+    }
+
+    if ((addr % ATA_SECTOR_SIZE) != 0) {
+        diag_printf("Need a sector-aligned (512 byte) address in ATA\n\n");
+        return;
+    }
+
+    total_sectors = (len / ATA_SECTOR_SIZE);
+    sect_addr = addr / ATA_SECTOR_SIZE;
+
+    do {
+        lba_addr[0] = sect_addr & 0xFF;
+        lba_addr[1] = (sect_addr >> 8) & 0xFF;
+        lba_addr[2] = (sect_addr >> 16) & 0xFF;
+        /* Enable the LBA bit */
+        lba_addr[3] = (1 << 6) | ((sect_addr >> 24) & 0xF);
+
+        if (total_sectors >= MAX_NUMBER_OF_SECTORS)
+            num_of_sectors = 0;
+        else
+            num_of_sectors = total_sectors;
+
+        ata_sff_busy_wait(ATA_BUSY | ATA_DRQ, 5000, 50);
+        writeb(num_of_sectors, ATA_BASE_ADDR + FSL_ATA_DSCR);
+        writeb(lba_addr[0], ATA_BASE_ADDR + FSL_ATA_DSNR);
+        writeb(lba_addr[1], ATA_BASE_ADDR + FSL_ATA_DCLR);
+        writeb(lba_addr[2], ATA_BASE_ADDR + FSL_ATA_DCHR);
+        writeb(lba_addr[3], ATA_BASE_ADDR + FSL_ATA_DDHR);
+
+        //Issue Read command
+        ata_sff_exec_command(ATA_CMD_READ);
+        status = ata_sff_busy_wait(ATA_BUSY, 5000, 50);
+        if (status & ATA_ERR) {
+            diag_printf("Error while issuing ATA Read command\n");
+            return;
+        }
+        if (num_of_sectors == 0) {
+            read_sector_pio((unsigned int *)data, MAX_NUMBER_OF_SECTORS);
+            total_sectors -= MAX_NUMBER_OF_SECTORS;
+            sect_addr += MAX_NUMBER_OF_SECTORS;
+            data += (MAX_NUMBER_OF_SECTORS * ATA_SECTOR_SIZE);
+        } else {
+            read_sector_pio((unsigned int *)data, num_of_sectors);
+            total_sectors -= num_of_sectors;
+            sect_addr += num_of_sectors;
+            data += (num_of_sectors * ATA_SECTOR_SIZE);
+        }
+    } while (total_sectors > 0);
+}
+
+static void ata_program_buf(int argc, char *argv[])
+{
+    int total_sectors, num_of_sectors, lba_addr[4];
+    CYG_ADDRESS addr, data;
+    unsigned long len;
+    unsigned long sect_addr;
+    unsigned char status;
+    bool mem_addr_set = false;
+    bool flash_addr_set = false;
+    bool length_set = false;
+    struct option_info opts[3];
+
+    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
+              (void *)&data, (bool *)&mem_addr_set, "memory base address");
+    init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
+              (void *)&addr, (bool *)&flash_addr_set, "FLASH memory base address");
+    init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
+              (void *)&len, (bool *)&length_set, "image length [in FLASH]");
+
+    if (!scan_opts(argc, argv, 1, opts, 3, 0, 0, 0)) {
+        diag_printf("invalid arguments");
+        return;
+    }
+
+    if (!mem_addr_set || !flash_addr_set || !length_set) {
+        diag_printf("required parameter missing\n");
+        return;
+    }
+
+    if ((addr % ATA_SECTOR_SIZE) != 0) {
+        diag_printf("Need a sector-aligned (512 byte) address in ATA\n\n");
+        return;
+    }
+
+    total_sectors = (len / ATA_SECTOR_SIZE);
+    sect_addr = addr / ATA_SECTOR_SIZE;
+
+    do {
+        lba_addr[0] = sect_addr & 0xFF;
+        lba_addr[1] = (sect_addr >> 8) & 0xFF;
+        lba_addr[2] = (sect_addr >> 16) & 0xFF;
+        /* Enable the LBA bit */
+        lba_addr[3] = (1 << 6) | ((sect_addr >> 24) & 0xF);
+
+        if (total_sectors >= MAX_NUMBER_OF_SECTORS)
+            num_of_sectors = 0;
+        else
+            num_of_sectors = total_sectors;
+
+        ata_sff_busy_wait(ATA_BUSY | ATA_DRQ, 5000, 50);
+        writeb(num_of_sectors, ATA_BASE_ADDR + FSL_ATA_DSCR);
+        writeb(lba_addr[0], ATA_BASE_ADDR + FSL_ATA_DSNR);
+        writeb(lba_addr[1], ATA_BASE_ADDR + FSL_ATA_DCLR);
+        writeb(lba_addr[2], ATA_BASE_ADDR + FSL_ATA_DCHR);
+        writeb(lba_addr[3], ATA_BASE_ADDR + FSL_ATA_DDHR);
+
+        //Issue Write command
+        ata_sff_exec_command(ATA_CMD_WRITE);
+        ata_sff_busy_wait(ATA_BUSY, 5000, 50);
+        if (status & ATA_ERR) {
+            diag_printf("Error while issuing ATA Write command\n");
+            return;
+        }
+        if (num_of_sectors == 0) {
+            write_sector_pio((unsigned int *)data, MAX_NUMBER_OF_SECTORS);
+            total_sectors -= MAX_NUMBER_OF_SECTORS;
+            sect_addr += MAX_NUMBER_OF_SECTORS;
+            data += (MAX_NUMBER_OF_SECTORS * ATA_SECTOR_SIZE);
+        } else {
+            write_sector_pio((unsigned int *)data, num_of_sectors);
+            total_sectors -= num_of_sectors;
+            sect_addr += num_of_sectors;
+            data += (num_of_sectors * ATA_SECTOR_SIZE);
+        }
+    } while (total_sectors > 0);
+}
+
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxc_mmc.c b/packages/devs/flash/arm/mxc/v2_0/src/mxc_mmc.c
new file mode 100644 (file)
index 0000000..9ecd22e
--- /dev/null
@@ -0,0 +1,252 @@
+// ==========================================================================
+//
+//   mxc_mmc.c
+//   (c) 2008, Freescale
+//
+//   MMC card driver for MXC platform
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//     Support SD/MMC cards based on eSDHC controller.
+//     only base functionality is implemented: Card init, read and write.
+//     Erase and write protection are not supported so far.
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#ifdef CYGPKG_REDBOOT_HAL_OPTIONS
+    #include <redboot.h>
+#endif
+#include <stdlib.h>
+#define  _FLASH_PRIVATE_
+#include <cyg/io/flash.h>
+#include <cyg/io/mxc_mmc.h>
+
+#if defined(CYGPKG_HAL_ARM_MX31ADS) || defined(CYGPKG_HAL_ARM_MX31_3STACK)
+    #include <cyg/io/card_mx32.h>
+#endif
+
+#if defined(CYGPKG_HAL_ARM_MX25_3STACK) || defined(CYGPKG_HAL_ARM_MX35_3STACK) || defined(CYGPKG_HAL_ARM_MX37_3STACK) || defined(CYGPKG_HAL_ARM_MX51)
+    #include <cyg/io/mxcmci_core.h>
+#endif
+
+//hardware init for MMC card
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_hwr_init(void)
+#else
+int mmcflash_hwr_init(void)
+#endif
+{
+    cyg_uint32 status = FAIL;
+    cyg_uint32 capacity = 0;
+    int i = 5;
+    while (status != SUCCESS && i--) {
+        hal_delay_us(100000);
+        status = mxcmci_init(1, ESDHC1_REG_BASE);
+    }
+
+    if (FAIL == status) {
+        diag_printf("Error: Card initialization failed!\n");
+        return status;
+    }
+    diag_printf("Card initialization successful!\n");
+    //set flash_info structure
+    externC struct flash_info flash_info;
+    flash_dprintf(FLASH_DEBUG_MAX,"%s: status=%d\n", __FUNCTION__, status);
+    capacity = card_get_capacity_size(); // in unit of KB
+    diag_printf("Actual capacity of the card is %dKB\n", capacity);
+    //if the capacity size is larger than 2G or equals zero, force to be 2G
+    if (capacity > 0x200000 || capacity == 0) {
+        capacity = 0x200000;
+    }
+    diag_printf("Redboot uses %dKB\n", capacity);
+
+    flash_info.block_size = 0x20000; // =  128KB
+    flash_info.blocks = capacity / 128;
+    flash_info.start = (void *)MXC_MMC_BASE_DUMMY;
+    flash_info.end = (void *)(MXC_MMC_BASE_DUMMY + flash_info.block_size * flash_info.blocks);
+
+    return status;
+}
+
+
+// Read data into buffer
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_read_buf(void* addr, void* data, int len)
+#else
+int mmcflash_read_buf(void* addr, void* data, int len)
+#endif
+{
+    flash_dprintf(FLASH_DEBUG_MAX,"%s:Debug:1:addr=%X, data=%X, len=%d\n", __FUNCTION__, (cyg_uint32)addr, (cyg_uint32)data, len);
+    return mmc_data_read(data, len, (cyg_uint32)addr);
+}
+
+
+// Get CID to pointer data (should hold 4*4 byte space)
+#ifndef MXCFLASH_SELECT_MULTI
+void flash_query(void* data)
+#else
+void mmcflash_query(void* data)
+#endif
+{
+    return card_flash_query(data);
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_hwr_map_error(int e)
+#else
+int mmcflash_hwr_map_error(int e)
+#endif
+{
+    return e;
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+bool flash_code_overlaps(void *start, void *end)
+#else
+bool mmcflash_code_overlaps(void *start, void *end)
+#endif
+{
+    extern char _stext[], _etext[];
+
+    bool ret = ((((unsigned long)&_stext >= (unsigned long)start) &&
+                 ((unsigned long)&_stext < (unsigned long)end)) ||
+                (((unsigned long)&_etext >= (unsigned long)start) &&
+                 ((unsigned long)&_etext < (unsigned long)end)));
+    flash_dprintf(FLASH_DEBUG_MAX,"%s: flash code overlap::%d\n", __FUNCTION__, ret);
+    return ret;
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_erase_block(void* block, unsigned int size)
+#else
+int mmcflash_erase_block(void* block, unsigned int size)
+#endif
+{
+    flash_dprintf(FLASH_DEBUG_MAX,"%s:Debug:1:block=0x%X, size=%d\n", __FUNCTION__, (cyg_uint32)block, size);
+    return mmc_data_erase((cyg_uint32)block, size);
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_program_buf(void* addr, void* data, int len)
+#else
+int mmcflash_program_buf(void* addr, void* data, int len)
+#endif
+{
+    flash_dprintf(FLASH_DEBUG_MAX,"%s:Debug:1:addr=0x%X, data=0x%X, len=%d\n", __FUNCTION__, (cyg_uint32)addr, (cyg_uint32)data, len);
+    return mmc_data_write((cyg_uint32*)data, len, (cyg_uint32)addr);
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_lock_block(void* block)
+#else
+int mmcflash_lock_block(void* block)
+#endif
+{
+    //not support yet
+    return 0;
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_unlock_block(void* block, int block_size, int blocks)
+#else
+int mmcflash_unlock_block(void* block, int block_size, int blocks)
+#endif
+{
+    //not support yet
+    return 0;
+}
+
+void mxc_mmc_print_info(void)
+{
+       extern card_type Card_type;
+    cyg_uint32 i = 0;
+    cyg_uint8* cmd_class[] = {
+        "basic",           //class 0
+        "reserved",        //class 1
+        "block-read",      //class 2
+        "reserved",        //class 3
+        "block-write",       //class 4
+        "erase",           //class 5
+        "write-protect",   //class 6
+        "lock",            //class 7
+        "app-command",       //class 8
+        "IO-mode",           //class 9
+        "switch",           //class 10
+        "reserved"           //class 11
+    };
+
+    switch (Card_type) {
+    case SD_CSD_1_0:
+        diag_printf("\nBooting from [SD card, CSD Version 1.0]\n");
+        break;
+    case SD_CSD_2_0:
+        diag_printf("\nBooting from [SD card, CSD Version 2.0]\n");
+        break;
+    case MMC_CSD_1_0:
+        diag_printf("\nBooting from [MMC card, CSD Version 1.0]\n");
+        break;
+    case MMC_CSD_1_1:
+        diag_printf("\nBooting from [MMC card, CSD Version 1.1]\n");
+        break;
+    case MMC_CSD_1_2:
+        diag_printf("\nBooting from [MMC card, CSD Version 1.2]\n");
+        break;
+    case MMC_UNKNOWN:
+        diag_printf("\nBooting from [MMC card (?) ]\n");
+        break;
+    default:
+        diag_printf("\nBooting from [unknown version card ]\n");
+        break;
+    }
+    diag_printf("Supporting Card Command Class: ");
+    for (;i<12;i++) {
+        if (CCC & (1 << i))
+            diag_printf("%s, ", cmd_class[i]);
+    }
+
+    diag_printf("\n\n");
+}
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_core.c b/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_core.c
new file mode 100644 (file)
index 0000000..56b7e41
--- /dev/null
@@ -0,0 +1,481 @@
+// ==========================================================================
+//
+//   mxcmci_core.c
+//   (c) 2008, Freescale
+//
+//   MMC card driver for MXC platform
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/io/mxcmci_host.h>
+#include <cyg/io/mxcmci_core.h>
+#include <cyg/io/mxcmci_mmc.h>
+#include <cyg/hal/hal_soc.h>
+#include <cyg/io/mxc_mmc.h>
+
+static cyg_uint32 csd_get_value(cyg_uint32 * pcsd, cyg_uint32 start_bit,
+                cyg_uint32 end_bit);
+
+#define MMCSD_INIT_DELAY 64
+
+cyg_uint32 Card_rca = 0x1;    /* Relative Card Address */
+card_ident Card_identification;    /* Card Identification Data */
+card_type Card_type;        /* Card Type */
+cyg_uint32 MMC_Spec_vers = 0x1;        /* Spec vers used for MMC */
+card_specific_data csd;        /* Global variable for Card Specific Data */
+cyg_uint32 Card_capacity_size = 0;    /*Card capacity size */
+cyg_uint32 CCC = 0;        /* Card Command Class */
+int Card_Mode = 2;
+int HighCapacityCard = 0;
+
+/*==========================================================================
+                                    Global FUNCTIONS
+==========================================================================*/
+
+cyg_uint32 mxcmci_init(cyg_uint32 bus_width, cyg_uint32 base_address)
+{
+    cyg_uint32 init_status = FAIL;
+
+    flash_dprintf(FLASH_DEBUG_MAX, "%s:try to init base address...\n",
+              __FUNCTION__);
+    /* initialize Interface Controller */
+    host_init(base_address);
+    flash_dprintf(FLASH_DEBUG_MAX, "%s:try to software reset...\n",
+              __FUNCTION__);
+
+    /* Software Reset to Interface Controller */
+    host_reset(ESDHC_ONE_BIT_SUPPORT, ESDHC_LITTLE_ENDIAN_MODE);
+    flash_dprintf(FLASH_DEBUG_MAX, "%s:try to set identification freq...\n",
+              __FUNCTION__);
+
+    /* Enable Identification Frequency */
+    host_cfg_clock(IDENTIFICATION_FREQ);
+
+    /* Add delay of 2 msec, let mmc/sd card to initialize */
+    hal_delay_us(2 * 1000);
+
+    flash_dprintf(FLASH_DEBUG_MAX, "%s:try to software resetto card...\n",
+              __FUNCTION__);
+
+    //diag_printf("SW Reset...\n");
+    /* Issue Software Reset to card */
+    if (mxcmci_software_reset())
+        return FAIL;
+
+    //diag_printf("Check Card...\n");
+
+    /* Check if the card is SD Memory Card */
+    if (!sd_voltage_validation()) {
+        flash_dprintf(FLASH_DEBUG_MAX, "%s:try to verify SD card...\n",
+                  __FUNCTION__);
+        /* Call SD Initialization Function */
+        init_status = sd_init(bus_width);
+        Card_type =
+            ((csd.csd3 & CSD_STRUCT_MSK) ? SD_CSD_2_0 : SD_CSD_1_0);
+        Card_Mode = 1;
+        /* Card Command Class */
+        CCC = csd_get_value(&csd, 84, 95);
+    } else {
+        flash_dprintf(FLASH_DEBUG_MAX, "%s:try to verify MMC card...\n",
+                  __FUNCTION__);
+        /* Check if the card is MMC Memory Card */
+        if (!mmc_voltage_validation()) {
+
+            /* Call MMC Initialization Function */
+            init_status = mmc_init(bus_width);
+            Card_Mode = 0;
+            Card_type = ((csd.csd3 & CSD_STRUCT_MSK) >> CSD_STRUCT_SHIFT) + SD_CSD_2_0;
+            MMC_Spec_vers = (csd.csd3 & MMC_CSD_SPEC_VERS_MASK) >> MMC_CSD_SPEC_VERS_SHIFT;
+            /* Card Command Class */
+            CCC = csd_get_value(&csd, 84, 95);
+        }
+    }
+
+    return init_status;
+}
+
+/*==========================================================================
+FUNCTION: static cyg_uint32 card_get_csd (void)
+DESCRIPTION:
+   this function will read MMC/SD CSD register and store in the global Variable.
+
+ARGUMENTS PASSED:
+   None
+
+RETURN VALUE:
+   cyg_uint32
+
+PRE-CONDITIONS:
+   None
+
+POST-CONDITIONS:
+   None
+
+Detailed Description:
+  1.Send CMD9 to get CSD value of MMC/SD Card.
+  2.Extract CSD value from CMDRSP0,CMDRSP1,CMDRSP2,CMDRSP3 registers.
+==============================================================================*/
+cyg_uint32 card_get_csd(void)
+{
+
+    command_t cmd;
+    command_response_t response;
+    cyg_uint32 status = FAIL;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    /* Configure CMD9 for MMC/SD card */
+    /* 16bit card address is expected as Argument */
+    mxcmci_cmd_config(&cmd, CMD9, card_address, READ, RESPONSE_136,
+              DATA_PRESENT_NONE, ENABLE, DISABLE);
+
+    /* Issue Command CMD9 to Extrace CSD register contents     */
+
+    if (host_send_cmd(&cmd) != FAIL) {
+        /* Read Command response */
+        response.format = RESPONSE_136;
+        host_read_response(&response);
+
+        /* Assign Response to CSD Strcuture */
+        csd.csd0 = response.cmd_rsp0;
+        csd.csd1 = response.cmd_rsp1;
+        csd.csd2 = response.cmd_rsp2;
+        csd.csd3 = response.cmd_rsp3;
+
+        flash_dprintf(FLASH_DEBUG_MAX, "CSD:%x:%x:%x:%x\n", csd.csd0,
+                  csd.csd1, csd.csd2, csd.csd3);
+        status = SUCCESS;
+    } else {
+        diag_printf("Get CSD Failed.\n");
+    }
+
+    return status;
+
+}
+
+static cyg_uint32 csd_get_value(cyg_uint32 * pcsd, cyg_uint32 start_bit,
+                cyg_uint32 end_bit)
+{
+    cyg_uint32 index = (start_bit / 32);
+    cyg_uint32 end_index = (end_bit / 32);
+    cyg_uint32 offset = (start_bit - 8) % 32;
+    cyg_uint32 end_offset = (end_bit - 8) % 32;
+    cyg_uint32 value;
+    cyg_uint32 temp;
+    //pcsd = &(csd.csd0);
+    flash_dprintf(FLASH_DEBUG_MAX,
+              "start_bit=%d, end_bit=%d, index=%d, end_index=%d, offset=%d\n",
+              start_bit, end_bit, index, end_index, offset);
+
+    if (index == end_index) {
+        flash_dprintf(FLASH_DEBUG_MAX, "onl1y in index register\n");
+        value =
+            (*((cyg_uint32 *) ((cyg_uint32) pcsd + (index << 2)))) &
+            ((1 << (end_offset + 1)) - (1 << offset));
+        value = (value >> offset);
+    } else {
+        flash_dprintf(FLASH_DEBUG_MAX, "index and index+1 registers\n");
+        value =
+            *((cyg_uint32 *) ((cyg_uint32) pcsd +
+                      (index << 2))) & (0xFFFFFFFF -
+                            (1 << offset) + 1);
+        value = (value >> offset);
+        temp = (1 << (offset + end_bit - start_bit - 31)) - 1;
+        temp =
+            (*((cyg_uint32 *) ((cyg_uint32) pcsd + (index + 1) * 4)) &
+             temp);
+        value += temp << (32 - offset);
+    }
+
+    flash_dprintf(FLASH_DEBUG_MAX, "%s:value=%x (CSD:%x:%x:%x:%x)\n",
+              __FUNCTION__, value, *pcsd, *(pcsd + 1), *(pcsd + 2),
+              *(pcsd + 3));
+    return value;
+
+}
+
+cyg_uint32 card_get_capacity_size(void)
+{
+    cyg_uint32 capacity = 0;
+    cyg_uint32 c_size, c_size_mult, blk_len;
+
+    if (!csd.csd0 && !csd.csd1 && !csd.csd2 && !csd.csd3)
+        flash_dprintf(FLASH_DEBUG_MAX,
+                  "WARNINGS:mxcmci_init should be done first!\n");
+
+    switch (Card_type) {
+    case SD_CSD_1_0:
+    case MMC_CSD_1_0:
+    case MMC_CSD_1_1:
+    case MMC_CSD_1_2:
+        c_size = csd_get_value(&csd, 62, 73);
+        c_size_mult = csd_get_value(&csd, 47, 49);
+        blk_len = csd_get_value(&csd, 80, 83);
+        capacity = (c_size + 1) << (c_size_mult + 2 + blk_len - 10);
+        break;
+    case SD_CSD_2_0:
+        //blk_len = csd_get_value(&csd, 80, 83);
+        c_size = csd_get_value(&csd, 48, 69);
+        capacity = (c_size + 1) * 512;    /* block length is fixed to 512B */
+        break;
+    default:
+        capacity = 1;
+        break;
+    }
+
+    /* check whether the card is high capacity card */
+    if(capacity>2*1024*1024)
+       HighCapacityCard = 1;
+    else
+       HighCapacityCard = 0;
+
+    return capacity;
+
+}
+
+cyg_uint32 mxcmci_data_read(cyg_uint32 * dest_ptr, cyg_uint32 len,
+                cyg_uint32 offset)
+{
+    cyg_uint32 read_status = FAIL;
+
+    read_status = mmc_data_read(dest_ptr, len, offset);
+
+    if (read_status) {
+        len = 0;
+    }
+    return len;
+
+}
+
+cyg_uint32 mxcmci_software_reset(void)
+{
+    command_t cmd;
+    cyg_uint32 response = FAIL;
+
+    /*Configure CMD0 for MMC/SD card */
+    /*CMD0 doesnt expect any response */
+    mxcmci_cmd_config(&cmd, CMD0, NO_ARG, READ, RESPONSE_NONE,
+              DATA_PRESENT_NONE, DISABLE, DISABLE);
+
+    /*Issue CMD0 to MMC/SD card to put in active state */
+    if (host_send_cmd(&cmd) != FAIL) {
+        response = SUCCESS;
+    } else {
+        diag_printf("Card SW Reset Failed.\n");
+    }
+
+    return response;
+}
+
+cyg_uint32 mxcmci_get_cid(void)
+{
+
+    command_t cmd;
+    cyg_uint32 cid_request = FAIL;
+    command_response_t response;
+
+    /* Configure CMD2 for card */
+    /* No Argument is expected for CMD2 */
+    mxcmci_cmd_config(&cmd, CMD2, NO_ARG, READ, RESPONSE_136,
+              DATA_PRESENT_NONE, ENABLE, DISABLE);
+
+    /* Issue CMD2 to card to determine CID contents */
+    if (host_send_cmd(&cmd) == FAIL) {
+        cid_request = FAIL;
+        diag_printf("Send CMD2 Failed.\n");
+    } else {
+        /* Read Command response  */
+        response.format = RESPONSE_136;
+        host_read_response(&response);
+
+        /* Assign CID values to mmc_cid structures */
+        Card_identification.cid0 = response.cmd_rsp0;
+        Card_identification.cid1 = response.cmd_rsp1;
+        Card_identification.cid2 = response.cmd_rsp2;
+        Card_identification.cid3 = response.cmd_rsp3;
+
+        /* Assign cid_request as SUCCESS */
+        cid_request = SUCCESS;
+    }
+
+    flash_dprintf(FLASH_DEBUG_MAX, "%s:CID=%X:%X:%X:%X\n", __FUNCTION__,
+              Card_identification.cid0, Card_identification.cid1,
+              Card_identification.cid2, Card_identification.cid3);
+    return cid_request;
+}
+
+cyg_uint32 mxcmci_trans_prepare(void)
+{
+    command_t cmd;
+    cyg_uint32 card_state = 0;
+    cyg_uint32 transfer_status = 0;
+    command_response_t response;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    /* Configure CMD7 for MMC card */
+    /* 16bit card address is expected as Argument */
+    mxcmci_cmd_config(&cmd, CMD7, card_address, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Sending the card from stand-by to transfer state    */
+    if (host_send_cmd(&cmd) == FAIL) {
+        transfer_status = FAIL;
+        diag_printf("Send CMD7 Failed.\n");
+    } else {
+
+        /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
+        mxcmci_cmd_config(&cmd, CMD13, card_address, READ, RESPONSE_48,
+                  DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+        if (host_send_cmd(&cmd) == FAIL) {
+            transfer_status = FAIL;
+            diag_printf("Send CMD13 Failed.\n");
+        } else {
+            /* Read Command response */
+            response.format = RESPONSE_48;
+            host_read_response(&response);
+
+            card_state = CURR_CARD_STATE(response.cmd_rsp0);
+
+            if (card_state == TRAN) {
+                transfer_status = SUCCESS;
+
+            } else {
+                diag_printf("card_state: 0x%x\n", card_state);
+                transfer_status = FAIL;
+            }
+        }
+
+    }
+
+    return transfer_status;
+
+}
+
+cyg_uint32 mxcmci_trans_status(void)
+{
+    command_t cmd;
+    cyg_uint32 card_state = 0;
+    cyg_uint32 transfer_status = 0;
+    command_response_t response;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
+    mxcmci_cmd_config(&cmd, CMD13, card_address, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    if (host_send_cmd(&cmd) == FAIL) {
+        diag_printf("Fail, CMD13\n");
+        transfer_status = FAIL;
+    }
+
+    else {
+        /* Read Command response */
+        response.format = RESPONSE_48;
+        host_read_response(&response);
+
+        card_state = CURR_CARD_STATE(response.cmd_rsp0);
+
+        if (card_state == TRAN) {
+            transfer_status = SUCCESS;
+            //diag_printf("card_state: 0x%x\n", card_state);
+        }
+
+        else {
+            //diag_printf("card_state: 0x%x\n", card_state);
+            transfer_status = FAIL;
+        }
+    }
+    return transfer_status;
+
+}
+
+void mxcmci_cmd_config(command_t * cmd_config, cyg_uint32 index,
+               cyg_uint32 argument, xfer_type_t transfer,
+               response_format_t format, data_present_select data,
+               crc_check_enable crc, cmdindex_check_enable cmdindex)
+{
+
+    command_t *cmd;
+
+    /* Assign cmd to cmd_config */
+    cmd = cmd_config;
+
+    /* Configure Command index */
+    cmd->command = index;
+
+    /* Configure Command Argument */
+    cmd->arg = argument;
+
+    /* Configure Data transfer type */
+    cmd->data_transfer = transfer;
+
+    /* Configure Response Format */
+    cmd->response_format = format;
+
+    /* Configure Data Present Select */
+    cmd->data_present = data;
+
+    /* Configiure CRC check Enable */
+    cmd->crc_check = crc;
+
+    /*Configure Command index check enable */
+    cmd->cmdindex_check = cmdindex;
+
+    /* if multi-block is used */
+    if (CMD18 == index || CMD25 == index) {
+        /*Configure Block count enable */
+        cmd->block_count_enable_check = ENABLE;
+        /*Configure Multi single block select */
+        cmd->multi_single_block = MULTIPLE;
+    } else {
+        /*Configure Block count enable */
+        cmd->block_count_enable_check = DISABLE;
+
+        /*Configure Multi single block select */
+        cmd->multi_single_block = SINGLE;
+    }
+}
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_host.c b/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_host.c
new file mode 100644 (file)
index 0000000..04b5ea1
--- /dev/null
@@ -0,0 +1,491 @@
+// ==========================================================================
+//
+//   mxcmci_host.c
+//   (c) 2008, Freescale
+//
+//   MMC card driver for MXC platform
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/io/mxcmci_host.h>
+#include <cyg/io/mxcmci_core.h>
+#include <cyg/io/mxcmci_mmc.h>
+#include <cyg/hal/hal_soc.h>
+#include <cyg/io/mxc_mmc.h>
+
+host_register_ptr esdhc_base_pointer;
+extern void mxc_mmc_init(unsigned int module_base);
+
+static void esdhc_cmd_config(command_t *);
+static int esdhc_wait_end_cmd_resp_intr(void);
+static cyg_uint32 esdhc_check_response(void);
+static void esdhc_wait_buf_rdy_intr(cyg_uint32, multi_single_block_select);
+static void esdhc_wait_op_done_intr(cyg_uint32);
+static cyg_uint32 esdhc_check_data(cyg_uint32, cyg_uint32, cyg_uint32);
+static void esdhc_set_data_transfer_width(cyg_uint32 data_transfer_width);
+static void esdhc_set_endianness(cyg_uint32 endian_mode);
+static int esdhc_check_for_send_cmd(int data_present);
+
+void host_reset(cyg_uint32 data_transfer_width, cyg_uint32 endian_mode)
+{
+    int counter = 0;
+
+    /* Reset the entire host controller by writing 1 to RSTA bit of SYSCTRL Register */
+    esdhc_base_pointer->system_control |= ESDHC_SOFTWARE_RESET;
+
+    //use WDOG timer: 3 ms delay
+    hal_delay_us(3 * 1000);
+
+    /* Wait for clearance of CIHB and CDIHB Bits */
+    while (esdhc_base_pointer->present_state & ESDHC_CMD_INHIBIT) {
+        if (counter++ > 200) {
+            diag_printf
+                ("%s: something goes wrong with the DSDHC and int is not received!\n",
+                 __FUNCTION__);
+            counter = 0;
+            break;
+        }
+    }
+
+    /* send 80 clock ticks for card to power up */
+    esdhc_base_pointer->system_control |= ESDHC_SOFTWARE_INIT;
+
+    /* Set data bus width of ESDCH */
+    esdhc_set_data_transfer_width(data_transfer_width);
+
+    /* Set Endianness of ESDHC */
+    esdhc_set_endianness(endian_mode);
+
+}
+
+void esdhc_softreset(cyg_uint32 mask)
+{
+    //wait max timeout 100ms
+    cyg_uint32 timeout = 100;
+
+    esdhc_base_pointer->system_control |= mask;
+
+    /* hw clears the bit when it's done */
+    while (esdhc_base_pointer->system_control & mask) {
+        if (timeout == 0) {
+            flash_dprintf(FLASH_DEBUG_MAX,
+                      "%s:Reset 0x%X never complete!\n");
+            return;
+        }
+        timeout--;
+        hal_delay_us(100);
+    }
+}
+
+void host_init(cyg_uint32 base_address)
+{
+    esdhc_base_pointer = (host_register_ptr) base_address;
+
+    flash_dprintf(FLASH_DEBUG_MAX, "%s: interface_esdc=%d\n", __FUNCTION__,
+              base_address);
+
+    mxc_mmc_init(base_address);
+}
+
+void host_cfg_clock(sdhc_freq_t frequency)
+{
+    unsigned int timeout = 9000;
+    /* Enable ipg_perclk, HCLK enable, IPG Clock enable.  */
+    esdhc_base_pointer->system_control |= ESDHC_CLOCK_ENABLE;
+
+    esdhc_base_pointer->system_control |= 0xe0000;    //set timeout counter
+
+    /* Clear DTOCV SDCLKFS bits, clear SD clk enable bit to change frequency */
+    esdhc_base_pointer->system_control &= ESDHC_FREQ_MASK;
+
+    /* Disable SD clock */
+    esdhc_base_pointer->system_control &= ~ESDHC_ENABLE;
+
+    if (frequency == IDENTIFICATION_FREQ) {
+        /* Input frequecy to eSDHC is 36 MHZ */
+        /* PLL3 is the source of input frequency */
+        /*Set DTOCV and SDCLKFS bit to get SD_CLK of frequency below 400 KHZ (70.31 KHZ) */
+        esdhc_base_pointer->system_control |= ESDHC_IDENT_FREQ;
+    } else if (frequency == OPERATING_FREQ) {
+        /*Set DTOCV and SDCLKFS bit to get SD_CLK of frequency around 25 MHz.(18 MHz) */
+        esdhc_base_pointer->system_control |= ESDHC_OPERT_FREQ;
+    }
+
+    /* Wait for clock to be steady */
+    while (((esdhc_base_pointer->present_state & 0x8) == 0) && (timeout != 0)) {
+        timeout--;
+        hal_delay_us(10);
+    }
+
+    /* Enable SD clock */
+    esdhc_base_pointer->system_control |= ESDHC_ENABLE;
+}
+
+static void esdhc_set_data_transfer_width(cyg_uint32 data_transfer_width)
+{
+
+    /* Set DWT bit of protocol control register according to bus_width */
+    esdhc_base_pointer->protocol_control &= ~0x6;
+    esdhc_base_pointer->protocol_control |= data_transfer_width;
+
+}
+
+static void esdhc_set_endianness(cyg_uint32 endian_mode)
+{
+
+    /* Set DWT bit of protocol control register according to bus_width */
+    esdhc_base_pointer->protocol_control |= endian_mode;
+
+}
+
+cyg_uint32 host_send_cmd(command_t * cmd)
+{
+
+    /* Clear Interrupt status register */
+    esdhc_base_pointer->interrupt_status = ESDHC_CLEAR_INTERRUPT;
+    //esdhc_base_pointer->interrupt_status = 0x117f01ff;
+
+    /* Enable Interrupt */
+    esdhc_base_pointer->interrupt_status_enable |= ESDHC_INTERRUPT_ENABLE;
+    //esdhc_base_pointer->interrupt_status_enable |= 0x007f0123;
+
+#if 0
+    if (esdhc_check_for_send_cmd(cmd->data_present)) {
+        diag_printf("Data/Cmd Line Busy.\n");
+        return FAIL;
+    }
+#endif
+
+    /* Configure Command    */
+    esdhc_cmd_config(cmd);
+
+    /* Wait interrupt (END COMMAND RESPONSE)  */
+    //diag_printf("Wait for CMD Response.\n");
+    if (esdhc_wait_end_cmd_resp_intr()) {
+        diag_printf("Wait CMD (%d) RESPONSE TIMEOUT.\n", cmd->command);
+        return FAIL;
+    }
+    //Just test for Erase functionality:Lewis-20080505:
+    if (cmd->command == CMD38) {
+        flash_dprintf(FLASH_DEBUG_MAX, "%s:Check DAT0 status:\n",
+                  __FUNCTION__);
+        //while(((esdhc_base_pointer->present_state) & 0x01000004)){
+        //   flash_dprintf(FLASH_DEBUG_MAX,".");
+        //   hal_delay_us(1000);
+        //}
+        /* I'm not sure the minimum value of delay */
+        hal_delay_us(100000);
+        hal_delay_us(100000);
+        hal_delay_us(100000);
+        flash_dprintf(FLASH_DEBUG_MAX,
+                  "\nCheck DAT0 status DONE: present_state=%x\n",
+                  (cyg_uint32) (esdhc_base_pointer->present_state));
+    }
+
+    /* Mask all interrupts     */
+    //esdhc_base_pointer->interrupt_signal_enable =0;
+
+    /* Check if an error occured    */
+    return esdhc_check_response();
+}
+
+static void esdhc_cmd_config(command_t * cmd)
+{
+    unsigned int transfer_type;
+
+    /* Write Command Argument in Command Argument Register */
+    esdhc_base_pointer->command_argument = cmd->arg;
+
+    /*    *Configure e-SDHC Register value according to Command    */
+    transfer_type = (((cmd->data_transfer) << DATA_TRANSFER_SHIFT) |
+             ((cmd->response_format) << RESPONSE_FORMAT_SHIFT) |
+             ((cmd->data_present) << DATA_PRESENT_SHIFT) |
+             ((cmd->crc_check) << CRC_CHECK_SHIFT) |
+             ((cmd->cmdindex_check) << CMD_INDEX_CHECK_SHIFT) |
+             ((cmd->command) << CMD_INDEX_SHIFT) |
+             ((cmd->
+               block_count_enable_check) <<
+              BLOCK_COUNT_ENABLE_SHIFT) | ((cmd->
+                            multi_single_block) <<
+                               MULTI_SINGLE_BLOCK_SELECT_SHIFT));
+
+    esdhc_base_pointer->command_transfer_type = transfer_type;
+
+    //diag_printf("arg: 0x%x | tp: 0x%x\n", esdhc_base_pointer->command_argument, esdhc_base_pointer->command_transfer_type);
+
+}
+
+static int esdhc_wait_end_cmd_resp_intr(void)
+{
+    /* Wait interrupt (END COMMAND RESPONSE)  */
+    cyg_uint32 i = 50000;
+    while (!
+           ((esdhc_base_pointer->
+         interrupt_status) & ESDHC_STATUS_END_CMD_RESP_TIME_MSK) && i) {
+        i--;
+        hal_delay_us(10);
+        //diag_printf("0x%x\n", esdhc_base_pointer->interrupt_status);
+    }
+
+    if (!
+        ((esdhc_base_pointer->
+          interrupt_status) & ESDHC_STATUS_END_CMD_RESP_TIME_MSK)) {
+        //diag_printf("%s: can't get END COMMAND RESPONSE! Tried %d times\n", __FUNCTION__, (5000000-i));
+        return FAIL;
+    }
+
+    return SUCCESS;
+}
+
+static cyg_uint32 esdhc_check_response(void)
+{
+    cyg_uint32 status = FAIL;
+
+    /* Check whether the interrupt is an END_CMD_RESP
+     * or a response time out or a CRC error
+     */
+    if ((esdhc_base_pointer->
+         interrupt_status & ESDHC_STATUS_END_CMD_RESP_MSK)
+        && !(esdhc_base_pointer->
+         interrupt_status & ESDHC_STATUS_TIME_OUT_RESP_MSK)
+        && !(esdhc_base_pointer->
+         interrupt_status & ESDHC_STATUS_RESP_CRC_ERR_MSK)
+        && !(esdhc_base_pointer->
+         interrupt_status & ESDHC_STATUS_RESP_INDEX_ERR_MSK)) {
+
+        status = SUCCESS;
+    } else {
+        //diag_printf("Warning: Check CMD response, Intr Status: 0x%x\n", esdhc_base_pointer->interrupt_status);
+        status = FAIL;
+    }
+
+    return status;
+
+}
+
+void host_read_response(command_response_t * cmd_resp)
+{
+    /* get response values from e-SDHC CMDRSP registers. */
+    cmd_resp->cmd_rsp0 = (cyg_uint32) esdhc_base_pointer->command_response0;
+    cmd_resp->cmd_rsp1 = (cyg_uint32) esdhc_base_pointer->command_response1;
+    cmd_resp->cmd_rsp2 = (cyg_uint32) esdhc_base_pointer->command_response2;
+    cmd_resp->cmd_rsp3 = (cyg_uint32) esdhc_base_pointer->command_response3;
+}
+
+static void esdhc_wait_buf_rdy_intr(cyg_uint32 mask,
+                    multi_single_block_select
+                    multi_single_block)
+{
+
+    /* Wait interrupt (BUF_READ_RDY)    */
+
+    cyg_uint32 i;
+    for (i = 3000; i > 0; i--) {
+        if (esdhc_base_pointer->interrupt_status & mask) {
+            break;
+        }
+        hal_delay_us(100);
+    }
+
+    if (multi_single_block == MULTIPLE
+        && esdhc_base_pointer->interrupt_status & mask)
+        esdhc_base_pointer->interrupt_status |= mask;
+    if (i == 0)
+        flash_dprintf(FLASH_DEBUG_MAX, "%s:Debug: tried %d times\n",
+                  __FUNCTION__, (3000 - i));
+
+}
+
+static void esdhc_wait_op_done_intr(cyg_uint32 transfer_mask)
+{
+    /* Wait interrupt (Transfer Complete)    */
+
+    cyg_uint32 i;
+    while (!(esdhc_base_pointer->interrupt_status & transfer_mask)) ;
+
+    //diag_printf("Wait OP Done Failed.\n");
+    //flash_dprintf(FLASH_DEBUG_MAX,"%s:Debug: tried %d times\n", __FUNCTION__, (3001-i));
+
+}
+
+static cyg_uint32 esdhc_check_data(cyg_uint32 op_done_mask,
+                   cyg_uint32 read_time_out_mask,
+                   cyg_uint32 read_crc_err_mask)
+{
+
+    cyg_uint32 status = FAIL;
+
+    /* Check whether the interrupt is an OP_DONE
+     * or a data time out or a CRC error     */
+    if ((esdhc_base_pointer->interrupt_status & op_done_mask) &&
+        !(esdhc_base_pointer->interrupt_status & read_time_out_mask) &&
+        !(esdhc_base_pointer->interrupt_status & read_crc_err_mask)) {
+        status = SUCCESS;
+    } else {
+        status = FAIL;
+        //diag_printf("Warning: Check data, interrupt_status=%X\n", (esdhc_base_pointer->interrupt_status));
+    }
+
+    return status;
+}
+
+void host_cfg_block(cyg_uint32 blk_len, cyg_uint32 nob)
+{
+    /* Configre block Attributes register */
+    esdhc_base_pointer->block_attributes =
+        ((nob << 16) | (blk_len & 0xffff));
+
+    //diag_printf("nob: 0x%x, block_attributes: 0x%x\n", nob, esdhc_base_pointer->block_attributes);
+
+    /* Set Read Water Mark Level register */
+    esdhc_base_pointer->watermark_level = WRITE_READ_WATER_MARK_LEVEL;
+}
+
+cyg_uint32 host_data_read(cyg_uint32 * dest_ptr, cyg_uint32 read_len)
+{
+    cyg_uint32 j, k;
+    cyg_uint32 status = FAIL;
+    unsigned int len = WRITE_READ_WATER_MARK_LEVEL & 0xff;
+    //int counter = 0;
+
+    /* Enable Interrupt */
+    esdhc_base_pointer->interrupt_status_enable |= ESDHC_INTERRUPT_ENABLE;
+
+    for (j = 0; j < read_len / (len * 4); j++) {
+        //StartCounter();
+        /* wait for read fifo full (equal or beyond the watermark) */
+        while (!(esdhc_base_pointer->present_state & (1 << 11))) ;
+
+        //counter = StopCounter();
+        //diag_printf("counter: 0x%x\n", counter);
+
+        for (k = 0; k < len; k++) {
+            *dest_ptr++ = esdhc_base_pointer->data_buffer_access;
+        }
+    }
+
+    /* Wait for transfer complete operation interrupt */
+    esdhc_wait_op_done_intr(ESDHC_STATUS_TRANSFER_COMPLETE_MSK);
+
+    /* Check for status errors */
+    status =
+        esdhc_check_data(ESDHC_STATUS_TRANSFER_COMPLETE_MSK,
+                 ESDHC_STATUS_TIME_OUT_READ, ESDHC_STATUS_READ_CRC_ERR_MSK);
+
+    return status;
+
+}
+
+cyg_uint32 host_data_write(cyg_uint32 * src_ptr, cyg_uint32 write_len)
+{
+    cyg_uint32 i = 0, k;
+    cyg_uint32 status = FAIL;
+    unsigned int len = (WRITE_READ_WATER_MARK_LEVEL >> 16) & 0xff;
+    //cyg_uint32 counter = 0;
+
+    /* Enable Interrupt */
+    esdhc_base_pointer->interrupt_status_enable |= ESDHC_INTERRUPT_ENABLE;
+
+    //StartCounter();
+    for (i = 0; i < (write_len) / (len * 4); i++) {
+        /* wait for write fifo empty (equal or less than the watermark), BWEN */
+        while (!(esdhc_base_pointer->present_state & (1 << 10))) ;
+
+        for (k = 0; k < len; k++) {
+            esdhc_base_pointer->data_buffer_access = *src_ptr++;
+        }
+
+    }
+
+    /* Wait for transfer complete operation interrupt */
+    esdhc_wait_op_done_intr(ESDHC_STATUS_TRANSFER_COMPLETE_MSK);
+
+    //counter = StopCounter();
+    //diag_printf("0x%x\n", counter);
+
+    /* Check for status errors */
+    status =
+        esdhc_check_data(ESDHC_STATUS_TRANSFER_COMPLETE_MSK,
+                 ESDHC_STATUS_TIME_OUT_READ, ESDHC_STATUS_READ_CRC_ERR_MSK);
+
+    return status;
+
+}
+
+static int esdhc_check_for_send_cmd(int data_present)
+{
+
+    int status = SUCCESS;
+    int counter;
+
+    /* Wait for the command line to be free (poll the CIHB bit of
+     * the present state register.
+     */
+    counter = 1000;
+    while (((esdhc_base_pointer->present_state & 0x1) == 0x1) && counter--) {
+        hal_delay_us(10);
+    }
+
+    if (!counter)
+        return FAIL;
+
+    /* Wait for the data line to be free (poll the CDIHB bit of
+     * the present state register.
+     */
+    counter = 1000;
+    if (data_present == DATA_PRESENT) {
+        while (((esdhc_base_pointer->present_state & 0x2) == 0x2) && counter--) {
+            hal_delay_us(10);
+        }
+
+    }
+
+    if (!counter)
+        return FAIL;
+
+    return status;
+}
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_mmc.c b/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_mmc.c
new file mode 100644 (file)
index 0000000..11c33a9
--- /dev/null
@@ -0,0 +1,694 @@
+// ==========================================================================
+//
+//   mxcmci_mmc.c
+//   (c) 2008, Freescale
+//
+//   MMC card driver for MXC platform
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/io/mxcmci_host.h>
+#include <cyg/io/mxcmci_core.h>
+#include <cyg/io/mxcmci_mmc.h>
+#include <cyg/io/mxc_mmc.h>
+
+extern int HighCapacityCard;
+
+static cyg_uint32 mmc_set_rca(void);
+static cyg_uint32 mmc_set_bus_width(cyg_uint32 bus_width);
+static cyg_uint32 mmc_set_high_speed_mode(void);
+
+cyg_uint32 address_mode;    /* Global variable for addressing mode */
+
+cyg_uint32 mmc_init(cyg_uint32 bus_width)
+{
+    cyg_uint32 status = FAIL;
+    cyg_uint32 spec_version;
+    /* Get CID number of MMC Card */
+    if (!mxcmci_get_cid()) {
+        /* Set RCA of the MMC Card */
+        if (!mmc_set_rca()) {
+            flash_dprintf(FLASH_DEBUG_MAX, "%s:  mmc_set_rca OK!",
+                      __FUNCTION__);
+            /* Get Spec version supported by the card */
+            spec_version = mmc_get_spec_ver();
+            //diag_printf("SPEC Version:  %d\n", spec_version);
+
+            /*Enable operating frequency */
+            host_cfg_clock(OPERATING_FREQ);
+
+            /*Put MMC in Transfer State */
+            if (!mxcmci_trans_prepare()) {
+#if 0
+                if (mmc_set_high_speed_mode()) {
+                    return FAIL;
+                }
+#endif
+
+                /* Set block length for transfer */
+                //diag_printf("Send CMD to Set Block Length.\n");
+                if (sdmmc_set_blklen(BLK_LEN))
+                    return FAIL;
+
+                flash_dprintf(FLASH_DEBUG_MAX, "%s:  mxcmci_trans_prepare OK!",
+                          __FUNCTION__);
+
+                if (!mmc_set_bus_width(bus_width)) {
+                    esdhc_base_pointer->protocol_control &= ~(0x3 << 1);
+                    esdhc_base_pointer->protocol_control |= (bus_width >> 2) << 1;
+                    status = SUCCESS;
+                    diag_printf("Bus Width:    %d\n",
+                            bus_width);
+                }
+
+            }
+        }
+    }
+
+    return status;
+
+}
+
+cyg_uint32 mmc_data_read(cyg_uint32 * dest_ptr, cyg_uint32 length,
+             cyg_uint32 offset)
+{
+    command_t cmd;
+    int len;
+    cyg_uint32 read_block_status = 0;
+    cyg_uint32 blk_len = BLK_LEN;
+    unsigned int SectorNum = 0;
+
+    /* Assing length of data to be read */
+    SectorNum = length / blk_len;
+    if ((length % blk_len) != 0)
+        SectorNum++;
+    /* hight capacity card uses sector mode */
+    if(HighCapacityCard)
+       offset = offset/512;
+
+    /* wait until in transfer mode */
+    while (mxcmci_trans_status()) {
+        hal_delay_us(5);
+    }
+
+      reread:
+    /* Configure interface block and number of blocks */
+    host_cfg_block(BLK_LEN, SectorNum);
+
+    if (SectorNum == 1) {
+        //diag_printf("Send CMD17...\n");
+        /* Comfigure command CMD17 for single block read */
+        mxcmci_cmd_config(&cmd, CMD17, offset, READ, RESPONSE_48,
+                  DATA_PRESENT, ENABLE, ENABLE);
+
+        if (host_send_cmd(&cmd) == FAIL) {
+            diag_printf("%s: Can't send CMD17!\n", __FUNCTION__);
+            esdhc_softreset(ESDHC_RESET_CMD_MSK |
+                    ESDHC_RESET_DAT_MSK);
+            read_block_status = FAIL;
+
+        } else {
+            //diag_printf("host_data_read! dest_ptr: 0%x \n", dest_ptr);
+            /* Call interface Data read function */
+            read_block_status = host_data_read(dest_ptr, BLK_LEN);
+
+            if (read_block_status) {    /* fail */
+                //diag_printf("%s: Failed, read_block_status =%d\n", __FUNCTION__, read_block_status);
+                /* re-transfer if data transfer error occurs */
+                goto reread;
+            }
+        }
+    } else {        /* read multi-blocks */
+
+        /* Comfigure command CMD18 for multiple block read */
+        mxcmci_cmd_config(&cmd, CMD18, offset, READ, RESPONSE_48,
+                  DATA_PRESENT, ENABLE, ENABLE);
+
+        if (host_send_cmd(&cmd) == FAIL) {
+            diag_printf("%s: Can't send CMD18!\n", __FUNCTION__);
+            esdhc_softreset(ESDHC_RESET_CMD_MSK | ESDHC_RESET_DAT_MSK);
+            read_block_status = FAIL;
+        } else {
+            /* Call interface Data read function */
+            read_block_status =
+                host_data_read(dest_ptr, BLK_LEN * SectorNum);
+
+            /* Comfigure command CMD12 for multi-block read stop */
+            mxcmci_cmd_config(&cmd, CMD12, 0, READ, RESPONSE_48,
+                      DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+            if (host_send_cmd(&cmd) == FAIL) {
+                diag_printf("%s: Can't send CMD12!\n",
+                        __FUNCTION__);
+                esdhc_softreset(ESDHC_RESET_CMD_MSK | ESDHC_RESET_DAT_MSK);
+                //read_block_status = FAIL;
+            }
+
+            if (read_block_status) {    /* fail */
+                //diag_printf("%s: Failed, read_block_status =%d\n", __FUNCTION__, read_block_status);
+                /* re-transfer if data transfer error occurs */
+                goto reread;
+            }
+
+        }
+
+    }
+    return read_block_status;
+}
+
+cyg_uint32 mmc_data_write(cyg_uint32 * src_ptr, cyg_uint32 length,
+              cyg_uint32 offset)
+{
+
+    command_t cmd;
+    cyg_int32 len;
+    cyg_uint32 blk_len = BLK_LEN;
+    cyg_uint32 write_block_status = SUCCESS;
+    unsigned int SectorNum;
+    //int counter;
+    //diag_printf("%s: src: 0x%x, offset: 0x%x, length: 0x%x\n", __FUNCTION__, (unsigned int)src_ptr, offset, length);
+    /* Write data size aligned with block size */
+    SectorNum = length / blk_len;
+    if ((length % blk_len) != 0)
+        SectorNum++;
+
+    /* hight capacity card uses sector mode */
+    if(HighCapacityCard)
+        offset = offset/512;
+
+    //need waiting until CARD out of Prg status, or will cause CMD25 timeout
+    //hal_delay_us(100);
+
+    //StartCounter();
+
+    while (mxcmci_trans_status()) {
+        hal_delay_us(2);
+    }
+
+    //counter = StopCounter();
+    //diag_printf("counter: 0x%x\n",counter);
+
+      rewrite:
+    /* Configure interface block and number of blocks , SctorNum will decrease to zero after transfer */
+    host_cfg_block(BLK_LEN, SectorNum);
+
+    if (SectorNum == 1) {
+        //diag_printf("Send CMD24...\n");
+        /* Comfigure command CMD24 for single block write */
+        mxcmci_cmd_config(&cmd, CMD24, offset, WRITE, RESPONSE_48,
+                  DATA_PRESENT, ENABLE, ENABLE);
+
+        if (host_send_cmd(&cmd) == FAIL) {
+            diag_printf("%s: Failed in configuring CMD24\n",
+                    __FUNCTION__);
+            esdhc_softreset(ESDHC_RESET_CMD_MSK | ESDHC_RESET_DAT_MSK);
+            write_block_status = FAIL;
+
+            //hal_delay_us(1000);
+            goto rewrite;
+
+        } else {
+            //diag_printf("Start host_data_write:\n");
+            /* Call interface write read function */
+            write_block_status = host_data_write(src_ptr, BLK_LEN);
+            //diag_printf("0x%x\n", esdhc_base_pointer->present_state);
+
+            if (write_block_status) {    /* fail */
+                //diag_printf("transfer failed.(0x%x)\n", esdhc_base_pointer->block_attributes);
+                while (mxcmci_trans_status()) ;
+                //diag_printf("%s: Failed, write_block_status=%d\n", __FUNCTION__, write_block_status);
+                /* re-transfer */
+                goto rewrite;
+            }
+
+        }
+    } else {        /* multi-block write */
+
+        //diag_printf("Send CMD25...\n");
+        /* Comfigure command CMD25 for single block write */
+        mxcmci_cmd_config(&cmd, CMD25, offset, WRITE, RESPONSE_48,
+                  DATA_PRESENT, ENABLE, ENABLE);
+
+        if (host_send_cmd(&cmd) == FAIL) {
+            //diag_printf("%s: Failed in configuring CMD25\n",
+            //        __FUNCTION__);
+            esdhc_softreset(ESDHC_RESET_CMD_MSK | ESDHC_RESET_DAT_MSK);
+            write_block_status = FAIL;
+            goto rewrite;
+        } else {
+            /* Call interface write read function */
+            write_block_status =
+                host_data_write(src_ptr, SectorNum * BLK_LEN);
+
+            /* Comfigure command CMD12 for multi-block read stop */
+            mxcmci_cmd_config(&cmd, CMD12, 0, READ, RESPONSE_48,
+                      DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+            if (host_send_cmd(&cmd) == FAIL) {
+                diag_printf("%s: Can't send CMD12!\n",
+                        __FUNCTION__);
+                esdhc_softreset(ESDHC_RESET_CMD_MSK | ESDHC_RESET_DAT_MSK);
+                //write_block_status = FAIL;
+            }
+
+            if (write_block_status) {    /* fail */
+                //diag_printf("%s: Failed, write_block_status=%d\n", __FUNCTION__, write_block_status);
+                while (mxcmci_trans_status());
+                /* re-transfer */
+                goto rewrite;
+            }
+        }
+    }
+
+    return write_block_status;
+
+}
+
+cyg_uint32 mmc_data_erase(cyg_uint32 offset, cyg_uint32 size)
+{
+    command_t cmd;
+    extern int Card_Mode;
+    cyg_uint8 startEraseBlockCmd = CMD35;
+    cyg_uint8 endEraseBlockCmd = CMD36;
+
+    cyg_uint32 startBlock = offset / BLK_LEN;
+    cyg_uint32 endBlock = (offset + size - 1) / BLK_LEN;
+    cyg_uint32 ret;
+//    diag_printf("card_data_erase\n");
+    if (Card_Mode == 0) {
+        startBlock *= BLK_LEN;
+        endBlock *= BLK_LEN;
+        startEraseBlockCmd = CMD35;
+        endEraseBlockCmd = CMD36;
+    }
+
+    else if (Card_Mode == 1) {
+        startBlock *= BLK_LEN;
+        endBlock *= BLK_LEN;
+        startEraseBlockCmd = CMD32;
+        endEraseBlockCmd = CMD33;
+    }
+#if 1
+    /* hight capacity card uses sector mode */
+    if(HighCapacityCard)
+        startBlock /= BLK_LEN;
+        endBlock /= BLK_LEN;
+#endif
+//     diag_printf("0x%x - 0x%x, size: 0x%x\n", startBlock, endBlock, size);
+    /* Configure start erase command to set first block */
+    mxcmci_cmd_config(&cmd, startEraseBlockCmd, startBlock, READ,
+              RESPONSE_48, DATA_PRESENT_NONE, ENABLE, ENABLE);
+    /* wait response */
+    if ((ret = host_send_cmd(&cmd)) == SUCCESS) {
+        flash_dprintf(FLASH_DEBUG_MAX,
+                  "%s: successful for host_send_cmd\n",
+                  __FUNCTION__);
+        /* Configure end erase command to set end block */
+        mxcmci_cmd_config(&cmd, endEraseBlockCmd, endBlock, READ,
+                  RESPONSE_48, DATA_PRESENT_NONE, ENABLE, ENABLE);
+        if ((ret = host_send_cmd(&cmd)) == SUCCESS) {
+            flash_dprintf(FLASH_DEBUG_MAX,
+                      "%s: successful for host_send_cmd:2\n",
+                      __FUNCTION__);
+            /* Comfigure command to start erase */
+            mxcmci_cmd_config(&cmd, CMD38, 0, READ, RESPONSE_48,
+                      DATA_PRESENT_NONE, ENABLE, ENABLE);
+            if ((ret = host_send_cmd(&cmd)) == SUCCESS) {
+                flash_dprintf(FLASH_DEBUG_MAX,
+                          "%s: successful for host_send_cmd:3\n",
+                          __FUNCTION__);
+                //wait for completion
+                return ret;
+            }
+        }
+    }
+
+    flash_dprintf(FLASH_DEBUG_MAX, "%s: Error return (%d)\n", __FUNCTION__,
+              ret);
+    return ret;
+}
+
+cyg_uint32 mmc_voltage_validation(void)
+{
+    command_t cmd;
+    command_response_t response;
+    cyg_uint32 voltage_validation_command = 0;
+    cyg_uint32 ocr_val = 0;
+    cyg_uint32 voltage_validation = FAIL;
+
+    ocr_val = (cyg_uint32) ((MMC_OCR_VALUE) & 0xFFFFFFFF);
+
+    while ((voltage_validation_command < MMCSD_READY_TIMEOUT)
+           && (voltage_validation != SUCCESS)) {
+        /* Configure CMD1 for MMC card */
+        mxcmci_cmd_config(&cmd, CMD1, ocr_val, READ, RESPONSE_48,
+                  DATA_PRESENT_NONE, DISABLE, DISABLE);
+
+        /* Issue CMD1 to MMC card to determine OCR value */
+        if (host_send_cmd(&cmd) == FAIL) {
+            voltage_validation = FAIL;
+            break;
+        } else {
+            /* Read Response from CMDRSP0 Register */
+            response.format = RESPONSE_48;
+            host_read_response(&response);
+
+            /* Check if card busy bit is cleared or not */
+            if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
+                /* Iterate One more time */
+                voltage_validation_command++;
+            } else {
+                if ((response.cmd_rsp0 & MMC_OCR_HC_RES) ==
+                    MMC_OCR_HC_RES) {
+                    address_mode = SECT_MODE;
+                    voltage_validation = SUCCESS;
+                } else if ((response.cmd_rsp0 & MMC_OCR_LC_RES)
+                       == MMC_OCR_LC_RES) {
+                    address_mode = BYTE_MODE;
+                    voltage_validation = SUCCESS;
+                }
+            }
+
+        }
+    }
+
+    return voltage_validation;
+}
+
+static cyg_uint32 mmc_set_rca(void)
+{
+    command_t cmd;
+    cyg_uint32 card_state = 0;
+    cyg_uint32 rca_request = 0;
+    command_response_t response;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    /* Configure CMD3 for MMC card */
+    /* 32bit card address is expected as Argument */
+    mxcmci_cmd_config(&cmd, CMD3, card_address, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Assigns relative address to the card
+     */
+
+    if (host_send_cmd(&cmd) == FAIL) {
+        rca_request = FAIL;
+    }
+
+    else {
+        /* Read Command response */
+        response.format = RESPONSE_48;
+        host_read_response(&response);
+        card_state = CURR_CARD_STATE(response.cmd_rsp0);
+        if (card_state == IDENT) {
+            rca_request = SUCCESS;
+
+        } else {
+            rca_request = FAIL;
+        }
+    }
+
+    return rca_request;
+}
+
+cyg_uint32 mmc_get_spec_ver(void)
+{
+
+    cyg_uint32 mmc_spec_version;
+
+    if (card_get_csd() == FAIL) {
+        mmc_spec_version = 0;
+    } else {
+        mmc_spec_version = ((csd.csd3 && MMC_SPEC_VER) >> MMC_SPEC_VER_SHIFT);
+    }
+
+    return mmc_spec_version;
+
+}
+
+cyg_uint32 card_flash_query(void *data)
+{
+    command_t cmd;
+    cyg_uint32 cid_request = FAIL;
+    command_response_t response;
+
+    /* Configure CMD2 for card */
+    mxcmci_cmd_config(&cmd, CMD2, NO_ARG, READ, RESPONSE_136,
+              DATA_PRESENT_NONE, ENABLE, DISABLE);
+    /* Issue CMD2 to card to determine CID contents */
+    if (host_send_cmd(&cmd) == FAIL) {
+        cid_request = FAIL;
+        flash_dprintf(FLASH_DEBUG_MAX, "%s: can't send query command\n",
+                  __FUNCTION__);
+    } else {
+        cyg_uint32 *d = (cyg_uint32 *) data;
+        /* Read Command response  */
+        response.format = RESPONSE_136;
+        host_read_response(&response);
+        /* Assign CID values to mmc_cid structures */
+        *d++ = response.cmd_rsp0;
+        *d++ = response.cmd_rsp1;
+        *d++ = response.cmd_rsp2;
+        *d = response.cmd_rsp3;
+
+        /* Assign cid_request as SUCCESS */
+        cid_request = SUCCESS;
+    }
+    flash_dprintf(FLASH_DEBUG_MAX,
+              "%s(Success?=%d):(ID=0x%x: 0x%x, 0x%x, 0x%x)\n",
+              __FUNCTION__, cid_request, *(cyg_uint32 *) (data),
+              *(cyg_uint32 *) ((cyg_uint32) data + 4),
+              *(cyg_uint8 *) ((cyg_uint32) data + 8),
+              *(cyg_uint8 *) ((cyg_uint32) data + 12));
+    return;
+}
+
+static cyg_uint32 mmc_set_bus_width(cyg_uint32 bus_width)
+{
+    command_t cmd;
+    cyg_uint32 set_bus_width_status = FAIL;
+    command_response_t response;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    if ((bus_width == FOUR) || (bus_width == EIGHT) || (bus_width == ONE)) {
+
+        /* Configure CMD6 to write to EXT_CSD register for BUS_WIDTH */
+        mxcmci_cmd_config(&cmd, CMD6, 0x03b70001 | ((bus_width >> 2) << 8), READ,
+                  RESPONSE_48, DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+        if (host_send_cmd(&cmd) == SUCCESS) {
+            set_bus_width_status = SUCCESS;
+        } else {
+            diag_printf("Setting MMC bus width failed.\n");
+        }
+    }
+
+    return set_bus_width_status;
+}
+
+static cyg_uint32 mmc_set_high_speed_mode(void)
+{
+    command_t cmd;
+    command_response_t response;
+    cyg_uint32 status = FAIL;
+
+    //diag_printf("Send CMD6 to Set High Speed Mode.\n");
+    /* Configure CMD6 to write to EXT_CSD register for BUS_WIDTH */
+    mxcmci_cmd_config(&cmd, CMD6, 0x03b90100, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    if (host_send_cmd(&cmd) == SUCCESS) {
+        /* wait until in transfer mode */
+        while (mxcmci_trans_status()) {
+            hal_delay_us(5);
+        }
+
+        status = SUCCESS;
+    } else {
+        diag_printf("Setting MMC High Speed Mode FAILED.\n");
+    }
+
+    return status;
+}
+
+int sdmmc_set_blklen(int len)
+{
+    int status = FAIL;
+    command_t cmd;
+    command_response_t response;
+
+    /* Configure CMD16 to set block length as 512 bytes. */
+    mxcmci_cmd_config(&cmd, CMD16, len, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Issue command CMD16 to set block length as 512 bytes */
+    if (host_send_cmd(&cmd) == FAIL) {
+        diag_printf("%s: Can't set block length!(CMD16)\n",
+                __FUNCTION__);
+        esdhc_softreset(ESDHC_RESET_CMD_MSK);
+        status = FAIL;
+    } else {
+        status = SUCCESS;
+    }
+
+    return status;
+}
+
+int sdmmc_stop_transmission(void)
+{
+    int status = FAIL;
+    command_t cmd;
+    command_response_t response;
+
+    /* Comfigure command CMD12 for read stop */
+    mxcmci_cmd_config(&cmd, CMD12, 0, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    if (host_send_cmd(&cmd) == FAIL) {
+        //diag_printf("%s: Can't send CMD12!\n", __FUNCTION__);
+        //esdhc_softreset(ESDHC_RESET_CMD_MSK | ESDHC_RESET_DAT_MSK);
+        //read_block_status = FAIL;
+    }
+
+    return 0;
+}
+
+static unsigned int mmc_set_extendCSD(unsigned int ECSD_index, unsigned int value, unsigned int access_mode)
+{
+    unsigned int argument = 0;
+    command_t cmd;
+
+    /* access mode: 0b01 set bits/ 0b10 clear bits/ 0b11 write bytes */
+    argument = (access_mode << 24) | (ECSD_index << 16) | (value << 8);
+    //argument = 0x1b30000;
+
+    mxcmci_cmd_config(&cmd, CMD6, argument, READ, RESPONSE_48,
+                      DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    if(host_send_cmd(&cmd) == SUCCESS) {
+        return 0;
+    } else {
+        //diag_printf("%s: Setting MMC boot Failed.\n", __FUNCTION__);
+        return 1;
+    }
+}
+
+static void mmc_set_boot_partition_size(unsigned int value)
+{
+    command_t cmd;
+    command_response_t response;
+    cyg_uint32 card_state = 0;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    mxcmci_cmd_config(&cmd, CMD62, 0XEFAC62EC, READ, RESPONSE_48,
+                      DATA_PRESENT_NONE, ENABLE, ENABLE);
+    host_send_cmd(&cmd);
+
+    mxcmci_cmd_config(&cmd, CMD62, 0X00CBAEA7, READ, RESPONSE_48,
+                      DATA_PRESENT_NONE, ENABLE, ENABLE);
+    host_send_cmd(&cmd);
+
+    mxcmci_cmd_config(&cmd, CMD62, value, READ, RESPONSE_48,
+                      DATA_PRESENT, ENABLE, ENABLE);
+    host_send_cmd(&cmd);
+}
+
+cyg_uint32 emmc_set_boot_partition (cyg_uint32 *src_ptr, cyg_uint32 length)
+{
+    cyg_uint32 status=FAIL;
+    unsigned int value;
+    unsigned int eMMCBootDataSize = (length / (128 * 1024)) + 1;
+
+    if (MMC_Spec_vers < 4)
+        return 1;
+
+    /* read back 1KB data as we are programming to user are and want to aviod erasing MBR
+      * will be removed once we program Redboot to boot partition of the card
+      */
+    mmc_data_read(src_ptr, 0x400, 0);
+
+    /* Set boot partition */
+    /* 1. Configure CMD6 to write to EXT_CSD register for eMMC boot partition, Byte 179*/
+    /* boot partition: user area enable and r/w enable */
+    value = (0x7 << 3) | (0x7);
+    //value = (0x1 << 3) | (0x1);
+    status = mmc_set_extendCSD(179, value, 0x3);
+    if(status) {
+        return 1; /* failed */
+    }
+
+    /* 2. Set boot partition size: n*128KB */
+    value = eMMCBootDataSize;
+    //status = mmc_set_extendCSD(226, value, 0x3);
+    //if(status) {
+    //    return 1; /* failed */
+    //}
+    //mmc_set_boot_partition_size(value);
+
+    //diag_printf("Boot partition size: 0x%xKB\n", eMMCBootDataSize * 128);
+
+    /* 3. Program to boot partition, default address is alway 0x0  */
+    status = mmc_data_write (src_ptr, eMMCBootDataSize*128*1024, 0);
+    if(status) {
+        return 1; /* failed */
+    }
+
+    while (mxcmci_trans_status());
+
+    /* 4. Clear boot partition access bits, to protect w/r of boot partition */
+    /* bit 6: send boot ack signal, boot partition: user area enable and r/w access disable */
+    //value = (0x1 << 6) | (0x1 << 3) | (0x0);
+    value = (0x1 << 6) | (0x7 << 3) | (0x0);
+    status = mmc_set_extendCSD(179, value, 0x3);
+    if(status) {
+        return 1; /* failed */
+    }
+
+    return 0;
+}
+
+/* end of mxcmci_mmc.c */
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_sd.c b/packages/devs/flash/arm/mxc/v2_0/src/mxcmci_sd.c
new file mode 100644 (file)
index 0000000..e2fa471
--- /dev/null
@@ -0,0 +1,588 @@
+// ==========================================================================
+//
+//   mxcmci_sd.c
+//   (c) 2008, Freescale
+//
+//   MMC card driver for MXC platform
+//
+// ==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lewis Liu <weizhi.liu@freescale.com>
+// Contributors: Lewis Liu <weizhi.liu@freescale.com>
+// Date:         2008-05-13 Initial version
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/io/mxcmci_host.h>
+#include <cyg/io/mxcmci_core.h>
+#include <cyg/io/mxcmci_mmc.h>
+
+static cyg_uint32 sd_get_rca(void);
+static cyg_uint32 sd_get_bit_mode_support(void);
+static cyg_uint32 sd_set_bus_width(cyg_uint32);
+static cyg_uint32 sd_set_high_speed_mode(void);
+
+#define SD_OCR_VALUE_HV_LC 0x00ff8000    /* nirp_oct07: <- 3.3v, LC */
+#define SD_OCR_VALUE_HV_HC 0x40ff8000    /* nirp_oct07: <- 3.3v, HC */
+/* nirp_oct07: LV_LC not needed - 1.8v is only supported under eSD which supports HC by default (SD>2.00) */
+#define SD_OCR_VALUE_LV_HC 0x40000080    /* nirp_oct07: <- 1.8v, HC */
+
+#define SD_OCR_HC_RES 0x40000000
+#define SD_OCR_LC_RES 0x00000000
+
+#define SD_IF_HV_COND_ARG 0x000001AA
+#define SD_IF_LV_COND_ARG 0x000002AA
+
+#define RCA_SHIFT 16
+#define SD_R1_STATUS_APP_CMD_MSK 0x20
+#define BIT_MODE_4_SUPPORT 5
+#define SD_BUS_WIDTH_OFFSET 6
+#define BIT_4_MODE 4
+#define SD_STATUS_LEN 64
+
+#define SD_BOOT_SWITCH_ARG 0x80FFFF2F
+#define SD_PARTITION1 0x01000000
+
+cyg_uint32 sd_init(cyg_uint32 bus_width)
+{
+    cyg_uint32 status = FAIL;
+    cyg_uint32 bus_size = bus_width;
+
+    /* Get CID number of SD Memory Card */
+    if (!mxcmci_get_cid()) {
+        //diag_printf("%s:mxcmci_get_cid OK!\n", __FUNCTION__);
+        /* Set RCA of the SD Card */
+        if (!sd_get_rca()) {
+            //diag_printf("%s:sd_get_rca OK!\n", __FUNCTION__);
+            /*Get CSD from Card */
+            if (card_get_csd())
+                return FAIL;
+
+            /*Enable operating frequency */
+            host_cfg_clock(OPERATING_FREQ);
+
+            //diag_printf("Set SD Card in Transfer State.\n");
+
+            /*Put SD Card in Transfer State */
+            if (!mxcmci_trans_prepare()) {
+#if 0
+                if (sd_set_high_speed_mode()) {
+                    return FAIL;
+                }
+#endif
+
+                if (sdmmc_set_blklen(BLK_LEN))
+                    return FAIL;
+
+                /* SD can only support 1/4 bit bitwidth, 8 bit is not supported */
+                if (EIGHT == bus_width) {
+                    bus_width = FOUR;
+                }
+                if (!sd_set_bus_width(bus_width)) {
+                    esdhc_base_pointer->protocol_control &=
+                        ~(0x3 << 1);
+                    esdhc_base_pointer->protocol_control |=
+                        (bus_width / 4) << 1;
+                    diag_printf("Bus Width:    %d\n",
+                            bus_width);
+                    status = SUCCESS;
+                }
+            }
+        }
+
+    } else {
+        diag_printf("Get CID Failed.\n");
+
+    }
+
+    //diag_printf("%s:failed to Init SD card!\n", __FUNCTION__);
+    return status;
+
+}
+
+cyg_uint32 sd_voltage_validation(void)
+{
+    //wait max timeout (unit: ms)
+    cyg_uint32 timeout = 15000;
+
+    command_t cmd;
+    command_response_t response;
+    cyg_uint32 voltage_validation_command = 0;
+    cyg_uint32 default_rca = 0;
+
+    cyg_uint32 ocr_value = SD_OCR_VALUE_HV_LC;    /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
+    cyg_uint32 voltage_validation = FAIL;
+    cyg_uint32 interface_value = 0;
+    cyg_uint32 card_usable = SUCCESS;
+
+    /* Configure Command CMD8 to check for High capacity support */
+    /* try 3.3V first */
+    mxcmci_cmd_config(&cmd, CMD8, SD_IF_HV_COND_ARG, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Issue Command CMD8  to SD Memory card */
+    if (host_send_cmd(&cmd) == SUCCESS) {    /* nirp_oct07: <- changed order of detection */
+        //diag_printf("%s:CMD8 OK!\n", __FUNCTION__);
+        response.format = RESPONSE_48;
+        host_read_response(&response);
+
+        /* Obtain Interface value from the response buffer */
+        interface_value = response.cmd_rsp0;
+
+        /* Check if volatge lies in range or not */
+        if ((interface_value & SD_IF_HV_COND_ARG) == SD_IF_HV_COND_ARG) {
+            ocr_value = ((cyg_uint32) (SD_OCR_VALUE_HV_HC) & 0xFFFFFFFF);    /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
+        }
+
+        /* start timer for a  delay of 1.5sec, for ACMD41 */
+        hal_delay_us(1500);
+
+        while ((voltage_validation_command < 20)
+               && (voltage_validation != SUCCESS)
+               && (card_usable == SUCCESS)) {
+            /* Configure CMD55 for SD card */
+            /* This command expects defualt RCA 0x0000 as argument. */
+            mxcmci_cmd_config(&cmd, CMD55, default_rca, READ,
+                      RESPONSE_48, DATA_PRESENT_NONE,
+                      ENABLE, ENABLE);
+
+            /* Issue CMD55 to SD Memory card */
+            if (host_send_cmd(&cmd) == FAIL) {
+                voltage_validation = FAIL;
+                //diag_printf("Send CMD55 Failed.\n");
+                break;
+            } else {
+                /* Configure ACMD41 for SD card */
+                /* This command expects operating voltage range as argument. */
+                /* CODE REVIEW START: Need to check why BUSY was expected */
+                /* INTERNAL CODE REVIEW: Accepted - to fix original code if needed */
+                /* nirp: changed RESPONSE_48_CHECK_BUSY to RESPONSE_48 */
+                /* nirp_oct03: why with busy again? ACMD41 doesn't hold busy line */
+                mxcmci_cmd_config(&cmd, ACMD41, ocr_value, READ,
+                          RESPONSE_48, DATA_PRESENT_NONE, DISABLE,
+                          DISABLE);
+
+                /* Issue ACMD41 to SD Memory card to determine OCR value */
+                if (host_send_cmd(&cmd) == FAIL) {
+                    voltage_validation = FAIL;
+                    diag_printf("Send CMD41 Failed.\n");
+                    break;
+                } else {
+                    /* Read Response from CMDRSP0 Register */
+                    response.format = RESPONSE_48;
+                    host_read_response(&response);
+
+                    /* Obtain OCR Values from the response */
+                    /* Obtain OCR value from the response buffer */
+                    ocr_value = response.cmd_rsp0;
+
+                    /* Check if card busy bit is cleared or not */
+                    if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
+                        /* Iterate One more time */
+                        voltage_validation_command++;
+                    } else {
+
+                        /*CODE REVIEW START: Update code and check only bit 30, HC or LC card type. All voltage bits needs to be masked. */
+                        /* INTERNAL CODE REVIEW: Accepted - need fix the code accordingly */
+                        /* nirp: It may be better to check the actual power supply voltage - requiring the entire range (0xff8000) may fail the sequence even if the device can be supported */
+                        /*CODE REVIEW END: */
+
+                        if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
+                            address_mode = SECT_MODE;
+                            voltage_validation = SUCCESS;
+                        }
+                        /* CODE REVIEW 3: (same as above) Check is logically correct, but seems redundent.
+                           Anything that fails the HC check, is assumed Low Capacity */
+                        /* nirp_oct03: this can be just an "else". the LC macro is 0 anyway,
+                           and anything not HC is LC by default */
+                        /* removed else if */
+                        else {
+                            address_mode = BYTE_MODE;
+                            voltage_validation = SUCCESS;
+                        }
+                    }
+                }
+            }
+
+            hal_delay_us(1000);
+        }
+
+        if (voltage_validation == FAIL) {
+            card_usable = FAIL;
+        }
+
+    } else {
+        /*3.3v test failed, try to test 1.8v mode! */
+        mxcmci_cmd_config(&cmd, CMD8, SD_IF_LV_COND_ARG, READ,
+                  RESPONSE_48, DATA_PRESENT_NONE, ENABLE,
+                  ENABLE);
+
+        /* Issue Command CMD8  to SD Memory card */
+        if (host_send_cmd(&cmd) == FAIL) {
+            //diag_printf("%s:CMD8 for 1.8v failed!\n", __FUNCTION__);
+            /* nirp_oct07: CMD8 failed both in 3.3 and in 1.8v, try SD 1.x case - no CMD8, LC, 3.3v only */
+            ocr_value = ((cyg_uint32) (SD_OCR_VALUE_HV_LC) & 0xFFFFFFFF);    /* nirp_oct07: <- changed order of detection */
+        } else {
+            //diag_printf("%s:CMD8 for 1.8v OK!\n", __FUNCTION__);
+            response.format = RESPONSE_48;
+            host_read_response(&response);
+
+            /* Obtain Interface value from the response buffer */
+            interface_value = response.cmd_rsp0;
+
+            /* Check if volatge lies in range or not */
+            if ((interface_value & SD_IF_LV_COND_ARG) == SD_IF_LV_COND_ARG) {
+                ocr_value = ((cyg_uint32) (SD_OCR_VALUE_LV_HC) & 0xFFFFFFFF);    /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
+            }
+            /* nirp_oct07: otherwise, try with HV_LC settings (set at function start) */
+        }
+
+    }
+
+    /* start timer for a  delay of 1.5sec, for ACMD41 */
+    hal_delay_us(1500);
+
+    /* nirp_oct03: MMCSD_READY_TIMEOUT too long.
+       ACMD41 also takes longer than CMD1 (twice - ~200 clocks for CMD55+resp+CMD41+resp */
+    /* In any case ,ACMD 41 will loop not more than 1.5 sec */
+    while ((voltage_validation_command < 20)
+           && (voltage_validation != SUCCESS) && (card_usable == SUCCESS)) {
+        /* Configure CMD55 for SD card */
+        /* This command expects defualt RCA 0x0000 as argument. */
+        mxcmci_cmd_config(&cmd, CMD55, default_rca, READ, RESPONSE_48,
+                  DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+        /* Issue CMD55 to SD Memory card */
+        if (host_send_cmd(&cmd) == FAIL) {
+            voltage_validation = FAIL;
+            //diag_printf("Send CMD55 Failed!\n");
+            break;
+        } else {
+            /* Configure ACMD41 for SD card */
+            /* This command expects operating voltage range as argument. */
+            /* CODE REVIEW START: Need to check why BUSY was expected */
+            /* INTERNAL CODE REVIEW: Accepted - to fix original code if needed */
+            /* nirp: changed RESPONSE_48_CHECK_BUSY to RESPONSE_48 */
+            /* nirp_oct03: why with busy again? ACMD41 doesn't hold busy line */
+            mxcmci_cmd_config(&cmd, ACMD41, ocr_value, READ,
+                      RESPONSE_48, DATA_PRESENT_NONE,
+                      DISABLE, DISABLE);
+
+            /* CODE REVIEW END:  */
+
+            /* Issue ACMD41 to SD Memory card to determine OCR value */
+            if (host_send_cmd(&cmd) == FAIL) {
+                voltage_validation = FAIL;
+                diag_printf("Send ACMD41 Failed!\n");
+                break;
+            } else {
+                /* Read Response from CMDRSP0 Register */
+                response.format = RESPONSE_48;
+                host_read_response(&response);
+
+                /* Obtain OCR Values from the response */
+                /* Obtain OCR value from the response buffer
+                 */
+                ocr_value = response.cmd_rsp0;
+
+                /* Check if card busy bit is cleared or not */
+                if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
+                    /* Iterate One more time */
+                    voltage_validation_command++;
+                } else {
+                    /*CODE REVIEW START: Update code and check only bit 30, HC or LC card type. All voltage bits needs to be masked. */
+                    /* INTERNAL CODE REVIEW: Accepted - need fix the code accordingly */
+                    /* nirp: It may be better to check the actual power supply voltage - requiring the entire range (0xff8000) may fail the sequence even if the device can be supported */
+                    /*CODE REVIEW END: */
+
+                    if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
+                        address_mode = SECT_MODE;
+                        voltage_validation = SUCCESS;
+                    }
+                    /* CODE REVIEW 3: (same as above) Check is logically correct, but seems redundent.
+                       Anything that fails the HC check, is assumed Low Capacity */
+                    /* nirp_oct03: this can be just an "else". the LC macro is 0 anyway,
+                       and anything not HC is LC by default */
+                    else {
+                        address_mode = BYTE_MODE;
+                        voltage_validation = SUCCESS;
+                    }
+                }
+            }
+
+        }
+
+        hal_delay_us(1000);
+
+    }
+
+    return voltage_validation;
+}
+
+static cyg_uint32 sd_get_rca(void)
+{
+    command_t cmd;
+    cyg_uint32 card_state = 0;
+    cyg_uint32 rca_request = 0;
+    command_response_t response;
+
+    /* Configure CMD3 for MMC card */
+    /* 32bit card address is expected as Argument */
+    mxcmci_cmd_config(&cmd, CMD3, NO_ARG, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Get relative address of the card     */
+
+    if (host_send_cmd(&cmd) == FAIL) {
+        rca_request = FAIL;
+        diag_printf("Send CMD3 Failed.\n");
+    } else {
+        /* Read Command response */
+        response.format = RESPONSE_48;
+        host_read_response(&response);
+
+        Card_rca = ((cyg_uint32) (response.cmd_rsp0 >> RCA_SHIFT));
+
+        card_state = CURR_CARD_STATE(response.cmd_rsp0);
+
+        if (card_state == IDENT) {
+            rca_request = SUCCESS;
+        } else {
+            rca_request = FAIL;
+            diag_printf("Get RCA Failed.\n");
+        }
+    }
+
+    return rca_request;
+}
+
+static cyg_uint32 sd_get_bit_mode_support(void)
+{
+    command_t cmd;
+    cyg_uint32 rd_data_buff[128];
+    cyg_uint32 bit4_mode_support;
+    command_response_t response;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    /* Configure CMD55 for SD card */
+    /* This command expects RCA as argument. */
+    mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Issue CMD55 to SD Memory card */
+    if (host_send_cmd(&cmd) == FAIL) {
+        bit4_mode_support = 0;
+    } else {
+        /* Read Command response */
+        response.format = RESPONSE_48;
+        host_read_response(&response);
+
+        /* Afetr giving ACMD Command, the R1 response should have
+         * STATUS_APP_CMD set
+         */
+        if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
+
+            /* Configure ACMD51 for SD card */
+            /* This command expects No argument. */
+
+            mxcmci_cmd_config(&cmd, ACMD51, NO_ARG, READ,
+                      RESPONSE_48, DATA_PRESENT, ENABLE,
+                      ENABLE);
+
+            /* Issue ACMD51 to SD Memory card */
+            if (host_send_cmd(&cmd) == FAIL) {
+                bit4_mode_support = 0;
+            } else {
+                /* Read Response from e-SDHC buffer */
+                host_data_read(rd_data_buff, 512);
+
+                /* Check for bus width supported */
+                bit4_mode_support = (rd_data_buff[SD_BUS_WIDTH_OFFSET] & BIT_MODE_4_SUPPORT);
+
+                if (bit4_mode_support) {
+                    bit4_mode_support = BIT_4_MODE;
+                }
+
+            }
+        }
+    }
+
+    return bit4_mode_support;
+}
+
+static cyg_uint32 sd_set_bus_width(cyg_uint32 bus_width)
+{
+    command_t cmd;
+    cyg_uint32 set_bus_width_status = 0;
+    command_response_t response;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+
+    if ((bus_width == FOUR) || (bus_width == ONE)) {
+        /* Configure CMD55 for SD card */
+        /* This command expects RCA as argument. */
+
+        mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
+                  DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+        /* Issue CMD55 to SD Memory card */
+        if (host_send_cmd(&cmd) == FAIL) {
+            set_bus_width_status = FAIL;
+        } else {
+            /* Read Command response */
+            response.format = RESPONSE_48;
+            host_read_response(&response);
+
+            /* Afetr giving ACMD Command, the R1 response should have
+             * STATUS_APP_CMD set
+             */
+            if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
+                bus_width = (bus_width >> ONE);
+
+                /* Configure ACMD6 for SD card */
+                mxcmci_cmd_config(&cmd, ACMD6, bus_width, READ,
+                          RESPONSE_48,
+                          DATA_PRESENT_NONE, ENABLE,
+                          ENABLE);
+
+                /* Issue ACMD6 to SD Memory card */
+                if (host_send_cmd(&cmd) == FAIL) {
+                    set_bus_width_status = FAIL;
+                } else {
+                    set_bus_width_status = SUCCESS;
+                }
+            }
+        }
+    }
+
+    return set_bus_width_status;
+}
+
+/*==========================================================================
+FUNCTION: cyg_uint32 sd_set_boot_partition (void)
+DESCRIPTION:
+  sd_set_boot_partition() will set set boot partition for Partition1
+
+RETURN VALUE:
+   SUCCESS / FAILURE
+
+PRE-CONDITIONS:
+   None
+
+POST-CONDITIONS:
+   None
+
+Detailed Description:
+
+==============================================================================*/
+
+cyg_uint32 esd_set_boot_partition(cyg_uint32 *src_ptr, cyg_uint32 length)
+{
+    command_t cmd;
+    cyg_uint32 set_partition_status = FAIL;
+    command_response_t response;
+    cyg_uint8 response_data[512];
+    cyg_uint32 *response_pointer = (cyg_uint32 *) response_data;
+    cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
+    cyg_uint32 card_state;
+
+   /* Send CMD43 to select partition PARTITION1 active */
+    mxcmci_cmd_config(&cmd, CMD43,
+                              0x1<<24,
+                              READ,
+                              RESPONSE_48,
+                              DATA_PRESENT_NONE,
+                              ENABLE,
+                              ENABLE);
+
+    if(host_send_cmd(&cmd) == FAIL) {
+        //diag_printf("%s: Send CMD43 Failed.\n", __FUNCTION__);
+        return 1;
+    }
+
+    set_partition_status = mmc_data_write (src_ptr, length, 0);
+    if(set_partition_status) {
+        return 1; /* failed */
+    }
+
+    return 0;
+}
+
+static cyg_uint32 sd_set_high_speed_mode(void)
+{
+    command_t cmd;
+    cyg_uint32 status = FAIL;
+    command_response_t response;
+
+    /* Configure CMD6 for SD card */
+    mxcmci_cmd_config(&cmd, CMD6, 0xfffff1, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Issue CMD6 to SD Memory card */
+    if (host_send_cmd(&cmd) == FAIL) {
+        status = FAIL;
+        diag_printf("Send CMD6 Failed.\n");
+        return FAIL;
+    } else {
+        hal_delay_us(1000);
+        status = SUCCESS;
+
+    }
+
+    mxcmci_cmd_config(&cmd, CMD6, 0x80fffff1, READ, RESPONSE_48,
+              DATA_PRESENT_NONE, ENABLE, ENABLE);
+
+    /* Issue CMD6 to SD Memory card */
+    if (host_send_cmd(&cmd) == FAIL) {
+        status = FAIL;
+        diag_printf("Send CMD6 Failed.\n");
+    } else {
+        /* wait until in transfer mode */
+        while (mxcmci_trans_status()) {
+            hal_delay_us(5);
+        }
+
+        status = SUCCESS;
+    }
+
+    return status;
+}
+
+/* end of mxcmic_sd.c */
diff --git a/packages/devs/flash/arm/mxc/v2_0/src/spi_nor.c b/packages/devs/flash/arm/mxc/v2_0/src/spi_nor.c
new file mode 100644 (file)
index 0000000..323f569
--- /dev/null
@@ -0,0 +1,598 @@
+//==========================================================================
+//
+//      spi_nor.c
+//
+//      SPI NOR flash support
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//========================================================================*/
+
+#include <pkgconf/hal.h>
+#include <pkgconf/system.h>
+#include <redboot.h>
+#include CYGHWR_MEMORY_LAYOUT_H
+#include <cyg/hal/hal_io.h>
+#define  _FLASH_PRIVATE_
+#include <cyg/io/flash.h>
+
+#include <cyg/io/imx_spi.h>
+#include <cyg/io/imx_spi_nor.h>
+
+static unsigned char g_tx_buf[256];
+static unsigned char g_rx_buf[256];
+static int spi_nor_init_ok;
+
+#define WRITE_ENABLE()          spi_nor_cmd_1byte(WREN)
+#define WRITE_DISABLE()         spi_nor_cmd_1byte(WRDI)
+#define ENABLE_WRITE_STATUS()   spi_nor_cmd_1byte(EWSR)
+
+#ifndef MXCFLASH_SELECT_MULTI
+void flash_query(void* data)
+#else
+void spi_norflash_query(void* data)
+#endif
+{
+    unsigned char tmp[4];
+    unsigned char *ptr = (unsigned char *)data;
+
+    g_tx_buf[3] = JEDEC_ID;
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, tmp, 4) != 0) {
+        return;
+    }
+    diag_printf("JEDEC ID: 0x%02x:0x%02x:0x%02x\n", tmp[2], tmp[1], tmp[0]);
+    ptr[0] = tmp[2];
+    ptr[1] = tmp[1];
+    ptr[2] = tmp[0];
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_program_buf(void* addr, void* data, int len)
+#else
+int spi_norflash_program_buf(void* addr, void* data, int len)
+#endif
+{
+    return spi_nor_program_buf(addr, data, len);
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_erase_block(void* block, unsigned int size)
+#else
+int spi_norflash_erase_block(void* block, unsigned int size)
+#endif
+{
+    return spi_nor_erase_block(block, size);
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+bool flash_code_overlaps(void *start, void *end)
+#else
+bool spi_norflash_code_overlaps(void *start, void *end)
+#endif
+{
+    extern unsigned char _stext[], _etext[];
+
+    return ((((unsigned long)&_stext >= (unsigned long)start) &&
+             ((unsigned long)&_stext < (unsigned long)end)) ||
+            (((unsigned long)&_etext >= (unsigned long)start) &&
+             ((unsigned long)&_etext < (unsigned long)end)));
+}
+
+#ifndef MXCFLASH_SELECT_MULTI
+int flash_hwr_map_error(int e)
+#else
+int spi_norflash_hwr_map_error(int e)
+#endif
+{
+    return e;
+}
+
+//----------------------------------------------------------------------------
+// Now that device properties are defined, include magic for defining
+// accessor type and constants.
+#include <cyg/io/flash_dev.h>
+
+// Information about supported devices
+typedef struct flash_dev_info {
+    cyg_uint8   device_id;
+    cyg_uint8   device_id2;
+    cyg_uint8   device_id3;
+    cyg_uint8   device_id4;
+    cyg_uint32  block_size;
+    cyg_int32   block_count;
+    cyg_uint32  device_size;
+    cyg_uint32  fis_start_addr;
+    cyg_uint8   vendor_info[96];
+} __attribute__((aligned(4),packed))flash_dev_info_t;
+
+static const flash_dev_info_t* flash_dev_info;
+static const flash_dev_info_t supported_devices[] = {
+#include <cyg/io/spi_nor_parts.inl>
+};
+
+#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
+
+#define ASSERT_SPI_NOR_INIT()       \
+    do {                                                                    \
+        if (spi_nor_init(&imx_spi_nor) != 0) {                              \
+            diag_printf("Error: failed to initialize SPI NOR\n");           \
+            return -1;                                                      \
+        }                                                                   \
+    } while (0);                                                            \
+
+int
+#ifndef MXCFLASH_SELECT_MULTI
+flash_hwr_init(void)
+#else
+spi_norflash_hwr_init(void)
+#endif
+{
+    cyg_uint8 id[4];
+    int i;
+
+    if (!spi_nor_init_ok) {
+        diag_printf("Initializing SPI-NOR flash...\n");
+        if (spi_nor_init(&imx_spi_nor) != 0) {
+            diag_printf("Error: failed to initialize SPI NOR\n");
+            return -1;
+        }
+        spi_nor_init_ok = 1;
+    }
+    // Look through table for device data
+    flash_dev_query(id);
+    flash_dev_info = supported_devices;
+    for (i = 0; i < NUM_DEVICES; i++) {
+        if ((flash_dev_info->device_id == id[0]) &&
+            (flash_dev_info->device_id2 == id[1]) &&
+            (flash_dev_info->device_id3 == id[2]))
+            break;
+        flash_dev_info++;
+    }
+
+    // Do we find the device? If not, return error.
+    if (NUM_DEVICES == i) {
+        diag_printf("Unrecognized SPI NOR part: 0x%02x, 0x%02x, 0x%02x\n",
+                    id[0], id[1], id[2]);
+        return FLASH_ERR_DRV_WRONG_PART;
+    }
+
+    // Hard wired for now
+    flash_info.block_size = flash_dev_info->block_size;
+    flash_info.blocks = flash_dev_info->block_count;
+    flash_info.start = (void *)0;
+    flash_info.end = (void *)flash_dev_info->device_size;
+
+    diag_printf("SPI NOR: block_size=0x%x, blocks=0x%x, start=%p, end=%p\n",
+               flash_info.block_size, flash_info.blocks,
+               flash_info.start, flash_info.end);
+
+    return FLASH_ERR_OK;
+}
+
+// used by redboot/current/src/flash.c
+int mxc_spi_nor_fis_start(void)
+{
+    return (flash_dev_info->fis_start_addr);
+}
+
+static int spi_nor_cmd_1byte(unsigned char cmd)
+{
+    g_tx_buf[0] = cmd;
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 1) != 0) {
+        diag_printf("Error: %s(): %d\n", __FUNCTION__, __LINE__);
+        return -1;
+    }
+    return 0;
+}
+
+/*!
+ * Read from SPI NOR at src address to RAM at dest with len bytes
+ * @param   src     source address in the flash
+ * @param   dest    destination address in the RAM
+ * @param   len     # of bytes to copy
+ */
+int spi_nor_read(void *src, void *dest, int len)
+{
+    unsigned int *cmd = (unsigned int *)g_tx_buf;
+    unsigned int max_rx_sz = imx_spi_nor.fifo_sz - 4; // max rx bytes per burst
+    unsigned char *d_buf = (unsigned char *) dest;
+    unsigned char *s_buf;
+    int i;
+
+    imx_spi_nor.us_delay = 100;
+    diag_printf1("%s(from flash=%p to ram=%p len=0x%x)\n", __FUNCTION__,
+                src, dest, len);
+
+    if (len == 0)
+        return 0;
+
+    *cmd = (READ << 24) | ((unsigned int)src & 0x00FFFFFF);
+
+    while (1) {
+        if (len == 0) {
+            imx_spi_nor.us_delay = 0;
+            return 0;
+        }
+        if (len < max_rx_sz) {
+            diag_printf1("last read len=0x%x\n", len);
+            // deal with the last read
+            if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, len + 4) != 0) {
+                diag_printf("Error: %s(%d): failed\n", __FILE__, __LINE__);
+                return -1;
+            }
+            s_buf = g_rx_buf + 4;   // throw away 4 bytes (5th received bytes is real)
+            // now adjust the endianness
+            for (i = len; i >= 0; i -= 4, s_buf += 4) {
+                if (i < 4) {
+                    if (i == 1) {
+                        *d_buf = s_buf[0];
+                    } else if (i == 2) {
+                        *d_buf++ = s_buf[1];
+                        *d_buf++ = s_buf[0];
+                    } else if (i == 3) {
+                        *d_buf++ = s_buf[2];
+                        *d_buf++ = s_buf[1];
+                        *d_buf++ = s_buf[0];
+                    }
+                    imx_spi_nor.us_delay = 0;
+                    return 0;
+                }
+                // copy 4 bytes
+                *d_buf++ = s_buf[3];
+                *d_buf++ = s_buf[2];
+                *d_buf++ = s_buf[1];
+                *d_buf++ = s_buf[0];
+            }
+        }
+        // now grab max_rx_sz data (+4 is needed due to 4-throw away bytes
+        if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, max_rx_sz + 4) != 0) {
+            diag_printf("Error: %s(%d): failed\n", __FILE__, __LINE__);
+            return -1;
+        }
+        s_buf = g_rx_buf + 4;   // throw away 4 bytes (5th received bytes is real)
+        // now adjust the endianness
+        for (i = 0; i < max_rx_sz; i += 4, s_buf += 4) {
+            *d_buf++ = s_buf[3];
+            *d_buf++ = s_buf[2];
+            *d_buf++ = s_buf[1];
+            *d_buf++ = s_buf[0];
+        }
+        *cmd += max_rx_sz;  // increase # of bytes in NOR address as cmd == g_tx_buf
+        len -= max_rx_sz;   // # of bytes left
+
+        diag_printf1("d_buf=%p, g_rx_buf=%p, len=0x%x\n", d_buf, g_rx_buf, len);
+    }
+
+    imx_spi_nor.us_delay = 0;
+}
+
+static int spi_nor_program_1byte(unsigned char data, void *addr)
+{
+    unsigned int addr_val = (unsigned int) addr;
+
+    // need to do write-enable command
+    if (WRITE_ENABLE() != 0) {
+        diag_printf("Error : %d\n", __LINE__);
+        return -1;
+    }
+    g_tx_buf[0] = BYTE_PROG;    // need to skip bytes 1, 2, 3
+    g_tx_buf[4] = data;
+    g_tx_buf[5] = addr_val & 0xFF;
+    g_tx_buf[6] = (addr_val >> 8) & 0xFF;
+    g_tx_buf[7] = (addr_val >> 16) & 0xFF;
+
+    diag_printf("0x%x: 0x%x\n", *(unsigned int*)g_tx_buf, *(unsigned int*)(g_tx_buf + 4));
+    diag_printf("addr=0x%x\n", addr_val);
+
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 5) != 0) {
+        diag_printf("Error: %s(%d): failed\n", __FILE__, __LINE__);
+        return -1;
+    }
+
+    while (spi_nor_status() & RDSR_BUSY) {
+    }
+    return 0;
+}
+
+/*!
+ * program data from RAM to flash
+ * @param addr          destination address in flash
+ * @param data          source address in RAM
+ * @param len           # of bytes to program
+ * Note: - when starting AAI programming, 
+ *       1) the starting addr has to be 16-bit aligned
+ *       2) the prog len has to be even number of bytes
+ */
+int spi_nor_program_buf(void *addr, void *data, int len)
+{
+    unsigned int d_addr = (unsigned int) addr;
+    unsigned char *s_buf = (unsigned char *) data;
+
+    if (len == 0)
+        return 0;
+
+    diag_printf1("%s(flash addr=%p, ram=%p, len=0x%x)\n", __FUNCTION__, addr, data, len);
+    imx_spi_nor.us_delay = 0;
+
+    if (ENABLE_WRITE_STATUS() != 0 || spi_nor_write_status(0) != 0) {
+        diag_printf("Error: %s: %d\n", __FUNCTION__, __LINE__);
+        return -1;
+    }
+
+    if ((d_addr & 1) != 0) {
+        // program 1st byte
+        if (spi_nor_program_1byte(s_buf[0], (void *)d_addr) != 0) {
+            diag_printf("Error: %s(%d)\n", __FUNCTION__, __LINE__);
+            return -1;
+        }
+        if (--len == 0)
+            return 0;
+        d_addr++;
+        s_buf++;
+    }
+
+    // need to do write-enable command
+    if (WRITE_ENABLE() != 0) {
+        diag_printf("Error : %d\n", __LINE__);
+        return -1;
+    }
+
+    // These two bytes write will be copied to txfifo first with
+    // g_tx_buf[1] being shifted out and followed by g_tx_buf[0].
+    // The reason for this is we will specify burst len=6. So SPI will
+    // do this kind of data movement.
+    g_tx_buf[0] = d_addr >> 16;
+    g_tx_buf[1] = AAI_PROG;    // need to skip bytes 1, 2
+    // byte shifted order is: 7, 6, 5, 4
+    g_tx_buf[4] = s_buf[1];
+    g_tx_buf[5] = s_buf[0];
+    g_tx_buf[6] = d_addr;
+    g_tx_buf[7] = d_addr >> 8;    
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 6) != 0) {
+        diag_printf("Error: %s(%d): failed\n", __FILE__, __LINE__);
+        return -1;
+    }
+
+    while (spi_nor_status() & RDSR_BUSY) {
+    }
+
+    for (d_addr += 2, s_buf += 2, len -= 2 ;
+         len > 1;
+         d_addr += 2, s_buf += 2, len -= 2) {
+        // byte shifted order is: 2,1,0
+        g_tx_buf[2] = AAI_PROG;
+        g_tx_buf[1] = s_buf[0];
+        g_tx_buf[0] = s_buf[1];
+
+        if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 3) != 0) {
+            diag_printf("Error: %s(%d): failed\n", __FILE__, __LINE__);
+            return -1;
+        }
+
+        while (spi_nor_status() & RDSR_BUSY) {
+        }
+        if ((len % flash_dev_info->block_size) == 0) {
+            diag_printf(".");
+        }
+    }
+    WRITE_DISABLE();
+    while (spi_nor_status() & RDSR_BUSY) {
+    }
+
+    if (WRITE_ENABLE() != 0) {
+        diag_printf("Error : %d\n", __LINE__);
+        return -1;
+    }
+    if (len == 1) {
+        // need to do write-enable command
+        // only 1 byte left
+        if (spi_nor_program_1byte(s_buf[0], (void *)d_addr) != 0) {
+            diag_printf("Error: %s(%d)\n", __FUNCTION__, __LINE__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int spi_nor_status(void)
+{
+    g_tx_buf[1] = RDSR;
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 2) != 0) {
+        diag_printf("Error: %s(): %d\n", __FUNCTION__, __LINE__);
+        return 0;
+    }
+    return g_rx_buf[0];
+}
+
+/*!
+ * Write 'val' to flash WRSR (write status register)
+ */
+static int spi_nor_write_status(unsigned char val)
+{
+    g_tx_buf[0] = val;
+    g_tx_buf[1] = WRSR;
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 2) != 0) {
+        diag_printf("Error: %s(): %d\n", __FUNCTION__, __LINE__);
+        return -1;
+    }
+    return 0;
+}
+
+/*!
+ * Erase a block_size data from block_addr offset in the flash
+ */
+int spi_nor_erase_block(void* block_addr, unsigned int block_size)
+{
+    unsigned int *cmd = (unsigned int *)g_tx_buf;
+    unsigned int addr = (unsigned int) block_addr;
+
+    imx_spi_nor.us_delay = 0;
+    
+    if (block_size != SZ_64K && block_size != SZ_32K && block_size != SZ_4K) {
+        diag_printf("Error - block_size is not 64kB: 0x%x\n", block_size);
+        return -1;
+    }
+
+    if ((addr & (block_size -1)) != 0) {
+        diag_printf("Error - block_addr is not 64kB aligned: %p\n", block_addr);
+        return -1;
+    }
+    if (ENABLE_WRITE_STATUS() != 0 || spi_nor_write_status(0) != 0) {
+        diag_printf("Error: %s: %d\n", __FUNCTION__, __LINE__);
+        return -1;
+    }
+
+    // need to do write-enable command
+    if (WRITE_ENABLE() != 0) {
+        diag_printf("Error : %d\n", __LINE__);
+        return -1;
+    }
+
+    if (block_size == SZ_64K) {
+        *cmd = (ERASE_64K << 24) | (addr & 0x00FFFFFF);
+    } else if (block_size == SZ_32K) {
+        *cmd = (ERASE_32K << 24) | (addr & 0x00FFFFFF);
+    } else if (block_size == SZ_4K) {
+        *cmd = (ERASE_4K << 24) | (addr & 0x00FFFFFF);
+    }
+
+    // now do the block erase
+    if (spi_nor_xfer(&imx_spi_nor, g_tx_buf, g_rx_buf, 4) != 0) {
+        return -1;
+    }
+
+    while (spi_nor_status() & RDSR_BUSY) {
+    }
+    return 0;
+}
+
+/*!
+ * Erase a variable bytes data from SPI NOR flash for 64K blocks
+ * @param block_addr        starting addresss in the SPI NOR flash
+ * @param size              # of bytes to erase
+ */
+int spi_nor_erase_64k(void* block_addr, unsigned int size)
+{
+    unsigned int addr = (unsigned int) block_addr;
+
+    if ((size % SZ_64K) != 0 || size == 0) {
+        diag_printf("Error: size (0x%x) is not integer multiples of 64kB(0x10000)\n", size);
+        return -1;
+    }
+    if ((addr & (SZ_64K -1)) != 0) {
+        diag_printf("Error - addr is not 64kB(0x10000) aligned: %p\n", block_addr);
+        return -1;
+    }
+    for (; size > 0; size -= SZ_64K, addr += SZ_64K) {
+        if (spi_nor_erase_block((void *)addr, SZ_64K) != 0) {
+            diag_printf("Error: spi_nor_erase_64k(): %d\n", __LINE__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+void spi_nor_setup(void)
+{
+    if (!spi_nor_init_ok) {
+        diag_printf("Initializing SPI-NOR flash...\n");
+        if (spi_nor_init(&imx_spi_nor) != 0) {
+            diag_printf("Error: failed to initialize SPI NOR\n");
+        }
+        spi_nor_init_ok = 1;
+    }
+}
+
+RedBoot_init(spi_nor_setup, RedBoot_INIT_PRIO(6800));
+
+////////////////////////////// commands ///////////////////
+static void do_spi_nor_op(int argc, char *argv[]);
+RedBoot_cmd("spiflash",
+            "Read/Write/Erase SPI NOR flash",
+            "<ram-addr> <flash-addr> <len-bytes> <r/w/e>",
+            do_spi_nor_op
+           );
+
+static void do_spi_nor_op(int argc,char *argv[])
+{
+    unsigned int ram, flash, len;
+    unsigned char op;
+    int stat = -1;
+
+    if (argc == 1 || argc != 5) {
+        diag_printf("\tRead:  spiflash <ram-addr> <flash-addr> <len-bytes> <r>\n");
+        diag_printf("\tWrite: spiflash <ram-addr> <flash-addr> <len-bytes> <w>\n");
+        diag_printf("\tErase: spiflash <ram-addr> <flash-addr> <len-bytes> <e>\n");
+        diag_printf("    NOTE: For erase, the ram-addr is ignored\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[1]), (unsigned long *)&ram, &argv[1], ":")) {
+        diag_printf("Error: Invalid ram parameter\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[2]), (unsigned long *)&flash, &argv[2], ":")) {
+        diag_printf("Error: Invalid flash parameter\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[3]), (unsigned long *)&len, &argv[3], ":")) {
+        diag_printf("Error: Invalid length parameter\n");
+        return;
+    }
+
+    op = argv[4][0];
+    switch (op) {
+    case 'r':
+    case 'R':
+        diag_printf("Reading SPI NOR flash 0x%x [0x%x bytes] -> ram 0x%x\n", flash, len, ram);
+        stat = spi_nor_read((void *)flash, (void *)ram, len);
+        break;
+    case 'w':
+    case 'W':
+        diag_printf("Writing SPI NOR flash 0x%x [0x%x bytes] <- ram 0x%x\n", flash, len, ram);
+        stat = spi_nor_program_buf((void *)flash, (void *)ram, len);
+        break;
+    case 'e':
+    case 'E':
+        diag_printf("Erasing SPI NOR flash 0x%x [0x%x bytes]\n", flash, len);
+        stat = spi_nor_erase_64k((void *)flash, len);
+        break;
+    default:
+        diag_printf("Error: unknown operation: 0x%02x\n", op);
+    }
+    diag_printf("%s\n\n", (stat == 0)? "SUCCESS": "FAILED");
+    return;
+}
diff --git a/packages/devs/i2c/arm/mxc/v2_0/cdl/mxc_i2c.cdl b/packages/devs/i2c/arm/mxc/v2_0/cdl/mxc_i2c.cdl
new file mode 100644 (file)
index 0000000..5d4fffa
--- /dev/null
@@ -0,0 +1,55 @@
+# ====================================================================
+#
+#      mxc_i2c.cdl
+#
+#      A Freescale MXC I2C package.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
+## Copyright (C) 2004 eCosCentric, Ltd
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Kevin Zhang
+# Contributors:
+# Date:           2006-08-23
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_MXC_I2C {
+    display     "I2C driver for FSL MXC-based platforms"
+
+    compile     -library=libextras.a mxc_i2c.c
+    
+    include_dir   cyg/io
+}
diff --git a/packages/devs/i2c/arm/mxc/v2_0/include/mxc_i2c.h b/packages/devs/i2c/arm/mxc/v2_0/include/mxc_i2c.h
new file mode 100644 (file)
index 0000000..2c76ef7
--- /dev/null
@@ -0,0 +1,83 @@
+//==========================================================================
+//
+//      mxc_i2c.h
+//
+//      I2C support on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+#ifndef __MXC_I2C_H__
+#define __MXC_I2C_H__
+
+#define I2C_AR                      0x0
+#define I2C_IFDR                    0x4
+#define I2C_I2CR                    0x8
+#define I2C_I2SR                    0xC
+#define I2C_I2DR                    0x10
+
+#define I2C_I2CR_IEN                (1 << 7)
+#define I2C_I2CR_IIEN               (1 << 6)
+#define I2C_I2CR_MSTA               (1 << 5)
+#define I2C_I2CR_MTX                (1 << 4)
+#define I2C_I2CR_TXAK               (1 << 3)
+#define I2C_I2CR_RSTA               (1 << 2)
+
+#define I2C_I2SR_ICF                (1 << 7)
+#define I2C_I2SR_IAAS               (1 << 6)
+#define I2C_I2SR_IBB                (1 << 5)
+#define I2C_I2SR_IAL                (1 << 4)
+#define I2C_I2SR_SRW                (1 << 2)
+#define I2C_I2SR_IIF                (1 << 1)
+#define I2C_I2SR_RXAK               (1 << 0)
+
+#define I2C_WRITE   0
+#define I2C_READ    1
+
+struct mxc_i2c_request {
+       unsigned int dev_addr;
+       unsigned int reg_addr;
+       unsigned int reg_addr_sz;
+       unsigned char * buffer;
+       unsigned int buffer_sz;
+};
+
+extern unsigned int i2c_base_addr[];
+extern unsigned int i2c_num;
+
+extern int i2c_init(unsigned int base, unsigned int baud);
+extern int i2c_xfer(unsigned int i2c_nr, struct mxc_i2c_request *rq, int dir);
+
+#endif                         /* __MXC_I2C_H__ */
diff --git a/packages/devs/i2c/arm/mxc/v2_0/src/mxc_i2c.c b/packages/devs/i2c/arm/mxc/v2_0/src/mxc_i2c.c
new file mode 100644 (file)
index 0000000..88c3d1d
--- /dev/null
@@ -0,0 +1,480 @@
+//==========================================================================
+//
+//      mxc_i2c.c
+//
+//      I2C support on Freescale MXC platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+#include <redboot.h>
+#include <stdlib.h>
+#include <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_io.h>
+
+#include <cyg/hal/fsl_board.h>
+#include <cyg/io/mxc_i2c.h>
+
+extern void mxc_i2c_init(unsigned int module_base);
+
+//#define MXC_I2C_DEBUG
+#undef MXC_I2C_DEBUG
+
+#ifdef MXC_I2C_DEBUG
+#define diag_printf1    diag_printf
+#else
+#define diag_printf1(fmt,args...)
+#endif
+
+struct clk_div_table {
+       int reg_value;
+       int div;
+};
+
+static const struct clk_div_table i2c_clk_table[] = {
+       {0x20, 22}, {0x21, 24}, {0x22, 26}, {0x23, 28},
+       {0, 30}, {1, 32}, {0x24, 32}, {2, 36},
+       {0x25, 36}, {0x26, 40}, {3, 42}, {0x27, 44},
+       {4, 48}, {0x28, 48}, {5, 52}, {0x29, 56},
+       {6, 60}, {0x2A, 64}, {7, 72}, {0x2B, 72},
+       {8, 80}, {0x2C, 80}, {9, 88}, {0x2D, 96},
+       {0xA, 104}, {0x2E, 112}, {0xB, 128}, {0x2F, 128},
+       {0xC, 144}, {0xD, 160}, {0x30, 160}, {0xE, 192},
+       {0x31, 192}, {0x32, 224}, {0xF, 240}, {0x33, 256},
+       {0x10, 288}, {0x11, 320}, {0x34, 320}, {0x12, 384},
+       {0x35, 384}, {0x36, 448}, {0x13, 480}, {0x37, 512},
+       {0x14, 576}, {0x15, 640}, {0x38, 640}, {0x16, 768},
+       {0x39, 768}, {0x3A, 896}, {0x17, 960}, {0x3B, 1024},
+       {0x18, 1152}, {0x19, 1280}, {0x3C, 1280}, {0x1A, 1536},
+       {0x3D, 1536}, {0x3E, 1792}, {0x1B, 1920}, {0x3F, 2048},
+       {0x1C, 2304}, {0x1D, 2560}, {0x1E, 3072}, {0x1F, 3840},
+       {0, 0}
+};
+
+#define ERR_TX             -1
+#define ERR_RX             -2
+#define ERR_ARB_LOST   -3
+#define ERR_NO_ACK         -4
+#define ERR_XFER           -5
+#define ERR_RX_ACK      -6
+
+static inline int wait_till_busy(unsigned int base)
+{
+    int i = 10000;
+
+    while(((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0) && (--i > 0)) {
+        if (readw(base + I2C_I2SR) & I2C_I2SR_IAL) {
+            diag_printf1("Error: arbitration lost!\n");
+            return ERR_ARB_LOST;
+        }
+    }
+
+    if (i <= 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static unsigned int g_dev_addr_width, g_dev_data_width;
+static unsigned char g_dev_value[4];
+static unsigned int g_i2c_nr = -1;
+
+static inline int is_bus_free(unsigned int base)
+{
+    return ((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0);
+}
+
+#define ASSERT_NO_ARBITRATION_LOST(stat)  \
+{ \
+       if (stat & I2C_I2SR_IAL) { \
+               diag_printf("Error %d: Arbitration lost\n", __LINE__); \
+               return ERR_ARB_LOST; \
+       } \
+}
+
+#define WAIT_RXAK_LOOPS     1000000
+
+static inline unsigned short wait_op_done(unsigned int base, int is_tx)
+{
+    volatile unsigned short v;
+    int i = WAIT_RXAK_LOOPS;
+
+    while ((((v = readw(base + I2C_I2SR)) & I2C_I2SR_IIF) == 0 ||
+           (v & I2C_I2SR_ICF) == 0) && --i > 0) {
+        if (v & I2C_I2SR_IAL) {
+            diag_printf1("Error %d: Arbitration lost\n", __LINE__);
+            return ERR_ARB_LOST;
+        }
+
+    }
+    if (i <= 0) {
+        diag_printf1("I2C Error: timeout unexpected\n");
+        return -1;
+    }
+    if (is_tx) {
+        if (v & I2C_I2SR_IAL) {
+            diag_printf1("Error %d: Arbitration lost\n", __LINE__);
+            return ERR_ARB_LOST;
+        }
+       if (v & I2C_I2SR_RXAK) {
+            diag_printf1("Error %d: no ack received\n", __LINE__);
+            return -1;
+       }
+    }
+    return 0;
+}
+
+//
+// For master TX, always expect a RXAK signal to be set!
+static int tx_byte(unsigned char *data, unsigned int base)
+{
+    diag_printf1("%s(data=0x%02x, base=0x%x)\n", __FUNCTION__, *data, base);
+
+    // clear both IAL and IIF bits
+    writew(0, base + I2C_I2SR);
+
+    writew(*data, base + I2C_I2DR);
+    
+    if (wait_op_done(base, 1) != 0)
+        return -1;
+
+    return 0;
+}
+
+// For master RX
+static int rx_bytes(unsigned char *data, unsigned int base, int sz)
+{
+    unsigned short i2cr;
+    int i;
+
+    for (i = 0; sz > 0; sz--, i++) {
+        if (wait_op_done(base, 0) != 0)
+            return -1;
+
+        // clear both IAL and IIF bits
+        writew(0, base + I2C_I2SR);
+
+        // the next two if-statements setup for the next read control register value
+        if (sz == 1) {
+            // last byte --> generate STOP
+            i2cr = readw(base + I2C_I2CR);
+            writew(i2cr & ~(I2C_I2CR_MSTA | I2C_I2CR_MTX), base + I2C_I2CR);
+        }
+        if (sz == 2) {
+            // 2nd last byte --> set TXAK bit to NOT generate ACK
+            i2cr = readw(base + I2C_I2CR);
+            writew(i2cr | I2C_I2CR_TXAK, base + I2C_I2CR);
+        }
+
+        // read the true data
+        data[i] = readw(base + I2C_I2DR);
+        diag_printf1("OK 0x%02x\n", data[i]);
+    }
+    return 0;
+}
+
+int i2c_xfer(unsigned int i2c_nr, struct mxc_i2c_request *rq, int dir)
+{
+    unsigned int base, reg;
+    unsigned char i, data;
+    unsigned short i2cr;
+    int ret = 0;
+    
+    if ( rq == NULL || i2c_nr >= i2c_num) {
+       diag_printf("Invalid request or invalid i2c port number\n");
+       return -1;
+    } 
+
+    base = i2c_base_addr[i2c_nr];
+    if (rq->reg_addr_sz == 0 || rq->buffer_sz == 0 || rq->buffer == NULL) {
+        diag_printf("Invalid register address size=%x, buffer size=%x, buffer=%x\n",
+                    rq->reg_addr_sz, rq->buffer_sz, (unsigned int)rq->buffer);
+        return -1;
+    }
+
+    // reset and enable I2C
+    writew(0, base + I2C_I2CR);
+
+    writew(I2C_I2CR_IEN, base + I2C_I2CR);
+
+    /* Need wait at least 2 cycles of per_clk*/
+    for (i = 0; i < 16; i++) {
+        asm("nop");
+    }
+    // Step 1: generate START signal
+    // 1.1 make sure bus is free
+    if (!is_bus_free(base)) {
+        return -1;
+    }
+    // 1.2 clear both IAL and IIF bits
+    writew(0, base + I2C_I2SR);
+
+    // 1.3 assert START signal and also indicate TX mode
+    i2cr = I2C_I2CR_IEN | I2C_I2CR_MSTA | I2C_I2CR_MTX;
+    writew(i2cr, base + I2C_I2CR);
+
+    // 1.4 make sure bus is busy after the START signal
+    if (wait_till_busy(base) != 0) {
+        return ERR_TX;
+    }
+
+    // Step 2: send slave address + read/write at the LSB
+    data = (rq->dev_addr << 1) | I2C_WRITE;
+    if (tx_byte(&data, base) != 0) {
+        return -1;
+    }
+
+    // Step 3: send I2C device register address
+    if (rq->reg_addr_sz > 4) {
+        diag_printf("Warning register address size %d should less than 4\n",
+                            rq->reg_addr_sz);
+        rq->reg_addr_sz = 4;
+    }
+    reg = rq->reg_addr;
+
+    for (i = 0; i <  rq->reg_addr_sz; i++, reg>>=8) {
+        data = reg & 0xFF;
+        diag_printf1("sending I2C=0x%x device register: data=0x%x, byte %d\n",
+                     base, data, i);
+        if (tx_byte(&data, base) != 0) {
+            return -1;
+        }
+    }
+    // Step 4: read/write data
+    if (dir == I2C_READ) {
+        // do repeat-start
+        i2cr = readw(base + I2C_I2CR);
+        writew(i2cr | I2C_I2CR_RSTA, base + I2C_I2CR);
+
+        // send slave address again, but indicate read operation
+        data = (rq->dev_addr << 1) | I2C_READ;
+        if (tx_byte(&data, base) != 0) {
+            return -1;
+        }
+
+        // change to receive mode
+        i2cr = readw(base + I2C_I2CR);
+        if (rq->buffer_sz == 1) {
+            // if only one byte to read, make sure don't send ack
+            i2cr |= I2C_I2CR_TXAK;
+        }
+        writew(i2cr & ~I2C_I2CR_MTX, base + I2C_I2CR);
+        // dummy read
+        readw(base + I2C_I2DR);
+
+        // now reading ...
+        if (rx_bytes(rq->buffer, base, rq->buffer_sz) != 0) {
+            return -1;
+        }
+    } else {
+        // I2C_WRITE
+        for (i = 0; i < rq->buffer_sz; i++) {
+            // send device register value
+            data = rq->buffer[i];
+            if ((ret = tx_byte(&data, base)) != 0) {
+                break;
+            }
+        }
+        // generate STOP by clearing MSTA bit
+        writew(I2C_I2CR_IEN | I2C_I2CR_MTX, base + I2C_I2CR);
+    }
+
+    return ret;
+}
+
+/*!
+ * Initialize and enable a i2c module -- mainly enable the I2C clock, module
+ * itself and the I2C clock prescaler.
+ *
+ * @param   base        base address of i2c module (also assigned for I2Cx_CLK)
+ * @param   baue        the desired data rate
+ *
+ * @return              0 if successful; non-zero otherwise
+ */
+int i2c_init(unsigned int base, unsigned int baud)
+{
+    unsigned int clock = get_main_clock(IPG_PER_CLK);
+    int div = clock / baud;
+    struct clk_div_table *p = (struct clk_div_table *)&i2c_clk_table[0];
+
+    mxc_i2c_init(base);
+
+    // reset and enable I2C
+    writew(0, base + I2C_I2CR);
+    writew(I2C_I2CR_IEN, base + I2C_I2CR);
+
+    while (p->div != 0) {
+        if (div <= p->div)
+            break;
+        p++;
+    }
+    
+    if (p->div == 0) {
+        diag_printf("Error: can't meet I2C baud rate request (%d) for 0x%x)\n",
+                    baud, base);
+        return -1;
+    }
+
+    diag_printf1("baud=%d, div=%d, reg_val=%d\n", baud, p->div, p->reg_value);
+
+    writew(p->reg_value, base + I2C_IFDR);
+
+    diag_printf1("requested data rate is: %d, actual rate is: %d\n",
+                 baud, clock / p->div);
+
+    return 0;
+}
+
+static void do_i2c(int argc, char *argv[]);
+RedBoot_cmd("i2c",
+            "i2c R/W operations as master",
+            "<i2c slave addr> <register index> [<regisetr val>]]",
+            do_i2c
+           );
+
+
+static void do_i2c(int argc,char *argv[])
+{
+    int dir = I2C_READ, i;
+    unsigned long v;
+    unsigned int dev_addr, dev_reg;
+    struct mxc_i2c_request rq;
+    if (g_i2c_nr == -1) {
+        diag_printf("I2C module [%d] not initialized. Issue i2c_init first\n\n", g_i2c_nr);
+        return;
+    }
+    if (argc == 1) {
+        diag_printf("\tRead:  i2c <i2c_dev_addr> <dev_reg_addr>\n");
+        diag_printf("\tWrite: i2c <i2c_dev_addr> <dev_reg_addr> <dev_reg_val>\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[1]), (unsigned long *)&dev_addr, &argv[1], ":")) {
+        diag_printf("Error: Invalid parameter %d\n", __LINE__);
+        return;
+    }
+
+    if (!parse_num(*(&argv[2]), (unsigned long *)&dev_reg, &argv[2], ":")) {
+        diag_printf("Error: Invalid parameter %d\n", __LINE__);
+        return;
+    }
+
+    if (argc == 4) {
+        if (!parse_num(*(&argv[3]), &v, &argv[3], ":")) {
+            diag_printf("Error: Invalid parameter\n");
+            return;
+        }
+        dir = I2C_WRITE;
+        diag_printf("Writing I2C[%d] for addr 0x%x register 0x%x with value 0x%08lx\n",
+                    g_i2c_nr, dev_addr, dev_reg, v);
+        for (i = 0; i < g_dev_data_width; i++) {
+            g_dev_value[i] = v >> (8 * (g_dev_data_width - i - 1)) & 0xff;
+        }
+        diag_printf1("testing reversed data: 0x%08x\n", *(unsigned int*)g_dev_value);
+
+    } else {
+        diag_printf("Reading I2C [%d] from slave addr [0x%x] register [0x%x]\n",
+                    g_i2c_nr, dev_addr,  dev_reg);
+    }
+
+    rq.dev_addr = dev_addr;
+    rq.reg_addr = dev_reg;
+    rq.reg_addr_sz = g_dev_addr_width;
+    rq.buffer = g_dev_value;
+    rq.buffer_sz = g_dev_data_width;
+
+    if (i2c_xfer(g_i2c_nr, &rq, dir) != 0) {
+        diag_printf("Error I2C transfer 1\n\n");
+        return;
+    }
+
+    if (dir == I2C_READ) {
+        diag_printf("--->  ");
+        for (i = 0; i < g_dev_data_width; i++) {
+            diag_printf("0x%02x ", g_dev_value[i]);
+        }
+        diag_printf("\n\n");
+    }
+}
+
+static void do_i2c_init(int argc, char *argv[]);
+RedBoot_cmd("i2c_init",
+            "Initialize i2c (i2c_num is 0-indexed)",
+            "<i2c_num> <frequency> <device addr width> <device reg width>",
+            do_i2c_init
+           );
+
+static void do_i2c_init(int argc,char *argv[])
+{
+    unsigned freq;
+
+    if (argc == 1 || argc != 5) {
+        diag_printf("\ni2c_init <i2c_num> <frequency> <device addr width> <device data width>\n\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[1]), (unsigned long *)&g_i2c_nr, &argv[1], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+    
+    if (g_i2c_nr > i2c_num - 1) {
+        diag_printf("invalide i2c number: %d, max number is: %d\n", g_i2c_nr, i2c_num - 1);
+        return;
+    }
+    diag_printf1("i2c max number is: %d\n", i2c_num - 1);
+
+    if (!parse_num(*(&argv[2]), (unsigned long *)&freq, &argv[2], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+    if (!parse_num(*(&argv[3]), (unsigned long *)&g_dev_addr_width, &argv[3], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+    if (!parse_num(*(&argv[4]), (unsigned long *)&g_dev_data_width, &argv[4], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+
+    i2c_init(i2c_base_addr[g_i2c_nr], freq);
+    
+    diag_printf("initializing i2c:%d, addr-width:%d, data-width:%d\n\n",
+                g_i2c_nr, g_dev_addr_width, g_dev_data_width);
+}
diff --git a/packages/devs/pmic/arm/mx25_3stack/v2_0/cdl/mc34704.cdl b/packages/devs/pmic/arm/mx25_3stack/v2_0/cdl/mc34704.cdl
new file mode 100644 (file)
index 0000000..260db5b
--- /dev/null
@@ -0,0 +1,85 @@
+# ====================================================================
+#
+#      mc34704.cdl
+#
+#      A PMIC package for i.MX25 3stack.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
+## Copyright (C) 2004 eCosCentric, Ltd
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Quinn Jensen
+# Contributors:
+# Date:           2008-05-08
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_PMIC_ARM_IMX25_3STACK {
+    display     "PMIC driver for i.MX25 3stack platforms"
+
+    compile     -library=libextras.a mc34704.c
+    
+    include_dir   cyg/io
+
+    define_proc {
+        puts $::cdl_header "#include <pkgconf/system.h>";
+    }
+
+    cdl_option  CYGHWR_DEVS_PMIC_I2C {
+       display "Support I2C interface to PMIC"
+       default_value 0
+       active_if CYGPKG_DEVS_MXC_I2C
+       description "
+               When this option is enabled, it enables i2c interface
+               to access pmic device on the i.MX25 3stack platform"
+       define_proc {
+               puts $::cdl_system_header "#define MXC_PMIC_I2C_ENABLED"
+       }
+    }
+
+    cdl_option CYGHWR_DEVS_PMIC_I2C_PORT {
+       display "I2C interface number to PMIC"
+       flavor  data
+       default_value 0
+       active_if CYGHWR_DEVS_PMIC_I2C
+    }
+
+    cdl_option CYGHWR_DEVS_PMIC_I2C_ADDR {
+       display "I2C addess of PMIC"
+       flavor  data
+       default_value 0
+       active_if CYGHWR_DEVS_PMIC_I2C
+    }
+}
diff --git a/packages/devs/pmic/arm/mx25_3stack/v2_0/include/mc34704.h b/packages/devs/pmic/arm/mx25_3stack/v2_0/include/mc34704.h
new file mode 100644 (file)
index 0000000..cb1d2f5
--- /dev/null
@@ -0,0 +1,47 @@
+//==========================================================================
+//
+//      mc34704.h
+//
+//      PMIC support on i.mx25 3stack platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+#ifndef __MC34704_H__
+#define __MC34704_H__
+
+unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write);
+
+#endif                         /* __MC34704_H__ */
diff --git a/packages/devs/pmic/arm/mx25_3stack/v2_0/src/mc34704.c b/packages/devs/pmic/arm/mx25_3stack/v2_0/src/mc34704.c
new file mode 100644 (file)
index 0000000..459b643
--- /dev/null
@@ -0,0 +1,137 @@
+//==========================================================================
+//
+//      mc34704.c
+//
+//      PMIC support on i.MX25 3stack platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+#include <redboot.h>
+#include <stdlib.h>
+#include <pkgconf/hal.h>
+#include <pkgconf/devs_pmic_arm_imx25_3stack.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/fsl_board.h>
+#include <cyg/io/mxc_i2c.h>
+#include <cyg/io/mc34704.h>
+
+#define MC34704_REG_MAX 0x59
+
+static void mxc_pmic_init(void)
+{
+       if (CYGHWR_DEVS_PMIC_I2C_PORT >= i2c_num) 
+               return;
+
+       i2c_init(i2c_base_addr[CYGHWR_DEVS_PMIC_I2C_PORT], 40000); 
+       
+       diag_printf("Turning on PMIC regulators: 1,2,3,4,5\n");
+
+       pmic_reg(0x02, 0x09, 1);
+}
+
+RedBoot_init(mxc_pmic_init, RedBoot_INIT_PRIO(100));
+
+static void do_pmic(int argc, char *argv[]);
+RedBoot_cmd("pmic",
+           "Read/Write internal PMIC register",
+           "<reg num> [value to be written]",
+           do_pmic);
+
+static void do_pmic(int argc,char *argv[])
+{
+       unsigned int reg, temp, val = 0, write = 0;
+
+       if (argc == 1) {
+               diag_printf("\tRead:  pmic <reg num>\n");
+               diag_printf("\tWrite: pmic <reg num> <value to be written>\n");
+               return;
+       }
+
+       if (!parse_num(*(&argv[1]), (unsigned long *)&reg, &argv[1], ":")) {
+               diag_printf("Error: Invalid parameter\n");
+               return;
+       }
+
+       if (argc == 3) {
+               if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
+                       diag_printf("Error: Invalid parameter\n");
+                       return;
+               }
+               write = 1;
+       }
+
+       temp = pmic_reg(reg, val, write);
+
+       diag_printf("\tval: 0x%08x\n\n", temp);
+}
+
+static unsigned int pmic_reg_i2c(unsigned int reg, unsigned int val, unsigned int write)
+{
+       struct mxc_i2c_request rq;
+       rq.dev_addr = CYGHWR_DEVS_PMIC_I2C_ADDR;
+       rq.reg_addr = reg;
+       rq.reg_addr_sz = 1;
+       rq.buffer = (unsigned char *)&val;
+       rq.buffer_sz = 1;
+       write =  write ? I2C_WRITE : I2C_READ;
+       if (i2c_xfer(CYGHWR_DEVS_PMIC_I2C_PORT, &rq, write) != 0) {
+               diag_printf("Error in I2C transaction\n\n");
+               return 0;
+       }
+       return val;     
+}
+
+/*!
+ * To read/write to a PMIC register. For write, it does another read for the
+ * actual register value.
+ *
+ * @param   reg         register number inside the PMIC
+ * @param   val         data to be written to the register; don't care for read
+ * @param   write       0 for read; 1 for write
+ *
+ * @return              the actual data in the PMIC register
+ */
+unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write)
+{
+       if (reg > MC34704_REG_MAX) {
+               diag_printf("<reg num> = %d is invalid. Should be less than %d\n",
+                       reg, MC34704_REG_MAX);
+               return 0;
+       }
+       return pmic_reg_i2c(reg, val, write);
+}
diff --git a/packages/devs/pmic/arm/mx35_3stack/v2_0/cdl/mc9s08dz.cdl b/packages/devs/pmic/arm/mx35_3stack/v2_0/cdl/mc9s08dz.cdl
new file mode 100644 (file)
index 0000000..d359412
--- /dev/null
@@ -0,0 +1,105 @@
+# ====================================================================
+#
+#      mc9s08dz.cdl
+#
+#      A PMIC package for i.MX35 3stack.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
+## Copyright (C) 2004 eCosCentric, Ltd
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):     Fred Fan 
+# Contributors:
+# Date:           2008-05-08
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_PMIC_ARM_IMX35_3STACK {
+    display     "PMIC driver for i.MX35 3stack platforms"
+
+    compile     -library=libextras.a mc9s08dz.c
+    
+    include_dir   cyg/io
+
+    define_proc {
+        puts $::cdl_header "#include <pkgconf/system.h>";
+    }
+
+    cdl_option CYGHWR_DEVS_PMIC_SPI {
+       display "Support SPI interface to PMIC"
+       default_value 0
+       active_if CYGPKG_DEVS_MXC_SPI
+
+       description "
+               When this option is enabled, it enables spi interface
+               to access pmic device on the i.MX35 3stack platform"
+       define_proc {
+               puts $::cdl_system_header "#define MXC_PMIC_SPI_ENABLED"
+       }
+    }
+    
+    cdl_option CYGHWR_DEVS_PMIC_SPI_PORT {
+       display "SPI interface number to PMIC"
+       flavor  data
+       default_value 0
+       active_if CYGHWR_DEVS_PMIC_SPI
+    }
+
+    cdl_option  CYGHWR_DEVS_PMIC_I2C {
+       display "Support I2C interface to PMIC"
+       default_value 0
+       active_if CYGPKG_DEVS_MXC_I2C
+       description "
+               When this option is enabled, it enables i2c interface
+               to access pmic device on the i.MX35 3stack platform"
+       define_proc {
+               puts $::cdl_system_header "#define MXC_PMIC_I2C_ENABLED"
+       }
+    }
+
+    cdl_option CYGHWR_DEVS_PMIC_I2C_PORT {
+       display "I2C interface number to PMIC"
+       flavor  data
+       default_value 0
+       active_if CYGHWR_DEVS_PMIC_I2C
+    }
+
+    cdl_option CYGHWR_DEVS_PMIC_I2C_ADDR {
+       display "I2C addess of PMIC"
+       flavor  data
+       default_value 0
+       active_if CYGHWR_DEVS_PMIC_I2C
+    }
+}
diff --git a/packages/devs/pmic/arm/mx35_3stack/v2_0/include/mc9s08dz.h b/packages/devs/pmic/arm/mx35_3stack/v2_0/include/mc9s08dz.h
new file mode 100644 (file)
index 0000000..f581a1e
--- /dev/null
@@ -0,0 +1,49 @@
+//==========================================================================
+//
+//      mc9s08dz.h
+//
+//      PMIC support on i.mx35 3stack platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+#ifndef __MC9S08DZ_H__
+#define __MC9S08DZ_H__
+
+#define MC9S08DZ_MAX_REGS 0x28
+
+unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write);
+
+#endif                         /* __MC9S08DZ_H__ */
diff --git a/packages/devs/pmic/arm/mx35_3stack/v2_0/src/mc9s08dz.c b/packages/devs/pmic/arm/mx35_3stack/v2_0/src/mc9s08dz.c
new file mode 100644 (file)
index 0000000..c325fa1
--- /dev/null
@@ -0,0 +1,212 @@
+//==========================================================================
+//
+//      mc9s08dz.c
+//
+//      PMIC support on i.MX35 3stack platforms
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+#include <redboot.h>
+#include <stdlib.h>
+#include <pkgconf/hal.h>
+#include <pkgconf/devs_pmic_arm_imx35_3stack.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/fsl_board.h>
+#ifdef MXC_PMIC_I2C_ENABLED
+#include <cyg/io/mxc_i2c.h>
+#endif                          // MXC_PMIC_I2C_ENABLED
+#include <cyg/io/mc9s08dz.h>
+
+extern unsigned int system_rev;
+
+static void mxc_pmic_init(void)
+{
+    volatile unsigned int rev_id;
+
+#ifdef MXC_PMIC_I2C_ENABLED
+    if (CYGHWR_DEVS_PMIC_I2C_PORT >= i2c_num)
+        return;
+// 40kHz data rate
+    i2c_init(i2c_base_addr[CYGHWR_DEVS_PMIC_I2C_PORT], 40000);
+#else
+#error "Please select a valid interface"
+#endif                          // MXC_PMIC_I2C_ENABLED
+
+    rev_id = pmic_reg(0, 0, 0);
+    diag_printf("PMIC ID: 0x%08x [Rev: ", rev_id);
+    switch (rev_id & 0x1F) {
+    case 0x10:
+        diag_printf("1.0");
+        break;
+    default:
+        diag_printf("unknown");
+        break;
+    }
+    diag_printf("]\n");
+}
+
+RedBoot_init(mxc_pmic_init, RedBoot_INIT_PRIO(100));
+
+static void do_pmic(int argc, char *argv[]);
+RedBoot_cmd("pmic",
+            "Read/Write internal PMIC register",
+            "<reg num> [value to be written]", do_pmic);
+
+static void do_pmic(int argc, char *argv[])
+{
+    unsigned int reg, temp, val = 0, write = 0;
+
+    if (argc == 1) {
+        diag_printf("\tRead:  pmic <reg num>\n");
+        diag_printf("\tWrite: pmic <reg num> <value to be written>\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[1]), (unsigned long *)&reg, &argv[1], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+
+    if (argc == 3) {
+        if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
+            diag_printf("Error: Invalid parameter\n");
+            return;
+        }
+        write = 1;
+    }
+
+    temp = pmic_reg(reg, val, write);
+
+    diag_printf("\tval: 0x%08x\n\n", temp);
+}
+
+#ifdef MXC_PMIC_I2C_ENABLED
+static unsigned int pmic_reg_i2c(unsigned int reg, unsigned int val,
+                                 unsigned int write)
+{
+    struct mxc_i2c_request rq;
+    rq.dev_addr = CYGHWR_DEVS_PMIC_I2C_ADDR;
+    rq.reg_addr = reg;
+    rq.reg_addr_sz = 1;
+    rq.buffer = (unsigned char *)&val;
+    rq.buffer_sz = 1;
+    write = write ? I2C_WRITE : I2C_READ;
+    if (i2c_xfer(CYGHWR_DEVS_PMIC_I2C_PORT, &rq, write) != 0) {
+        diag_printf("Error I2C transfer\n\n");
+        return 0;
+    }
+    return val;
+}
+#endif                          //MXC_PMIC_I2C_ENABLED
+/*!
+ * To read/write to a PMIC register. For write, it does another read for the
+ * actual register value.
+ *
+ * @param   reg         register number inside the PMIC
+ * @param   val         data to be written to the register; don't care for read
+ * @param   write       0 for read; 1 for write
+ *
+ * @return              the actual data in the PMIC register
+ */
+unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write)
+{
+    if (reg > MC9S08DZ_MAX_REGS) {
+        diag_printf("<reg num> = %d is invalide. Should be less then 0x28\n",
+                    reg);
+        return 0;
+    }
+#ifdef MXC_PMIC_I2C_ENABLED
+    return pmic_reg_i2c(reg, val, write);
+#else
+    return 0;
+#endif                          //MXC_PMIC_I2C_ENABLED
+}
+
+static void mxc_pmic_detect(void)
+{
+    struct mxc_i2c_request rq;
+    unsigned char buf[4] = { 0 };
+
+    rq.dev_addr = 0x34;
+    rq.reg_addr = 0x10;
+    rq.reg_addr_sz = 1;
+    rq.buffer = buf;
+    rq.buffer_sz = 1;
+
+    if (i2c_xfer(0, &rq, I2C_WRITE) != 0) {
+        /* v2.0 board which does not have max8660 */
+        system_rev |= 0x1 << 8;
+        /* workaround for WDOG reset pin */
+        writel(0x11, IOMUXC_BASE_ADDR + 0xC);
+        diag_printf("Board version V2.0\n");
+    } else {
+        diag_printf("Board version V1.0\n");
+    }
+
+#ifdef CYGPKG_DEVS_ETH_FEC
+    /**
+     * if we have v2.0 board, need to enable
+     * APLite VGEN1 regulator
+     */
+    if (system_rev & 0xF00) {
+        /* set VGEN voltage to 3.3v */
+        rq.dev_addr = 0x08;
+        rq.reg_addr = 0x1E;     /* VGEN REG0 setting */
+        rq.reg_addr_sz = 1;
+        rq.buffer = buf;
+        rq.buffer_sz = 3;
+        i2c_xfer(0, &rq, I2C_READ);
+        rq.buffer_sz = 3;
+        buf[2] |= 0x3;
+        i2c_xfer(0, &rq, I2C_WRITE);
+        /* enable FEC 3v3 */
+        rq.dev_addr = 0x08;
+        rq.reg_addr = 0x20;     /* VGEN REG0 */
+        rq.reg_addr_sz = 1;
+        rq.buffer = buf;
+        rq.buffer_sz = 3;
+        i2c_xfer(0, &rq, I2C_READ);
+        rq.buffer_sz = 3;
+        buf[2] |= 0x1;
+        i2c_xfer(0, &rq, I2C_WRITE);
+    }
+#endif
+
+}
+
+RedBoot_init(mxc_pmic_detect, RedBoot_INIT_PRIO(101));
diff --git a/packages/devs/spi/arm/imx/v2_0/cdl/spi.cdl b/packages/devs/spi/arm/imx/v2_0/cdl/spi.cdl
new file mode 100644 (file)
index 0000000..56a474d
--- /dev/null
@@ -0,0 +1,56 @@
+# ====================================================================
+#
+#      spi.cdl
+#
+#      A Freescale i.MX SPI package.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
+## Copyright (C) 2004 eCosCentric, Ltd
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Kevin Zhang
+# Contributors:
+# Date:           2008-11-14
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_IMX_SPI {
+    display     "SPI driver for FSL i.MX based platforms"
+
+    compile     -library=libextras.a imx_spi.c
+
+    include_dir   cyg/io
+
+}
diff --git a/packages/devs/spi/arm/imx/v2_0/include/imx_spi.h b/packages/devs/spi/arm/imx/v2_0/include/imx_spi.h
new file mode 100644 (file)
index 0000000..a6e1e57
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __IMX_SPI_H__
+#define __IMX_SPI_H__
+
+#undef IMX_SPI_DEBUG
+//#define IMX_SPI_DEBUG
+
+#ifdef IMX_SPI_DEBUG
+#define diag_printf1    diag_printf
+#else
+#define diag_printf1(fmt,args...)
+#endif
+
+#define IMX_SPI_ACTIVE_HIGH     1
+#define IMX_SPI_ACTIVE_LOW      0
+#define SPI_RETRY_TIMES         100
+
+// Only for SPI master support
+struct imx_spi_dev {
+    unsigned int base;      // base address of SPI module the device is connected to
+    unsigned int freq;      // desired clock freq in Hz for this device
+    unsigned int ss_pol;    // ss polarity: 1=active high; 0=active low
+    unsigned int ss;        // slave select
+    unsigned int in_sctl;   // inactive sclk ctl: 1=stay low; 0=stay high
+    unsigned int in_dctl;   // inactive data ctl: 1=stay low; 0=stay high
+    unsigned int ssctl;     // single burst mode vs multiple: 0=single; 1=multi
+    unsigned int sclkpol;   // sclk polarity: active high=0; active low=1
+    unsigned int sclkpha;   // sclk phase: 0=phase 0; 1=phase1
+    unsigned int fifo_sz;   // fifo size in bytes for either tx or rx. Don't add them up!
+    unsigned int us_delay;  // us delay in each xfer
+    void *reg;              // pointer to a set of SPI registers
+};
+
+struct spi_v2_3_reg {
+    unsigned int ctrl_reg;
+    unsigned int cfg_reg;
+};
+
+// setup IOMUX for the spi device
+// 
+int imx_spi_init_v2_3 (
+    struct imx_spi_dev *dev
+    );
+
+// transfer up to fifo bytes data via spi. The data transferred is the sum of both the tx and rx
+int imx_spi_xfer_v2_3 (
+    struct imx_spi_dev *dev,    // spi device pointer
+    unsigned char *tx_buf,      // tx buffer (has to be 4-byte aligned)
+    unsigned char *rx_buf,      // rx buffer (has to be 4-byte aligned)
+    int burst_bytes             // total number of bytes in one burst or xfer
+    );
+
+typedef int imx_spi_init_func_t(struct imx_spi_dev *);
+typedef int imx_spi_xfer_func_t(struct imx_spi_dev *, unsigned char *, unsigned char *, int);
+
+unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write);
+
+void io_cfg_spi(struct imx_spi_dev *dev);
+
+#endif // __IMX_SPI_H__
diff --git a/packages/devs/spi/arm/imx/v2_0/src/imx_spi.c b/packages/devs/spi/arm/imx/v2_0/src/imx_spi.c
new file mode 100644 (file)
index 0000000..a064cf2
--- /dev/null
@@ -0,0 +1,452 @@
+#include <redboot.h>
+#include <stdlib.h>
+#include <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_io.h>
+
+#include <cyg/hal/fsl_board.h>
+#include <cyg/io/imx_spi.h>
+
+/*!
+ * Initialization function for a spi slave device. It must be called BEFORE
+ * any spi operations. The SPI module will be -disabled- after this call.
+ */
+int imx_spi_init_v2_3 (struct imx_spi_dev *dev)
+{
+    unsigned int clk_src = get_peri_clock(dev->base);
+    unsigned int pre_div = 0, post_div = 0, i, reg_ctrl, reg_config;
+    struct spi_v2_3_reg *reg = (struct spi_v2_3_reg *)dev->reg;
+
+    if (dev->freq == 0) {
+        diag_printf("Error: desired clock is 0\n");
+        return -1;
+    }
+    // iomux config
+    io_cfg_spi(dev);
+
+    reg_ctrl = readl(dev->base + 0x8);
+    // reset the spi
+    writel(0, dev->base + 0x8);
+    writel(reg_ctrl | 0x1, dev->base + 0x8);
+
+    // control register setup
+    if (clk_src > dev->freq) {
+        pre_div = clk_src / dev->freq;
+        if (pre_div > 16) {
+            post_div = pre_div / 16;
+            pre_div = 15;
+        }
+        if (post_div != 0) {
+            for (i = 0; i < 16; i++) {
+                if ((1 << i) >= post_div)
+                    break;
+            }
+            if (i == 16) {
+                diag_printf("Error: no divider can meet the freq: %d\n",
+                            dev->freq);
+                return -1;
+            }
+            post_div = i;
+        }
+    }
+    diag_printf1("pre_div = %d, post_div=%d\n", pre_div, post_div);
+    reg_ctrl = (reg_ctrl & ~(3 << 18)) | dev->ss << 18;
+    reg_ctrl = (reg_ctrl & ~(0xF << 12)) | pre_div << 12;
+    reg_ctrl = (reg_ctrl & ~(0xF << 8)) | post_div << 8;
+    reg_ctrl |= 1 << (dev->ss + 4);     // always set to master mode !!!!
+    reg_ctrl &= ~0x1;                   // disable spi
+
+    reg_config = readl(dev->base + 0xC);
+    // configuration register setup
+    reg_config = (reg_config & ~(1 << ((dev->ss + 12)))) |
+        (dev->ss_pol << (dev->ss + 12));
+    reg_config = (reg_config & ~(1 << ((dev->ss + 20)))) |
+        (dev->in_sctl << (dev->ss + 20));
+    reg_config = (reg_config & ~(1 << ((dev->ss + 16)))) |
+        (dev->in_dctl << (dev->ss + 16));
+    reg_config = (reg_config & ~(1 << ((dev->ss + 8)))) |
+        (dev->ssctl << (dev->ss + 8));
+    reg_config = (reg_config & ~(1 << ((dev->ss + 4)))) |
+        (dev->sclkpol << (dev->ss + 4));
+    reg_config = (reg_config & ~(1 << ((dev->ss + 0)))) |
+        (dev->sclkpha << (dev->ss + 0));
+
+    diag_printf1("reg_ctrl = 0x%x\n", reg_ctrl);
+    writel(reg_ctrl, dev->base + 0x8);
+    diag_printf1("reg_config = 0x%x\n", reg_config);
+    writel(reg_config, dev->base + 0xC);
+    // save config register and control register
+    reg->cfg_reg = reg_config;
+    reg->ctrl_reg = reg_ctrl;
+
+    // clear interrupt reg
+    writel(0, dev->base + 0x10);
+    writel(3 << 6, dev->base + 0x18);
+
+    return 0;
+}
+
+/*!
+ * This function should only be called after the imx_spi_init_xxx().
+ * It sets up the spi module according to the initialized value and then
+ * enables the SPI module. This function is called by the xfer function.
+ *
+ * Note: If one wants to change the SPI parameters such as clock, the 
+ *       imx_spi_init_xxx() needs to be called again.
+ */
+static void spi_start_v2_3(struct imx_spi_dev *dev,
+                           struct spi_v2_3_reg *reg, int len)
+{
+    if (reg->ctrl_reg == 0) {
+        diag_printf("Error: spi(base=0x%x) has not been initialized yet\n",
+                    dev->base);
+        return;
+    }
+    // iomux config
+    io_cfg_spi(dev);
+    reg->ctrl_reg = (reg->ctrl_reg & ~0xFFF00000) | ((len * 8 - 1) << 20);
+
+    writel(reg->ctrl_reg | 0x1, dev->base + 0x8);
+    writel(reg->cfg_reg, dev->base + 0xC);
+    diag_printf1("ctrl_reg=0x%x, cfg_reg=0x%x\n",
+                 readl(dev->base + 0x8), readl(dev->base + 0xC));
+}
+
+/*!
+ * Stop the SPI module that the slave device is connected to.
+ */
+static void spi_stop_v2_3(struct imx_spi_dev *dev)
+{
+    writel(0, dev->base + 0x8);
+}
+
+/*!
+ * Transfer up to burst_bytes bytes data via spi. The amount of data
+ * is the sum of both the tx and rx.
+ * After this call, the SPI module that the slave is connected to will
+ * be -disabled- again.
+ */
+int imx_spi_xfer_v2_3 (
+    struct imx_spi_dev *dev,    // spi device pointer
+    unsigned char *tx_buf,      // tx buffer (has to be 4-byte aligned)
+    unsigned char *rx_buf,      // rx buffer (has to be 4-byte aligned)
+    int burst_bytes             // total number of bytes in one burst (or xfer)
+    )
+{
+    int val = SPI_RETRY_TIMES;
+    unsigned int *p_buf;
+    unsigned int reg;
+    int len, ret_val = 0;
+
+    if (burst_bytes > dev->fifo_sz) {
+        diag_printf("Error: maximum burst size is 0x%x bytes, asking 0x%x\n",
+                    dev->fifo_sz, burst_bytes);
+        return -1;
+    }
+
+    spi_start_v2_3(dev, dev->reg, burst_bytes);
+
+    // move data to the tx fifo
+    for (p_buf = (unsigned int *)tx_buf, len = burst_bytes; len > 0;
+         p_buf++, len -= 4) {
+        writel(*p_buf, dev->base + 0x4);
+    }
+    reg = readl(dev->base + 0x8);
+    reg |= (1 << 2); // set xch bit
+    diag_printf1("control reg = 0x%08x\n", reg);
+    writel(reg, dev->base + 0x8);
+
+    // poll on the TC bit (transfer complete)
+    while ((val-- > 0) && (readl(dev->base + 0x18) & (1 << 7)) == 0) {
+        if (dev->us_delay != 0) {
+            hal_delay_us(dev->us_delay);
+        }
+    }
+
+    // clear the TC bit
+    writel(3 << 6, dev->base + 0x18);
+    if (val == 0) {
+        diag_printf("Error: re-tried %d times without response. Give up\n", SPI_RETRY_TIMES);
+        ret_val = -1;
+        goto error;
+    }
+
+    // move data in the rx buf
+    for (p_buf = (unsigned int *)rx_buf, len = burst_bytes; len > 0;
+         p_buf++, len -= 4) {
+        *p_buf = readl(dev->base + 0x0);
+    }
+error:
+    spi_stop_v2_3(dev);
+    return ret_val;
+}
+
+#ifdef PMIC_SPI_BASE
+extern imx_spi_init_func_t *spi_pmic_init;
+extern imx_spi_xfer_func_t *spi_pmic_xfer;
+extern struct imx_spi_dev imx_spi_pmic;
+
+static void show_pmic_info(void)
+{
+    volatile unsigned int rev_id;
+
+    spi_pmic_init(&imx_spi_pmic);
+    rev_id = pmic_reg(7, 0, 0);
+    diag_printf("PMIC ID: 0x%08x [Rev: ", rev_id);
+    switch (rev_id & 0x1F) {
+    case 0x1:
+        diag_printf("1.0");
+        break;
+    case 0x9:
+        diag_printf("1.1");
+        break;
+    case 0xA:
+        diag_printf("1.2");
+        break;
+    case 0x10:
+        diag_printf("2.0");
+        break;
+    case 0x11:
+        diag_printf("2.1");
+        break;
+    case 0x18:
+        diag_printf("3.0");
+        break;
+    case 0x19:
+        diag_printf("3.1");
+        break;
+    case 0x1A:
+        diag_printf("3.2");
+        break;
+    case 0x2:
+        diag_printf("3.2A");
+        break;
+    case 0x1B:
+        diag_printf("3.3");
+        break;
+    case 0x1D:
+        diag_printf("3.5");
+        break;
+    default:
+        diag_printf("unknown");
+        break;
+    }
+    diag_printf("]\n");
+}
+
+RedBoot_init(show_pmic_info, RedBoot_INIT_PRIO(100));
+
+static void do_pmic(int argc, char *argv[]);
+RedBoot_cmd("pmic",
+            "Read/Write internal PMIC register",
+            "<reg num> [value to be written]",
+            do_pmic
+           );
+
+static void do_pmic(int argc, char *argv[])
+{
+    unsigned int reg, temp, val = 0, write = 0;
+
+    if (argc == 1) {
+        diag_printf("\tRead:  pmic <reg num>\n");
+        diag_printf("\tWrite: pmic <reg num> <value to be written>\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[1]), (unsigned long *)&reg, &argv[1], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+
+    if (argc == 3) {
+        if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
+            diag_printf("Error: Invalid parameter\n");
+            return;
+        }
+        write = 1;
+    }
+
+    spi_pmic_init(&imx_spi_pmic);
+    temp = pmic_reg(reg, val, write);
+
+    diag_printf("\tval: 0x%08x\n\n", temp);
+}
+
+static unsigned int pmic_tx, pmic_rx;
+/*!
+ * To read/write to a PMIC register. For write, it does another read for the
+ * actual register value.
+ *
+ * @param   reg         register number inside the PMIC
+ * @param   val         data to be written to the register; don't care for read
+ * @param   write       0 for read; 1 for write
+ *
+ * @return              the actual data in the PMIC register
+ */
+unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write)
+{
+    if (reg > 63 || write > 1 ) {
+        diag_printf("<reg num> = %d is invalide. Should be less then 63\n", reg);
+        return 0;
+    }
+    pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
+    diag_printf1("reg=0x%x, val=0x%08x\n", reg, pmic_tx);
+
+    spi_pmic_xfer(&imx_spi_pmic, (unsigned char *)&pmic_tx,
+                  (unsigned char *)&pmic_rx, 4);
+
+    if (write) {
+        pmic_tx &= ~(1 << 31);
+        spi_pmic_xfer(&imx_spi_pmic, (unsigned char *)&pmic_tx,
+                      (unsigned char *)&pmic_rx, 4);
+    }
+
+    return pmic_rx;
+}
+#endif // PMIC_SPI_BASE
+
+#ifdef CPLD_SPI_BASE
+
+unsigned int spi_cpld_xchg_single(unsigned int data, unsigned int data1, unsigned int base)
+{
+    volatile unsigned int cfg_reg = readl(base + SPI_CTRL_REG_OFF);
+    unsigned int temp;
+
+    /* Activate the SS signal */
+    cfg_reg |= CPLD_SPI_CHIP_SELECT_NO;
+    writel(cfg_reg, CPLD_SPI_BASE + SPI_CTRL_REG_OFF);
+
+    /* Write the data */
+    writel(data, base + SPI_TX_REG_OFF);
+    writel(data1, base + SPI_TX_REG_OFF);
+
+    cfg_reg |= SPI_CTRL_REG_XCH_BIT;
+    writel(cfg_reg, base + SPI_CTRL_REG_OFF);
+
+    while ((((cfg_reg = readl(base + SPI_TEST_REG_OFF)) &
+              SPI_TEST_REG_RXCNT_MASK) >> SPI_TEST_REG_RXCNT_OFFSET) != 2) {
+    }
+
+    /* Deactivate the SS signal */
+    cfg_reg = readl(base + SPI_CTRL_REG_OFF);
+    cfg_reg &= ~SPI_CTRL_CS_MASK;
+    writel(cfg_reg, base + SPI_CTRL_REG_OFF);
+
+    /* Read from RX FIFO, second entry contains the data */
+    temp = readl(base + SPI_RX_REG_OFF);
+    temp = readl(base + SPI_RX_REG_OFF);
+    return ((temp >> 6) & 0xffff);
+}
+
+static void mxc_cpld_spi_init(void)
+{
+    unsigned int ctrl;
+
+    ctrl = SPI_CTRL_REG_BIT_COUNT46 | CPLD_SPI_CTRL_MODE_MASTER | SPI_CTRL_EN;
+
+    spi_init(CPLD_SPI_BASE, 18000000,      // 54MHz data rate
+             ctrl);
+}
+
+RedBoot_init(mxc_cpld_spi_init, RedBoot_INIT_PRIO(102));
+
+static void do_cpld(int argc, char *argv[]);
+
+RedBoot_cmd("spi_cpld",
+            "Read/Write 16-bit internal CPLD register over CSPI",
+            "<reg num> [16-bit value to be written]",
+            do_cpld
+           );
+
+static void do_cpld(int argc,char *argv[])
+{
+    unsigned int reg, temp, val = 0, read = 1;
+
+    if (argc == 1) {
+        diag_printf("\tRead:  spi_cpld <reg num>\n");
+        diag_printf("\tWrite: spi_cpld <reg num> <value to be written>\n");
+        return;
+    }
+
+    if (!parse_num(*(&argv[1]), (unsigned long *)&reg, &argv[1], ":")) {
+        diag_printf("Error: Invalid parameter\n");
+        return;
+    }
+
+    if (argc == 3) {
+        if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
+            diag_printf("Error: Invalid parameter\n");
+            return;
+        }
+        read = 0;
+    }
+
+    mxc_cpld_spi_init();
+    temp = cpld_reg(reg, val, read);
+
+    diag_printf("\tval: 0x%04x\n\n", temp);
+}
+
+/*!
+ * To read/write to a CPLD register.
+ *
+ * @param   reg         register number inside the CPLD
+ * @param   val         data to be written to the register; don't care for read
+ * @param   read        0 for write; 1 for read
+ *
+ * @return              the actual data in the CPLD register
+ */
+unsigned int cpld_reg_xfer(unsigned int reg, unsigned int val, unsigned int read)
+{
+    unsigned int local_val1, local_val2;
+
+    reg >>= 1;
+
+    local_val1 = (read << 13) | ((reg & 0x0001FFFF) >> 5) | 0x00001000;
+    if (read) {
+        //local_val1 = (read << 22) | (reg << 4) | 0x00200004;
+        //local_val2 = 0x1F;
+        local_val2 = ( ((reg & 0x0000001F) << 27) | 0x0200001f);
+
+    } else {
+        //local_val1 = (read << 22) | (reg << 4) | 0x00200007;
+        //local_val2 = ((val & 0xFFFF) << 6) | 0x00400027;
+        local_val2 = ( ((reg & 0x0000001F) << 27) | ((val & 0x0000FFFF) << 6) | 0x03C00027);
+
+    }
+
+    diag_printf1("reg=0x%x, val=0x%08x\n", reg, val);
+    return spi_cpld_xchg_single(local_val1, local_val2, CPLD_SPI_BASE);
+}
+
+/*!
+ * To read/write to a CPLD register. For write, it does another read for the
+ * actual register value.
+ *
+ * @param   reg         register number inside the CPLD
+ * @param   val         data to be written to the register; don't care for read
+ * @param   read        0 for write; 1 for read
+ *
+ * @return              the actual data in the CPLD register
+ */
+unsigned int cpld_reg(unsigned int reg, unsigned int val, unsigned int read)
+{
+    unsigned int temp;
+
+    if (reg > 0x20068 || read > 1 ) {
+        diag_printf("<reg num> = %x is invalid. Should be less then 0x20068\n", reg);
+        return 0;
+    }
+
+    temp = cpld_reg_xfer(reg, val, read);
+    diag_printf1("reg=0x%x, val=0x%08x\n", reg, val);
+
+    if (read == 0) {
+        temp = cpld_reg_xfer(reg, val, 1);
+    }
+
+    return temp;
+}
+
+#endif // CPLD_SPI_BASE
diff --git a/packages/devs/usb/imx/v2_0/cdl/usbs_imx.cdl b/packages/devs/usb/imx/v2_0/cdl/usbs_imx.cdl
new file mode 100644 (file)
index 0000000..033bdaa
--- /dev/null
@@ -0,0 +1,107 @@
+# ====================================================================
+#
+#      usbs_mx37.cdl
+#
+#      MX37 USB OTG Device Mode support.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+# This file is a part of Diagnosis Package based on eCos for Freescale i.MX 
+# Family microprocessor.
+## Copyright (C) 2008 Freescale Semiconductor, Inc.
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      fisherz
+# Original data:  fisherz
+# Contributors:
+# Date:           2008-10-16
+# Comment:        Porting to MX51
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+cdl_package CYGPKG_DEVS_USB_IMX_OTG {
+    display     "Freescale i.MX51 or i.MX37 USB OTG Device Driver"
+    include_dir "cyg/io/usb"
+    parent      CYGPKG_USB
+    implements  CYGHWR_IO_USB_SLAVE
+
+    # Make sure that we are running on the right hardware.
+    requires CYGPKG_HAL_ARM
+#   requires CYGPKG_HAL_ARM_MX51
+#   requires CYGPKG_HAL_ARM_MX51_3STACK
+       requires CYGPKG_IO_USB
+       requires CYGPKG_IO_USB_SLAVE
+       compile  usbs_imx.c
+    
+    description "
+        The on-chip USB OTG core on the MX51 or MX37 works as a USB
+        device controller, facilitating the use of this processor
+        in USB peripherals. This package provides a suitable eCos
+        device driver."
+
+    cdl_option CYGHWR_USB_DEVS_MX51_OTG {
+        display       "i.MX51 USB OTG"
+        flavor        bool
+        default_value 0
+        description "
+        i.MX51 is the default OTG device for this package"
+     }
+
+     cdl_option CYGHWR_USB_DEVS_MX37_OTG {
+        display       "i.MX37 USB OTG"
+        flavor        bool
+        default_value 0
+        description "
+        i.MX37 is not the default OTG device for this package"
+     }
+
+    cdl_option CYGHWR_MXC_USB_BUFFER_USE_IRAM {
+        display       "Determine where the USB buffer is"
+        flavor        bool
+        default_value 1
+        description "
+        USB buffer is defaultly in the internal RAM for better performance"
+     }
+
+    cdl_option CYGHWR_IMX_USB_DOWNLOAD_SUPPORT {
+        display       "USB Download for redboot is supported, i.MX OTG works in poll mode"
+        flavor        bool
+        default_value 0
+        description "
+        USB Download function is an add-value function for redboot, and USB OTG will work
+        under poll mode"
+     }
+
+}
+    
+    
\ No newline at end of file
diff --git a/packages/devs/usb/imx/v2_0/include/usbs_imx.h b/packages/devs/usb/imx/v2_0/include/usbs_imx.h
new file mode 100644 (file)
index 0000000..11d9fd5
--- /dev/null
@@ -0,0 +1,837 @@
+//==========================================================================
+//
+//      include/usbs_imx.h
+//
+//      The interface exported by the i.MX37 or i.MX51 USB OTG device driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is a part of Diagnosis Package based on eCos for Freescale i.MX 
+// Family microprocessor.
+// Copyright (C) 2008 Freescale Semiconductor, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    fisherz
+// Contributors: fisherz
+// Date:         2008-07-22
+// Purpose:
+//
+//####DESCRIPTIONEND####
+//==========================================================================
+#ifndef CYGONCE_USBS_IMX_H
+#define CYGONCE_USBS_IMX_H
+
+#include <cyg/io/usb/usbs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define USBS_DEBUG   0
+
+/*
+ * This function is an exported API for application to initialize 
+ * MX37 or MX51 USB OTG in device mode from hardware to driver.
+ */
+void usbs_imx_otg_device_init(void);
+void usbs_imx_otg_device_deinit(void);
+#if defined(CYGBLD_IMX_USB_DOWNLOAD_SUPPORT)
+void usbs_imx_otg_download(unsigned char * buffer, unsigned int length);
+#endif
+/*
+ * The i.MX37 and 51 family comes with on-chip USB OTG support. This
+ * provides three endpoints. Endpoint 0 can only be used for control
+ * messages. Endpoints 1 and 2 can only be used for bulk transfers,
+ * host->slave for endpoint 1 and slave->host for endpoint 2.
+ */
+extern usbs_control_endpoint    usbs_imx_otg_ep0;
+extern usbs_rx_endpoint         usbs_imx_otg_ep1;
+extern usbs_tx_endpoint         usbs_imx_otg_ep2;
+
+
+/************************************************************************/
+#define BUFFER_SIZE    0x800
+
+#if defined(CYGHWR_USB_DEVS_MX37_OTG)
+#define USB_BASE_ADDRESS 0xC3FD4000
+#define MX37_IRQ_USB_SERVICE_REQUEST   18      //i.MX37 USB OTG Interrupt 
+#define MX37_IRQ_USB_PRIORITY                  99      //i.MX37 USB Interrupt Priority 
+#define IMX_IRQ_USB_DEV_SERVICE_REQUEST        MX37_IRQ_USB_SERVICE_REQUEST
+#define IMX_IRQ_USB_DEV_PRIORITY               MX37_IRQ_USB_PRIORITY
+
+#define CCM_BASE_ADDR 0xE3F8C000
+#define CCM_CSCMR1_OFFSET      0x34    
+#define CCM_CSCMR1 (CCM_BASE_ADDR + CCM_CSCMR1_OFFSET)
+#define REGVAL_CCM_CSCMR1 (*((volatile cyg_uint32*)CCM_CSCMR1))
+#define USB_MX37_SET_PHY_CLK_24MHZ() (REGVAL_CCM_CSCMR1&=(~((0x1) <<26)))
+       
+#define USB_IMX_SET_TD_OFFSET(offset,num) offset=num
+#endif
+
+
+#if defined(CYGHWR_USB_DEVS_MX51_OTG)
+#define USB_BASE_ADDRESS 0x73F80000
+#define MX51_IRQ_USB_SERVICE_REQUEST   18      //i.MX51 USB OTG Interrupt 
+#define MX51_IRQ_USB_PRIORITY                  99      //i.MX51 USB Interrupt Priority 
+#define IMX_IRQ_USB_DEV_SERVICE_REQUEST        MX51_IRQ_USB_SERVICE_REQUEST
+#define IMX_IRQ_USB_DEV_PRIORITY               MX51_IRQ_USB_PRIORITY
+
+#define  USB_OTG_BASE_ADDR     ((cyg_uint32)USB_BASE_ADDRESS + 0x000) 
+#define  USB_H1_BASE_ADDR      ((cyg_uint32)USB_BASE_ADDRESS + 0x200) 
+#define  USB_H2_BASE_ADDR      ((cyg_uint32)USB_BASE_ADDRESS + 0x400) 
+#define  USB_H3_BASE_ADDR      ((cyg_uint32)USB_BASE_ADDRESS + 0x400) 
+#define  USB_CONTROL_REG       ((cyg_uint32)USB_BASE_ADDRESS + 0x800) 
+#define  USB_OTG_MIRROR_REG ((cyg_uint32)USB_BASE_ADDRESS + 0x804) 
+#define  USB_PHY_CTRL_0_REG ((cyg_uint32)USB_BASE_ADDRESS + 0x808) 
+#define  USB_PHY_CTRL_1_REG ((cyg_uint32)USB_BASE_ADDRESS + 0x80c) 
+#define  USB_CTRL_1_REG                ((cyg_uint32)USB_BASE_ADDRESS + 0x810) 
+
+#define CCM_BASE_ADDR 0x73FD4000
+#define CCM_CSCMR1_OFFSET 0x1C
+#define CCM_CSCDR1_OFFSET 0x24
+#define CCM_CSCMR1 (CCM_BASE_ADDR + CCM_CSCMR1_OFFSET)
+#define CCM_CSCDR1 (CCM_BASE_ADDR + CCM_CSCDR1_OFFSET)
+#define CCM_CSCMR1_REGVAL (*(cyg_uint32 *)(CCM_BASE_ADDR + CCM_CSCMR1_OFFSET))
+#define CCM_CSCDR1_REGVAL (*(cyg_uint32 *)(CCM_BASE_ADDR + CCM_CSCDR1_OFFSET))
+/* CSCMR1 register */
+#define CSCMR1_USBOH3_PHY_CLK_SEL_MASK         0x04000000
+#define CSCMR1_USBOH3_PHY_CLK_SEL_VALUE        0x04000000
+#define CSCMR1_USBOH3_CLK_SEL_MASK                     0x00c00000
+#define CSCMR1_USBOH3_CLK_SEL_VALUE                    0x00400000
+/*CSCDR1 register config*/
+#define CSCDR1_USBOH3_CLK_PRED_SEL_MASK                0x00000700
+#define CSCDR1_USBOH3_CLK_PRED_SEL_VALUE       0x00000400  /* divide by 5 */
+#define CSCDR1_USBOH3_CLK_PODF_SEL_MASK                0x000000C0
+#define CSCDR1_USBOH3_CLK_PODF_SEL_VALUE       0x00000040  /* divide by 2 */
+/* CDCDR register */
+#define CDCDR_USB_CLK_PREDF_MASK   0x00000070
+#define CDCDR_USB_CLK_PREDF_VALUE  0x00000010  /* divide by 2 */
+#define CDCDR_USB_CLK_PODF_MASK    0x0000000E
+#define CDCDR_USB_CLK_PODF_VALUE   0x00000002  /* divide by 2 */
+
+/*Hash Defines for PHY_CTRL_REG_1*/
+#define  USB_PHY_CTRL_PLLDIVVALUE_MASK  0x00000003
+#define  USB_PHY_CTRL_PLLDIVVALUE_19_2_MHZ  0x00000000
+#define  USB_PHY_CTRL_PLLDIVVALUE_24_MHZ  0x00000001
+#define  USB_PHY_CTRL_PLLDIVVALUE_26_MHZ  0x00000002
+#define  USB_PHY_CTRL_PLLDIVVALUE_27_MHZ  0x00000003
+
+
+#define USB_IMX_SET_TD_OFFSET(offset,num) offset=num//do{}while(0) 
+#endif
+/************************************************************************/
+#define IMX_USB_INTR_DEV_SLE           (1<<8)  //DCSuspend - Sleep Enable
+#define IMX_USB_INTR_DEV_SRE           (1<<7)  //SOF Received Enable
+#define IMX_USB_INTR_DEV_RESET         (1<<6)  //USB Reset Enable
+#define IMX_USB_INTR_DEV_SEE           (1<<4)  //System Error Enable           
+#define IMX_USB_INTR_DEV_PCE           (1<<2)  //Port Change Detect Enable
+#define IMX_USB_INTR_DEV_USBINT        (1<<0)  //USBINT Enable, IOS@dQH, IOC@dTD will be available
+
+#define IMX_USB_STS_DCSPD                      (1<<8)  //DCSuspend Interrupt
+#define IMX_USB_STS_SOFRSV                     (1<<7)  //SOF Received Interrupt
+#define IMX_USB_STS_RESET                      (1<<6)  //USB Reset Received Interrupt
+#define IMX_USB_STS_SYSERR                     (1<<4)  //System Error Interrupt, not implemented in Marley, always '0'
+#define IMX_USB_STS_PTCHANGE           (1<<2)  //Port Change Detect Interrupt
+#define IMX_USB_STS_USBINT                     (1<<0)  //USB Interrupt
+/************************************************************************/
+#define BIT0   0x00000001
+#define BIT1   0x00000002
+#define BIT2   0x00000004
+#define BIT3   0x00000008
+#define BIT4   0x00000010
+#define BIT5   0x00000020
+#define BIT6   0x00000040
+#define BIT7   0x00000080
+#define BIT8   0x00000100
+#define BIT9   0x00000200
+#define BIT10  0x00000400
+#define BIT11  0x00000800
+#define BIT12  0x00001000
+#define BIT13  0x00002000
+#define BIT14  0x00004000
+#define BIT15  0x00008000
+#define BIT16  0x00010000
+#define BIT17  0x00020000
+#define BIT18  0x00040000
+#define BIT19  0x00080000
+#define BIT20  0x00100000
+#define BIT21  0x00200000
+#define BIT22  0x00400000
+#define BIT23  0x00800000
+#define BIT24  0x01000000
+#define BIT25  0x02000000
+#define BIT26  0x04000000
+#define BIT27  0x08000000
+#define BIT28  0x10000000
+#define BIT29  0x20000000
+#define BIT30  0x40000000
+#define BIT31  0x80000000
+/* Device Queue Head and Device Transfer Descriptor Related Defination */
+#define SIZE_OF_QHD            0x40
+#define SIZE_OF_DTD0   0x20
+#define SIZE_OF_DTD1   0x20
+#define dTD_SIZE_EPIN  (SIZE_OF_DTD0 + SIZE_OF_DTD1)   //0x40
+#define dTD_SIZE_EPOUT         (SIZE_OF_DTD0 + SIZE_OF_DTD1)   //0x40
+
+#define BUFFER_USED_PER_EP ((SIZE_OF_QHD + dTD_SIZE_EPIN) +(SIZE_OF_QHD + dTD_SIZE_EPOUT)) //0x100
+
+#define ZLT_ENABLE             0
+#define ZLT_DISABLE    1
+
+#define IOS_NOTSET             0
+#define IOS_SET                        1
+
+#define IOC_NOTSET             0
+#define IOC_SET                        1
+
+#define TERMINATE              1
+#define NOT_TERMINATE  0
+
+#define NO_STATUS              0
+#define ACTIVE                 BIT7
+
+#define EPOUT_COMPLETE  BIT0
+#define EPIN_COMPLETE  BIT16
+       
+#define EPOUT_PRIME            BIT0
+#define EPIN_PRIME             BIT16
+
+#define EPOUT_ENABLE   BIT7
+#define EPIN_ENABLE    BIT23
+
+#define STALL_RX               0x00000001
+#define STALL_TX               0x00010000
+
+/* Buffer size of the buffer used for bulk data transfer */ 
+
+#define        CONTROL_BUFFER_SIZE             0x40
+#define BULK_BUFFER_SIZE               0x200
+#define NUM_OF_BULK_BUFFER             0x2
+#define TOTAL_DATA_BUFFER_SIZE ((BULK_BUFFER_SIZE * NUM_OF_BULK_BUFFER) + CONTROL_BUFFER_SIZE)//512*2+64=1088
+
+#define BULK_TD_BUFFER_TOTAL_SIZE      0x4000
+#define BULK_TD_BUFFER_PAGE_SIZE       0x1000
+/************************************************************************/
+#define USB_OTG_TRANS_MASK      0xC0000000
+#define USB_OTG_TRANS_SERIAL    0xC0000000
+#define USB_OTG_TRANS_ULPI      0x80000000
+#define USB_OTG_TRANS_PHILIP    0x40000000
+#define USB_OTG_TRANS_UTMI      0x00000000
+#define USB_OTG_FS_ONLY         0x01000000
+#define USB_OTG_TRANS_WIDTH     0x10000000
+
+/***********************USB OTG Register Map*****************************/
+// ----------------------------------------------------------------------------
+// This device driver for i.MX37 has three endpoints.
+//
+// Endpoint 0 can only be used for bi-directional control messages. 
+//
+// Endpoint 1 can only be used for host->slave bulk OUT transfers. 
+//
+// Endpoint 2 can only be used for slave-host bulk IN transfers. 
+//
+// Start with definitions of the hardware. The use of a structure and
+// a const base pointer should allow the compiler to do base/offset
+// addressing and keep the hardware base address in a register. This
+// is better than defining each hardware register via a separate
+// address. Although the registers are only a byte wide, the peripheral
+// bus only supports word accesses.
+//
+// The USB_OTG_ID etc. macros allow for an alternative way of
+// accessing the hardware if a better approach is presented, without
+// having to rewrite all the code. Macros that correspond to registers
+// are actually addresses, making it easier in the code to distinguish
+// them from bit values: the & and * operators will just cancel out.
+typedef struct usbs_imx_otg_hardware{
+  volatile cyg_uint32 id;             //0x000, Identification Register
+  volatile cyg_uint32 hwgeneral;      //0x004, General HW Parameters
+  volatile cyg_uint32 hwhost;         //0x008, Host HW Parameters
+  volatile cyg_uint32 hwdevice;       //0x00c, Device HW Parameters
+  volatile cyg_uint32 hwtxbuf;        //0x010, TX Buffer HW Parameters
+  volatile cyg_uint32 hwrxbuf;        //0x014, RX Buffer HW Parameters
+                    int rsv1[26];
+  volatile cyg_uint32 gptimer0ld;     //0x080, GP Timer0 Load Register
+  volatile cyg_uint32 gptimer0ctrl;   //0x084, GP Timer0 Control Register
+  volatile cyg_uint32 gptimer1ld;     //0x088, GP Timer1 Load Register
+  volatile cyg_uint32 gptimer1ctrl;   //0x08c, GP Timer1 control register
+  volatile cyg_uint32 sbuscfg;        //0x090, System Bus Interface Control
+                    int rsv2[27];
+  volatile unsigned char caplength;     //0x100, Capability Length Register
+                    char rsv3;
+  volatile cyg_uint16 hciversion;   //0x102, Host Interface Version Number
+  volatile cyg_uint32 hcsparams;      //0x104, Host Control Structural Parameters
+  volatile cyg_uint32 hccparams;      //0x108, Host Control Capability Parameters
+                    int rsv4[5];
+  volatile cyg_uint16 dciversion;   //0x120, Device Interface Version Number
+                    short rsv5;       
+  volatile cyg_uint32 dccparams;      //0x124, Device Control Capability Parameters
+                    int rsv6[6];
+  volatile cyg_uint32 usbcmd;         //0x140, USB Command
+  volatile cyg_uint32 usbsts;         //0x144, USB Status
+  volatile cyg_uint32 usbintr;        //0x148, USB Interrupt Enable
+  volatile cyg_uint32 frindex;        //0x14c, USB Frame Index
+                    int rsv7;
+  volatile cyg_uint32 devaddr;        //0x154, USB Device Address
+  volatile cyg_uint32 endptlistaddr;  //0x158, Address of Endpoint list in memory
+  volatile cyg_uint32 ttctrl;         //0x15c, TT status and control
+  volatile cyg_uint32 burstsize;      //0x160, Programmable Burst Size
+  volatile cyg_uint32 txfilltuning;   //0x164, Host Transmit Pre-Buffer Packet Tuning
+  volatile cyg_uint32 txttfilltuning; //0x168,Host TT Transmit Pre-Buffer packet Tuning
+                    int rsv8;
+  volatile cyg_uint32 ulpiviewpoint;  //0x170, ULPI Viewport
+                    int rsv9;
+  volatile cyg_uint32 endptnak;       //0x178, Endpoint NAK
+  volatile cyg_uint32 endptnaken;     //0x17c, Endpoint NAK Enable
+  volatile cyg_uint32 configflag;     //0x180, Configured Flag Register
+  volatile cyg_uint32 portsc1;      //0x184~0x1a0, Port Status/Control 1~8
+       volatile cyg_uint32 portsc2;
+       volatile cyg_uint32 portsc3;
+       volatile cyg_uint32 portsc4;
+       volatile cyg_uint32 portsc5;
+       volatile cyg_uint32 portsc6;
+       volatile cyg_uint32 portsc7;
+       volatile cyg_uint32 portsc8;            
+  volatile cyg_uint32 otgsc;          //0x1a4, OTG Status and Control
+  volatile cyg_uint32 usbmode;        //0x1a8, USB Device Mode
+  volatile cyg_uint32 endptsetupstat; //0x1ac,Endpoint Setup Status
+  volatile cyg_uint32 endptprime;     //0x1b0, Endpoint Initialization
+  volatile cyg_uint32 endptflush;     //0x1b4, Endpoint De-Initialization
+  volatile cyg_uint32 endptstatus;    //0x1b8, Endpoint Status
+  volatile cyg_uint32 endptcomplete;  //0x1bc, Endpoint Complete
+  volatile cyg_uint32 endptctrl[16];  //0x1c0~0x1fc, Endpoint Control 0~15
+}usbs_imx_otg_hardware;
+/*************************usb structures typedefs*************************/
+//-----------------------------------------------
+//USB buffer data structure
+typedef struct {
+    cyg_uint32 buffer_address;
+    cyg_uint32 buffer_size;
+}usb_plat_config_data_t;
+
+//setup data for Queue Header
+typedef struct dqh_setup_t{
+       cyg_uint32 dqh_word0;   
+       cyg_uint32 dqh_word1;   
+       cyg_uint32 dqh_word2;   
+       cyg_uint32 dqh_word3;   
+       cyg_uint32 dqh_word4;   
+       cyg_uint32 dqh_word5;   
+       cyg_uint32 dqh_word6;   
+       cyg_uint32 dqh_word7;   
+       cyg_uint32 dqh_word8;   
+       cyg_uint32 dqh_word9;   
+       cyg_uint32 dqh_word10;  
+       cyg_uint32 dqh_word11;  
+} dqh_setup_t;
+//setup data for Transfer Descriptor
+typedef struct dtd_setup_t {
+       cyg_uint32 dtd_word0;   
+       cyg_uint32 dtd_word1;   
+       cyg_uint32 dtd_word2;   
+       cyg_uint32 dtd_word3;   
+       cyg_uint32 dtd_word4;   
+       cyg_uint32 dtd_word5;   
+       cyg_uint32 dtd_word6;   
+       cyg_uint32 dtd_word7;   
+} dtd_setup_t;
+
+//structure for Queue Header
+typedef struct dqh_t {
+       cyg_uint32 dqh_base;
+       cyg_uint32 next_link_ptr;
+       cyg_uint32 buffer_ptr0; 
+       cyg_uint32 buffer_ptr1; 
+       cyg_uint32 buffer_ptr2; 
+       cyg_uint32 buffer_ptr3; 
+       cyg_uint32 buffer_ptr4;
+       cyg_uint16 total_bytes;
+  cyg_uint16 mps;
+  cyg_uint16 current_offset;
+  cyg_uint8 zlt; 
+  cyg_uint8 ios;
+  cyg_uint8 terminate;
+  cyg_uint8 ioc;
+  cyg_uint8 status; 
+}dqh_t;
+
+//structure for Transfer Descriptor
+typedef struct dtd_t {
+       cyg_uint32 dtd_base; 
+       cyg_uint32 next_link_ptr;
+       cyg_uint32 buffer_ptr0; 
+       cyg_uint32 buffer_ptr1; 
+       cyg_uint32 buffer_ptr2;
+       cyg_uint32 buffer_ptr3;
+       cyg_uint32 buffer_ptr4;
+       cyg_uint16 total_bytes;
+       cyg_uint16 current_offset;
+       cyg_uint8 terminate;
+       cyg_uint8 ioc;
+       cyg_uint8 status;
+}dtd_t;
+
+//structure for Transfer Descriptor layout
+typedef volatile struct TransferDescriptor {
+       unsigned terminal                       :1      ;
+       unsigned rsv1                           :4      ;
+       unsigned nxt_pt                         :27     ;
+               
+       unsigned status                         :8      ;
+       unsigned rsv2                           :2      ;
+       unsigned multo                          :2      ;
+       unsigned rsv3                           :3      ;
+       unsigned ioc                            :1      ;
+       unsigned totalbytes                     :15     ;
+       unsigned rsv4                           :1      ;
+               
+       unsigned offset                         :12     ;
+       unsigned bufferptr0                     :20     ;
+       
+       unsigned frame_num                      :11     ;
+       unsigned rsv5                           :1      ;
+       unsigned bufferptr1                     :20     ;
+               
+       unsigned rsv6                           :12     ;
+       unsigned bufferptr2                     :20     ;
+               
+       unsigned rsv7                           :12     ;
+       unsigned bufferptr3                     :20     ;
+               
+       unsigned rsv8                           :12     ;
+       unsigned bufferptr4                     :20     ;
+}__attribute__((packed)) TransferDescriptor;
+
+//structure for Queue Header layout
+typedef volatile struct QueueHeader {
+       unsigned rsv1                           :15             ;
+       unsigned ios                            :1              ;
+       unsigned mps                            :11             ;
+       unsigned rsv2                           :2              ;
+       unsigned zlt                            :1              ;
+       unsigned mult                           :2              ;
+       
+       unsigned rsv3                           :5              ;               
+       unsigned current_dtd            :27             ;
+               
+       struct TransferDescriptor       dtd             ;
+       
+       unsigned rsv4                           :32             ;
+       
+       unsigned setupbuf0                      :8              ;
+       unsigned setupbuf1                      :8              ;
+       unsigned setupbuf2                      :8              ;
+       unsigned setupbuf3                      :8              ;
+       
+       unsigned setupbuf4                      :8              ;
+       unsigned setupbuf5                      :8              ;
+       unsigned setupbuf6                      :8              ;
+       unsigned setupbuf7                      :8              ;                                                                                               
+}__attribute__((packed)) QueueHeader;
+
+//bulk buffer status
+enum {
+       BUFFER_FREED,
+       BUFFER_RELEASED,
+       BUFFER_ALLOCATED
+};
+
+//structure of bulk buffer
+typedef struct {
+       unsigned char * buffer;
+       cyg_uint32    stat;
+}bulk_buffer_t;
+
+//bulk buffer status
+enum {
+       MASS_STORAGE_CBW_TYPE = 1,
+       MASS_STORAGE_DATA_TYPE
+};
+
+//structure of USB buffer map
+typedef struct {
+    cyg_uint32 ep_dqh_base_addrs;      /* Base Address of Queue Header */
+    cyg_uint32 ep_dtd_base_addrs;      /* Base Address of Transfer Descriptor */
+    cyg_uint32 ep0_buffer_addrs;       /* Buffer Addres for EP0 IN  */
+    cyg_uint32 buffer1_address;                /* Buffer1 address for bulk transfer */
+    cyg_uint32 buffer1_status;         /* Status of Buffer1 */
+    cyg_uint32 buffer2_address;                /* Buffer2 address for bulk transfer */
+    cyg_uint32 buffer2_status;         /* Status of Buffer2 */
+}buffer_map_t;
+
+//Data Structure used for configuring the Endpoints.
+typedef struct {
+    cyg_uint8  end_pt_no;                                      /* Endpoint number */
+    cyg_uint8  direction;                                      /* Direction of endpoint */
+    cyg_uint8  transfer_type;                  /* type of transfer supporting on the endpoint */
+    cyg_uint16  max_pkt_size;                  /* maximum packet size in bytes */
+}usb_end_pt_info_t;
+
+//Buffer descriptor used for data transfer on USB
+typedef struct {
+    void * buffer ;                                                            /* Address of the buffer to/from data is to be transmitted */
+    cyg_uint32 size ;                          /*  size of the buffer to  be transmitted/recieved */
+    cyg_uint32 bytes_transfered;       /* actual number of bytes transfered */
+}usb_buffer_descriptor_t;
+
+/*************************important constant in usb transaction*************************/
+/* Maximum packet size defination */
+#define MPS_8          8
+#define MPS_64         64
+
+#define SETUP_DATA_LENGTH                      0x8
+#define ENDPT_NUMBER_MASK                      0x0F
+#define ENDPT_DIR_MASK                         0x80
+#define ENDPT_DIR_SHIFT                                0x7 
+#define ENDPT_TRNS_TYPE_MASK           0x03
+
+#define USB_MAX_DEVICE_ADDR                    127
+#define USB_DEV_VALUE_OF_UNCONFIG      0x0
+
+#define USB_DEV_CONFIG_DESC_CONFIG_VALUE       0x01
+/* Default device address */
+#define USB_DEFAULT_ADDR                       0x00
+
+/* DESCRIPTOR Type */
+#define DEVICE_DESC                                    0x1
+#define CONF_DESC                                      0x2
+#define STRING_DESC                                    0x3
+#define INTERFACE_DESC                         0x4
+#define ENDPOINT_DESC                          0x5
+#define DEVICE_QUALIFIER                       0x6
+#define OTHER_SPEED_CONF_DESC          0x7
+
+/* String SUB DESCRIPTOR type */
+#define STR_DES0                                       0x0
+#define STR_DES1                                       0x1
+#define STR_DES2                                       0x2
+#define STR_DES3                                       0x3
+#define STR_DES4                                       0x4
+#define STR_DES5                                       0x5
+
+/* Descriptor Index */ 
+#define FILL_DEVICE_DESC                       0x1
+#define FILL_DEVICE_QF_DESC                    0x2
+#define FILL_CONF_DESC                         0x3
+#define FILL_OT_CONF_DESC                      0x4
+#define FILL_STR_DES0                          0x5
+#define FILL_STR_DES1                          0x6
+#define FILL_STR_DES2                          0x7
+#define FILL_STR_DES3                          0x8
+#define FILL_SN_DESC                           0x9     //mandatory descriptor for mass storage device
+
+#define LEN_OF_CONFIG_VALUE                    0x1
+       
+#define        NUM_OF_ENDPT_OFFSET             0x4
+#define        CONFIG_NUMBER_OFFSET            0x5
+#define STRING_DESC_LEN_OFFSET         0x0
+#define DEVICE_DESC_LEN_OFFSET         0x0
+#define CONF_DESC_LEN_OFFSET           0x0
+#define INF_DESC_LEN_OFFSET                    0x0
+#define EP_DESC_LEN_OFFSET                     0x0
+
+/*************************usb enums typedefs*************************/
+typedef enum {
+       USB_DEFAULT_STATE,
+       USB_ADDRESSED_STATE,
+       USB_CONFIGURED_STATE,
+       USB_SUSPENDED_STATE
+} USB_DEVICE_STATE_T;
+
+/* USB Device State which are handled by DCD */
+typedef enum
+{
+    USB_DEV_DUMMY_STATE,
+    USB_DEV_DEFAULT_STATE,
+    USB_DEV_ADDRESSED_STATE,
+    USB_DEV_CONFIGURED_STATE
+}usb_state_t;
+
+/* Status of all transaction on USB */
+typedef enum
+{
+    USB_SUCCESS,
+    USB_FAILURE,
+    USB_INVALID = -1 /* Always Keep this entry in last */
+}usb_status_t;
+
+/* enum for endpoint numbers */
+enum
+{
+    EP0,
+    EP1,
+    EP2,
+    EP3,
+    EP4,
+    EP5
+};
+
+enum 
+{
+    OUT,
+    IN
+};   
+/* enum for data transfer type on endpoints */
+enum
+{
+    CONTROL,
+    ISOCHRONOUS,
+    BULK,
+    INTERRUPT
+};
+
+/* Constants defined to represent the elements within the setup packet. */
+enum 
+{
+    BMREQUESTTYPE,
+    BREQUEST,
+    WVALUE_LOWBYTE,
+    WVALUE_HIGHBYTE,
+    WINDEX_LOWBYTE,
+    WINDEX_HIGHBYTE,
+    WLENGTH_LOWBYTE,
+    WLENGTH_HIGHBYTE
+};
+
+/* Enum constants for function to identify the USB Standard Request defined 
+ * in USB Specification. 
+ */
+enum 
+{
+   USB_GET_STATUS,
+   USB_CLEAR_FEATURE,
+   USB_RESERVED_REQ_ONE,
+   USB_SET_FEATURE,
+   USB_RESERVED_REQ_TWO,
+   USB_SET_ADDRESS,
+   USB_GET_DESCRIPTOR,
+   USB_SET_DESCRIPTOR,
+   USB_GET_CONFIGURATION,
+   USB_SET_CONFIGURATION,
+   USB_GET_INTERFACE,
+   USB_SET_INTERFACE,
+   USB_SYNCH_FRAME
+};
+
+/* Mass Storage Class-specific request
+ */
+enum{
+       USB_MSC_GET_MAX_LUN=0xFE,
+       USB_MSC_BOT_RESET
+};
+#define USB_REQTYPE_RESET      0x21
+#define USB_REQTYE_GETMAXLUN   0xA1
+
+/* Status of the buffer used for bulk transfer */
+enum {
+    BUFFER_FREE,
+    BUFFER_IN_USE
+};
+
+/***********************usb_descriptor_definitions*************************/
+#define VID    0x15A2
+#define        PID     0x002C
+
+/* Constants defined to represent device descriptor elements. */
+#define USB_DEV_DESC_LEN                                 0x12
+#define USB_DEV_DESC_TYPE                                0x01
+#define USB_DEV_DESC_SPEC_LB                             0x00
+#define USB_DEV_DESC_SPEC_HB                             0x02
+#define USB_DEV_DESC_DEV_CLASS                           0x00  /*ROM Code definition*///0x02   /* Fisher: CDC bDeviceClass */                                                                              
+#define USB_DEV_DESC_DEV_SUBCLASS                                               0x00   //0x02  /* Fisher: Abstract Control Model*/                                                                                 
+#define USB_DEV_DESC_DEV_PROTOCOL                        0x00
+#define USB_DEV_DESC_EP0_MAXPACKETSIZE                   0x40
+#define USB_DEV_DESC_VENDORID_LB                         (VID & 0x00FF) 
+#define USB_DEV_DESC_VENDORID_HB                         ((VID & 0xFF00) >> 0x8) 
+#define USB_DEV_DESC_PRODUCTID_LB                        (PID & 0x00FF)
+#define USB_DEV_DESC_PRODUCTID_HB                        ((PID & 0xFF00) >> 0x8)
+#define USB_DEV_DESC_DEV_RELEASE_NUM_LB                  0x01
+#define USB_DEV_DESC_DEV_RELEASE_NUM_HB                  0x00
+#define USB_DEV_DESC_DEV_STRING_IND_MANUFACTURE          0x01
+#define USB_DEV_DESC_DEV_STRING_IND_PRODUCT              0x02
+#if defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+#define USB_DEV_DESC_DEV_STRING_IND_SERIAL_NUM           0x00 
+#else
+#define USB_DEV_DESC_DEV_STRING_IND_SERIAL_NUM           0x05 /*for mass storage device, it must >0*/
+#endif
+#define USB_DEV_DESC_DEV_NUM_CONFIGURATIONS              0x01
+
+
+
+/* Constants defindes to represent elements of configuration descriptor. */
+
+#define USB_DEV_CONFIG_DESC_LEN                          0x09 /* Length of configuration descriptor. */ 
+#define USB_DEV_CONFIG_DESC_TYPE                         0x02 /* Descriptor type. */
+#define USB_DEV_CONFIG_DESC_TTL_LEN_LB                   0x20 /* Total length of configuration information. */
+#define USB_DEV_CONFIG_DESC_TTL_LEN_HB                   0x00 /* Total length of configuration information. */
+#define USB_DEV_CONFIG_DESC_NUM_0F_INF                   0x01 /* Number of interfaces in this configuration. */ 
+#define USB_DEV_CONFIG_DESC_CONFIG_VALUE                 0x01 /* Configuration value. */
+#if defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+#define USB_DEV_CONFIG_DESC_STRING_INDEX                 0x04 /* String index for this configuration. */
+#else
+#define USB_DEV_CONFIG_DESC_STRING_INDEX                 0x00 /* String index for this configuration. */
+#endif
+#define USB_DEV_CONFIG_DESC_ATTRIBUTES                   0xC0/*  Self powered and supported remote wakeup. */ 
+                                                                                                                               /* 0x80 Self powered and supported remote wakeup. */
+                                                                                                                         
+#define USB_DEV_CONFIG_DESC_MAX_POWER                    0x32 /* 100ma,Max power consumed by phone. */
+#define USB_DEV_INF_DESC_LEN                             0x09 /* Interface descriptor length. */
+#define USB_DEV_INF_DESC_TYPE                            0x04 /* The descriptor type, 4 interface descriptor. */
+#define USB_DEV_INF_DESC_INF_INDEX                       0x00 /* Interface index. */
+#define USB_DEV_INF_DESC_ALT_SETTING                     0x00 /* The alternate setting is 0. */
+#define USB_DEV_INF_DESC_NUM_OF_EP                       0x02 /* Control endpoint and data endpoint 1 and 2. */
+#define USB_DEV_INF_DESC_INF_CLASS_VENDOR                0xFF /* Interface class: Vendor Specific. */                  
+#define USB_DEV_INF_DESC_INF_CLASS_MSC                   0x08 /* Interface class: Mass Storage. */                                                                          
+#define USB_DEV_INF_DESC_INF_SUBCLASS_S_BLANK                                           0x40 /* (Subclass) Motorola Flash Download. */                                                                                         
+#define USB_DEV_INF_DESC_INF_SUBCLASS_NS_BLANK           0x42                          
+#define USB_DEV_INF_DESC_INF_SUBCLASS_MSC_SCSI           0x06  /* SCSI transparent command set for mass storage*/                                                      
+#define USB_DEV_INF_DESC_INF_PROTOCOL                    0x01 /* (Interface protocol) Vendor Specific, ROM bootloader interface. */
+#define USB_DEV_INF_DESC_INF_PROTOCOL_MSC_BOT                                           0x50   /* Mass Storage Bulk Only Transport*/
+#if defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+#define USB_DEV_INF_DESC_STRING_INDEX                    0x05  /* Index of interface string descriptor. */
+#else
+#define USB_DEV_INF_DESC_STRING_INDEX                    0x04  /* Index of interface string descriptor. */
+#endif
+
+/* Constants defined to represent the endpoint descriptor elements. */
+#define USB_MAX_PACKET_SIZE                    0x0200
+#define USB_MAX_PACKET_SIZE_LO         (USB_MAX_PACKET_SIZE&0xFF)
+#define USB_MAX_PACKET_SIZE_HI         ((USB_MAX_PACKET_SIZE>>8)&0xFF)
+
+/* Endpoint 1 descriptor. */
+#define USB_EP1_DESC_SIZE                                0x07 /* Size of descriptor in bytes. */
+#define USB_EP1_DESC_TYPE                                0x05 /* Descriptor type. */
+#define USB_EP1_DESC_EP_ADDR                             0x01 /* (Endpoint address) Endpoint 1, OUT. */
+#define USB_EP1_DESC_ATTRIBUTES                          0x02 /* (Attributes) Bulk Endpoint. */
+#define USB_EP1_DESC_MAX_PACKET_SIZE_FS_LB               0x40 /* Max Packet Size. */
+#define USB_EP1_DESC_MAX_PACKET_SIZE_FS_HB               0x00 /* Max Packet Size. */
+#define USB_EP1_DESC_MAX_PACKET_SIZE_HS_LB               USB_MAX_PACKET_SIZE_LO /* Max Packet Size. */
+#define USB_EP1_DESC_MAX_PACKET_SIZE_HS_HB               USB_MAX_PACKET_SIZE_HI /* Max Packet Size. */
+#define USB_EP1_DESC_INTERVAL                            0x00 /* Interval, ignored. */
+#define USB_EP1_DESC_INTERVAL_HS                        0x01 /* at most 1NAK. */
+/* Endpoint 2 descriptor. */
+#define USB_EP2_DESC_SIZE                                0x07 /* Size of descriptor in bytes. */
+#define USB_EP2_DESC_TYPE                                0x05 /* Descriptor type. */
+#define USB_EP2_DESC_EP_ADDR                             0x82 /* (Endpoint address) Endpoint 2, IN. */
+#define USB_EP2_DESC_ATTRIBUTES                          0x02 /* (Attributes) Bulk Endpoint. */
+#define USB_EP2_DESC_MAX_PACKET_SIZE_FS_LB               0x40 /* Max Packet Size. */
+#define USB_EP2_DESC_MAX_PACKET_SIZE_FS_HB               0x00 /* Max Packet Size. */
+#define USB_EP2_DESC_MAX_PACKET_SIZE_HS_LB               USB_MAX_PACKET_SIZE_LO/* Max Packet Size. */
+#define USB_EP2_DESC_MAX_PACKET_SIZE_HS_HB               USB_MAX_PACKET_SIZE_HI /* Max Packet Size. */
+
+#define USB_EP2_DESC_INTERVAL                            0x00 /* Interval, ignored. */
+#define USB_EP2_DESC_INTERVAL_HS                                                0x01 /* at most 1NAK. */
+/* String Descriptor 0 */
+#define USB_STR0_DESC_SIZE                               0x04 /* Size of descriptor in bytes. */
+#define USB_STR0_DESC_TYPE                               0x03 /* Descriptor type. */
+#define USB_LANGUAGE_ID_LB                                                              0x09 /* Language id of english */
+#define USB_LANGUAGE_ID_HB                                                              0x04 /* Language id of english */
+
+/* String Descriptor 1 */
+#define USB_STR1_DESC_SIZE                                0x3A /* Size of descriptor in bytes. */
+#define USB_STR1_DESC_TYPE                                0x03 /* Descriptor type. */
+
+/* String Descriptor 2 */
+#define USB_STR2_DESC_SIZE_NS                             0x20 /* Size of descriptor in bytes for Non Secure Download*/
+#define USB_STR2_DESC_SIZE_SE                             0x20 /* Size of descriptor in bytes for Secure Engg. download*/
+#define USB_STR2_DESC_SIZE_S                              0x20 /* Size of descriptor in bytes for Secure production download*/
+#define USB_STR2_DESC_TYPE                                0x03 /* Descriptor type. */
+
+/* String Descriptor 3 */
+#define USB_STR3_DESC_SIZE                                0x20 /* Size of descriptor in bytes. */
+#define USB_STR3_DESC_TYPE                                0x03 /* Descriptor type. */
+
+/* Serial number string descriptor */
+#define USB_SN_DESC_LEN                                                                        0x1A /* Size of descriptor length*/
+#define USB_SN_DESC_TYPE                                                               0x03 /* type of descriptor*/
+/*************************usb descriptor typedefs********************/
+typedef struct {
+       usb_configuration_descriptor usb_config_desc;
+    usb_interface_descriptor  usb_interface_desc;
+    usb_endpoint_descriptor  usb_endpoint_desc[USB_DEV_INF_DESC_NUM_OF_EP];            
+}__attribute__((packed)) usb_conf_desc;
+/* USB device serial number for mass storage requiremen*/
+typedef struct {
+       cyg_uint8  length;
+       cyg_uint8  descriptor_type;
+       cyg_uint8  string[24];
+}__attribute__((packed)) usb_str4_desc;
+/* USB string Descriptor structure 0 according to USB2.0 Specification */
+typedef struct {
+    cyg_uint8  length;
+    cyg_uint8  descriptor_type;
+    cyg_uint8  language_id0_l;
+    cyg_uint8  language_id0_h;
+}__attribute__((packed)) usb_str0_desc;
+
+/* USB string Descriptor structure 1 according to USB2.0 Specification */
+typedef struct {
+    cyg_uint8  length;
+    cyg_uint8  descriptor_type;
+    cyg_uint8  string[56];
+}__attribute__((packed)) usb_str1_desc;
+
+/* USB string Descriptor structure 2 according to USB2.0 Specification */
+typedef struct {
+    cyg_uint8  length;
+    cyg_uint8  descriptor_type;
+    cyg_uint8  string[34];
+}__attribute__((packed)) usb_str2_desc;
+
+/* USB string Descriptor structure 3 according to USB2.0 Specification */
+typedef struct {
+    cyg_uint8  length;
+    cyg_uint8  descriptor_type;
+    cyg_uint8  string[30];
+}__attribute__((packed)) usb_str3_desc;
+
+#define usb_dev_desc usb_device_descriptor     //rename the structure
+
+/* ALL USB Descriptors for both FS and HS */
+typedef struct {
+    usb_dev_desc*  device_desc; 
+    usb_conf_desc* config_desc;        
+       usb_str4_desc*   sn_desc;
+    usb_str0_desc* str_desc0; 
+    usb_str1_desc* str_desc1;
+    usb_str2_desc* str_desc2; 
+    usb_str3_desc* str_desc3;
+       
+}usb_descriptor;
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+
+#endif /* CYGONCE_USBS_IMX_H */
diff --git a/packages/devs/usb/imx/v2_0/src/usbs_imx.c b/packages/devs/usb/imx/v2_0/src/usbs_imx.c
new file mode 100644 (file)
index 0000000..9c93da3
--- /dev/null
@@ -0,0 +1,3440 @@
+//==========================================================================
+//
+//      usbs_imx.c
+//
+//      Device driver for the i.MX51 or i.MX37 USB OTG port.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is a part of Diagnosis Package based on eCos for Freescale i.MX 
+// Family microprocessor.
+// Copyright (C) 2008 Freescale Semiconductor, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    fisherz
+// Contributors: fisherz
+// Date:         2008-10-16
+//
+// This code implements support for the on-chip USB OTG port on the Freescale i.MX
+// family of processors. The code has been developed on the i.MX and
+// may or may not work on other members of the i.MX family. There
+// have problems with the USB support on certain revisions of the silicon,
+// so the errata sheet appropriate to the specific processor being used
+// should be consulted. There also appear to be problems which do not
+// appear on any errata, which this code attempts to work around.
+//
+// [Note] DMA is not enabled for USB transfer
+//####DESCRIPTIONEND####
+//
+//####REVISION HISTORY####
+//     Date                    Author                          Comments
+//  22Jul08                    Fisher ZHU(b18985)      Created for i.MX37 eCos USB device driver
+//  16Oct08                    Fisher ZHU(b18985)  Ported to i.MX51 USB OTG core
+//==========================================================================
+#include <string.h>    //use memset() of C run-time library
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/cyg_trac.h>
+#include <cyg/infra/diag.h>
+#include <pkgconf/hal_arm.h>
+#include <pkgconf/devs_usb_imx_otg.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_cache.h>
+#if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+#include <cyg/error/codes.h>
+#endif
+#include <cyg/io/usb/usb.h>
+#include <cyg/io/usb/usbs.h>
+#include <cyg/io/usb/usbs_imx.h>
+
+#pragma O0     //this pragma is useful when Realview tool chain is used
+#define VOLATILE volatile
+
+#if defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+//this error code is defined in error/include/codes.h
+//but when the usb driver is used in redboot, the codes.h won't
+//be included, so that this definition will solve the problem
+#define EPIPE 304      
+
+/* Constants */
+#define SDP_CMD_MAX_LEN        0x10  /* 16 bytes */
+#define SDP_CMD_ACK_LEN        0x4   /*  4 bytes */
+/* Command Packet Format: Header(2)+Address(4)+Format(1)+ByteCount(4)+Data(4) */
+#define        READ_HEADER             0x0101  //Read the flag in an assigned address on the target board
+#define        WRITE_HEADER    0x0202
+#define        WRITE_FILE              0x0404  //Write a file in host PC to target board
+#define        READ_FILE               0x0A0A  //Read a block of RAM to host PC and save in a file
+#define        ERROR_STATUS_HEADER     0x0505
+
+/* SDP Responses */
+#define WRITE_COMPLETE 0x128A8A12
+
+/* SDP States */
+#define CONTINUE        0
+#define DONE            1
+#define COMPLETE        0x88
+
+#define USB_DOWNLOAD_TIMEOUT_LIMIT     0x1D000000
+cyg_uint32 usb_download_address;
+cyg_uint32 usb_download_length;
+static cyg_uint8 sdp_payload_data[SDP_CMD_MAX_LEN]; /* Used to send or receive Command/ACK */
+static cyg_uint8 sdp_command[SDP_CMD_MAX_LEN];      /* Used to store Command */
+static cyg_uint8 g_error_status;
+static cyg_uint8 g_usb_download_state = CONTINUE;
+static cyg_uint32 g_timeout_value = 0;
+static cyg_uint32 g_load_cycle;
+static cyg_bool pl_get_command(void);
+static cyg_uint8 pl_command_start(void);
+static cyg_uint8 pl_handle_command(cyg_uint8 g_error_status);
+static void pl_command_ack(cyg_uint32 ack);
+static void pl_handle_write_file(cyg_uint32 address, cyg_uint32 total_bytes);
+static cyg_uint32 usb_rx_processing(cyg_uint8* read_ptr, usb_status_t* status, cyg_uint32 data_length);
+static usb_status_t usb_tx_processing(cyg_uint8* write_ptr, cyg_uint32 data_len);
+#endif
+
+/*     Bit3 - Mass Storage Information
+       Bit2 - Enumeration Information
+       Bit1 - Transaction Information
+       Bit0 - Basic Information        
+*/
+//#define DEBUG_TRANS  0x8     //also defined in usbs_msc.c
+#define DEBUG_ENUM     0x4
+#define DEBUG_TRANS    0x2
+#define DEBUG_BASIC    0x1
+
+//#define USBDBGMSG(str) if(g_debug_switch&0x1) diag_printf(str)
+#if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+extern cyg_uint32 g_debug_switch; //the lowest 4-bit is used for USB debug
+#if 1
+#define USBDBGMSG(opt,fmt,args...) if(g_debug_switch&opt) diag_printf(fmt, ## args)
+#else
+#define USBDBGMSG(opt,fmt,args...)
+#endif
+
+#else
+#define USBDBGMSG(opt,fmt,args...) //diag_printf(fmt, ## args)
+#define D(fmt,args...) diag_printf(fmt, ## args)
+#endif
+
+// ----------------------------------------------------------------------------
+//volatile cyg_uint8 g_bulkbuffer[BULK_TD_BUFFER_TOTAL_SIZE*NUM_OF_BULK_BUFFER] __attribute__((aligned(0x1000)));
+bulk_buffer_t g_bulkbuffer_a;
+bulk_buffer_t g_bulkbuffer_b;
+
+//This variable is used to workaround the 31-byte packet issue in i.MX37
+//It is initialized as "0x1",
+//When data read/write, it must initialize as '0x0'
+cyg_uint32 g_td_buffer_offset = 0;     
+
+//The below two flags is used to distinguish the received data is data or command
+cyg_uint32 g_received_data_type;
+
+/* This is used to pause the EP2 In wait for complete, just a workaround for this issue
+   It is not sure to be a bug of IC or software, need to check later.
+*/
+//cyg_uint8 g_tx_done=1;       //to keep EP1 issue sempahore to scsi after the previous CBW processed
+cyg_uint8 g_ep2_complete_bit_set = 0;
+
+#if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+extern cyg_sem_t usbs_msc_sem;                         //semaphore to schedule mass storage command handling thread
+#endif
+
+// ----------------------------------------------------------------------------
+// Static pointers for USB buffer layout
+/*=============================================================================
+                                      STATIC VARIABLES
+//============================================================================*/
+
+// Allocate 2k-byte buffer as USB QueueHeaderList region.
+// Don't use #pragma arm section in GCC
+// !!!!USB buffer should not be cached and buffered.
+//#pragma arm section rwdata="usb_buffer_no_init", zidata="usb_buffer_no_init"
+//2k aligned, this buffer must be uncacheable and unbufferable.
+
+#if defined(CYGHWR_IMX_USB_BUFFER_USE_IRAM)
+static volatile cyg_uint8 usb_buffer[BUFFER_SIZE] __attribute__((aligned(0x800)));     
+static volatile cyg_uint8 bulk_buffer[BULK_TD_BUFFER_TOTAL_SIZE*NUM_OF_BULK_BUFFER] __attribute__((aligned(0x1000)));
+//#pragma arm section
+#else
+/* iRAM is configured as uncacheable and unbufferable in MMU initialization
+    Reserve 0x800 bytes as USB buffer
+    Don't use 0x10001000~0x10001800 for other program. */
+#if defined(CYGHWR_USB_DEVS_MX37_OTG)
+static volatile cyg_uint8 * usb_buffer=(cyg_uint8 *)(0x10001000); 
+static volatile cyg_uint8 * bulk_buffer = (cyg_uint8 *)(0x10002000);
+#endif
+
+#if defined(CYGHWR_USB_DEVS_MX51_OTG)
+static volatile cyg_uint8 * usb_buffer=(cyg_uint8 *)(0x1FFE9000); 
+static volatile cyg_uint8 * bulk_buffer = (cyg_uint8 *)(0x1FFEA000);
+#endif
+// 
+#endif //defined(CYGHWR_IMX_USB_BUFFER_USE_IRAM)
+
+VOLATILE usbs_imx_otg_hardware* usbs_imx_otg_base = (VOLATILE usbs_imx_otg_hardware* const) USB_BASE_ADDRESS;
+
+static void usbs_imx_otg_config_utmi_clock(void);
+
+
+/* Base address of the buffer allocated to IP Layer */
+static VOLATILE cyg_uint32             g_bulkbuffer_address_base;
+/* length of the buffer */
+static VOLATILE cyg_uint32             g_bulkbuffer_length;    
+/* Buffer information used for data transfer */
+static VOLATILE buffer_map_t           g_bulkbuffer_map;               
+/* Number of Endpoints configured in system */
+static VOLATILE cyg_uint8              g_max_ep_supported;   
+/* State os USB Device */
+static VOLATILE usb_state_t            g_usb_dev_state = USB_DEV_DUMMY_STATE; 
+/* Length of setup data received */
+static VOLATILE cyg_uint8 *            g_usb_setup_data;
+/* Array to keep information about the endpoints used */
+static VOLATILE usb_end_pt_info_t      g_end_pt_info[USB_DEV_INF_DESC_NUM_OF_EP]; 
+/* Number of endpoints */
+static VOLATILE cyg_uint8              g_number_of_endpoints; 
+/* USB Descriptors */
+static VOLATILE usb_descriptor g_usb_desc;             
+/* Number of Endpoint configured as IN */
+static VOLATILE cyg_uint8              g_in_endpoint;  
+/* Number of Endpoint configured as OUT*/
+static VOLATILE cyg_uint8              g_out_endpoint;         
+
+/* Support for the interrupt handling code.*/
+static cyg_interrupt   g_usbs_dev_intr_data;
+static cyg_handle_t            g_usbs_dev_intr_handle;
+static volatile int            g_isr_status_bits = 0;
+
+// ----------------------------------------------------------------------------
+// get the base address of queue header for an endpointer
+#define USBS_EP_GET_dQH(endptno,dir) (g_bulkbuffer_map.ep_dqh_base_addrs + (SIZE_OF_QHD * (endptno * 2 + dir)))
+#define USBS_EP_GET_dTD(endptno,dir)   (g_bulkbuffer_map.ep_dtd_base_addrs + (SIZE_OF_DTD0 + SIZE_OF_DTD1) * ( endptno * 2 + dir))
+// ----------------------------------------------------------------------------
+// USB interrupt enable/disable macros
+#define USBS_IMX_OTG_INTR_MASK()               (usbs_imx_otg_base->usbintrclr = 0xFFFFFFFF)//0|IMX_USB_INTR_DEV_RESET|IMX_USB_INTR_DEV_USBINT)
+#define USBS_IMX_OTG_INTR_UNMASK(intr) (usbs_imx_otg_base->usbintr = 0|(intr))
+
+// ----------------------------------------------------------------------------
+// Check if the IOS bit of QueueHeader or the IOC bit of Transfer Descriptor are set
+#define USBS_dQH_IOS_CHECK(ep_num,dir) (((*(cyg_uint32*)USBS_EP_GET_dQH(ep_num,dir))&0x8000)?1:0)
+#define USBS_dTD_IOC_CHECK(ep_num,dir) (((*(cyg_uint32*)USBS_EP_GET_dTD(ep_num,dir))&0x8000)?1:0)
+
+// ----------------------------------------------------------------------------
+// Set USB device address
+#define USBS_DEVICE_SET_ADDRESS(addr) (usbs_imx_otg_base->devaddr = ((cyg_uint32)addr & 0x7F) << 25)
+/*  
+#*************  
+#   OTG  
+#*************  
+*/
+#define  USB_OTG_ID                                    (&(usbs_imx_otg_base->id))                                      /*   Identification Register                                    */
+#define  USB_OTG_HWGENERAL                     (&(usbs_imx_otg_base->hwgeneral))       /*   General Hardware Parameters                        */
+#define  USB_OTG_HWHOST                                (&(usbs_imx_otg_base->hwhost))                  /*   Host Hardware Parameters                           */
+#define  USB_OTG_HWDEVICE                      (&(usbs_imx_otg_base->hwdevice))                /*   Device Hardware Parameters                         */
+#define  USB_OTG_HWTXBUF                       (&(usbs_imx_otg_base->hwtxbuf))         /*   TX Buffer Hardware Parameters              */
+#define  USB_OTG_HWRXBUF                       (&(usbs_imx_otg_base->hwrxbuf))         /*   RX Buffer Hardware Parameters              */
+
+#define  USB_OTG_CAPLENGTH                     (&(usbs_imx_otg_base->caplength))       /*   Capability Register Length                         */
+#define  USB_OTG_HCIVERSION                    (&(usbs_imx_otg_base->hciversion)) /*   Host Interface Version Number           */
+#define  USB_OTG_HCSPARAMS                     (&(usbs_imx_otg_base->hcsparams))       /*   Host Ctrl. Structural Parameters */
+#define  USB_OTG_HCCPARAMS                     (&(usbs_imx_otg_base->hccparams))  /*   Host Ctrl. Capability Parameters */
+#define  USB_OTG_DCIVERSION                    (&(usbs_imx_otg_base->dciversion)) /*   Dev. Interface Version Number           */
+#define  USB_OTG_DCCPARAMS                     (&(usbs_imx_otg_base->dccparams))       /*   Dev. Ctrl. Capability Parameters */
+
+#define  USB_OTG_USBCMD                                (&(usbs_imx_otg_base->usbcmd))                  /*   USB Command                                                                                        */
+#define  USB_OTG_USBSTS                                (&(usbs_imx_otg_base->usbsts))                  /*   USB Status                                                                                         */
+#define  USB_OTG_USBINTR                       (&(usbs_imx_otg_base->usbintr))         /*   USB Interrupt Enable                                               */
+#define  USB_OTG_FRINDEX                       (&(usbs_imx_otg_base->frindex))         /*   USB Frame Index                                                                    */
+
+#define  USB_OTG_DEVICEADDR                    (&(usbs_imx_otg_base->devaddr))         /*   USB Device Address                                                         */
+#define  USB_OTG_PERIODICLISTBASE      USB_OTG_DEVICEADDR                                              /*   Frame List Base Address                                    */
+#define  USB_OTG_ENDPOINTLISTADDR      (&(usbs_imx_otg_base->endptlistaddr)) /*Address of Endpt list in memory*/
+#define  USB_OTG_ASYNCLISTADDR         USB_OTG_ENDPOINTLISTADDR                                /*   Next Asynchronous List Address     */
+
+#define  USB_OTG_BURSTSIZE                     (&(usbs_imx_otg_base->burstsize))  /*   Programmable Burst Size                                         */
+#define  USB_OTG_TXFILLTUNING          (&(usbs_imx_otg_base->txfilltuning)) /* Host TX Pre-Buffer Packet Tuning */
+#define  USB_OTG_VIEWPORT                      (&(usbs_imx_otg_base->ulpiviewport)) /* ULPI Register                                                                           */
+#define  USB_OTG_ENDPTNAK                      (&(usbs_imx_otg_base->endptnak))        /*Endpoint NAK                                                                                          */
+#define  USB_OTG_ENDPTNAKEN                    (&(usbs_imx_otg_base->endptnaken)) /*Endpoint NAK Enable                                                                */
+#define  USB_OTG_CONFIGFLAG                    (&(usbs_imx_otg_base->configflg))       /*   Configured Flag Register                           */
+#define  USB_OTG_PORTSC1                       (&(usbs_imx_otg_base->portsc1))  /*   Port 0 Status/Control                                     */
+#define  USB_OTG_OTGSC                         (&(usbs_imx_otg_base->otgsc))           /*   OTG Status and Control                                             */  
+#define  USB_OTG_USBMODE                       (&(usbs_imx_otg_base->usbmode))         /*   USB Device Mode                                                                    */
+#define  USB_OTG_ENDPTSETUPSTAT                (&(usbs_imx_otg_base->endptsetupstat)) /*   Endpoint Setup Status                               */
+#define  USB_OTG_ENDPTPRIME                    (&(usbs_imx_otg_base->endptprime)) /*   Endpoint Initialization                                         */
+#define  USB_OTG_ENDPTFLUSH                    (&(usbs_imx_otg_base->endptflush)) /*   Endpoint De-Initialize                                  */
+#define  USB_OTG_ENDPTSTATUS           (&(usbs_imx_otg_base->endptstatus))/*   Endpoint Status                                                                         */
+#define  USB_OTG_ENDPTCOMPLETE         (&(usbs_imx_otg_base->endptcomplete))   /*   Endpoint Complete                                          */
+#define  USB_OTG_ENDPTCTRL0            (&(usbs_imx_otg_base->endptctrl[0]))            /*   Endpoint Control 0                                         */
+#define  USB_OTG_ENDPTCTRL1                    (&(usbs_imx_otg_base->endptctrl[1]))            /*   Endpoint Control 1                                         */
+#define  USB_OTG_ENDPTCTRL2                    (&(usbs_imx_otg_base->endptctrl[2]))            /*   Endpoint Control 2                                         */
+#define  USB_OTG_ENDPTCTRL3                    (&(usbs_imx_otg_base->endptctrl[3]))            /*   Endpoint Control 3                                         */
+#define  USB_OTG_ENDPTCTRL4                    (&(usbs_imx_otg_base->endptctrl[4]))            /*   Endpoint Control 4                                         */
+#define  USB_OTG_ENDPTCTRL5                    (&(usbs_imx_otg_base->endptctrl[5]))            /*   Endpoint Control 5                                         */
+#define  USB_OTG_ENDPTCTRL6                    (&(usbs_imx_otg_base->endptctrl[6]))            /*   Endpoint Control 6                                         */
+#define  USB_OTG_ENDPTCTRL7                    (&(usbs_imx_otg_base->endptctrl[7]))            /*   Endpoint Control 7                                         */
+// ****************************************************************************
+// -----------------------USB Device Descriptors-------------------------------
+// ****************************************************************************
+/* USB Device Descriptor according to USB2.0 Specification */
+static VOLATILE usb_device_descriptor g_usb_device_desc ={
+       USB_DEV_DESC_LEN,
+    USB_DEV_DESC_TYPE,             
+    USB_DEV_DESC_SPEC_LB,              
+    USB_DEV_DESC_SPEC_HB,        
+    USB_DEV_DESC_DEV_CLASS,          
+    USB_DEV_DESC_DEV_SUBCLASS,        
+    USB_DEV_DESC_DEV_PROTOCOL,         
+    USB_DEV_DESC_EP0_MAXPACKETSIZE,     
+    USB_DEV_DESC_VENDORID_LB,               
+    USB_DEV_DESC_VENDORID_HB,               
+    USB_DEV_DESC_PRODUCTID_LB,               
+    USB_DEV_DESC_PRODUCTID_HB,               
+    USB_DEV_DESC_DEV_RELEASE_NUM_LB,          
+    USB_DEV_DESC_DEV_RELEASE_NUM_HB,         
+    USB_DEV_DESC_DEV_STRING_IND_MANUFACTURE,
+    USB_DEV_DESC_DEV_STRING_IND_PRODUCT,  
+    USB_DEV_DESC_DEV_STRING_IND_SERIAL_NUM,
+    USB_DEV_DESC_DEV_NUM_CONFIGURATIONS
+};
+
+
+/* USB Config Descriptor according to USB2.0 Specification */
+static VOLATILE usb_conf_desc g_usb_config_desc = {
+       { 
+       USB_DEV_CONFIG_DESC_LEN,   
+    USB_DEV_CONFIG_DESC_TYPE,   
+    USB_DEV_CONFIG_DESC_TTL_LEN_LB ,   
+    USB_DEV_CONFIG_DESC_TTL_LEN_HB ,   
+    USB_DEV_CONFIG_DESC_NUM_0F_INF,  
+    USB_DEV_CONFIG_DESC_CONFIG_VALUE ,  
+    USB_DEV_CONFIG_DESC_STRING_INDEX, 
+    USB_DEV_CONFIG_DESC_ATTRIBUTES,    
+       USB_DEV_CONFIG_DESC_MAX_POWER
+       },
+               /* USB Interface Descriptor according to USB2.0 Specification */
+       {//09
+       USB_DEV_INF_DESC_LEN,  
+    USB_DEV_INF_DESC_TYPE,  
+    USB_DEV_INF_DESC_INF_INDEX, 
+    USB_DEV_INF_DESC_ALT_SETTING,
+    USB_DEV_INF_DESC_NUM_OF_EP,  /* NOTE : This should not be more than 2 */
+    #if defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+       USB_DEV_INF_DESC_INF_CLASS_VENDOR,
+       USB_DEV_INF_DESC_INF_SUBCLASS_NS_BLANK,
+       USB_DEV_INF_DESC_INF_PROTOCOL,
+       #else
+       USB_DEV_INF_DESC_INF_CLASS_MSC, 
+    USB_DEV_INF_DESC_INF_SUBCLASS_MSC_SCSI,   
+    USB_DEV_INF_DESC_INF_PROTOCOL_MSC_BOT, 
+    #endif
+       USB_DEV_INF_DESC_STRING_INDEX
+       },
+               /* USB Endpoint 1 Descriptors according to USB2.0 Specification, OUT */
+       {
+       {//18
+       USB_EP1_DESC_SIZE,
+    USB_EP1_DESC_TYPE,
+    USB_EP1_DESC_EP_ADDR,
+    USB_EP1_DESC_ATTRIBUTES, 
+    USB_EP1_DESC_MAX_PACKET_SIZE_HS_LB, 
+    USB_EP1_DESC_MAX_PACKET_SIZE_HS_HB, 
+       USB_EP1_DESC_INTERVAL
+       },
+               /* USB Endpoint 2 Descriptors according to USB2.0 Specification, IN */
+       {//25
+       USB_EP2_DESC_SIZE, 
+    USB_EP2_DESC_TYPE,
+    USB_EP2_DESC_EP_ADDR,    
+    USB_EP2_DESC_ATTRIBUTES,  
+    USB_EP2_DESC_MAX_PACKET_SIZE_HS_LB,  
+    USB_EP2_DESC_MAX_PACKET_SIZE_HS_HB,  
+       USB_EP2_DESC_INTERVAL
+       }
+       }
+};
+
+/* USB String Descriptors 0, according to USB2.0 Specification */
+static VOLATILE usb_str0_desc g_usb_otg_str0_desc ={
+    USB_STR0_DESC_SIZE,
+    USB_STR0_DESC_TYPE,
+    USB_LANGUAGE_ID_LB,
+    USB_LANGUAGE_ID_HB
+};
+
+/* 
+ STRING DESCRIPTOR
+ See table 9-15 in USB2.0 spec (www.usb.org)
+ iManufacturer
+*/
+static VOLATILE usb_str1_desc g_usb_otg_string_desc1 ={
+       USB_STR1_DESC_SIZE,             /* bLength */
+       USB_STR1_DESC_TYPE,                     /* bDescriptorType */
+       {
+       'F', 0x00,                                                      /* bString */
+       'r', 0x00,
+       'e', 0x00,
+       'e', 0x00,
+       's', 0x00,
+       'c', 0x00,
+       'a', 0x00,
+       'l', 0x00,
+       'e', 0x00,
+       ' ', 0x00,
+       'S', 0x00,
+       'e', 0x00,
+       'm', 0x00,
+       'i', 0x00,
+       'C', 0x00,
+       'o', 0x00,
+       'n', 0x00,
+       'd', 0x00,
+       'u', 0x00,
+       'c', 0x00,
+       't', 0x00,
+       'o', 0x00,
+       'r', 0x00,
+       ' ', 0x00,
+       'I', 0x00,
+       'n', 0x00,
+       'c', 0x00,
+       '.', 0x00
+       }
+};
+#if defined(CYGHWR_USB_DEVS_MX37_OTG)
+/*iProduct*/    
+static VOLATILE usb_str2_desc g_usb_otg_string_desc2 = {
+       USB_STR2_DESC_SIZE_NS,          /* bLength */
+       USB_STR2_DESC_TYPE,                                             /* bDescriptorType */
+       {
+       'M', 0x00,                              /* bString */
+       'A', 0x00,              
+       'R', 0x00,                      
+       'L', 0x00,
+       'E', 0x00,      
+       'Y', 0x00,              
+       ' ', 0x00,      
+       'U', 0x00,              
+       'S', 0x00,                      
+       'B', 0x00,
+       ' ', 0x00,
+       'O', 0x00,
+       'T', 0x00,
+       'G', 0x00,
+       ' ', 0x00
+       }
+};
+//#if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+/* USB Serial Number Descriptor which is mandatory to Mass Storage Device */
+static VOLATILE usb_str4_desc g_usb_serialnumber_desc = {
+               USB_SN_DESC_LEN,
+               USB_SN_DESC_TYPE,
+               {
+               '2',0x00,
+               '0',0x00,
+               '0',0x00,
+               '8',0x00,
+               '1',0x00,
+               '8',0x00,
+               '9',0x00,
+               '8',0x00,
+               '5',0x00,
+               '0',0x00,
+               '3',0x00,
+               '7',0x00
+         }
+};
+//#endif
+#endif
+
+#if defined(CYGHWR_USB_DEVS_MX51_OTG)
+static VOLATILE usb_str2_desc g_usb_otg_string_desc2 = {
+       USB_STR2_DESC_SIZE_NS,          /* bLength */
+       USB_STR2_DESC_TYPE,                                             /* bDescriptorType */
+       {
+       'E', 0x00,                              /* bString */
+       'l', 0x00,              
+       'v', 0x00,                      
+       'i', 0x00,
+       's', 0x00,      
+       ' ', 0x00,              
+       'U', 0x00,      
+       'S', 0x00,              
+       'B', 0x00,                      
+       ' ', 0x00,
+       'O', 0x00,
+       'T', 0x00,
+       'T', 0x00,
+       ' ', 0x00,
+       ' ', 0x00
+       }
+};
+//#if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+/* USB Serial Number Descriptor which is mandatory to Mass Storage Device */
+static VOLATILE usb_str4_desc g_usb_serialnumber_desc = {
+               USB_SN_DESC_LEN,
+               USB_SN_DESC_TYPE,
+               {
+               '2',0x00,
+               '0',0x00,
+               '0',0x00,
+               '8',0x00,
+               '1',0x00,
+               '8',0x00,
+               '9',0x00,
+               '8',0x00,
+               '5',0x00,
+               '0',0x00,
+               '5',0x00,
+               '1',0x00
+         }
+};
+//#endif
+#endif
+
+/* STRING DESCRIPTOR
+   See table 9-15 in USB2.0 spec (www.usb.org)
+   iSerialNumber */
+static VOLATILE usb_str3_desc g_usb_otg_string_desc3 = {
+       USB_STR3_DESC_SIZE,                                     /* bLength */
+       USB_STR3_DESC_TYPE,                                     /* bDescriptorType */
+       {
+       'F', 0x00,                                                                      /* bString */
+       'r', 0x00,
+       'e', 0x00,
+       'e', 0x00,
+       's', 0x00,
+       'c', 0x00,
+       'a', 0x00,
+       'l', 0x00,
+       'e', 0x00,
+       ' ', 0x00,
+       'F', 0x00,
+       'l', 0x00,
+       'a', 0x00,
+       's', 0x00,
+       'h', 0x00
+       }
+};      
+
+
+// ****************************************************************************
+// ----------------------------------------------------------------------------
+// ****************************************************************************
+// ----------------------------------------------------------------------------
+// Static data. There is a data structure for each endpoint. The
+// implementation is essentially a private class that inherits from
+// common classes for control and data endpoints, but device drivers
+// are supposed to be written in C so some ugliness is required.
+
+// ----------------------------------------------------------------------------
+// Endpoint 0 is always present, this module would not get compiled
+// otherwise.
+static void usbs_imx_otg_dev_ep0_start(usbs_control_endpoint*);
+static void usbs_imx_otg_dev_poll(usbs_control_endpoint*);
+
+typedef enum ep0_state {
+    EP0_STATE_IDLE      = 0,
+    EP0_STATE_IN        = 1,
+    EP0_STATE_OUT       = 2
+} ep0_state;
+
+typedef struct ep0_impl {
+    usbs_control_endpoint   common;                    //struct usbs_control_endpoint defined in usbs.h
+    ep0_state               ep_state;
+    int                     length;
+    int                     transmitted;
+} ep0_impl;
+
+static ep0_impl ep0 = {
+    common:
+    {
+        state:                  USBS_STATE_POWERED, // The hardware does not distinguish  between detached, attached and powered.
+        enumeration_data:       (usbs_enumeration_data*) 0,
+        start_fn:               &usbs_imx_otg_dev_ep0_start,
+        poll_fn:                &usbs_imx_otg_dev_poll,
+        interrupt_vector:       IMX_IRQ_USB_DEV_SERVICE_REQUEST,
+        control_buffer:         { 0, 0, 0, 0, 0, 0, 0, 0 },
+        state_change_fn:        (void (*)(usbs_control_endpoint*, void*, usbs_state_change, int)) 0,
+        state_change_data:      (void*) 0,
+        standard_control_fn:    (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
+        standard_control_data:  (void*) 0,
+        class_control_fn:       (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
+        class_control_data:     (void*) 0,
+        vendor_control_fn:      (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
+        vendor_control_data:    (void*) 0,
+        reserved_control_fn:    (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,
+        reserved_control_data:  (void*) 0,
+        buffer:                 (unsigned char*) 0,
+        buffer_size:            0,
+        fill_buffer_fn:         (void (*)(usbs_control_endpoint*)) 0,
+        fill_data:              (void*) 0,
+        fill_index:             0,
+        complete_fn:            (usbs_control_return (*)(usbs_control_endpoint*, int)) 0
+    },
+    ep_state:           EP0_STATE_IDLE,
+    length:             0,
+    transmitted:        0
+};
+
+extern usbs_control_endpoint usbs_imx_otg_ep0 __attribute__((alias ("ep0")));
+
+// Endpoint 1 is optional. If the application only involves control
+// messages or only slave->host transfers then the endpoint 1
+// support can be disabled.
+//#ifdef CYGPKG_DEVS_USB_MX37_EP1
+
+typedef struct ep1_impl {
+    usbs_rx_endpoint    common;                        //struct usbs_rx_endpoint defined in usbs.h
+    int                 fetched;
+    cyg_bool            using_buf_a;
+} ep1_impl;
+
+static void ep1_start_rx(usbs_rx_endpoint*);
+static void ep1_set_halted(usbs_rx_endpoint*, cyg_bool);
+
+static ep1_impl ep1 = {
+    common: {
+        start_rx_fn:        &ep1_start_rx,
+        set_halted_fn:      &ep1_set_halted,
+        complete_fn:        (void (*)(void*, int)) 0,
+        complete_data:      (void*) 0,
+        buffer:             (unsigned char*) 0,
+        buffer_size:        0,
+        halted:             0,
+    },
+    fetched:            0,
+    using_buf_a:        0
+};
+
+extern usbs_rx_endpoint usbs_imx_otg_ep1 __attribute__((alias ("ep1")));
+//#endif
+
+// Endpoint 2 is optional. If the application only involves control
+// messages or only host->slave transfers then the endpoint 2 support
+// can be disabled.
+//#ifdef CYGPKG_DEVS_USB_MX37_EP2
+
+typedef struct ep2_impl {
+    usbs_tx_endpoint        common;                    //struct usbs_tx_endpoint defined in usbs.h
+    int                     transmitted;
+    int                     pkt_size;
+} ep2_impl;
+
+static void ep2_start_tx(usbs_tx_endpoint*);
+static void ep2_set_halted(usbs_tx_endpoint*, cyg_bool);
+
+static ep2_impl ep2 = {
+    common: {
+        start_tx_fn:        &ep2_start_tx,
+        set_halted_fn:      &ep2_set_halted,
+        complete_fn:        (void (*)(void*, int)) 0,
+        complete_data:      (void*) 0,
+        buffer:             (const unsigned char*) 0,
+        buffer_size:        0,
+        halted:             0,
+    }, 
+    transmitted:        0,
+    pkt_size:           0
+};
+
+extern usbs_tx_endpoint usbs_imx_otg_ep2 __attribute__ ((alias ("ep2")));
+//#endif
+
+// ****************************************************************************
+// -----------------------Static Functions Initialization----------------------
+// ****************************************************************************
+static void usbs_handle_get_descriptor(void);
+static void usbs_handle_set_configuration(void);
+static void usbs_handle_get_device_desc(void);
+static void usbs_handle_get_config_desc(void);
+static void usbs_handle_get_string_desc(void);
+static void usbs_handle_get_configuration(void);
+static void usbs_handle_set_address(void);
+
+static void usbs_ep0in_fill_buffer(cyg_uint8 type, cyg_uint32 buffer_addrs);
+static usb_status_t usbs_ep0_send_data(usb_buffer_descriptor_t* bd,cyg_uint8 zlt);
+static usb_status_t usbs_ep0_receive_data(usb_buffer_descriptor_t* bd);
+
+static void usbs_setup_queuehead(struct dqh_t* qhead);
+static void usbs_setup_transdesc(struct dtd_t* td);
+static void usbs_endpoint_stall(cyg_uint8 endpoint , cyg_uint8 direction);
+static void usbs_status_phase(cyg_uint8 trans_type, cyg_uint8 direction);
+
+static void usbs_imx_otg_dev_set_configuration(usb_end_pt_info_t* config_data);
+static void usbs_imx_otg_dev_handle_bus_reset(void);
+static void usbs_imx_otg_dev_handle_port_change(void);
+static void usbs_imx_otg_hardware_init(void);
+
+cyg_uint32 util_alloc_buffer(void);
+void util_free_buffer(cyg_uint32 address);
+void util_set_status_bulk_buffer(cyg_uint32 buffer_addr,int buffer_status);
+// ****************************************************************************
+// -----------------------Static Functions ------------------------------------
+// ****************************************************************************
+/*=============================================================================
+FUNCTION:              usbs_setup_queuehead
+DESCRIPTION:   This function is used to setup the dQH
+        ------------------------
+       |       EP0 IN  (64 bytes)       |
+       |                                |
+        ------------------------       dQH1
+       |       EP0 OUT (64 bytes)       |
+       |                                |
+        ------------------------       dQH0
+ARGUMENTS PASSED:
+       cyg_uint32 dqh_base - Base Address of the dQH
+       cyg_uint8       zlt - zero lengh packet termination (enable - ZLT_ENABLE; disable - ZLT_DISABLE)
+       cyg_uint16 mps - Max packet length
+       cyg_uint8       ios - interrupt on Setup
+       cyg_uint32 next_link_ptr - Next Link Pointer, 
+       cyg_uint8       terminate - terminate - TERMINATE; not terminate - NOT_TERMINATE
+       cyg_uint16 total_bytes - Total Bytes to be transfered in this dQH
+       cyg_uint8       ioc - interrupt on complete, set - IOC_SET, not set - IOC_NOTSET
+       cyg_uint8       status - status 
+       cyg_uint32 buffer_ptr0 - Buffer Pointer page 0
+       cyg_uint16 current_offset - current offset
+       cyg_uint32 buffer_ptr1 - Buffer Pointer page 1
+       cyg_uint32 buffer_ptr2 - Buffer Pointer page 1
+       cyg_uint32 buffer_ptr3 - Buffer Pointer page 1
+       cyg_uint32 buffer_ptr4 - Buffer Pointer page 1
+         
+RETURN VALUE:  None            
+IMPORTANT NOTES:None           
+=============================================================================*/
+static void 
+usbs_setup_queuehead(struct dqh_t* qhead)
+{
+    volatile struct dqh_setup_t* dqh_word = (volatile struct dqh_setup_t*) qhead->dqh_base;
+
+    /*Bit31:30 Mult; Bit29 zlt; Bit26:16 mps; Bit15 ios */
+    dqh_word->dqh_word0 = (((cyg_uint32)(qhead->zlt) << 29)|((cyg_uint32)(qhead->mps) <<16) | ((cyg_uint32)(qhead->ios) <<15));
+
+    /*Current dTD Pointer => for hw use, not modified by DCD software */
+    dqh_word->dqh_word1 = 0x0;
+       
+    /*Next dTD Pointer */
+    dqh_word->dqh_word2 = (((qhead->next_link_ptr) & 0xFFFFFFE0) | qhead->terminate);
+       
+    /*Bit30:16 total_bytes; Bit15 ioc; Bit11:10 MultO; Bit7:0 status */        
+    dqh_word->dqh_word3 = ((((cyg_uint32)(qhead->total_bytes) & 0x7FFF)  << 16) | ((cyg_uint32)(qhead->ioc) <<15) | (qhead->status));
+
+    /*Bit31:12 Buffer Pointer (Page 0) */
+    dqh_word->dqh_word4 = ((qhead->buffer_ptr0 & 0xFFFFF000) | (qhead->current_offset & 0xFFF));
+
+    /*Bit31:12 Buffer Pointer (Page 1) */
+    dqh_word->dqh_word5 = (qhead->buffer_ptr1 & 0xFFFFF000);
+       
+    /*Bit31:12 Buffer Pointer (Page 2) */
+    dqh_word->dqh_word6 = (qhead->buffer_ptr2 & 0xFFFFF000);
+
+    /*Bit31:12 Buffer Pointer (Page 3) */
+    dqh_word->dqh_word7 = (qhead->buffer_ptr3 & 0xFFFFF000);
+       
+    /*Bit31:12 Buffer Pointer (Page 4) */
+    dqh_word->dqh_word8 = (qhead->buffer_ptr4 & 0xFFFFF000);
+
+    /*Reserved */
+    dqh_word->dqh_word9 = 0;
+
+    /*Setup Buffer 0 */
+    dqh_word->dqh_word10 = 0;
+
+    /*Setup Buffer 1 */
+    dqh_word->dqh_word11 = 0;
+}
+/*=============================================================================
+FUNCTION: usbs_setup_transdesc
+DESCRIPTION: This function is used to setup the dTD
+ARGUMENTS PASSED:
+       cyg_uint32 dtd_base - Base Address of the dTD
+       cyg_uint32 next_link_ptr - Next Link Pointer, 
+       cyg_uint8       terminate - terminate - TERMINATE; not terminate - NOT_TERMINATE
+       cyg_uint16 total_bytes - Total Bytes to be transfered in this dQH
+       cyg_uint8       ioc - interrupt on complete, set - IOC_SET, not set - IOC_NOTSET
+       cyg_uint8       Status - Status 
+       cyg_uint32 buffer_ptr0 - Buffer Pointer page 0
+       cyg_uint16 current_offset - current offset
+       cyg_uint32 buffer_ptr1 - Buffer Pointer page 1
+       cyg_uint32 buffer_ptr2 - Buffer Pointer page 1
+       cyg_uint32 buffer_ptr3 - Buffer Pointer page 1
+       cyg_uint32 buffer_ptr4 - Buffer Pointer page 1    
+RETURN VALUE:  None            
+IMPORTANT NOTES:None           
+==============================================================================*/
+static void 
+usbs_setup_transdesc(struct dtd_t* td)
+{
+    volatile struct dtd_setup_t* dtd_word = (volatile struct dtd_setup_t *) td->dtd_base;
+
+    /* Bit31:5 Next Link Pointer ; Bit0 terminate */
+    dtd_word->dtd_word0 = ((td->next_link_ptr & 0xFFFFFFE0) | td->terminate);
+
+    /* Bit30:16 total_bytes, Bit15 ioc, Bit7:0 status */
+    dtd_word->dtd_word1 = ((((cyg_uint32)td->total_bytes & 0x7FFF) << 16)| ((cyg_uint32)td->ioc <<15) | (td->status));
+       
+    /* Bit31:12 Buffer Pointer Page 0 ; Bit11:0 Current Offset */
+    dtd_word->dtd_word2 = ((td->buffer_ptr0 & 0xFFFFF000) | (td->current_offset & 0xFFF));
+       
+    /* Bit31:12 Buffer Pointer Page 1 ; Bit10:0 Frame Number */
+    dtd_word->dtd_word3 = (td->buffer_ptr1 & 0xFFFFF000);
+
+    /* Bit31:12 Buffer Pointer Page 2 ; */
+    dtd_word->dtd_word4 = (td->buffer_ptr2 & 0xFFFFF000);
+
+    /* Bit31:12 Buffer Pointer Page 3 ; */
+    dtd_word->dtd_word5 = (td->buffer_ptr3 & 0xFFFFF000);
+
+    /* Bit31:12 Buffer Pointer Page 4 ; */
+    dtd_word->dtd_word6 = (td->buffer_ptr4 & 0xFFFFF000);
+
+}
+
+/*==================================================================================================
+FUNCTION: util_alloc_buffer
+DESCRIPTION:           This utility function allocate the free buffer available
+ARGUMENTS PASSED:      None
+RETURN VALUE:          cyg_uint32 address : address of the allocated buffer    
+IMPORTANT NOTES:       If Buffer1 is FREE then return Buffer1 and mark this as Busy else check for buffer2 . If 
+       none of the buffer is free then return NULL.
+==================================================================================================*/
+cyg_uint32 util_alloc_buffer(void)
+{
+    cyg_uint32 buffer_addr = (cyg_uint32)NULL; //force type conversion for multiple NULL definitions
+    
+    /* Check if buffer1 is free then mark it busy and return address */ 
+    if (g_bulkbuffer_map.buffer1_status == BUFFER_FREE )
+    {
+        buffer_addr = g_bulkbuffer_map.buffer1_address;
+               g_bulkbuffer_map.buffer1_status = BUFFER_IN_USE;
+    }
+    /* Check if buffer2 is free then mark it busy and return address */ 
+    else if(g_bulkbuffer_map.buffer2_status == BUFFER_FREE)
+    {
+        buffer_addr = g_bulkbuffer_map.buffer2_address;
+               g_bulkbuffer_map.buffer2_status = BUFFER_IN_USE;
+    }
+    
+    return buffer_addr ;
+}
+/*==================================================================================================
+FUNCTION:                      util_free_buffer
+DESCRIPTION:           This function put the buffer in free state.
+ARGUMENTS PASSED:      cyg_uint32 address : address of the buffer .    
+RETURN VALUE:          None
+IMPORTANT NOTES:       None
+               
+==================================================================================================*/
+void util_free_buffer(cyg_uint32 address)
+{
+       if( address == g_bulkbuffer_map.buffer1_address )
+    {
+        g_bulkbuffer_map.buffer1_status = BUFFER_FREE;
+    }
+    else if ( address == g_bulkbuffer_map.buffer2_address )
+    {
+        g_bulkbuffer_map.buffer2_status = BUFFER_FREE;
+    }
+}
+/*==================================================================================================
+FUNCTION:                      util_set_bulk_buffer_stat
+DESCRIPTION:           This function change the bulk buffer status
+ARGUMENTS PASSED:      cyg_uint32 buffer_addr: buffer base address
+                                       int buffer_status: new buffer_status
+enum {
+       BUFFER_FREED,
+       BUFFER_RELEASED,
+       BUFFER_ALLOCATED
+};
+RETURN VALUE:          None
+IMPORTANT NOTES:       None
+               
+==================================================================================================*/
+void util_set_status_bulk_buffer(cyg_uint32 buffer_addr,int buffer_status)
+{
+       if( buffer_addr == (cyg_uint32)g_bulkbuffer_a.buffer)
+    {
+        g_bulkbuffer_a.stat = buffer_status;
+    }
+    else if ( buffer_addr == (cyg_uint32)g_bulkbuffer_b.buffer )
+    {
+        g_bulkbuffer_b.stat = buffer_status;
+    }
+       else
+               return;
+}
+/*=============================================================================
+FUNCTION:      usbs_endpoint_stall
+DESCRIPTION: This function Send/Receive the STALL HANDSHAKE to  USB Host
+ARGUMENTS PASSED:
+       cyg_uint8 endpoint  -   Endpoint Number .       
+       cyg_uint8 direction -   IN/OUT :  direction of EndPoint.
+RETURN VALUE:  None
+IMPORTANT NOTES:None           
+==============================================================================*/
+static void
+usbs_endpoint_stall(cyg_uint8 endpoint , cyg_uint8 direction)
+{
+    if( direction == OUT )
+    { 
+       usbs_imx_otg_base->endptctrl[endpoint]|= STALL_RX;
+    }              
+    else 
+    {
+       usbs_imx_otg_base->endptctrl[endpoint] |= STALL_TX;
+    }
+
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - EP%d - %d stalled\n",endpoint,direction);
+}
+
+static void
+usbs_endpoint_unstall(cyg_uint8 endpoint , cyg_uint8 direction)
+{
+       if( direction == OUT )
+    { 
+       usbs_imx_otg_base->endptctrl[endpoint]&= ~STALL_RX;
+    }              
+    else 
+    {
+       usbs_imx_otg_base->endptctrl[endpoint]&= ~STALL_TX;
+    }
+}
+
+/*=============================================================================
+FUNCTION:                      usbs_status_phase
+DESCRIPTION:           This function Send/Receive the Status to/from Host.
+ARGUMENTS PASSED:   cyg_uint8    direction             OUT     Receive Status Command From Host
+                                                                                       IN      Send Status Command to Host
+RETURN VALUE:          None
+IMPORTANT NOTES:       
+===============================================================================*/
+static void 
+usbs_status_phase(cyg_uint8 trans_type, cyg_uint8 direction)
+{
+       usb_buffer_descriptor_t bd ;
+       
+    /* Buffer pointer is not used for EP0 */
+    bd.buffer = (cyg_uint32 *) 0xFFFFFFFF;
+    bd.size = 0x0;
+       
+    if(trans_type==CONTROL)
+    {
+       switch ( direction )
+       {
+                       case OUT :
+                       /*  Receive ZERO length Length Data */
+                       usbs_ep0_receive_data(&bd);
+               break;
+                       case IN :
+                       /* Send ZERO length Length Data */
+                       usbs_ep0_send_data(&bd,0);
+                       break;
+       }
+    }
+    else if(trans_type==BULK)/*TODO*/
+    {
+       switch ( direction )
+       {
+                       case OUT :          
+                       /* Send ZERO length Length Data */
+                       //usbs_ep2_send_data(EP2,&bd,FALSE);
+               break;
+                       case IN :
+                       /*  Receive ZERO length Length Data */
+                       //usbs_ep1_receive_data(EP1,&bd);
+                       break;
+       }
+    } 
+    
+}
+// ---------------------------------------------------------------------------
+// The following static functions are for USB device enumeration processing
+/*============================================================================
+FUNCTION:                              usbs_handle_get_descriptor
+DESCRIPTION:                   This function Handle the GET DESCRIPTOR request
+ARGUMENTS PASSED:      None  
+RETURN VALUE:                  None
+IMPORTANT NOTES:       None            
+============================================================================*/
+static void
+usbs_handle_get_descriptor()
+{
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get descriptor handler\n");
+       switch (g_usb_setup_data[WVALUE_HIGHBYTE])
+       {
+               case DEVICE_DESC:       /* device descriptor*/
+                       usbs_handle_get_device_desc();  //Device will send the MPS to host
+                       break;
+               case CONF_DESC:         /* configuration descriptor*/
+                       usbs_handle_get_config_desc();  //Device will send the whole device descriptor to host
+               break;
+               case STRING_DESC:       /* string descriptor*/
+                       usbs_handle_get_string_desc();
+               break;
+               case INTERFACE_DESC:
+               case ENDPOINT_DESC:
+               case DEVICE_QUALIFIER:
+               case OTHER_SPEED_CONF_DESC:
+               default:        /* Send STALL Handshake  */
+               usbs_endpoint_stall(EP0,IN);
+               break;
+       }
+
+       
+}
+/*=============================================================================
+FUNCTION:                      usbs_handle_get_device_desc
+DESCRIPTION:           This function Handle the GET DEVICE DESCRIPTOR request
+ARGUMENTS PASSED:      None
+RETURN VALUE:          None
+IMPORTANT NOTES:       None            
+==============================================================================*/
+static void 
+usbs_handle_get_device_desc(void)
+{
+    usb_buffer_descriptor_t bd ;
+    cyg_uint32 buffer_addrs;
+    cyg_uint16 desc_length = 0x0;
+    cyg_uint8  zlt = 0;//0 means false
+
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get device descriptor\n");
+    
+    /* get the buffer address for data transfer over EP0 */
+    buffer_addrs = g_bulkbuffer_map.ep0_buffer_addrs;  //256bytes before the two Bulk buffers
+       
+    /* Fill the buffer with the descriptor data */
+    usbs_ep0in_fill_buffer(FILL_DEVICE_DESC,buffer_addrs);
+
+    /* Get the length of descriptor requested */
+    desc_length = g_usb_setup_data[WLENGTH_LOWBYTE];
+    desc_length |= ( g_usb_setup_data[WLENGTH_HIGHBYTE] <<0x8);
+
+    /* If requested length of descriptor is lesser than actual length of descriptor then send 
+     * requested length of descroptor only else send the actual length of descriptor*/
+    if( g_usb_dev_state == USB_DEV_DEFAULT_STATE )
+    {
+        bd.size = MPS_8;
+    }
+    else 
+    {
+        bd.size = USB_DEV_DESC_LEN;
+    }
+
+    /* Send descriptor - Data Phase*/
+    usbs_ep0_send_data(&bd,zlt);       //zlt is false=>not zero length packet
+                                                               //send dev descriptor to host.
+       
+    /* Status Phase -- OUT */
+    usbs_status_phase(CONTROL,OUT); //Get Zero-length data packet from Host, Device sends status: ACK(success), NAK(busy), or STALL(failed)
+
+               
+}
+/*=============================================================================
+FUNCTION:              usbs_handle_get_config_desc
+DESCRIPTION:   This function Handle the GET CONFIGURATION DESCRIPTOR request
+ARGUMENTS PASSED:
+RETURN VALUE:  None
+IMPORTANT NOTES:None           
+=============================================================================*/
+static void 
+usbs_handle_get_config_desc(void)
+{
+       usb_buffer_descriptor_t bd;
+    cyg_uint32 buffer_addrs;
+    cyg_uint16 desc_length_req = 0x0;
+    cyg_uint16 desc_length = 0x0;
+    int zlt = 0;
+
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get config descriptor\n");
+    /* get the buffer address for data transfer over EP0 */
+    buffer_addrs = g_bulkbuffer_map.ep0_buffer_addrs;
+
+       /* Fill the buffer with the descriptor data */
+       usbs_ep0in_fill_buffer(FILL_CONF_DESC, buffer_addrs);
+    
+       /* total length of descriptor */
+       desc_length = ((g_usb_desc.config_desc->usb_config_desc.total_length_lo) \
+                               | ( g_usb_desc.config_desc->usb_config_desc.total_length_hi << 0x8 ));
+    /* Get the length of descriptor requested */
+    desc_length_req = g_usb_setup_data[WLENGTH_LOWBYTE];
+    desc_length_req |= ( g_usb_setup_data[WLENGTH_HIGHBYTE] <<0x8);
+
+
+    /* If requested length of descriptor is lesser than actual length of descriotor then send 
+     * requested length of descroptor only else send the actual length of descriptor*/
+    if(desc_length_req <= desc_length)
+    {
+        bd.size = desc_length_req;
+    }
+    else
+    {
+        bd.size = desc_length;
+
+               if ( bd.size > MPS_64)
+               {
+               zlt = 1;
+               }
+    }
+    usbs_ep0_send_data(&bd,zlt);       
+       
+    /* Status Phase -- OUT */
+    usbs_status_phase(CONTROL,OUT); 
+               
+}
+/*=============================================================================
+FUNCTION:                      usbs_handle_get_string_desc
+DESCRIPTION:           This function Handle the GET STRING DESCRIPTOR request
+ARGUMENTS PASSED:      None
+RETURN VALUE:          None    
+IMPORTANT NOTES:       None            
+==============================================================================*/
+static void 
+usbs_handle_get_string_desc(void)
+{
+       usb_buffer_descriptor_t bd;
+    cyg_uint32 buffer_addrs;
+    cyg_uint16 desc_length_req = 0x0;
+    cyg_uint16 length_of_desc = 0x0;
+    int zlt = 0;
+
+       
+    /* Get Buufer to fill the data to be received/transmitted.    */ 
+    buffer_addrs = g_bulkbuffer_map.ep0_buffer_addrs;
+          
+    /* Get the length of descriptor requested */
+    desc_length_req = g_usb_setup_data[WLENGTH_LOWBYTE];
+    desc_length_req |= ( g_usb_setup_data[WLENGTH_HIGHBYTE] <<0x8);
+
+    switch (g_usb_setup_data[WVALUE_LOWBYTE])
+    {
+        case STR_DES0:
+            usbs_ep0in_fill_buffer(FILL_STR_DES0,buffer_addrs);
+           /* If requested length of descriptor is lesser than actual length of descriotor then send 
+                    * requested length of descroptor only else send the actual length of descriptor*/
+               if(desc_length_req <= g_usb_desc.str_desc0->length )
+               {
+                       bd.size = desc_length_req;
+               }
+               else
+               {
+                               bd.size = g_usb_desc.str_desc0->length;
+                if (  bd.size > MPS_64)
+                       {
+                       zlt = 1;
+                       }
+               }
+               /* Data Phase -- IN */
+               usbs_ep0_send_data(&bd,zlt);            
+               /* Status Phase -- OUT */
+               usbs_status_phase(CONTROL,OUT);    
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get string descriptor 0\n");
+               break;
+        
+        case STR_DES1:         /*iManufacturer */
+            usbs_ep0in_fill_buffer(FILL_STR_DES1,buffer_addrs);
+               /* If requested length of descriptor is lesser than actual length of descriotor then send 
+                * requested length of descroptor only else send the actual length of descriptor*/
+                   if(desc_length_req <= g_usb_desc.str_desc1->length )
+                   {
+                   bd.size = desc_length_req;
+               }
+               else
+               {
+                               bd.size = g_usb_desc.str_desc1->length;
+                if (  bd.size > MPS_64) 
+                               {
+                       zlt = 1;
+                       }
+               }
+               /* Data Phase -- IN */
+               usbs_ep0_send_data(&bd,zlt);    
+                   /* Status Phase -- OUT */
+                   usbs_status_phase(CONTROL,OUT); 
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get string descriptor 1\n");
+           break;
+        
+        case STR_DES2:         /*iProduct */
+            usbs_ep0in_fill_buffer(FILL_STR_DES2,buffer_addrs );
+                       length_of_desc = g_usb_desc.str_desc2->length; 
+                   /* If requested length of descriptor is lesser than actual length of descriotor then send 
+               * requested length of descroptor only else send the actual length of descriptor*/
+                   if(desc_length_req <= length_of_desc )
+                   {
+                   bd.size = desc_length_req;
+                   }
+                   else
+               {
+                               bd.size = length_of_desc;
+                if (  bd.size > MPS_64)
+                   {
+                           zlt = 1;
+                       }
+                   }
+                   /* Data Phase -- IN */
+               usbs_ep0_send_data(&bd,zlt);    
+                   /* Status Phase -- OUT */
+                   usbs_status_phase(CONTROL,OUT);     
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get string descriptor 2\n");
+                   break;
+        
+        case STR_DES3: 
+                       /* send zero length data */
+                       usbs_status_phase(CONTROL,IN);
+                       /* Status Phase -- OUT */
+            usbs_status_phase(CONTROL,OUT);
+                       break;
+        
+        case STR_DES5:         /*iSerialNumber */
+                       #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+            usbs_ep0in_fill_buffer(FILL_SN_DESC,buffer_addrs );
+                   /* If requested length of descriptor is lesser than actual length of descriotor then send 
+                       * requested length of descroptor only else send the actual length of descriptor*/
+                   if(desc_length_req <= g_usb_desc.sn_desc->length )
+                   {
+                   bd.size = desc_length_req;
+                   }
+                   else
+                   {
+                               bd.size = g_usb_desc.sn_desc->length;
+                if (  bd.size > MPS_64)
+                       {
+                           zlt = 1;
+                       }
+                   }
+               /* Data Phase -- IN */
+                   usbs_ep0_send_data(&bd,zlt);        
+                   /* Status Phase -- OUT */
+                   usbs_status_phase(CONTROL,OUT); 
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get string descriptor - SN\n");
+                   break;
+                       #endif
+               case STR_DES4:          /*iSerialNumber */
+                       usbs_ep0in_fill_buffer(FILL_STR_DES3,buffer_addrs );
+                   /* If requested length of descriptor is lesser than actual length of descriotor then send 
+                       * requested length of descroptor only else send the actual length of descriptor*/
+                   if(desc_length_req <= g_usb_desc.str_desc3->length )
+                   {
+                   bd.size = desc_length_req;
+                   }
+                   else
+                   {
+                               bd.size = g_usb_desc.str_desc3->length;
+                if (  bd.size > MPS_64)
+                       {
+                           zlt = 1;
+                       }
+                   }
+               /* Data Phase -- IN */
+                   usbs_ep0_send_data(&bd,zlt);        
+                   /* Status Phase -- OUT */
+                   usbs_status_phase(CONTROL,OUT); 
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get string descriptor 3\n");
+                   break;
+               default:
+               /* Send STALL Handshake  */
+                   usbs_endpoint_stall(EP0,IN);
+                       //USBDBGMSG("+USBDBGMSG:EP0 IN stalled at get string desc\n");
+                   break;
+    }
+
+               
+}
+
+/*=============================================================================
+FUNCTION:              usbs_handle_set_address
+DESCRIPTION:           This function Handle the SET ADDRESS Request from USB Host
+ARGUMENTS PASSED:      None
+RETURN VALUE:          None
+IMPORTANT NOTES:       
+==============================================================================*/
+static void 
+usbs_handle_set_address(void)
+{
+               cyg_uint16 device_addrs;
+
+               USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - set address handler\n");   
+    /* Get the Device Address to be SET from the Setup Data  */
+    device_addrs = g_usb_setup_data[WVALUE_LOWBYTE] + (g_usb_setup_data[WVALUE_HIGHBYTE]<<8);
+       
+    if ((g_usb_setup_data[WINDEX_LOWBYTE] == 0) &&
+               (g_usb_setup_data[WINDEX_HIGHBYTE] == 0) &&
+               (g_usb_setup_data[WLENGTH_LOWBYTE] == 0) &&
+               (g_usb_setup_data[WLENGTH_HIGHBYTE] == 0) &&
+               (device_addrs <= USB_MAX_DEVICE_ADDR))
+    { 
+        switch(g_usb_dev_state)
+               {
+               case USB_DEV_DEFAULT_STATE :
+                               /* Send Ack to Host */
+                               usbs_status_phase(CONTROL,IN);
+                               if (device_addrs != USB_DEFAULT_ADDR)
+                               {
+                                       /* Set the Device Address */
+                       USBS_DEVICE_SET_ADDRESS(device_addrs);
+                                       /* Change state to ADDRESSED STATE  */
+                                       g_usb_dev_state  = USB_DEV_ADDRESSED_STATE;
+                               }
+                       break;
+               
+                       case USB_DEV_ADDRESSED_STATE :
+                               /* Send Ack to Host */
+                               usbs_status_phase(CONTROL,IN);
+                               if ( device_addrs == USB_DEFAULT_ADDR )
+                               {
+                               /* Set the Device Address */
+                               USBS_DEVICE_SET_ADDRESS(USB_DEFAULT_ADDR);
+                                       /* Change state to ADDRESSED STATE  */
+                                       g_usb_dev_state = USB_DEV_DEFAULT_STATE;    
+                       }
+                               else
+                               {
+                                       /* Set the Device Address */
+                                       USBS_DEVICE_SET_ADDRESS(device_addrs);
+                               }
+                               break;
+       
+           case USB_DEV_CONFIGURED_STATE :
+                       if ( device_addrs == USB_DEFAULT_ADDR)
+                               {
+                                       /* Send Ack to Host */
+                                       usbs_status_phase(CONTROL,IN);
+                                       /* Set the Device Address */
+                                       USBS_DEVICE_SET_ADDRESS(device_addrs);
+                                       /* Change state to ADDRESSED STATE  */
+                                       g_usb_dev_state = USB_DEV_DEFAULT_STATE;    
+                               }
+                               else
+                               {
+                                       /* Send STALL Handshake  */ 
+                                       usbs_endpoint_stall(EP0,IN);
+                               }
+                       default :
+                               break;
+               }
+    }
+    else
+    {
+        /* Send STALL Handshake */
+        usbs_endpoint_stall(EP0,IN);
+    }
+
+               
+}
+/*=============================================================================
+FUNCTION:                      usbs_handle_get_configuration
+DESCRIPTION:           This function Handle the GET CONFIGURATION request
+ARGUMENTS PASSED:      None  
+RETURN VALUE:          None    
+IMPORTANT NOTES:       None            
+=============================================================================*/
+static void 
+usbs_handle_get_configuration(void)
+{
+       usb_buffer_descriptor_t bd;
+       cyg_uint32 buffer_addrs;
+    cyg_uint32* buffer_ptr;
+    if((g_usb_setup_data[WINDEX_LOWBYTE] == 0) &&
+        (g_usb_setup_data[WINDEX_HIGHBYTE] == 0) &&
+               (g_usb_setup_data[WVALUE_LOWBYTE] == 0) &&
+               (g_usb_setup_data[WVALUE_HIGHBYTE] == 0) &&
+               (g_usb_setup_data[WLENGTH_LOWBYTE] == LEN_OF_CONFIG_VALUE) &&
+               (g_usb_setup_data[WLENGTH_HIGHBYTE] == 0)) 
+    {
+        switch(g_usb_dev_state)
+               {
+               case USB_DEV_DEFAULT_STATE :
+                       /* Send STALL Handshake */
+                       usbs_endpoint_stall(EP0,IN);
+                               break;
+               case USB_DEV_ADDRESSED_STATE:
+                               /* If the Device is in Address state then return 0x0 : See USB2.0 Spec */
+                               buffer_addrs = g_bulkbuffer_map.ep0_buffer_addrs;
+                               buffer_ptr = (cyg_uint32 *)buffer_addrs;
+                               *buffer_ptr = 0x0;
+
+                               bd.buffer = buffer_ptr;
+                               bd.size=LEN_OF_CONFIG_VALUE;
+
+                               usbs_ep0_send_data(&bd,0);
+
+                               /* Receive Ack from Host*/
+                               usbs_status_phase(CONTROL,OUT);
+                               break;
+
+                       case USB_DEV_CONFIGURED_STATE:
+                               buffer_addrs = g_bulkbuffer_map.ep0_buffer_addrs;
+                buffer_ptr = (cyg_uint32 *)buffer_addrs;
+
+                               *buffer_ptr = (cyg_uint32 )g_usb_desc.config_desc->usb_config_desc.configuration_id;
+
+                               bd.buffer = buffer_ptr;
+                               bd.size=LEN_OF_CONFIG_VALUE;
+
+                               usbs_ep0_send_data(&bd,0);
+               
+                               /* Receive Ack from Host*/
+                               usbs_status_phase(CONTROL,OUT);
+                               break;
+
+                       default:
+                       /* Send STALL Handshake */
+                       usbs_endpoint_stall(EP0,IN);
+               }
+
+    } 
+
+               USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - get config handler\n");
+}
+/*=============================================================================
+FUNCTION:                      usbs_handle_set_configuration
+DESCRIPTION:           This function Handle the SET CONFIGURATION request
+ARGUMENTS PASSED:      None  
+RETURN VALUE:          None    
+IMPORTANT NOTES:       None            
+=============================================================================*/
+static void 
+usbs_handle_set_configuration(void)
+{
+       usb_end_pt_info_t config_data ; 
+    cyg_uint8 i;
+
+    switch (g_usb_dev_state)
+    {
+               case USB_DEV_ADDRESSED_STATE :
+                       if (g_usb_setup_data[WVALUE_LOWBYTE] == USB_DEV_VALUE_OF_UNCONFIG)
+                       {       
+                               /* Send Ack to Host*/
+                               usbs_status_phase(CONTROL,IN);
+                   }
+            /* Check if the configuration value received request is same as in Config descriptor */
+                   else if(g_usb_setup_data[WVALUE_LOWBYTE] == g_usb_desc.config_desc->usb_config_desc.configuration_id)
+                   {
+                               /* Configure endpoints */
+                               for ( i = 0 ; i< g_number_of_endpoints ; i++)
+                               {
+                               config_data.end_pt_no           = g_end_pt_info[i].end_pt_no; 
+                               config_data.direction           = g_end_pt_info[i].direction;
+                               config_data.transfer_type       = g_end_pt_info[i].transfer_type;
+                               config_data.max_pkt_size        = g_end_pt_info[i].max_pkt_size;
+               
+                                       usbs_imx_otg_dev_set_configuration(&config_data);
+                               }
+
+                               /* Send Ack to Host*/
+                               usbs_status_phase(CONTROL,IN);
+
+                               g_usb_dev_state = USB_DEV_CONFIGURED_STATE ;
+               }
+               else
+               {
+                               /* Invalid configuration value.  Send STALL Handshake */
+                       usbs_endpoint_stall(EP0,IN);
+                               //USBDBGMSG("+USBDBGMSG:EP0 IN stalled at set conf in addr state\n");
+               }
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - set conf@ADDRESSED_STATE\n");
+                       break;  
+               case USB_DEV_CONFIGURED_STATE :
+               if(g_usb_setup_data[WVALUE_LOWBYTE] == USB_DEV_CONFIG_DESC_CONFIG_VALUE)
+               {
+                               /* Send Ack to Host*/
+                               usbs_status_phase(CONTROL,IN);
+               }
+               else if (g_usb_setup_data[WVALUE_LOWBYTE] == USB_DEV_VALUE_OF_UNCONFIG)
+               {       
+                               /* Send Ack to Host*/
+                               usbs_status_phase(CONTROL,IN);
+
+                               /* Change USB State to Addressed State  */
+                               g_usb_dev_state = USB_DEV_ADDRESSED_STATE;
+               }
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - set conf@CONFIGURED_STATE\n");
+                       break;
+               default :
+               /* Send STALL Handshake */
+               usbs_endpoint_stall(EP0,IN);
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - set conf@incorrect state\n");
+               break;  
+    }
+
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: enum - set config handler\n");
+}
+/*=============================================================================
+FUNCTION:                      usbs_handle_msc_get_maxlun
+DESCRIPTION:           This function Handle the GET MAX LUN Mass Storage class
+                               specific request
+ARGUMENTS PASSED:      None  
+RETURN VALUE:          None    
+IMPORTANT NOTES:       None            
+=============================================================================*/
+static void 
+usbs_handle_msc_get_maxlun(void)
+{
+       usb_buffer_descriptor_t bd ;
+    cyg_uint32 buffer_addrs;
+    cyg_uint16 desc_length = 0x0;
+    cyg_uint8  zlt = 0;//0 means false
+       cyg_uint8 Max_Lun=0;
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: MASS - Get MAX LUN\n");
+    
+    /* get the buffer address for data transfer over EP0 */
+    buffer_addrs = g_bulkbuffer_map.ep0_buffer_addrs;  //256bytes before the two Bulk buffers
+
+    /* Get the length of descriptor requested */
+    desc_length = g_usb_setup_data[WLENGTH_LOWBYTE];
+    desc_length |= ( g_usb_setup_data[WLENGTH_HIGHBYTE] <<0x8);
+
+    /* If requested length of descriptor is zero*/
+       if(desc_length==0)
+       {
+               /* Fill the buffer with the descriptor data */
+               *(cyg_uint8 *)buffer_addrs = 0;//Max_Lun;
+               bd.size = 0; 
+       }
+       else
+       {
+               /* Fill the buffer with the descriptor data */
+               *(cyg_uint8 *)buffer_addrs = Max_Lun;
+               bd.size = desc_length;
+       }
+       
+    /* Send descriptor - Data Phase*/
+    usbs_ep0_send_data(&bd,zlt);       //zlt is false=>not zero length packet
+                                                               //send dev descriptor to host.
+       
+    /* Status Phase -- OUT */
+    usbs_status_phase(CONTROL,OUT); //Get Zero-length data packet from Host, Device sends status: ACK(success), NAK(busy), or STALL(failed)
+
+               
+}
+/*=============================================================================
+FUNCTION:              usbs_ep0in_fill_buffer
+DESCRIPTION:   This function is used to fill the corresponding 
+                               response for the data phase of SETUP Transfer
+ARGUMENTS PASSED:
+                               cyg_uint8 type: type of descriptor
+                               cyg_uint32 buffer_addrs - buffer pointer to be filled    
+RETURN VALUE:  None
+IMPORTANT NOTES:None
+=============================================================================*/
+static void 
+usbs_ep0in_fill_buffer(cyg_uint8 type, cyg_uint32 buffer_addrs)
+{
+    const cyg_uint8 *data=0;
+    cyg_uint32 *buffer_page = (cyg_uint32*)buffer_addrs;    
+    int k = 0;
+       //USBDBGMSG("+USBDBGMSG: enum - copy descriptor to buffer\n");
+    switch (type)
+    {
+        case FILL_DEVICE_DESC: /*5*32 bit */
+               data = (cyg_uint8 *)g_usb_desc.device_desc;
+           break;
+               case FILL_CONF_DESC:            /*8*32 bit */
+                   data = (cyg_uint8 *)g_usb_desc.config_desc;
+               break;  
+               case FILL_STR_DES0:             /*1*32 bit */
+               data = (cyg_uint8 *)g_usb_desc.str_desc0;
+               break;  
+               case FILL_STR_DES1:             /*7*32 bit */
+                   data =(cyg_uint8 *)g_usb_desc.str_desc1; 
+               break;  
+               case FILL_STR_DES2:             /*7*32 bit */
+                       data = (cyg_uint8 *)g_usb_desc.str_desc2;
+                   break;      
+               case FILL_STR_DES3:             /*6*32 bit */
+                   data = (cyg_uint8 *)g_usb_desc.str_desc3;
+               break;
+               #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+               case FILL_SN_DESC:
+                       data = (cyg_uint8 *)g_usb_desc.sn_desc;
+                       break;
+               #endif
+    }
+    
+    for (k=0; k<(MPS_64/sizeof(cyg_uint32)); k++)
+    {
+        *buffer_page = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24); 
+                                //USBDBGMSG("+USBDBGMSG: desc[k] = 0x%x\n",(*buffer_page));
+         buffer_page++;
+                                data += 4;
+                               
+    }
+
+               
+}
+
+/*=============================================================================
+FUNCTION:                      usbs_ep0_init_dqh
+DESCRIPTION:           This function is used to initialize the queue header of EP0
+ARGUMENTS PASSED:      NONE                             
+RETURN VALUE:          NONE
+IMPORTANT NOTES:       called by usbs_imx_otg_dev_ep0_init(),usbs_imx_otg_dev_handle_bus_reset()
+=============================================================================*/
+static void
+usbs_ep0_init_dqh(void)
+{
+       struct dqh_t qhead;
+       cyg_uint32 total_bytes;
+       volatile cyg_uint32 * ep_q_hdr_base;
+       cyg_int8 i;
+       
+       //clear queue header
+       ep_q_hdr_base = ((volatile cyg_uint32 *)g_bulkbuffer_map.ep_dqh_base_addrs);
+       /* Clear the dQH Memory */
+    for ( i = 0; i < (SIZE_OF_QHD*g_max_ep_supported*2)/sizeof(cyg_uint32) ; i++)
+    {
+        *ep_q_hdr_base++ = 0;
+    }
+    
+     /******************************************************************************
+    / =================
+    / dQH0 for EP0OUT
+    / =================
+    / Initialize device queue heads in system memory
+    / 8 bytes for the 1st setup packet */
+       
+    total_bytes                                        = 0x8;
+    qhead.dqh_base                             = USBS_EP_GET_dQH(EP0,OUT);
+    qhead.zlt                                  = ZLT_DISABLE;
+    qhead.mps                                  = MPS_64;
+    qhead.ios                                  = IOS_SET;
+    qhead.next_link_ptr = USBS_EP_GET_dTD(EP0,OUT);
+    qhead.terminate            = NOT_TERMINATE;
+    qhead.total_bytes          = total_bytes;
+    qhead.ioc                                  = IOC_SET;
+    qhead.status                               = NO_STATUS;
+    qhead.buffer_ptr0          = 0;
+    qhead.current_offset= 0;
+    qhead.buffer_ptr1          = 0;
+    qhead.buffer_ptr2  = 0;
+    qhead.buffer_ptr3          = 0;
+    qhead.buffer_ptr4  = 0;
+    /* Set Device Queue Head */
+    usbs_setup_queuehead(&qhead);
+
+    /* ==================
+    END of dQH0 setup
+    ====================*/
+     /*=================
+    dQH1 for EP0IN
+    ================= */
+
+    total_bytes                = 0x8;
+    qhead.dqh_base             = USBS_EP_GET_dQH(EP0,IN);
+    qhead.zlt                  = ZLT_DISABLE;
+    qhead.mps                  = MPS_64;
+    qhead.ios                  = IOS_SET;
+    qhead.next_link_ptr = USBS_EP_GET_dTD(EP0,IN);
+    qhead.terminate    = TERMINATE;
+    qhead.total_bytes          = total_bytes;
+    qhead.ioc                  = IOC_SET;
+    qhead.status               = NO_STATUS;
+    qhead.buffer_ptr0          = g_bulkbuffer_map.ep0_buffer_addrs;
+    qhead.current_offset= (g_bulkbuffer_map.ep0_buffer_addrs & 0xFFF);
+    qhead.buffer_ptr1          = 0;
+    qhead.buffer_ptr2  = 0;
+    qhead.buffer_ptr3          = 0;
+    qhead.buffer_ptr4  = 0;
+
+    /* Set Device Queue Head */
+    usbs_setup_queuehead(&qhead);
+
+    /* ==================
+    /  END of dQH1 setup
+    /  ================*/
+}
+/*=============================================================================
+FUNCTION:                      usbs_ep0_send_data 
+DESCRIPTION:           This function Send Data to host through EP0-IN Pipe.
+ARGUMENTS PASSED:
+       usb_buffer_descriptor_t *bd : This is the pointer to the buffer descriptor. 
+       cyg_uint8 zlt                           : Flag to decide if Zero Length Packet to be sent
+RETURN VALUE:
+       USB_SUCCESS - The buffer was successfully processed by the USB device and 
+                                       data sent to the Host.
+       USB_FAILURE - Some failure occurred in transmitting the data.
+IMPORTANT NOTES:       None            
+=============================================================================*/
+static usb_status_t 
+usbs_ep0_send_data(usb_buffer_descriptor_t* bd,cyg_uint8 zlt)
+{
+       struct dtd_t td;
+    cyg_uint32 total_bytes ;
+    cyg_uint32 dtd_address,dqh_address;
+    
+    usb_status_t status = USB_FAILURE;
+
+       /* Get Device Transfer Descriptor of the requested endpoint */
+       dtd_address = USBS_EP_GET_dTD(EP0,IN);
+    
+       /* Get Device Queue head of the requested endpoint */
+       dqh_address = USBS_EP_GET_dQH(EP0,IN);
+
+       /* Get Total Bytes to Be recieved */
+       total_bytes = bd->size;
+
+       /* Setup Transfer Descriptor for EP0 IN*/
+       td.dtd_base             = dtd_address; 
+       td.next_link_ptr        = 0;
+       td.terminate            = TERMINATE;
+       td.total_bytes          = total_bytes;
+       td.ioc                          = IOC_SET;
+       td.status                       = ACTIVE;
+       td.buffer_ptr0          = g_bulkbuffer_map.ep0_buffer_addrs;
+       td.current_offset       = (g_bulkbuffer_map.ep0_buffer_addrs & 0xFFF);
+       td.buffer_ptr1          = 0;
+       td.buffer_ptr2          = 0;
+       td.buffer_ptr3          = 0;
+       td.buffer_ptr4          = 0;
+              
+       /* Set the transfer descriptor */       
+       usbs_setup_transdesc(&td);
+          
+       /* Enable ZLT when data size is in multiple of Maximum Packet Size  */
+       if(zlt)
+       {
+               /* set ZLT enable */
+               (*(volatile cyg_uint32*)(dqh_address)) &= ~0x20000000;
+       }
+           
+       /* 1. write dQH next ptr and dQH terminate bit to 0  */
+       *(volatile cyg_uint32*)(dqh_address+0x8)= (dtd_address); 
+           
+       /* 2. clear active & halt bit in dQH */
+       *(volatile cyg_uint32*)(dqh_address+0xC) &= ~0xFF;
+          
+       /* 3. prime endpoint by writing '1' in ENDPTPRIME */
+       usbs_imx_otg_base->endptprime |= BIT16;
+    
+       /* wait for complete set and clear */
+       while (!(usbs_imx_otg_base->endptcomplete & EPIN_COMPLETE));
+       
+       usbs_imx_otg_base->endptcomplete = EPIN_COMPLETE;
+       
+       status = USB_SUCCESS;
+
+       return status;
+}
+/*=============================================================================
+FUNCTION: usbs_ep0_recevie_data
+DESCRIPTION:   This function Handle the Status Token (IN/OUT) from USB Host
+ARGUMENTS PASSED:
+       usb_buffer_descriptor_t *bd : This is the pointer to the buffer descriptor. 
+RETURN VALUE:
+       USB_SUCCESS -   : The buffer was successfully processed by the USB device and 
+                                                       data is received from the host.
+       USB_FAILURE -   : Some failure occurred in receiving the data.
+       USB_INVALID -   : If the endpoint is invalid.
+IMPORTANT NOTES:None           
+=============================================================================*/
+static usb_status_t usbs_ep0_receive_data(usb_buffer_descriptor_t* bd)
+{
+               struct dtd_t td;
+    usb_status_t status = USB_FAILURE;
+    cyg_uint32 total_bytes;
+    cyg_uint32 dtd_address;
+    cyg_uint32 dqh_address;
+
+               /* Get Device Device Queue Head of the requested endpoint */
+    dqh_address = USBS_EP_GET_dQH(EP0, OUT);
+        
+               /* Get Device Transfer Descriptor of the requested endpoint */
+    dtd_address = USBS_EP_GET_dTD(EP0, OUT);
+
+               /* Get the total bytes to be received   */
+               total_bytes             = bd->size; 
+               
+               td.dtd_base                     = dtd_address;
+               td.next_link_ptr        = dtd_address + 0x20;
+               td.terminate            = TERMINATE;
+               td.total_bytes          = total_bytes;
+               td.ioc                          = IOC_SET;
+               td.status                       = ACTIVE;
+               td.buffer_ptr0          = g_bulkbuffer_map.ep0_buffer_addrs;
+               td.current_offset       = (g_bulkbuffer_map.ep0_buffer_addrs & 0xFFF);
+               td.buffer_ptr1          = 0;
+               td.buffer_ptr2          = 0;
+               td.buffer_ptr3          = 0;
+               td.buffer_ptr4          = 0;
+               
+       /* Set the Transfer Descriptor  */
+       usbs_setup_transdesc(&td);
+
+       /* 1. write dQH next ptr and dQH terminate bit to 0 */
+       *(volatile cyg_uint32*)(dqh_address+0x8)= dtd_address;
+           
+       /* 2. clear active & halt bit in dQH */
+       *(volatile cyg_uint32*)(dqh_address+0xC) &= ~0xFF;
+           
+       /* 3. prime endpoint by writing '1' in ENDPTPRIME */
+       usbs_imx_otg_base->endptprime |= (  EPOUT_PRIME << EP0 );
+
+       /* 4. Wait for the Complete Status */
+       while (!((usbs_imx_otg_base->endptprime) & ( EPOUT_COMPLETE << EP0)));
+           
+       /*clear the complete status */
+       usbs_imx_otg_base->endptprime = (EPOUT_COMPLETE << EP0);
+   
+       status = USB_SUCCESS;
+
+       return status;
+}
+// ****************************************************************************
+// -----------------------Endpoint 0 Functions---------------------------------
+// ****************************************************************************
+/*=============================================================================
+// This is where all the hard work happens. It is a very large routine
+// for a DSR, but in practice nearly all of it is nested if's and very
+// little code actually gets executed. Note that there may be
+// invocations of callback functions and the driver has no control
+// over how much time those will take, but those callbacks should be
+// simple.
+// so far, ep0 DSR works only during enumeration here.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_ep0_dsr(void)
+{
+       usb_buffer_descriptor_t bd ;
+       usb_status_t status = USB_FAILURE;
+       volatile struct dqh_setup_t * dqh_word ;
+       cyg_uint32 dqh_address;
+       cyg_uint32 temp;
+       
+       //USBDBGMSG("+USBDBGMSG: enter ep0 dsr.\n");
+       /* 1. Receive Setup Data*/
+       bd.buffer = (cyg_uint32 *)g_usb_setup_data;
+       bd.size   = 0;
+       
+       /* Get the Device Queue Head Address for EP0 OUT   */ 
+       dqh_address = USBS_EP_GET_dQH(EP0,OUT);
+       dqh_word = (volatile struct dqh_setup_t*)dqh_address;
+  
+       /* write '1' to clear corresponding bit in ENDPTSETUPSTAT */
+       temp = usbs_imx_otg_base->endptsetupstat;
+       usbs_imx_otg_base->endptsetupstat = temp;           
+
+//     if(usbs_imx_otg_base->endptsetupstat & BIT0)
+//             usbs_imx_otg_base->endptsetupstat = BIT0;           
+       
+       do{
+           /* write '1' to Setup Tripwire (SUTW) in USBCMD register */
+           usbs_imx_otg_base->usbcmd |= BIT13;
+               
+           /* Copy the SetupBuffer into local software byte array */
+           temp  = (dqh_word->dqh_word10);
+
+         *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )(temp & 0x000000FF);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )((temp & 0x0000FF00)>>8);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )((temp & 0x00FF0000)>>16);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )((temp & 0xFF000000)>>24);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+         
+               temp  = (dqh_word->dqh_word11);
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )(temp & 0x000000FF);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )((temp & 0x0000FF00)>>8);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )((temp & 0x00FF0000)>>16);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+               *((cyg_uint8 *)(bd.buffer)) = (cyg_uint8 )((temp & 0xFF000000)>>24);
+               (bd.buffer) =(cyg_uint8 *)(bd.buffer) + 1;
+       }while (!(usbs_imx_otg_base->usbcmd & BIT13));  
+       
+       /* Write '0' to clear SUTW in USBCMD register */
+       usbs_imx_otg_base->usbcmd &= ~BIT13;
+       status = USB_SUCCESS;
+
+       #if 0
+       USBDBGMSG("+USBDBGMSG: setup packet:(LSB)");
+       for(temp=0;temp<8;temp++)
+       {
+               USBDBGMSG("%02X",g_usb_setup_data[temp]);
+       }
+       USBDBGMSG("(MSB)\n");
+       #endif
+       
+       /* 2. Process Setup Data*/
+       /* switch construct to handle different request*/
+       /* Parser the Setup Request Type */
+       switch (g_usb_setup_data[BREQUEST])             
+       { 
+               case USB_GET_DESCRIPTOR:
+                       /* Handle the GET DESCRIPTOR Request */
+                       usbs_handle_get_descriptor();
+           break;
+       
+               case USB_SET_ADDRESS:
+                       /* Handle the SET ADDRESS Request */
+                       usbs_handle_set_address();
+                       break;
+           
+               case USB_SET_CONFIGURATION:
+                       /* Handle the SET CONFIGURATION Request */
+                       if ((g_usb_setup_data[WINDEX_LOWBYTE] == 0)     &&
+                               (g_usb_setup_data[WINDEX_HIGHBYTE] == 0)&&
+                               (g_usb_setup_data[WLENGTH_LOWBYTE] == 0)&&
+                               (g_usb_setup_data[WLENGTH_HIGHBYTE] == 0)&&
+                               (g_usb_setup_data[WVALUE_HIGHBYTE] == 0)) 
+                       {
+                               usbs_handle_set_configuration();
+                       }
+                       else
+                       {
+                               /* Send STALL Handshake   */
+                               usbs_endpoint_stall(EP0,IN);
+                               //USBDBGMSG("+USBDBGMSG:EP0 IN stalled at set conf in ep0 dsr\n");
+               }
+               break;
+           
+               case USB_GET_CONFIGURATION:
+                       /* GET CONFIGURATION request handler */
+                       usbs_handle_get_configuration();
+                       break;
+               case USB_MSC_GET_MAX_LUN:
+                       usbs_handle_msc_get_maxlun();
+                       break;
+               case USB_MSC_BOT_RESET:
+                       
+               default:
+                       /* Send STALL Handshake   */
+               usbs_endpoint_stall(EP0,IN);                    
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG:EP0 IN stalled in ep0 dsr\n");
+                       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG:Setup Request Type 0x%02x,0x%02X\n",g_usb_setup_data[BMREQUESTTYPE],g_usb_setup_data[BREQUEST]);
+               break;
+       }
+       
+       USBDBGMSG(DEBUG_ENUM,"+USBDBGMSG: ep0 dsr\n");
+}
+/*=============================================================================
+// Endpoint 0 initialization.
+// Control Endpoint, bi-direction
+// This may get called during system start-up or following a reset
+// from the host.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_ep0_init(void)
+{
+       /*initialize Endpoint 0 Queue Header*/
+       usbs_ep0_init_dqh();
+
+       {
+               /*fill the structure for ep0*/
+               if ((EP0_STATE_IDLE != ep0.ep_state) &&
+       ((usbs_control_return (*)(usbs_control_endpoint*, int)) 0 != ep0.common.complete_fn)) 
+    {
+               #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+          (*ep0.common.complete_fn)(&ep0.common, -EPIPE);
+               #endif
+    }
+    ep0.common.state            = USBS_STATE_POWERED;
+    memset(ep0.common.control_buffer, 0, 8);
+    ep0.common.buffer           = (unsigned char*) 0;
+    ep0.common.buffer_size      = 0;
+    ep0.common.fill_buffer_fn   = (void (*)(usbs_control_endpoint*)) 0;
+    ep0.common.fill_data        = (void*) 0;
+    ep0.common.fill_index       = 0;
+    ep0.common.complete_fn      = (usbs_control_return (*)(usbs_control_endpoint*, int)) 0;
+    ep0.ep_state                = EP0_STATE_IDLE;
+    ep0.length                  = 0;
+    ep0.transmitted             = 0;
+       }
+}
+// ----------------------------------------------------------------------------
+/*=============================================================================
+// The start function is called by higher-level code when things have
+// been set up, i.e. the enumeration data is available, appropriate
+// handlers have been installed for the different types of control
+// messages, and communication with the host is allowed to start. The
+// next event that should happen is a reset operation from the host,
+// so all other interrupts should be blocked. However it is likely
+// that the hardware will detect a suspend state before the reset
+// arrives, and hence the reset will act as a resume as well as a
+// reset.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_ep0_start(usbs_control_endpoint* endpoint)
+{
+       cyg_uint32 temp;
+       
+       CYG_ASSERT( endpoint == &ep0.common, "USB startup involves the wrong endpoint");
+       
+       /*clear all interrupt status bits*/
+       temp = usbs_imx_otg_base->usbsts;
+       usbs_imx_otg_base->usbsts = temp;               //clear all the previous interrupts
+       
+       /*enable all the sub-interrupt sources for USB device*/
+       USBS_IMX_OTG_INTR_UNMASK(IMX_USB_INTR_DEV_PCE|IMX_USB_INTR_DEV_RESET|IMX_USB_INTR_DEV_USBINT);
+       
+       /*set Run/Stop bit to Run Mode*/
+       usbs_imx_otg_base->usbcmd |= BIT0;      
+
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: mx37 ep0 start.\n");
+}
+// ****************************************************************************
+// -----------------------Endpoint 1 Functions---------------------------------
+// ****************************************************************************
+/*=============================================================================
+// Complete a transfer. This takes care of invoking the completion
+// callback and resetting the buffer.
+=============================================================================*/
+static void
+ep1_rx_complete(int result)
+{
+       //cyg_uint32 total_bytes;
+       cyg_uint32 dtd_address;
+       cyg_uint32 dqh_address;
+       cyg_uint32 received_buffer_addrs = 0x0;
+       cyg_uint32 received_data_length = 0x0;
+       cyg_uint32* temp = 0x0;    
+
+       int i;
+       
+       if(g_usb_dev_state != USB_DEV_CONFIGURED_STATE) 
+               return; //EP1 only receives data when the USB device has been configured
+       
+       if(ep1.common.buffer == NULL)
+       {
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_rx_complete: NULL buffer \n");
+               return; //there is not a buffer used to store the data from host
+       }       
+       
+       /* Get Device Device Queue Head of the out endpoint */
+       dqh_address = USBS_EP_GET_dQH(EP1,OUT);
+        
+       /* Get Device Transfer Descriptor of the out endpoint */
+       dtd_address = USBS_EP_GET_dTD(EP1,OUT);
+       
+       /*clear the complete status */
+       usbs_imx_otg_base->endptcomplete |= (EPOUT_COMPLETE << EP1);
+
+       //received_buffer_addrs = (*((unsigned int *)dtd_address + 2)) & 0xFFFFF000;
+       received_buffer_addrs = (cyg_uint32)ep1.common.buffer;
+       USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_rx_complete: received_buffer_addrs 0x%08X \n",received_buffer_addrs);
+       if( received_buffer_addrs == 0)
+       {
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_rx_complete: NULL rx buffer \n");
+               return;
+       }
+               
+       /* calculate the received data length using number of bytes left in TD */
+       temp =  (cyg_uint32 *)dtd_address;
+       temp++;                 //pointer to total bytes in dtd, second work in dTD
+       received_data_length = (ep1.common.buffer_size - (((*temp) >> 16 )&0x7FFF));    //recevied data length <= BULK_TD_BUFFER_TOTAL_SIZE
+       USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_rx_complete: received length %d \n",received_data_length);
+       #if 0
+       /* Check if the received packet is SCSI WRITE, if yes, assign the TD buffer offset
+          is zero, otherwise, one. This is a bug in MX37 USB OTG */
+       if((received_data_length==31)&&(*(destination_ptr+0xF)==0x2A))//WRITE10 received
+       {
+               g_bulk_out_transdesc_buffer_offset = 0;
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_start_rx - set offset to zero \n");
+       }
+
+       else if((g_bulk_out_sector_number_is_one == 1)&&(received_data_length!=31)) //last bulk out data sector
+               g_bulk_out_transdesc_buffer_offset = 1;
+       #endif
+       
+       /* tell ep1 how many bytes data is received*/
+       ep1.fetched     = received_data_length; 
+       
+       if(ep1.fetched) 
+       {
+               if(ep1.fetched == 31)
+                       g_received_data_type = MASS_STORAGE_CBW_TYPE;
+               else 
+                       g_received_data_type = MASS_STORAGE_DATA_TYPE;
+               ep1.common.complete_data    = (void*)(ep1.common.buffer);
+
+               #if 0
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_rx_complete: \n");
+               USBDBGMSG(DEBUG_TRANS,"----Dump Bulk-Out Recevied Data----\n");
+               for(i=0;i<32;i++)
+               {
+                       USBDBGMSG(DEBUG_TRANS,"%02X ", *((cyg_uint8 *)(ep1.common.complete_data)+i));
+               }
+               USBDBGMSG(DEBUG_TRANS,"\n");
+               #endif
+               //USB_IMX_SET_TD_OFFSET(g_td_buffer_offset, 0);
+           ep1.common.buffer      = (unsigned char*) 0;
+       ep1.common.buffer_size = 0;
+               ep1_start_rx((usbs_rx_endpoint *)(&(ep1.common))); //prevent to receive more CBW before processing done
+       }
+       
+    #if 0
+       if(ep1.fetched == 31)
+       {
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_rx_complete - recevied data: \n");
+               for(i=0;i<32;i++)
+               {
+                       USBDBGMSG(DEBUG_TRANS,"%02X ", *((cyg_uint8 *)(ep1.common.complete_data)+i));
+               }
+               USBDBGMSG(DEBUG_TRANS,"\n");
+
+               for(i=0;i<32;i++)
+               {
+                       USBDBGMSG(DEBUG_TRANS,"%02X ", *((cyg_uint8 *)received_buffer_addrs+i));
+               }
+               USBDBGMSG(DEBUG_TRANS,"\n");
+       }
+       #endif
+       
+       
+}
+/*=============================================================================
+// Start to receive data from host. This functionality is overloaded to cope with
+// waiting for stalls to complete.
+// The transfer descriptor is prepared 
+=============================================================================*/
+static void
+ep1_start_rx(usbs_rx_endpoint* endpoint)
+{
+       struct dtd_t td;
+       cyg_uint32 total_bytes;
+       cyg_uint32 dtd_address;
+       cyg_uint32 dqh_address;
+    cyg_uint32 buffer_addrs_page0;
+
+       if(g_usb_dev_state != USB_DEV_CONFIGURED_STATE) 
+               return; //EP1 only receives data when the USB device has been configured
+       #if 0   //don't check to prevent EP1 from receiving data before processing the previous.
+       if(endpoint->buffer == NULL)
+       {
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1_start_rx: NULL buffer \n");
+               return; //there is not a buffer used to store the data from host
+       }
+       #endif
+       /* Get Device Device Queue Head of the out endpoint */
+       dqh_address = USBS_EP_GET_dQH(EP1,OUT);
+        
+       /* Get Device Transfer Descriptor of the out endpoint */
+       dtd_address = USBS_EP_GET_dTD(EP1,OUT);
+
+       /* ==Prepare TD for next bulk out transfer== */
+       /* get the dTD buffer pointer */
+       buffer_addrs_page0 = (cyg_uint32)(endpoint->buffer);
+       
+       /* Get the total bytes to be received   */
+       total_bytes = endpoint->buffer_size;
+       
+       /* OUT setup dTD */
+       td.dtd_base             = dtd_address;  
+       td.next_link_ptr        = dtd_address + 0x20;
+       td.terminate            = TERMINATE;
+       td.total_bytes          = total_bytes;
+       td.ioc                          = IOC_SET;
+       td.status                       = ACTIVE;
+       td.buffer_ptr0          = buffer_addrs_page0 ; 
+       td.current_offset       = ( buffer_addrs_page0 & 0xFFF ) + g_td_buffer_offset; 
+       td.buffer_ptr1          = 0;
+       td.buffer_ptr2          = 0;
+       td.buffer_ptr3          = 0;
+       td.buffer_ptr4          = 0;
+
+       /* re-define the buffer page pointers based on the total_bytes*/
+       if(total_bytes > BULK_TD_BUFFER_PAGE_SIZE)
+               td.buffer_ptr1          = (td.buffer_ptr0 + BULK_TD_BUFFER_PAGE_SIZE);
+       if(total_bytes > BULK_TD_BUFFER_PAGE_SIZE*2)
+               td.buffer_ptr2          = (td.buffer_ptr1 + BULK_TD_BUFFER_PAGE_SIZE);
+       if(total_bytes > BULK_TD_BUFFER_PAGE_SIZE*3)
+               td.buffer_ptr3          = (td.buffer_ptr2 + BULK_TD_BUFFER_PAGE_SIZE);
+            
+       /* Set the Transfer Descriptor  */
+       usbs_setup_transdesc(&td);
+
+       /* 1. write dQH next ptr and dQH terminate bit to 0 */
+       *(volatile cyg_uint32 *)(dqh_address+0x8)= dtd_address;
+           
+       /* 2. clear active & halt bit in dQH */
+       *(volatile cyg_uint32 *)(dqh_address+0xC) &= ~0xFF;
+
+       /* 3. prime endpoint by writing '1' in ENDPTPRIME 
+               prime bulk out endpoint after sending the CSW of last command
+       */
+       //usbs_imx_otg_base->endptprime |= ( EPOUT_PRIME << EP1 );
+
+}
+/*=============================================================================
+// The exported interface to halt the EP1
+=============================================================================*/
+static void
+ep1_set_halted(usbs_rx_endpoint* endpoint, cyg_bool new_value)
+{
+       if (ep1.common.halted == new_value) {
+        return;
+    }
+    if (new_value) {
+        // The endpoint should be stalled. There is a potential race
+        // condition here with the current transfer and DSR invocation.
+        // Updating the stalled flag means that the DSR will do nothing.
+               usbs_endpoint_stall(EP1,OUT);
+               ep1.common.halted = 1;
+    } 
+       else {
+        // Take care of the hardware so that a new transfer is allowed. 
+        usbs_endpoint_unstall(EP1,OUT);
+        ep1.common.halted = 0;
+    }
+
+}
+/*=============================================================================
+// The DSR is invoked following an interrupt. According to the docs an
+// endpoint 1 interrupt can only happen if the receive-packet-complete
+// bit is set.
+// [Note] EP1 DSR is only used to receive the command block wrapper from host
+// to USB mass storage device
+=============================================================================*/
+
+static void
+usbs_imx_otg_dev_ep1_dsr(void)
+{
+       int result = 0; //contains the actual recevied data length from bulk-out endpoint
+       g_received_data_type = 0;//MASS_STORAGE_CBW_TYPE
+       
+       if(ep1.common.buffer)//buffer of TD is not null, then receive
+       {
+               ep1_rx_complete(result);
+       }
+       //USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1 dsr - result = %d\n",result);
+       //recevie mass storage device CBW
+       
+       if((ep1.fetched == 31)&&(g_received_data_type == MASS_STORAGE_CBW_TYPE))
+       {
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1 dsr - CBW received\n");
+               //post the semaphore of MSC command handler thread
+               #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+               cyg_semaphore_post(&usbs_msc_sem);
+               #endif
+               ep1.fetched = 0;
+       }
+       else
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep1 dsr - received %d byte\n",ep1.fetched);
+       
+}
+
+/*=============================================================================
+// Endpoint 1 initialization.
+// Bulk-OUT Endpoint
+// This may get called during system start-up or following a reset
+// from the host.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_ep1_init(void)
+{
+       //at present, ep1.common.buffer is NULL. The buffer should be initialized 
+       //by upper layer caller.
+       /*buffer is assigned in MSC initialization*/
+       
+       // Endpoints should never be halted during a start-up.
+    ep1.common.halted      = 0;        //false =0, true =1
+       ep1.common.complete_fn = ep1_rx_complete;
+    // If there has been a reset and there was a receive in progress,
+    // abort it. This also takes care of sorting out the endpoint
+    // fields ready for the next rx.
+    ep1_rx_complete(-EPIPE);
+}
+
+// ****************************************************************************
+// -----------------------Endpoint 2 Functions---------------------------------
+// ****************************************************************************
+/*=============================================================================
+// A utility routine for completing a transfer. This takes care of the
+// callback as well as resetting the buffer.
+=============================================================================*/
+static void
+ep2_tx_complete(int result)
+{
+    void (*complete_fn)(void*, int)  = ep2.common.complete_fn;
+    void* complete_data = ep2.common.complete_data;
+    
+    ep2.common.buffer           = (unsigned char*) 0;
+    ep2.common.buffer_size      = 0;
+    ep2.common.complete_fn      = (void (*)(void*, int)) 0;
+    ep2.common.complete_data    = (void*) 0;
+
+    if ((void (*)(void*, int))0 != complete_fn) {
+        (*complete_fn)(complete_data, result);
+    }
+}
+
+/*=============================================================================
+// The exported interface to start to transmit data to Host
+=============================================================================*/
+static void
+ep2_start_tx(usbs_tx_endpoint* endpoint)
+{
+       int timeout = 400;
+       struct dtd_t td;
+    cyg_uint32 total_bytes ;
+    cyg_uint32 dtd_address,dqh_address;
+    cyg_uint32 buffer_addrs_page0;
+    cyg_uint32 size = 0x0;
+
+       /* Get Device Transfer Descriptor of the requested endpoint */
+       dtd_address = USBS_EP_GET_dTD(EP2,IN);
+    
+       /* Get Device Queue head of the requested endpoint */
+       dqh_address = USBS_EP_GET_dQH(EP2,IN);  
+       
+       /* allocate memory for data transfer */
+       buffer_addrs_page0 = endpoint->buffer;
+
+       if(buffer_addrs_page0 == 0)
+       {
+               USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep2_start_tx: NULL tx buffer \n");
+               return;
+       }
+
+       total_bytes = (cyg_uint32)(endpoint->buffer_size);
+       size = (total_bytes < BULK_TD_BUFFER_TOTAL_SIZE )?total_bytes:(BULK_TD_BUFFER_TOTAL_SIZE);
+           
+       td.dtd_base             = dtd_address; 
+       td.next_link_ptr        = dtd_address + 0x20 ;
+       td.terminate            = TERMINATE;
+       td.total_bytes          = size;
+       td.ioc                          = IOC_SET;
+       td.status                       = ACTIVE;
+       td.buffer_ptr0          = buffer_addrs_page0 ;
+       td.current_offset       = (buffer_addrs_page0 & 0xFFF)+ g_td_buffer_offset; 
+       td.buffer_ptr1          = 0;
+       td.buffer_ptr2          = 0;
+       td.buffer_ptr3          = 0;
+       td.buffer_ptr4          = 0;
+
+       /* re-define the buffer page pointers based on the total_bytes*/
+       if(size > BULK_TD_BUFFER_PAGE_SIZE)
+               td.buffer_ptr1          = (td.buffer_ptr0 + BULK_TD_BUFFER_PAGE_SIZE);
+       if(size > BULK_TD_BUFFER_PAGE_SIZE*2)
+               td.buffer_ptr2          = (td.buffer_ptr1 + BULK_TD_BUFFER_PAGE_SIZE);
+       if(size > BULK_TD_BUFFER_PAGE_SIZE*3)
+               td.buffer_ptr3          = (td.buffer_ptr2 + BULK_TD_BUFFER_PAGE_SIZE);
+
+       /* Set the Transfer Descriptor  */ 
+       usbs_setup_transdesc(&td);
+
+       /* 1. write dQH next ptr and dQH terminate bit to 0  */
+       *(volatile cyg_uint32 *)(dqh_address+0x8)= (dtd_address); 
+       
+       /* 2. clear active & halt bit in dQH */
+       *(volatile cyg_uint32 *)(dqh_address+0xC) &= ~0xFF;
+
+       /* 3. prime endpoint by writing '1' in ENDPTPRIME */
+       usbs_imx_otg_base->endptprime = ( EPIN_PRIME << EP2 );
+       
+       /* wait for complete set and clear */
+       while (!((usbs_imx_otg_base->endptcomplete) & (EPIN_COMPLETE<<EP2)));
+       
+       usbs_imx_otg_base->endptcomplete |= (EPIN_COMPLETE << EP2);
+
+       ep2.transmitted = size;
+
+       ep2_tx_complete(-EPIPE);
+       
+       USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep2 tx done\n");// ep2.transmitted);
+       
+}
+/*=============================================================================
+// The exported interface to halt the EP2
+=============================================================================*/
+static void
+ep2_set_halted(usbs_tx_endpoint* endpoint, cyg_bool new_value)
+{
+       if (ep2.common.halted == new_value) {
+        return;
+    }
+    if (new_value) {
+        // The endpoint should be stalled. There is a potential race
+        // condition here with the current transfer and DSR invocation.
+        // Updating the stalled flag means that the DSR will do nothing.
+               usbs_endpoint_stall(EP2,IN);
+               ep2.common.halted = 1;
+    } 
+       else {
+        // Take care of the hardware so that a new transfer is allowed. 
+        usbs_endpoint_unstall(EP2,IN);
+        ep2.common.halted = 0;
+    }
+}
+/*=============================================================================
+// The dsr will be invoked when the transmit-packet-complete bit is
+// set. Typically this happens when a packet has been completed
+=============================================================================*/
+
+static void
+usbs_imx_otg_dev_ep2_dsr(void)
+{
+       USBDBGMSG(DEBUG_TRANS,"+USBDBGMSG: ep2 dsr\n");
+       /* EP2 DSR will be called as soon as a transfer complete to clear status*/
+       usbs_imx_otg_base->endptcomplete |= (EPIN_COMPLETE << EP2);
+
+       
+       if(ep2.common.buffer_size==0)
+       {
+               ep2_tx_complete(-EPIPE);
+               ep2.transmitted = 0;    //clear the field to wait for the next transmit
+       }
+       
+}
+
+/*=============================================================================
+// Endpoint 2 initialization.
+// Bulk-IN Endpoint
+// This may be called during system start-up or following a reset
+// from the host.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_ep2_init(void)
+{
+       //at initialization, ep2.common.buffer is NULL. The buffer should be initialized 
+       //by upper layer caller.
+
+       // Endpoints should never be halted after a reset
+    ep2.common.halted   = false;
+
+    // If there has been a reset and there was a receive in progress,
+    // abort it. This also takes care of clearing the endpoint
+    // structure fields.
+    ep2_tx_complete(-EPIPE);
+}
+
+// ****************************************************************************
+// -----------------------MX37 USB Device Driver API Functions-----------------
+// ****************************************************************************
+
+/*=============================================================================
+// The DSR. This can be invoked directly by poll(), or via the usual
+// interrupt subsystem. It acts as per the current value of
+// g_isr_status_bits. If another interrupt goes off while this
+// DSR is running, there will be another invocation of the DSR and
+// the status bits will be updated.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    int status = 0;
+    cyg_uint32 temp;
+    CYG_ASSERT(MX51_IRQ_USB_SERVICE_REQUEST == vector, "USB DSR should only be invoked for USB interrupts" );
+    CYG_ASSERT(0 == data, "The i.MX37 USB DSR needs no global data pointer");
+       //USBDBGMSG("+USBDBGMSG: enter mx37 dsr\n");
+    // There is no atomic swap support, so interrupts have to be
+    // blocked. It might be possible to do this via the USBS_CONTROL
+    // register, but at the risk of messing up the status register
+    // if another interrupt comes in. Blocking interrupts at the
+    // processor level is less intrusive on the USB code.
+    //cyg_drv_isr_lock();
+    status = g_isr_status_bits;
+    g_isr_status_bits = 0;
+    //cyg_drv_isr_unlock();
+               
+    // Reset is special, since it invalidates everything else.
+    // If the reset is still ongoing then do not attempt any
+    // further processing, there will just be another interrupt.
+    // Otherwise handle_reset() does the hard work. Unmasking
+    // the interrupt means that another interrupt will occur
+    // immediately if reset is still asserted, i.e. no threads
+    // will run, but there is no easy way of triggering action
+    // at the end of reset.
+    if (status & IMX_USB_STS_RESET) 
+    {
+        int new_status = usbs_imx_otg_base->usbsts; 
+        if (0 == (new_status & IMX_USB_STS_RESET)) 
+        {
+                       usbs_imx_otg_dev_handle_bus_reset();
+                       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: !!USB BUS RESET\n");
+        } 
+               
+        // This unmask is likely to cause another interrupt immediately
+        #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+        cyg_interrupt_unmask(MX51_IRQ_USB_SERVICE_REQUEST);
+               #endif
+    } 
+       else if(status & IMX_USB_STS_USBINT)
+       {
+               
+               if(usbs_imx_otg_base->endptsetupstat & BIT0)
+       {// if Setup Packet arrived                     
+               usbs_imx_otg_dev_ep0_dsr();
+               }
+
+               else if((usbs_imx_otg_base->endptcomplete) & ( EPIN_COMPLETE << EP2))   
+        {//    EP2 Queue Header buffer completes sending data
+               //complete bit is cleared in ep2_start_tx
+        }
+               
+               
+               else if((usbs_imx_otg_base->endptcomplete) & ( EPOUT_COMPLETE << EP1))
+        {// EP1 Queue Header buffer get data           
+                       usbs_imx_otg_dev_ep1_dsr();
+                       
+        }
+
+               else if((usbs_imx_otg_base->endptcomplete) & ( EPOUT_COMPLETE << EP0))
+               {
+                       //usbs_imx_otg_dev_ep0_dsr();
+                       usbs_imx_otg_base->endptcomplete = ( EPOUT_COMPLETE << EP0);
+               }
+        else
+        {//do nothing, only for constructure integrity
+                       temp = usbs_imx_otg_base->endptcomplete;
+                       usbs_imx_otg_base->endptcomplete = temp;
+                       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: usbsts int - unknown.\n");
+               }
+
+               #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+               // This unmask is likely to cause another interrupt immediately
+               cyg_interrupt_unmask(MX51_IRQ_USB_SERVICE_REQUEST);
+               #endif
+       }
+    else 
+    {
+       #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+               // This unmask is likely to cause another interrupt immediately
+               cyg_interrupt_unmask(MX51_IRQ_USB_SERVICE_REQUEST);
+               #endif
+    }  
+
+               
+}
+/*=============================================================================
+// The DSR thread
+=============================================================================*/
+#if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+#define CYGNUM_DEVS_USB_OTG_DEV_THREAD_STACK_SIZE      1024
+#define CYGNUM_DEVS_USB_OTG_DEV_THREAD_PRIORITY        29
+static unsigned char usbs_imx_otg_dev_thread_stack[CYGNUM_DEVS_USB_OTG_DEV_THREAD_STACK_SIZE];
+static cyg_thread    usbs_imx_otg_dev_thread;
+static cyg_handle_t  usbs_imx_otg_dev_thread_handle;
+static cyg_sem_t     usbs_imx_otg_dev_sem;
+
+
+static void
+usbs_imx_otg_dev_thread_fn(cyg_addrword_t param)
+{
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: usb driver thread\n");
+       for (;;) {
+        cyg_semaphore_wait(&usbs_imx_otg_dev_sem);
+               usbs_imx_otg_dev_dsr(IMX_IRQ_USB_DEV_SERVICE_REQUEST, 0, 0);
+    }
+    CYG_UNUSED_PARAM(cyg_addrword_t, param);
+}
+
+static void
+usbs_imx_otg_dev_thread_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    CYG_ASSERT( 0 != isr_status_bits, "DSR's should only be scheduled when there is work to do");
+    cyg_semaphore_post(&usbs_imx_otg_dev_sem);
+
+       
+    CYG_UNUSED_PARAM(cyg_vector_t, vector);
+    CYG_UNUSED_PARAM(cyg_ucount32, count);
+    CYG_UNUSED_PARAM(cyg_addrword_t, data);
+}
+#endif
+/*=============================================================================
+// The interrupt handler. This does as little as possible.
+=============================================================================*/
+static cyg_uint32
+usbs_imx_otg_dev_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+       cyg_uint32 old_status_bits = g_isr_status_bits;
+       cyg_uint32 status_bits;
+
+    CYG_ASSERT(IMX_IRQ_USB_DEV_SERVICE_REQUEST == vector, "USB ISR should only be invoked for USB interrupts" );
+    CYG_ASSERT(0 == data, "The MX51 USB ISR needs no global data pointer" );
+
+       //USBDBGMSG("+USBDBGMSG: enter mx51 isr\n");
+    // Read the current status. Reset is special, it means that the
+    // whole chip has been reset apart from the one bit in the status
+    // register. Nothing should be done about this until the DSR sets
+    // the endpoints back to a consistent state and re-enables
+    // interrupts in the control register.
+    status_bits         = usbs_imx_otg_base->usbsts;
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: usb intr 0x%08X\n",status_bits);
+    if (status_bits & IMX_USB_STS_RESET) 
+    {
+       
+        g_isr_status_bits |= IMX_USB_STS_RESET;
+        usbs_imx_otg_base->usbsts |= IMX_USB_STS_RESET;
+        cyg_interrupt_mask(IMX_IRQ_USB_DEV_SERVICE_REQUEST);
+    } 
+       else if(status_bits & IMX_USB_STS_USBINT)
+       {
+               g_isr_status_bits |= IMX_USB_STS_USBINT;
+        usbs_imx_otg_base->usbsts |= IMX_USB_STS_USBINT;
+        cyg_interrupt_mask(IMX_IRQ_USB_DEV_SERVICE_REQUEST);
+       }
+    else 
+    {
+        usbs_imx_otg_base->usbsts  = status_bits;      //clear the status bit of USBSTS
+        g_isr_status_bits &= ~status_bits;
+        USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: unknown usb intr\n");
+       }
+
+    // Now keep the rest of the system happy.
+    cyg_interrupt_acknowledge(vector);                 //reenable the USB interrupt
+    return (old_status_bits != g_isr_status_bits) ? CYG_ISR_CALL_DSR : CYG_ISR_HANDLED;
+}
+/*=============================================================================
+// Polling support. This acts mostly like the interrupt handler: it
+// sets the isr status bits and causes the dsr to run. Reset has to be
+// handled specially: polling does nothing as long as reset is asserted.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_poll(usbs_control_endpoint* endpoint)
+{
+       CYG_ASSERT( endpoint == &ep0.common, "USB poll involves the wrong endpoint");
+    
+    if (g_isr_status_bits & IMX_USB_STS_RESET) 
+    {
+        // Reset was detected the last time poll() was invoked. If
+        // reset is still active, do nothing. Once the reset has
+        // completed things can continue.
+        if (0 == (IMX_USB_STS_RESET & usbs_imx_otg_base->usbsts)) 
+        {
+            g_isr_status_bits = 0;
+            usbs_imx_otg_dev_handle_bus_reset();
+        }
+    } 
+    else 
+    {
+        g_isr_status_bits = usbs_imx_otg_base->usbsts;
+        if (IMX_USB_STS_PTCHANGE & g_isr_status_bits) 
+        {
+            //process Port Change Detect
+            usbs_imx_otg_dev_handle_port_change();
+        } 
+        else if (IMX_USB_STS_USBINT & g_isr_status_bits)
+        {
+            usbs_imx_otg_dev_dsr(IMX_IRQ_USB_DEV_SERVICE_REQUEST, 0, (cyg_addrword_t) 0);
+        }
+        else
+        {
+               usbs_imx_otg_base->usbsts = g_isr_status_bits;  //clear the don't-care status
+        }
+    }
+}
+/*=============================================================================
+// Perform reset operations on all endpoints that have been
+// configured in. It is convenient to keep this in a separate
+// routine to allow for polling, where manipulating the
+// interrupt controller mask is a bad idea.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_handle_bus_reset(void)
+{
+       cyg_uint32 temp;
+       
+       usbs_imx_otg_base->usbcmd &= ~BIT0; //detach device from bus temprorarily
+       usbs_imx_otg_base->usbsts |= BIT6;      //clear reset bit in USBSTS
+
+       //temp = usbs_imx_otg_base->usbsts;
+       //usbs_imx_otg_base->usbsts = temp;
+  
+       /*1. Reading and writing back the ENDPTSETUPSTAT register
+      clears the setup token semaphores */
+       temp = usbs_imx_otg_base->endptsetupstat;
+       usbs_imx_otg_base->endptsetupstat = temp;
+
+       /*2. Reading and writing back the ENDPTCOMPLETE register
+      clears the endpoint complete status bits */
+       temp = usbs_imx_otg_base->endptcomplete;
+       usbs_imx_otg_base->endptcomplete = temp;
+       
+       /*3. Cancel all primed status by waiting until all bits in ENDPTPRIME are 0
+       and then write 0xFFFFFFFF to ENDPTFLUSH */
+       while(usbs_imx_otg_base->endptprime);   
+       usbs_imx_otg_base->endptflush = 0xFFFFFFFF;     
+
+
+       /*4. Initialize EP0 Queue Head again*/
+       usbs_ep0_init_dqh();
+       
+       usbs_imx_otg_base->endptlistaddr = g_bulkbuffer_map.ep_dqh_base_addrs; 
+     
+       usbs_imx_otg_base->usbcmd |= BIT0; //re-attach device to the bus
+
+       g_usb_dev_state = USB_DEV_DEFAULT_STATE;
+
+       
+}
+/*=============================================================================
+// Perform port change operations on all endpoints that have been
+// configured in. It is convenient to keep this in a separate
+// routine to allow for polling, where manipulating the
+// interrupt controller mask is a bad idea.
+=============================================================================*/
+static void
+usbs_imx_otg_dev_handle_port_change(void)
+{
+       /*Port Change happens when USB device enters/exits FS or HS mode
+       When exiting from FS or HS due to Bus reset or DCSuspend, the notification
+       mechanisms are Reset Received and DCSuspend.
+       This function only processes the port change on entering FS or HS
+       Don't enable Port Change Detect interrupt, it's no sense for operation.*/
+       usbs_imx_otg_base->usbsts |= IMX_USB_STS_PTCHANGE;      //clear Port change status
+
+}
+
+// ****************************************************************************
+// ----------------------------------------------------------------------------
+// ****************************************************************************
+/*=============================================================================
+FUNCTION: usbs_imx_otg_dev_set_configuration
+DESCRIPTION:           This function Handle the SET CONFIGRATION Request.
+ARGUMENTS PASSED:      usb_end_pt_info_t* config_data;
+RETURN VALUE:          None    
+IMPORTANT NOTES:       None            
+=============================================================================*/
+static void
+usbs_imx_otg_dev_set_configuration(usb_end_pt_info_t* config_data)
+{
+    struct dtd_t td;
+    cyg_uint32 total_bytes = 0x0;
+    cyg_uint32 buffer_addrs_page0 = 0;
+    cyg_uint32 dqh_address = 0;
+    cyg_uint32 dtd_address = 0;
+    cyg_uint8  endpt_num,direction;
+    
+    struct dqh_t qhead;
+
+       
+    /* get endpoint number to be configured and its direction */
+    endpt_num= config_data->end_pt_no; 
+    direction= config_data->direction;
+    USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: set config - ep%d\n",endpt_num);
+    /* Check if the endpoint number and direction is withing the permitted range or not */
+    if (( endpt_num != EP0 ) && (endpt_num <= ( g_max_ep_supported - 1)) && 
+                   ( direction == OUT || direction == IN))
+    {
+               /* get the device q head and deice TD */
+               dqh_address = USBS_EP_GET_dQH(endpt_num,direction); 
+               dtd_address = USBS_EP_GET_dTD(endpt_num,direction);
+
+               if ( direction ==  OUT )
+               {
+               total_bytes = BULK_BUFFER_SIZE ;
+               
+               qhead.dqh_base          = dqh_address;
+               qhead.zlt                       = ZLT_DISABLE;
+               qhead.mps                       = config_data->max_pkt_size;
+               qhead.ios                       = IOS_SET;
+               qhead.next_link_ptr     = dtd_address ;
+               qhead.terminate         = TERMINATE;
+               qhead.total_bytes       = total_bytes;
+               qhead.ioc                       = IOC_SET;
+               qhead.status            = NO_STATUS;
+               qhead.buffer_ptr0       = 0;
+               qhead.current_offset= 0;
+               qhead.buffer_ptr1       = 0;
+               qhead.buffer_ptr2       = 0;
+               qhead.buffer_ptr3       = 0;
+               qhead.buffer_ptr4       = 0;
+
+               usbs_setup_queuehead(&qhead);
+               
+               /* Endpoint 1 : MPS = 64, OUT (Rx endpoint) */
+               usbs_imx_otg_base->endptctrl[endpt_num] = 0x00080048;
+               /* Enable EP1 OUT */
+               usbs_imx_otg_base->endptctrl[endpt_num] |= EPOUT_ENABLE;
+               
+               /* allocate buffer for receiving data */
+               /* free the usb buffer after re-enumeration*/
+               //g_bulkbuffer_map.buffer1_status = BUFFER_FREE;
+               //g_bulkbuffer_map.buffer2_status = BUFFER_FREE;
+               g_bulkbuffer_a.stat = BUFFER_FREED;
+               g_bulkbuffer_b.stat = BUFFER_FREED;     
+               
+           //buffer_addrs_page0 = util_alloc_buffer();
+           ep1.common.buffer      = g_bulkbuffer_a.buffer;
+               ep1.common.buffer_size = total_bytes;
+               g_bulkbuffer_a.stat = BUFFER_ALLOCATED;
+               buffer_addrs_page0 = (cyg_uint32)(ep1.common.buffer);
+               
+               
+               USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: set config - ep1 dtd buffer 0x%08X\n",buffer_addrs_page0);
+               
+               /* OUT setup dTD */
+               td.dtd_base                     = dtd_address;
+               td.next_link_ptr        = dtd_address + 0x20;
+               td.terminate            = TERMINATE;
+               td.total_bytes          = total_bytes;
+               td.ioc                          = IOC_SET;
+               td.status                       = ACTIVE;
+               td.buffer_ptr0          = buffer_addrs_page0;
+               td.current_offset       = (buffer_addrs_page0 & 0xFFF) + g_td_buffer_offset;
+               td.buffer_ptr1          = 0x0;
+               td.buffer_ptr2          = 0x0;
+               td.buffer_ptr3          = 0x0;
+               td.buffer_ptr4          = 0x0;
+            
+               /* Set the Transfer Descriptor  */
+               usbs_setup_transdesc(&td);
+
+               /* 1. write dQH next ptr and dQH terminate bit to 0 */
+               *(volatile cyg_uint32*)(dqh_address+0x8)= dtd_address; 
+           
+               /* 2. clear active & halt bit in dQH */
+               *(volatile cyg_uint32*)(dqh_address+0xC) &= ~0xFF;
+       
+               /* 3. prime endpoint by writing '1' in ENDPTPRIME */
+               usbs_imx_otg_base->endptprime |= (  EPOUT_PRIME << endpt_num );
+               /* Endpoint Configured for output */
+               g_out_endpoint= endpt_num;
+
+               
+           }
+
+               else
+               {
+               total_bytes = 0x4 ;
+               
+               qhead.dqh_base          = USBS_EP_GET_dQH(endpt_num,direction);
+               qhead.zlt                       = ZLT_DISABLE;
+               qhead.mps                       = config_data->max_pkt_size;
+               qhead.ios                       = IOS_SET;
+               qhead.next_link_ptr     = USBS_EP_GET_dQH(endpt_num,direction);
+               qhead.terminate         = TERMINATE;
+               qhead.total_bytes       = total_bytes;
+               qhead.ioc                       = IOC_SET;
+               qhead.status            = NO_STATUS;
+               qhead.buffer_ptr0       = 0;
+               qhead.current_offset= 0;
+               qhead.buffer_ptr1       = 0;
+               qhead.buffer_ptr2       = 0;
+               qhead.buffer_ptr3       = 0;
+               qhead.buffer_ptr4       = 0;
+
+               usbs_setup_queuehead(&qhead);
+                   
+               /* Endpoint Configured for Input */
+               g_in_endpoint= endpt_num;
+    
+               /* Endpoint 2: MPS = 64, IN (Tx endpoint) */
+               usbs_imx_otg_base->endptctrl[endpt_num] = 0x00480008;
+
+               /* Enable EP2 IN */
+               usbs_imx_otg_base->endptctrl[endpt_num] |= EPIN_ENABLE;
+    
+               /* 3. prime endpoint by writing '1' in ENDPTPRIME */
+               usbs_imx_otg_base->endptprime |= (EPIN_PRIME << g_in_endpoint);
+               
+           }
+    }
+    else 
+    {
+        /* TODO: error handling TBD */
+    }    
+
+}
+
+static void usbs_imx_otg_config_utmi_clock(void)
+{
+       #if defined(CYGHWR_USB_DEVS_MX37_OTG)
+       USB_MX37_SET_PHY_CLK_24MHZ();
+       #endif
+
+       #if defined(CYGHWR_USB_DEVS_MX51_OTG)
+       cyg_uint32 temp;
+       /*Configure USB_PHYCLOCK_ROOT source as 24MHz OSC*/ 
+       CCM_CSCMR1_REGVAL = CCM_CSCMR1_REGVAL & (~CSCMR1_USBOH3_PHY_CLK_SEL_VALUE); //configure USB CRM
+       /*Configure plldivvalue of USB_PHY_CTRL_1_REG for 24 Mhz*/         
+       temp  = *(volatile cyg_uint32 *)USB_PHY_CTRL_1_REG;        
+       temp &= ~USB_PHY_CTRL_PLLDIVVALUE_MASK;        
+       temp |= USB_PHY_CTRL_PLLDIVVALUE_24_MHZ;                
+       *(volatile cyg_uint32 *)USB_PHY_CTRL_1_REG = temp;
+       #endif
+}
+
+/*=============================================================================
+// The USB OTG hardware relevant initialization.
+=============================================================================*/
+static void
+usbs_imx_otg_hardware_init(void)
+{
+       cyg_uint32 temp;
+       cyg_uint32 timeout = 0x1D0000;
+       usb_plat_config_data_t config_data_ptr; 
+       cyg_uint8 i;
+       
+       /*Enable USB Internal PHY Clock as 24MHz on-board Ocsillator*/
+       usbs_imx_otg_config_utmi_clock();
+       
+       {/*Setup USB Buffer Map*/
+    config_data_ptr.buffer_address = (cyg_uint32)usb_buffer;
+    config_data_ptr.buffer_size  = BUFFER_SIZE;
+    
+    /* Base address of the buffer allocated to IP Layer */
+    g_bulkbuffer_address_base =  config_data_ptr.buffer_address;
+    
+    /* length of the buffer */
+    g_bulkbuffer_length = config_data_ptr.buffer_size;  
+    
+    /* Maximum Number of EPs to be confiured */
+    g_max_ep_supported = (( g_bulkbuffer_length - TOTAL_DATA_BUFFER_SIZE)/(BUFFER_USED_PER_EP)); //=(2048-1088)/256~=3.75->3
+    
+    /* Base of queue Head Pointer */
+    g_bulkbuffer_map.ep_dqh_base_addrs = g_bulkbuffer_address_base; 
+    
+    /* Total size of qhead */
+    temp = (SIZE_OF_QHD * (g_max_ep_supported * 2));   //total size of QH is 384byte
+
+    /* Base Address of dTDs */
+    g_bulkbuffer_map.ep_dtd_base_addrs = (g_bulkbuffer_map.ep_dqh_base_addrs + temp);
+  
+    /* Total size of transfer descriptor */ 
+    temp =  ((dTD_SIZE_EPIN * g_max_ep_supported) + (dTD_SIZE_EPOUT * g_max_ep_supported )); //total size of TD is 384 byte
+    
+    /* Base Address of EP0 Buffer */
+    g_bulkbuffer_map.ep0_buffer_addrs = (g_bulkbuffer_map.ep_dtd_base_addrs + temp  ); //256byte
+    
+    /*Bulk Buffer Areas, 512byte per buffer*/
+       /*Actually, the dual 512 byte bulk buffers are not used, because two larger 16kB bulk buffers are used*/
+    /* transfer buffer 1 */    
+    g_bulkbuffer_map.buffer1_address=(g_bulkbuffer_address_base + g_bulkbuffer_length -(BULK_BUFFER_SIZE*NUM_OF_BULK_BUFFER));
+    g_bulkbuffer_map.buffer1_status  = BUFFER_FREE;
+
+    /* transfer buffer 2 */
+    g_bulkbuffer_map.buffer2_address = g_bulkbuffer_map.buffer1_address + BULK_BUFFER_SIZE;
+    g_bulkbuffer_map.buffer2_status  = BUFFER_FREE;
+       }
+       
+       {/*Set USB OTG at device only mode*/
+               usbs_imx_otg_base->usbmode = 0x2;                                       //set OTG as a device controller
+               temp = 0xA5A55A5A;
+               while (!(usbs_imx_otg_base->usbmode == 0x2))
+               {
+                       if(temp != (usbs_imx_otg_base->usbmode))
+                       {
+                               temp = (usbs_imx_otg_base->usbmode);
+                               USBDBGMSG(DEBUG_BASIC,"usbmode is 0x%08X\n",temp);
+                       }
+                       timeout--;
+                       if(timeout==0) break;
+               }               //check that device controller was configured to device mode only
+       }
+
+       {
+               usbs_imx_otg_base->endptlistaddr = g_bulkbuffer_map.ep_dqh_base_addrs; // Configure ENDPOINTLISTADDR Pointer
+               usbs_imx_otg_base->otgsc |= BIT3;                                       // Set OTG termination, controls the pulldown on DM
+               usbs_imx_otg_base->endptnak = 0x00010001;                       // Enable Endpoint NAK
+               usbs_imx_otg_base->usbmode |= BIT3;                             // Disable Setup Lockout by writing '1' to SLOM in USBMODE
+               //usbs_imx_otg_base->usbcmd |= BIT0;                            // Set Run/Stop bit to Run Mode, make USB run in usbs_imx_otg_dev_ep0_start()
+       }
+       
+       {
+               /* set it to be utmi interface */
+               temp  = usbs_imx_otg_base->portsc1;
+               temp &= ~USB_OTG_TRANS_MASK;
+               temp |= USB_OTG_TRANS_UTMI;
+               temp &= ~USB_OTG_FS_ONLY;                                                               //enable high speed
+               temp |= USB_OTG_TRANS_WIDTH;
+
+               usbs_imx_otg_base->portsc1 = temp;
+       }
+
+       {// The USB OTG transaction relevant initialization.
+               /* Select the common descriptors , these descriptor are independent of speed and security mode */ 
+               g_usb_desc.device_desc  = &g_usb_device_desc ;
+               g_usb_desc.config_desc  = &g_usb_config_desc;
+               g_usb_desc.sn_desc              = &g_usb_serialnumber_desc;
+               g_usb_desc.str_desc0    = &g_usb_otg_str0_desc;         //language desc
+               g_usb_desc.str_desc1    = &g_usb_otg_string_desc1;      //Manufacturer desc
+               g_usb_desc.str_desc2    = &g_usb_otg_string_desc2;      //USB Name Desc
+               g_usb_desc.str_desc3    = &g_usb_otg_string_desc3;      //Device Name Desc
+       
+               /* Get Number of Endpoints supported from Configuration Descriptor*/
+               g_number_of_endpoints = g_usb_desc.config_desc->usb_interface_desc.number_endpoints;
+   
+               /* Store the Endpoint specific information in local variable structure to this Layer */
+               for ( i = 0 ; i< g_number_of_endpoints ; i++)
+               {
+                       g_end_pt_info[i].end_pt_no = ((g_usb_desc.config_desc->usb_endpoint_desc[i].endpoint) & ENDPT_NUMBER_MASK);
+                       g_end_pt_info[i].direction = (((g_usb_desc.config_desc->usb_endpoint_desc[i].endpoint) & ENDPT_DIR_MASK )>>ENDPT_DIR_SHIFT);
+                       g_end_pt_info[i].transfer_type = (g_usb_desc.config_desc->usb_endpoint_desc[i].attributes & ENDPT_TRNS_TYPE_MASK);
+                       g_end_pt_info[i].max_pkt_size = ((g_usb_desc.config_desc->usb_endpoint_desc[i].max_packet_lo)   \
+                                                                               | (( g_usb_desc.config_desc->usb_endpoint_desc[i].max_packet_hi ) << 8 ));
+               }
+       
+               g_usb_dev_state = USB_DEV_DEFAULT_STATE;
+       }
+}
+// ****************************************************************************
+// ----------------------------------------------------------------------------
+// ****************************************************************************
+/*=============================================================================
+// Initialization i.MX37(Marley) USB OTG Hardware
+// This function is the only extern function of this device driver, and it 
+// registers the driver ISR and DSRs to the kernel. 
+=============================================================================*/
+void
+usbs_imx_otg_device_init(void) //works like usb port open when 
+{      
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: USB Device Driver Start Initializing...\n");
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: USB OTG REG BASE@0x%08X\n",USB_BASE_ADDRESS);
+       g_usb_setup_data = ep0.common.control_buffer;
+       
+       g_td_buffer_offset = 0;
+       #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+       USB_IMX_SET_TD_OFFSET(g_td_buffer_offset,1);
+       #endif
+
+       /*ping-pang buffer A*/
+       g_bulkbuffer_a.buffer = bulk_buffer;
+       g_bulkbuffer_a.stat   = BUFFER_FREED;
+       
+       /*ping-pang buffer B*/
+       g_bulkbuffer_b.buffer = bulk_buffer + BULK_TD_BUFFER_TOTAL_SIZE;
+       g_bulkbuffer_b.stat   = BUFFER_FREED;
+       
+       usbs_imx_otg_hardware_init();   
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: Usb Hardware Initialize Complete.\n");
+       usbs_imx_otg_dev_ep0_init();
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: Usb Ep0 Initialize Complete.\n");
+       usbs_imx_otg_dev_ep1_init();
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: Usb Ep1 Initialize Complete.\n");
+       usbs_imx_otg_dev_ep2_init();
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: Usb Ep2 Initialize Complete.\n"); 
+
+       #if !defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+       cyg_semaphore_init(&usbs_imx_otg_dev_sem, 0);
+    cyg_thread_create(CYGNUM_DEVS_USB_OTG_DEV_THREAD_PRIORITY,
+                      &usbs_imx_otg_dev_thread_fn,
+                      0,
+                      "i.MX37/51 USB Device",
+                      usbs_imx_otg_dev_thread_stack,
+                      CYGNUM_DEVS_USB_OTG_DEV_THREAD_STACK_SIZE,
+                      &usbs_imx_otg_dev_thread_handle,
+                      &usbs_imx_otg_dev_thread
+        );
+    cyg_thread_resume(usbs_imx_otg_dev_thread_handle);
+       // It is also possible and desirable to install the interrupt
+       // handler here, even though there will be no interrupts for a
+       // while yet.
+       cyg_interrupt_create(IMX_IRQ_USB_DEV_SERVICE_REQUEST,
+                             IMX_IRQ_USB_DEV_PRIORITY,        // priority
+                             0,         // data
+                             &usbs_imx_otg_dev_isr,                             
+                                                        &usbs_imx_otg_dev_thread_dsr,
+                             &g_usbs_dev_intr_handle,
+                             &g_usbs_dev_intr_data);
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: cyg_interrupt_create@vector %d.\n",IMX_IRQ_USB_DEV_SERVICE_REQUEST);
+       cyg_interrupt_attach(g_usbs_dev_intr_handle);           //fill interrupt handler table for USB 
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: cyg_interrupt_attach.\n");
+       cyg_interrupt_unmask(IMX_IRQ_USB_DEV_SERVICE_REQUEST);  //enable USB interrrupt
+       USBDBGMSG(DEBUG_BASIC,"+USBDBGMSG: cyg_interrupt_unmask.\n");
+       #endif
+       ep0.common.start_fn(&(ep0.common));
+
+}
+
+void 
+usbs_imx_otg_device_deinit(void) //works like usb port close
+{
+       usbs_imx_otg_base->usbcmd &= (~BIT0);                           // Set Run/Stop bit to Stop Mode
+       g_usb_dev_state = USB_DEV_DUMMY_STATE;
+}
+
+#if defined(CYGHWR_IMX_USB_DOWNLOAD_SUPPORT)
+
+static cyg_uint32 get_free_bulk_buffer(void)
+{
+       cyg_uint32 buff_addr = 0;
+       int i = 0;
+       while(buff_addr == 0)
+       {
+               if(g_bulkbuffer_a.stat == BUFFER_FREED)
+               {
+                       buff_addr = (cyg_uint32)(g_bulkbuffer_a.buffer);
+                       break;
+               }
+               else if(g_bulkbuffer_b.stat == BUFFER_FREED)
+               {
+                       buff_addr = (cyg_uint32)(g_bulkbuffer_b.buffer);
+                       break;
+               }
+               /*
+               else
+               {
+                       i++;
+                       if(i==0xD0000) 
+                       {
+                               diag_printf("no bulk buffer free\n");
+                               break;
+                       }
+                       
+               }
+               */
+       }
+       return buff_addr;
+}
+
+cyg_bool set_status_bulk_buffer(cyg_uint32 buff_addr, int buff_stat)
+{
+       cyg_bool ret = true;
+       if(buff_addr == (cyg_uint32)(g_bulkbuffer_a.buffer))
+               g_bulkbuffer_a.stat = buff_stat;
+       else if (buff_addr == (cyg_uint32)(g_bulkbuffer_b.buffer))
+               g_bulkbuffer_b.stat = buff_stat;
+       else
+               ret = false;
+
+       return ret;
+}
+static usb_status_t usb_bulk_receive_data(usb_buffer_descriptor_t * bd)
+{
+       usb_status_t status;
+       int res;
+
+       /* Check if Bus Reset Received */
+    if((usbs_imx_otg_base->usbsts) & IMX_USB_STS_RESET)
+    {
+       /* Handle Bus Reset */
+        usbs_imx_otg_dev_handle_bus_reset(); 
+    }  
+    /* Check if Reset is already received and Setup Token Received */
+    if((usbs_imx_otg_base->endptsetupstat) & BIT0)
+    {
+               /* Handle Setup Token */
+       usbs_imx_otg_dev_ep0_dsr();
+    }
+       
+       if((usbs_imx_otg_base->endptcomplete) & ( EPOUT_COMPLETE << EP1))
+       {
+               ep1_rx_complete(res);
+               if(ep1.common.complete_data)
+               {
+                       bd->bytes_transfered = ep1.fetched;
+                       memcpy(bd->buffer,ep1.common.complete_data,ep1.fetched);
+                       ep1.fetched = 0;
+                       //D("+USBDBGMSG:bd->bytes_transfered %d\n",bd->bytes_transfered);
+                       set_status_bulk_buffer((cyg_uint32)(ep1.common.complete_data), BUFFER_FREED);
+                       ep1.common.buffer = (unsigned char *)get_free_bulk_buffer();
+                       ep1.common.buffer_size = BULK_TD_BUFFER_TOTAL_SIZE;
+                       ep1_start_rx(&(ep1.common));
+                       usbs_imx_otg_base->endptprime |= ( EPOUT_PRIME << EP1 );//prime ep1 td
+                       status = USB_SUCCESS;
+               }
+
+               else
+                       status = USB_FAILURE;
+       }
+       return status;
+}
+
+static usb_status_t usb_bulk_transmit_data(usb_buffer_descriptor_t * bd)
+{
+       //usb_state_t status;
+
+       while(bd->size)
+       {
+               ep2.common.buffer = (unsigned char *)get_free_bulk_buffer();
+               set_status_bulk_buffer((cyg_uint32)(ep2.common.buffer), BUFFER_ALLOCATED);
+               ep2.common.buffer_size = (BULK_TD_BUFFER_TOTAL_SIZE<(bd->size))?BULK_TD_BUFFER_TOTAL_SIZE:(bd->size);
+               memcpy((ep2.common.buffer),(bd->buffer),(ep2.common.buffer_size));
+               ep2_start_tx(&(ep2.common));
+
+               bd->size -= (ep2.common.buffer_size);
+       }
+
+       return USB_SUCCESS;
+}
+static cyg_uint32 usb_rx_processing(cyg_uint8* read_ptr, usb_status_t* status, cyg_uint32 data_length)
+{
+       cyg_uint32 bytes_received = 0;
+    if ( (status != NULL) && (read_ptr != NULL) )
+    {
+        usb_status_t trans_status = USB_FAILURE;
+
+        usb_buffer_descriptor_t  buf_desc;
+
+        /* Prepare the buffer descriptor for USB transfer */
+        //(cyg_uint8*)(buf_desc.buffer) = read_ptr;
+               buf_desc.buffer = (void *)read_ptr;
+        while(data_length != 0)
+        { 
+            buf_desc.size = data_length;
+            buf_desc.bytes_transfered = 0;
+
+            /* Receive data from USB */
+            trans_status = (usb_status_t )usb_bulk_receive_data(&buf_desc);
+            if(trans_status == USB_SUCCESS)
+            {
+                data_length -= buf_desc.bytes_transfered;
+                bytes_received += buf_desc.bytes_transfered;
+                //(cyg_uint8*)
+                               (buf_desc.buffer) += buf_desc.bytes_transfered;
+            }
+            else
+            {
+                *status = USB_FAILURE;
+            }
+
+                       g_timeout_value++;
+                       if(g_timeout_value%0x1000000==0) D("C");
+                       if(g_timeout_value == USB_DOWNLOAD_TIMEOUT_LIMIT) return 0;
+        }
+    }
+   
+    return ( bytes_received );
+}
+static usb_status_t usb_tx_processing(cyg_uint8* write_ptr, cyg_uint32 data_len)
+{
+    usb_status_t trans_status = USB_FAILURE;
+
+    /* Prepare the buffer descriptor for USB transfer */
+    usb_buffer_descriptor_t  buf_desc;
+
+    /* Prepare transfer buffer descriptor*/ 
+    buf_desc.buffer = (void *)write_ptr;
+    buf_desc.size = data_len;
+    buf_desc.bytes_transfered = 0;
+
+    /* Send data over USB */
+    trans_status = usb_bulk_transmit_data(&buf_desc);
+
+       return trans_status;
+}
+static cyg_bool pl_get_command(void)
+{
+       cyg_uint8 i = 0;
+       usb_status_t status;
+    cyg_uint32 bytes_recvd = 0;
+    cyg_uint8 start_command = 0xFF;
+
+    while(start_command == 0xFF)
+    {
+               //g_timeout_value++;
+               //if(g_timeout_value%1000==0) D("C");
+               //D("%d\n",g_timeout_value);
+               bytes_recvd = usb_rx_processing(sdp_payload_data, &status, SDP_CMD_MAX_LEN);
+        start_command = pl_command_start();            
+               if(g_timeout_value == USB_DOWNLOAD_TIMEOUT_LIMIT) return false;
+    }
+       //D("+USBDBGMSG: start_command = 0x%02X\n",start_command);
+    if(start_command == 0xF0)
+    {
+        //copy rest of the bytes
+        for(i=1; i < SDP_CMD_MAX_LEN; i++)
+        {
+            sdp_command[i] = sdp_payload_data[i-1];
+        }
+    }
+    else 
+    {
+        //copy starting bytes
+        for(i=0; i < (SDP_CMD_MAX_LEN - start_command) ; i++)
+        {
+            sdp_command[i] = sdp_payload_data[i + start_command];
+        }
+
+        if(start_command != 0)
+        {
+            //receive rest of the bytes
+            bytes_recvd = usb_rx_processing(sdp_payload_data, &status, start_command);
+        
+            if(bytes_recvd == start_command)
+            {
+                for(i=0; i <start_command; i++)
+                {
+                    sdp_command[SDP_CMD_MAX_LEN - start_command + i] = sdp_payload_data[i];
+                }
+            }
+        }
+    }
+
+    return true;
+}
+static cyg_uint8 pl_command_start(void)
+{
+       cyg_uint8 i=0;
+    static cyg_uint8 last_byte = 0;
+   
+    if(last_byte != 0x0)
+    {
+        if(last_byte == sdp_payload_data[0])
+        {
+            sdp_command[0] = last_byte;
+            last_byte = sdp_payload_data[SDP_CMD_MAX_LEN -1];
+            return 0xF0;
+        }
+    }
+
+    for(i=0; i < SDP_CMD_MAX_LEN -1; i++)
+    {
+        if((sdp_payload_data[i] == 0x01) && (sdp_payload_data[i+1] == 0x01) ||
+           (sdp_payload_data[i] == 0x02) && (sdp_payload_data[i+1] == 0x02) ||
+           (sdp_payload_data[i] == 0x03) && (sdp_payload_data[i+1] == 0x03) ||
+           (sdp_payload_data[i] == 0x04) && (sdp_payload_data[i+1] == 0x04) ||
+           (sdp_payload_data[i] == 0x05) && (sdp_payload_data[i+1] == 0x05) ||
+           (sdp_payload_data[i] == 0x06) && (sdp_payload_data[i+1] == 0x06) ||
+           (sdp_payload_data[i] == 0x07) && (sdp_payload_data[i+1] == 0x07) ||
+           (sdp_payload_data[i] == 0x08) && (sdp_payload_data[i+1] == 0x08) ||
+           (sdp_payload_data[i] == 0x09) && (sdp_payload_data[i+1] == 0x09) ||
+           (sdp_payload_data[i] == 0x0A) && (sdp_payload_data[i+1] == 0x0A)) 
+         {
+             return i;
+         }
+    }
+
+    //handle last byte
+    last_byte = sdp_payload_data[SDP_CMD_MAX_LEN -1];
+    if(!(last_byte == 0x1 || last_byte == 0x2 || last_byte == 0x3 || last_byte == 0x4 ||
+       last_byte == 0x5 || last_byte == 0x6 || last_byte == 0x7 || last_byte == 0x8 || last_byte == 0x8 ||
+       last_byte == 0x9))
+    {
+        last_byte = 0;
+    }
+    
+    return 0xFF;
+}
+static cyg_uint8 pl_handle_command(cyg_uint8 g_error_status)
+{
+       cyg_uint16 Header = 0;
+    cyg_uint32 Address = 0;
+    cyg_uint32 ByteCount = 0;
+    cyg_uint32 g_error_statusAck = 0;
+    cyg_uint8 status = 0;
+       //int i;
+    /* Command Packet Format: Header(2)+Address(4)+Format(1)+ByteCount(4)+Data(4)+Execute(1) */
+    Header = ((sdp_command[0]<<8) | (sdp_command[1]));
+    Address = ((sdp_command[2]<<24) | (sdp_command[3]<<16) | (sdp_command[4] << 8) | (sdp_command[5]));
+    ByteCount = ((sdp_command[7]<<24) | (sdp_command[8]<<16) | (sdp_command[9] << 8) | (sdp_command[10]));
+
+    /* Save g_error_status ack */
+    g_error_statusAck = (cyg_uint32)((g_error_status<<24) | (g_error_status <<16) | (g_error_status<<8) | (g_error_status));
+       //D("+USBDBGMSG: Command Header 0x%04X\n",Header);
+    switch (Header)
+    {
+        case WRITE_FILE:
+                       //D("+USBDBGMSG: usb download file to address 0x%08X, length %d\n",usb_download_address,ByteCount);
+            pl_handle_write_file(usb_download_address, ByteCount);     
+            //pl_handle_write_file(Address, ByteCount);
+                       //if(g_load_cycle==0) usb_download_address=Address;
+                       //g_load_cycle ++;
+                       usb_download_address += ByteCount;
+                       usb_download_length +=ByteCount;
+                       D(".");
+                       if(ByteCount<BULK_TD_BUFFER_TOTAL_SIZE) 
+                       {
+                               status = COMPLETE;
+                       }
+            break;
+        case ERROR_STATUS_HEADER:
+            pl_command_ack(g_error_statusAck);
+                       status = COMPLETE;
+            break;
+               case READ_FILE:
+        case WRITE_HEADER:
+       case READ_HEADER:
+        default:
+            break;
+    }
+
+    return status;
+
+}
+static void pl_handle_write_file(cyg_uint32 address, cyg_uint32 total_bytes)
+{
+       usb_status_t status;    
+    usb_rx_processing((cyg_uint8*)address, &status, total_bytes);
+}
+
+static void pl_command_ack(cyg_uint32 ack)
+{
+    usb_tx_processing((cyg_uint8*)&ack, SDP_CMD_ACK_LEN);
+}      
+
+void 
+usbs_imx_otg_download(unsigned char * buffer, unsigned int length)
+{
+       cyg_bool bytes_recvd = false;
+       //D("+usbdownload: enter usbs_imx_otg_download\n");
+       //D("+USBDBGMSG: re-enumerate USB device\n");
+       /*enumeration*/
+       /*TODO*/
+       while(g_usb_dev_state!=USB_DEV_CONFIGURED_STATE)
+       {
+               
+               /* Check if Bus Reset Received */
+        if((usbs_imx_otg_base->usbsts) & IMX_USB_STS_RESET)
+        {
+           /* Handle Bus Reset */
+               usbs_imx_otg_dev_handle_bus_reset(); 
+        }      
+        /* Check if Reset is already received and Setup Token Received */
+        if((g_usb_dev_state != USB_DEV_DUMMY_STATE) && (usbs_imx_otg_base->endptsetupstat & BIT0))
+        {
+               /* Handle Setup Token */
+               usbs_imx_otg_dev_ep0_dsr();
+        }              
+       }
+
+       if(g_usb_dev_state==USB_DEV_CONFIGURED_STATE)
+       {
+               //D("+USBDBGMSG: enumeration done\n");
+               /*file download*/
+               D("USB file download start\n");
+               g_timeout_value = 0;
+               usb_download_length = 0;
+               //usb_download_address = 0;
+               //g_load_cycle = 0;
+               while(1)
+               {
+                       
+                       bytes_recvd = pl_get_command();
+               if(bytes_recvd == true)
+               {
+               g_usb_download_state = pl_handle_command(g_error_status);  
+               } 
+       
+                       if((g_usb_download_state==COMPLETE)||(g_timeout_value == USB_DOWNLOAD_TIMEOUT_LIMIT)) 
+                               break;
+                       
+               }
+               diag_printf("\n");
+               if(g_timeout_value == USB_DOWNLOAD_TIMEOUT_LIMIT) //timeout value
+                       D("USB download timeout to wait none file to download\n");
+               else
+               {
+                       D("USB file download complete\n");
+                       //D("+usbdownload: image base 0x%08X, length %d\n",usb_download_address,usb_download_length);
+               }
+               
+       }
+}
+#endif
+
+//EOF
diff --git a/packages/services/diagnosis/v2_0/cdl/diagnosis.cdl b/packages/services/diagnosis/v2_0/cdl/diagnosis.cdl
new file mode 100644 (file)
index 0000000..1102806
--- /dev/null
@@ -0,0 +1,112 @@
+# ====================================================================
+#
+#      diagnosis.cdl
+#
+#      diagnosis configuration data.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2008 Freescale
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Fred.Fan
+# Original data:  Fred.Fan
+# Contributors:
+# Date:           2008-03-15
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DIAGNOSIS {
+    display       "Diagnostic tools"
+    include_dir   cyg/diagnosis
+#   doc           ref/services-diagnosis.html
+
+    description "
+      This package provides support for hardware diagnosis."
+
+    compile -library=libextras.a core.c
+
+    cdl_component CYGPKG_MEMORY_DIAGNOSIS {
+        display "memory diagnosis"
+        flavor  bool
+
+       description "This option includes memory test cases."
+
+       compile -library=libextras.a memory/routine.S
+       cdl_option CYGSEM_RAM_RW_DIAGNOSIS {
+                display "perform ram read/write diagnosis"
+                flavor  bool
+                default_value 1
+
+               description      "
+                    This option is overriden by the configuration in hal."
+
+               compile memory/ram_rw.c
+       }
+
+       cdl_option CYGSEM_RAM_PM_DIAGNOSIS {
+                display "perform ram performance diagnosis"
+                flavor  bool
+                default_value 1
+
+               description      "
+                    This option is overriden by the configuration in hal."
+
+               compile memory/ram_pm.c
+       }
+    }
+
+    cdl_component CYGPKG_WDT_DIAGNOSIS {
+        display "watchdog diagnosis"
+        flavor  bool
+
+       description "This option includes watchdog test cases."
+
+       compile -library=libextras.a
+       cdl_option CYGSEM_WDT_DIAGNOSIS {
+                display "perform watchdog diagnosis"
+                flavor  bool
+                default_value 1
+
+               description      "
+                    This option is overriden by the configuration in hal."
+
+               compile wdt/wdt.c
+       }
+    }
+}
+
+
diff --git a/packages/services/diagnosis/v2_0/include/diagnosis.h b/packages/services/diagnosis/v2_0/include/diagnosis.h
new file mode 100644 (file)
index 0000000..e76b350
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _DIAGNOSIS_H_
+#define _DIAGNOSIS_H_
+
+#include <pkgconf/hal.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_cache.h>
+#include <redboot.h>
+#include <stdlib.h>
+
+#include <pkgconf/diagnosis.h>
+
+#ifdef CYGPKG_MEMORY_DIAGNOSIS
+#include <cyg/diagnosis/memory.h>
+#endif
+
+extern struct cmd __DIAGNOSIS_cmds_TAB__[], __DIAGNOSIS_cmds_TAB_END__;
+extern void diagnosis_usage(char *why);
+
+#endif                 /* _DIAGNOSIS_H_ */
diff --git a/packages/services/diagnosis/v2_0/include/memory.h b/packages/services/diagnosis/v2_0/include/memory.h
new file mode 100644 (file)
index 0000000..c747d88
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __DIAGNOSIS_MEMORY_H_
+#define __DIAGNOSIS_MEMORY_H_
+
+extern void diagnosis_mem_read_block(unsigned long start, int size);
+extern void diagnosis_mem_write_block(unsigned long start, int size);
+extern int diagnosis_mem_copy_block(unsigned long start, unsigned long dest, int size);
+
+#ifdef CYGSEM_RAM_RW_DIAGNOSIS
+
+enum {
+DIAGNOSIS_MEM_RAM_RD = 0,
+};
+#endif
+
+#endif                 /* __DIAGNOSIS_MEMORY_H_ */
diff --git a/packages/services/diagnosis/v2_0/src/core.c b/packages/services/diagnosis/v2_0/src/core.c
new file mode 100644 (file)
index 0000000..27a22a4
--- /dev/null
@@ -0,0 +1,40 @@
+#include <redboot.h>
+#include <stdlib.h>
+#include <cyg/diagnosis/diagnosis.h>
+
+#include CYGHWR_MEMORY_LAYOUT_H
+
+// Define table boundaries
+CYG_HAL_TABLE_BEGIN( __DIAGNOSIS_cmds_TAB__, DIAGNOSIS_cmds);
+CYG_HAL_TABLE_END( __DIAGNOSIS_cmds_TAB_END__, DIAGNOSIS_cmds);
+
+// CLI function
+static cmd_fun do_diagnosis_cmds;
+RedBoot_nested_cmd("diag",
+           "Tools for system diagnostics",
+           "{cmds}",
+           do_diagnosis_cmds,
+           __DIAGNOSIS_cmds_TAB__, &__DIAGNOSIS_cmds_TAB_END__
+          );
+
+void diagnosis_usage(char *why)
+{
+    diag_printf("*** invalid 'diag' command: %s\n", why);
+    cmd_usage(__DIAGNOSIS_cmds_TAB__, &__DIAGNOSIS_cmds_TAB_END__, "diag ");
+}
+
+static void do_diagnosis_cmds(int argc, char *argv[])
+{
+       struct cmd * cmd;
+       if (argc < 2) {
+               diagnosis_usage("too few arguments");
+               return;
+       }
+       if ((cmd = cmd_search(__DIAGNOSIS_cmds_TAB__, 
+                         &__DIAGNOSIS_cmds_TAB_END__,
+                          argv[1])) != (struct cmd *)0) {
+               (cmd->fun)(argc, argv);
+               return;
+       }
+       diagnosis_usage("unrecognized command");
+}
diff --git a/packages/services/diagnosis/v2_0/src/memory/ram_pm.c b/packages/services/diagnosis/v2_0/src/memory/ram_pm.c
new file mode 100644 (file)
index 0000000..91cacff
--- /dev/null
@@ -0,0 +1,183 @@
+#include <redboot.h>
+#include <stdlib.h>
+#include <cyg/diagnosis/diagnosis.h>
+#include <cyg/hal/plf_io.h>
+
+#include CYGHWR_MEMORY_LAYOUT_H
+
+#define DEFAULT_TEST_TIME      2
+#define MIN_TEST_TIME  1
+#define MAX_TEST_TIME  20
+
+#define DEFAULT_BLOCK_SIZE     4096
+#define MAX_BLOCK_SIZE         32768
+#define MIN_BLOCK_SIZE         1024
+
+local_cmd_entry("ram_pm",
+       "ram performance test",
+       "-t time -b size [-m mode]\n"
+       "    -t time: set test time\n"
+       "    -b size: set block size < 8192\n"
+       "    -m mode: set 0:read, 1:write, 2:copy\n",
+       ram_pm_test,
+       DIAGNOSIS_cmds
+);
+
+enum {
+       RAM_PM_READ = 0,
+       RAM_PM_WRITE,
+       RAM_PM_COPY,
+       RAM_PM_MAX,
+};
+
+static char * mode_str[RAM_PM_MAX] =
+{
+       "read",
+       "write",
+       "copy"
+};
+
+static inline void start_timer(int second)
+{
+       unsigned int reg;
+       reg = readl(CCM_BASE_ADDR + CLKCTL_CGR1);
+       writel(reg | 0x30, CCM_BASE_ADDR + CLKCTL_CGR1);
+
+       reg = readl(GPT_BASE_ADDR + GPTCR) | 0x8002;
+       writel(reg&(~1), GPT_BASE_ADDR + GPTCR);
+       while(readl(GPT_BASE_ADDR + GPTCR) & 0x8000);
+
+       reg = second * 1000;
+       writel(reg, GPT_BASE_ADDR + GPTOCR1);
+       writel(0, GPT_BASE_ADDR + GPTIR);
+       writel(0, GPT_BASE_ADDR + GPTCNT);
+       writel(31, GPT_BASE_ADDR + GPTPR);
+       writel(0x3F, GPT_BASE_ADDR + GPTSR);
+
+       reg = readl(GPT_BASE_ADDR + GPTCR) | 0x303;
+       writel(reg, GPT_BASE_ADDR + GPTCR);
+}
+
+static inline int get_time(int * cycles)
+{
+       *cycles = readl(GPT_BASE_ADDR + GPTCNT);
+       if (readl(GPT_BASE_ADDR + GPTSR)& 1)
+               *cycles -= readl(GPT_BASE_ADDR + GPTOCR1);
+       return readl(GPT_BASE_ADDR + GPTSR) & 1;
+}
+
+static inline void stop_timer(void)
+{
+       unsigned int reg;
+       reg = readl(GPT_BASE_ADDR + GPTCR) | 0x8000;
+       writel(reg&(~1), GPT_BASE_ADDR + GPTCR);
+}
+
+static int performance_read_write(int time, int bsize, int read)
+{
+       unsigned long start = CYGMEM_REGION_ram + 1*1024*1024;
+       int size = CYGMEM_REGION_ram_SIZE / 2;
+       int cycles;
+       long long i;
+
+       if ( (bsize % 32) || (size % bsize) || size < (1*1024*1024)) {
+               diag_printf("size is illegal(size=%d)\n", size);
+       }
+
+       size = (size / bsize) * bsize;
+       diag_printf("%s:size=%d, bsize=%d\n", read?"READ":"WRITE", size, bsize);
+       start_timer(time);
+       for (i=0; !get_time(&cycles); i += bsize) {
+               if (read)
+                       diagnosis_mem_read_block(start + (i % size), bsize);
+               else
+                       diagnosis_mem_write_block(start + (i % size), bsize);
+       }
+       stop_timer();
+       diag_printf("Finished size=%ld ", i);
+       diag_printf("time=%d", time);
+       diag_printf(" %d(ms)\n", cycles);
+       i = (i * 1000) / ((time * 1000) + cycles);
+       return i / 1024;
+}
+
+static int performance_copy(int time, int bsize)
+{
+       unsigned long start = CYGMEM_REGION_ram + 1 * 1024 * 1024;
+       unsigned long dest = start + 1 * 1024 * 1024;
+       int size = CYGMEM_REGION_ram_SIZE / 4;
+       int cycles;
+       long long i;
+
+       dest += size;
+
+       if ( (bsize % 32) || (size % bsize) || size < (1 * 1024 * 1024)) {
+               diag_printf("size is illegal(size=%d)\n", size);
+       }
+
+       start_timer(time);
+
+       size = (size / bsize) * bsize;
+       for (i = 0; !get_time(&cycles); i += bsize) {
+               if (diagnosis_mem_copy_block(start + (i % size),
+                                           dest + (i % size), bsize)
+                                               < 0) {
+                       diag_printf("verify data fail\n");
+                       break;
+               }
+       }
+       stop_timer();
+       i = (i * 1000) / ((time * 1000) + cycles);
+       return i / 1024;
+}
+
+static void ram_pm_test(int argc, char * argv[])
+{
+       int opts_map[3];
+       struct option_info opts[3];
+       int time, mode, result, bsize;
+
+       memset(opts_map, 0, sizeof(int)*2);
+       init_opts(&opts[0], 't', true, OPTION_ARG_TYPE_NUM,
+                (void *)&time, (bool *)&opts_map[0], "test time");
+       init_opts(&opts[1], 'b', true, OPTION_ARG_TYPE_NUM,
+                (void *)&bsize, (bool *)&opts_map[1], "block size");
+       init_opts(&opts[2], 'm', true, OPTION_ARG_TYPE_NUM,
+                (void *)&mode, (bool *)&opts_map[2], "operate mode");
+
+       if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0)) {
+               diagnosis_usage("invalid arguments");
+               return;
+       }
+
+       if (!opts_map[0] || time < MIN_TEST_TIME || time > MAX_TEST_TIME)
+               time = DEFAULT_TEST_TIME;
+
+       if(!opts_map[1] || bsize < MIN_BLOCK_SIZE || bsize > MAX_BLOCK_SIZE)
+               bsize = DEFAULT_BLOCK_SIZE;
+
+       if (!opts_map[2] || mode >= RAM_PM_MAX)
+               mode = RAM_PM_READ;
+
+       diag_printf("Start memory performance test (%s)...\n",
+               mode_str[mode]);
+       switch(mode) {
+       case RAM_PM_READ:
+               result = performance_read_write(time, bsize, 1);
+               break;
+       case RAM_PM_WRITE:
+               result = performance_read_write(time, bsize, 0);
+               break;
+       case RAM_PM_COPY:
+               result = performance_copy(time, bsize);
+               break;
+       default:
+               result = -1;
+       }
+       if (result < 0) {
+               diag_printf("memory performance test fails\n");
+       } else {
+               diag_printf("memory performance test success:%d.%d(MB/s)\n",
+                             result / 1024, (result % 1024));
+       }
+}
diff --git a/packages/services/diagnosis/v2_0/src/memory/ram_rw.c b/packages/services/diagnosis/v2_0/src/memory/ram_rw.c
new file mode 100644 (file)
index 0000000..b27bd16
--- /dev/null
@@ -0,0 +1,262 @@
+#include <redboot.h>
+#include <stdlib.h>
+#include <cyg/diagnosis/diagnosis.h>
+#include <cyg/hal/plf_io.h>
+
+#include CYGHWR_MEMORY_LAYOUT_H
+
+static int loops1;
+static unsigned int pattern1, pattern2;
+static unsigned int start;
+static int length;
+static int burst = 0;
+
+local_cmd_entry("ram_rw",
+        "ram read/write accessing",
+       "-c iterators -b <base address> -l <length> "\
+       "-p pattern -m case [-s]\n",
+       ram_rw_test,
+       DIAGNOSIS_cmds
+);
+
+local_cmd_entry("memcpybm",
+       "ram memory copy benchmarking",
+       "-c <loops> -s <start size KB> -e <end size KB>  -a <source align Byte> -b <dest align Byte>\n",
+       memcpybm,
+       DIAGNOSIS_cmds
+);
+
+static void raw_rw_case1(void)
+{
+       unsigned int * current_write;
+       unsigned int * current_read;
+       int round = 0;
+       diag_printf("RAM diagnostical pattern from David.Young of freescale\n");
+       diag_printf("burst is %s\n", burst?"enabled":"disabled");
+       while( (round++) < loops1) {
+               if (_rb_break(0))
+                       return;
+               if(burst) {
+                       current_write =(unsigned int *)start;
+                       memset(current_write, (pattern1&0xFF000000)>>24, length);
+               } else {
+                       for(current_write=(unsigned int *)start; current_write<(unsigned int *)(start + length); current_write += 2) {
+                               *current_write = ((unsigned int)current_write & 0x0000FFFF)|(0xFFFF0000 & pattern1);
+                       }
+                       for(current_write=(unsigned int *)start + 1; current_write<(unsigned int *)(start + length); current_write += 2) {
+                               *current_write = ((unsigned int)current_write & 0x0000FFFF)|(0xFFFF0000 & pattern2);
+                       }
+               }
+               for(current_read=(unsigned int *)start; current_read<(unsigned int *)(start + length); current_read ++) {
+                       if(burst) {
+                               if((*current_read) != pattern2) {
+                                       diag_printf("\tround %d::[0x%08x]=0x%08x:0x%08x\n", round, current_read, pattern2, *current_read);
+                                       goto fail;
+                               }
+                       } else {
+                               if((current_read - (unsigned int *)start) & 1) {
+                                       if(((*current_read)&0xFFFF0000) != (pattern2&0xFFFF0000)) {
+                                               diag_printf("\tround %d::[0x%08x]=0x%08x:0x%08x\n", round, current_read, (pattern2&0xFFFF0000)|((unsigned int)current_read)&0xFFFF, *current_read);
+                                               goto fail;
+                                       }
+                               } else {
+                                       if(((*current_read)&0xFFFF0000) != (pattern1&0xFFFF0000)) {
+                                               diag_printf("\tround %d::[0x%08x]=0x%08x:0x%08x\n", round, current_read, (pattern1&0xFFFF0000)|((unsigned int)current_read)&0xFFFF, *current_read);
+                                               goto fail;
+                                       }
+                               }
+                       }
+               }
+       }
+       diag_printf("Diagnosis is successful!\n");
+       return;
+fail:
+       diag_printf("Diagnosis is failure !\n");
+}
+
+static void ram_rw_test(int argc, char * argv[])
+{
+       int opts_map[6];
+       struct option_info opts[6];
+       int mode;
+
+       memset(opts_map, 0, sizeof(int)*6);
+
+       init_opts(&opts[0], 'c', true, OPTION_ARG_TYPE_NUM,
+                (void *)&loops1, (bool *)&opts_map[0], "the rounds of test");
+       init_opts(&opts[1], 'b', true, OPTION_ARG_TYPE_NUM,
+                (void *)&start, (bool *)&opts_map[1], "accessing start address");
+       init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
+                (void *)&length, (bool *)&opts_map[2], "accessing size(bytes)");
+       init_opts(&opts[3], 'p', true, OPTION_ARG_TYPE_NUM,
+                (void *)&pattern1, (bool *)&opts_map[3], "High 16bit is valid");
+       init_opts(&opts[4], 'm', true, OPTION_ARG_TYPE_NUM,
+                (void *)&mode, (bool *)&opts_map[4], "Test case number");
+       init_opts(&opts[5], 's', false, OPTION_ARG_TYPE_FLG,
+                (void *)&burst, (bool *)0, "enable bust mode(based on memset)");
+
+       if (!scan_opts(argc, argv, 2, opts, 6, 0, 0, 0)) {
+               diagnosis_usage("invalid arguments");
+               return;
+       }
+
+       if(!opts_map[0]) {
+               loops1 = 32;
+       }
+
+       if(!opts_map[1]) {
+               start = 0x80000;
+       }
+
+       if(!opts_map[2]) {
+               length = 8192;
+       }
+
+       if(!opts_map[3]) {
+               pattern1 = 0x55550000;
+       }
+
+       if(!opts_map[4]) {
+               mode = DIAGNOSIS_MEM_RAM_RD;
+       }
+
+       if(burst) {
+               pattern2 = (pattern1&0xFF000000);
+               pattern2 |= pattern2>>8;
+               pattern2 |= pattern2>>16;
+       } else {
+               pattern2 = (~pattern1)&0xFFFF0000;
+       }
+
+       if(!valid_address((unsigned char *)start)) {
+               if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)start))
+                       return;
+       }
+
+       switch(mode) {
+       case DIAGNOSIS_MEM_RAM_RD:
+               raw_rw_case1();
+               break;
+       default:
+               diag_printf("Invalid memory diagnosis case!\n");
+       }
+}
+
+/* Defines */
+#define SIZE_1K                        1024
+#define SIZE_4K                        (4*SIZE_1K)
+#define SIZE_1M                        (1024*1024)
+#define START_SIZE             (2*SIZE_1K)
+#define END_SIZE               SIZE_1M
+#define ALIGN                  SIZE_4K
+#define START_LOOPS            200000
+
+#define OPT_SIZE        5
+#define printf          diag_printf
+#define CLOCKS_PER_SEC  32768
+extern unsigned int hal_timer_count(void);
+#define clock()         hal_timer_count()
+
+//#define memcpy diagnosis_mem_copy_block
+static void memcpybm(int argc, char * argv[])
+{
+       int opts_map[OPT_SIZE];
+       struct option_info opts[OPT_SIZE];
+       int mode;
+       int size = START_SIZE / SIZE_1K;
+       int end_size = END_SIZE / SIZE_1K;
+       int salign = ALIGN;
+       int dalign = ALIGN;
+       int loops = START_LOOPS / 1000;
+       int src, dst, asrc, adst;
+
+
+       memset(opts_map, 0, sizeof(int)*OPT_SIZE);
+
+       init_opts(&opts[0], 'c', true, OPTION_ARG_TYPE_NUM,
+                (void *)&loops, (bool *)&opts_map[0], "the rounds of test in thousands");
+       init_opts(&opts[1], 's', true, OPTION_ARG_TYPE_NUM,
+                (void *)&size, (bool *)&opts_map[1], "start size in KB");
+       init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,
+                (void *)&end_size, (bool *)&opts_map[2], "end size in KB");
+       init_opts(&opts[3], 'a', true, OPTION_ARG_TYPE_NUM,
+                (void *)&salign, (bool *)&opts_map[3], "source align in byte");
+       init_opts(&opts[4], 'b', true, OPTION_ARG_TYPE_NUM,
+                (void *)&dalign, (bool *)&opts_map[4], "destination align in byte");
+
+       if (!scan_opts(argc, argv, 2, opts, OPT_SIZE, 0, 0, 0)) {
+               diagnosis_usage("invalid arguments");
+               return;
+       }
+
+       loops *= 1000;
+       size *=  SIZE_1K;
+       end_size *= SIZE_1K;
+       /* Allocate buffers */
+       if ((src = (int) malloc(end_size + salign + SIZE_4K)) == 0) {
+               printf("%s: insufficient memory\n", argv[0]);
+               return;
+       }
+       memset((void*)src, 0xaa, end_size + salign + SIZE_4K);
+       if ((dst = (int) malloc(end_size + dalign + SIZE_4K)) == 0) {
+               free((void*)src);
+               printf("%s: insuficient memory\n", argv[0]);
+               return;
+       }
+       memset((void*)dst, 0x55, end_size + dalign + SIZE_4K);
+
+       /* Align buffers */
+       if (src % SIZE_4K == 0)
+               asrc = src + salign;
+       else
+               asrc = src + SIZE_4K - (src % SIZE_4K) + salign;
+       if (dst % SIZE_4K == 0)
+               adst = dst + dalign;
+       else
+               adst = dst + SIZE_4K - (dst % SIZE_4K) + dalign;
+
+       /* Print Banner */
+       printf("\nMEMCPY Benchmark\n\n");
+       printf("Src Buffer 0x%08x\n", asrc);
+       printf("Dst Buffer 0x%08x\n\n", adst);
+       printf("%10s %10s\n", "Cached", "Bandwidth");
+       printf("%10s %10s\n", "(KBytes)", "(MB/sec)");
+
+       /* Loop over copy sizes */
+       while (size <= end_size)
+       {
+               unsigned int start_time;
+               unsigned int elapsed_time;
+               int loop;
+               unsigned long long sz;
+
+               printf("%10d", size / SIZE_1K);
+
+               /* Do data copies */
+               start_time = clock();
+               for (loop = 0; loop < loops; loop++)
+                       memcpy((void*)adst, (void*)asrc, size);
+               elapsed_time = (clock() - start_time);
+
+               sz = size *loops * 2;
+               printf("   %d", sz*CLOCKS_PER_SEC/elapsed_time/SIZE_1M);
+               printf("\t elapsed=%d", elapsed_time);
+               printf("\tsize=%d, loops=%d, sz=%d", size, loops, sz);
+               printf("\n");
+
+/*
+               printf(" %10.0f\n", ((float)size*loops*2)/elapsed_time/SIZE_1M);
+               printf("   %d.%d.%d\n", elapsed_time / CLOCKS_PER_SEC,
+               (elapsed_time % CLOCKS_PER_SEC) * 1000 / CLOCKS_PER_SEC,
+               (((elapsed_time % CLOCKS_PER_SEC) * 1000) % CLOCKS_PER_SEC) * 1000 / CLOCKS_PER_SEC);
+*/
+               /* Adjust for next test */
+               size *= 2;
+               loops /= 2;
+       }
+
+       /* Free buffers */
+       free((void*)src);
+       free((void*)dst);
+}
+
diff --git a/packages/services/diagnosis/v2_0/src/memory/routine.S b/packages/services/diagnosis/v2_0/src/memory/routine.S
new file mode 100644 (file)
index 0000000..5474051
--- /dev/null
@@ -0,0 +1,48 @@
+       .text
+/*
+ * void diagnosis_mem_read_block(unsigned long start, int size)
+ */
+       .global diagnosis_mem_read_block
+diagnosis_mem_read_block:
+       stmdb sp!, {r2 - r9}
+       add r1, r1, r0 
+1:     cmp r0, r1
+       ldmloia r0!, {r2-r9}
+       blo 1b
+       ldmia sp!, {r2 - r9}    
+       mov pc, lr
+/*
+ * void diagnosis_mem_write_block(unsigned long start, int size)
+ */
+       .global diagnosis_mem_write_block
+diagnosis_mem_write_block:     
+       stmdb sp!, {r2 - r9}
+       add r1, r1, r0
+1:     cmp r0, r1
+       stmloia r0!, {r2 - r9}
+       blo 1b
+       ldmia sp!, {r2 - r9}    
+       mov pc, lr
+/*
+ * int diagnosis_mem_copy_block(unsigned long start, unsigned long dest, int size)
+ */
+       .global diagnosis_mem_copy_block
+diagnosis_mem_copy_block:
+       stmdb sp!, {r3 - r11}
+       stmdb sp!, {r0, r1}
+       add r11, r1, r2
+1:     cmp r1, r11
+       ldmloia r0!, {r3-r10}
+       stmloia r1!, {r3-r10}
+       blo 1b
+       ldmia sp!, {r0, r1}
+1:     cmp r1, r11
+       movhs r0, #0
+       bhs 2f
+       ldrlo r3, [r0], #4      
+       ldrlo r4, [r1], #4
+       cmp r3, r4
+       beq 1b
+       mov r0, #-1     
+2:     ldmia sp!, {r3 - r11}
+       mov pc, lr      
diff --git a/packages/services/diagnosis/v2_0/src/wdt/wdt.c b/packages/services/diagnosis/v2_0/src/wdt/wdt.c
new file mode 100644 (file)
index 0000000..79b581c
--- /dev/null
@@ -0,0 +1,141 @@
+#include <redboot.h>
+#include <stdlib.h>
+#include <cyg/diagnosis/diagnosis.h>
+#include <cyg/hal/plf_io.h>
+
+#include CYGHWR_MEMORY_LAYOUT_H
+
+#define WDT_WCR        0x00
+#define WDT_WSR        0x02
+
+#define WDT_CNT_MASK   0xFF00
+#define WDT_WCR_MASK   0xFF
+#define WDT_CNT_OFF    8
+
+#define WDT_WCR_WDW    (1 << 7)
+#define WDT_WCR_WOE    (1 << 6)
+#define WDT_WCR_WDA    (1 << 5)
+#define WDT_WCR_SRS    (1 << 4)
+#define WDT_WCR_WDT    (1 << 3)
+#define WDT_WCR_WDE    (1 << 2)
+#define WDT_WCR_WDBG   (1 << 1)
+#define WDT_WCR_WDZST  (1)
+
+#define WDT_MAGIC_1    (0x5555)
+#define WDT_MAGIC_2    (0xAAAA)
+
+local_cmd_entry("wdt",
+       "watchdog test:Warning after run test, please reboot",
+       "-s sleep_time -t timeout [-c ctrl_bits] -b\n"
+       "-b:Insert memory access during ping operation\n",
+       wdt_test,
+       DIAGNOSIS_cmds
+);
+
+static unsigned char wdt_wcr;
+
+static unsigned int wdt_ping_mode;
+
+static inline void wdt_setup(unsigned int timeout)
+{
+       unsigned short int reg;
+       reg = readw(WDOG_BASE_ADDR + WDT_WCR) & WDT_WCR_MASK;   
+       reg |= (timeout * 2 << WDT_CNT_OFF) & WDT_CNT_MASK;
+
+       if (wdt_wcr)
+               reg |= wdt_wcr & WDT_WCR_MASK;
+       else
+               reg |= WDT_WCR_WOE | WDT_WCR_WDA | WDT_WCR_SRS|
+                       WDT_WCR_WDBG | WDT_WCR_WDZST;
+
+       diag_printf("WCR=%x\n", reg | WDT_WCR_WDE);     
+       writew(reg | WDT_WCR_WDE, WDOG_BASE_ADDR + WDT_WCR);
+}
+
+static inline void wdt_stop(void)
+{
+       unsigned short int reg;
+       reg = readw(WDOG_BASE_ADDR + WDT_WCR) & (~WDT_WCR_WDE); 
+       reg |= WDT_CNT_MASK;
+       writew(reg, WDOG_BASE_ADDR + WDT_WCR);
+}
+
+static inline void wdt_keepalive(void)
+{
+       int j;
+       volatile unsigned int i;
+
+       if (wdt_ping_mode) {
+               writew(WDT_MAGIC_1, WDOG_BASE_ADDR + WDT_WSR);
+               for (i = 0, j &= 0x7; i <= j; i++)
+                       asm("nop");
+       } else {
+               writew(WDT_MAGIC_1, WDOG_BASE_ADDR + WDT_WSR);
+       }
+       writew(WDT_MAGIC_2, WDOG_BASE_ADDR + WDT_WSR);
+}
+
+static void wdt_sleep(int second)
+{
+       int i;
+       unsigned int delayCount = 32000;
+
+       for ( i = 0; i < second; i++) { 
+               writel(0x01, EPIT_BASE_ADDR + EPITSR);
+               writel(delayCount, EPIT_BASE_ADDR + EPITLR);
+               while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0);
+       }
+}
+
+static void wdt_test(int argc, char * argv[])
+{
+       int opts_map[4];
+       struct option_info opts[4];
+       unsigned int sleep_timeout;
+       unsigned int wdt_timeout;
+
+       memset(opts_map, 0, sizeof(int)*4);
+
+       init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM,
+                (void *)&sleep_timeout, (bool *)&opts_map[0], "sleep time");
+       init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM,
+                (void *)&wdt_timeout, (bool *)&opts_map[1], "watchdog timeout");
+       init_opts(&opts[2], 'c', true, OPTION_ARG_TYPE_NUM,
+                (void *)&wdt_wcr, (bool *)&opts_map[2], "watchdog control bits");
+       init_opts(&opts[3], 'b', false, OPTION_ARG_TYPE_FLG,
+                (void *)&wdt_ping_mode, (bool *)0, "Add nop between ping operation");
+
+       if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
+               diagnosis_usage("invalid arguments");
+               return;
+       }
+
+       if(!opts_map[0]) {
+                sleep_timeout = 1;
+       } 
+
+       if(!opts_map[1]) {
+               wdt_timeout = 2;
+       }
+
+       if(!opts_map[2]) {
+               wdt_wcr = 0;
+       }
+
+       diag_printf("Watchdog sleeptime=%d timeout=%d %s in ping", 
+                       sleep_timeout, wdt_timeout,
+                       wdt_ping_mode?"Add memory access":"No memory access");
+       wdt_setup(wdt_timeout);
+       
+       while(1) {
+               if(_rb_break(0)) {
+                       diag_printf("break Watchdog test\n");
+                       wdt_sleep(wdt_timeout*2);
+                       break;
+               }
+               wdt_keepalive();
+               wdt_sleep(sleep_timeout);
+       }
+       wdt_stop(); 
+       diag_printf("Exit Watchdog test\n");
+}