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..