diff options
Diffstat (limited to 'package/system/ltq-vmmc/patches/400-falcon.patch')
-rw-r--r-- | package/system/ltq-vmmc/patches/400-falcon.patch | 968 |
1 files changed, 968 insertions, 0 deletions
diff --git a/package/system/ltq-vmmc/patches/400-falcon.patch b/package/system/ltq-vmmc/patches/400-falcon.patch new file mode 100644 index 0000000..490d6e5 --- /dev/null +++ b/package/system/ltq-vmmc/patches/400-falcon.patch @@ -0,0 +1,968 @@ +--- a/configure.in ++++ b/configure.in +@@ -956,14 +956,15 @@ AC_DEFINE([VMMC],[1],[enable VMMC suppor + AM_CONDITIONAL(DANUBE, false) + AM_CONDITIONAL(AR9, false) + AM_CONDITIONAL(VR9, false) ++AM_CONDITIONAL(FALCON, false) + AC_ARG_WITH(device, + AC_HELP_STRING( +- [--with-device=DANUBE|TWINPASS|AR9|VR9], ++ [--with-device=DANUBE|TWINPASS|AR9|VR9|FALCON], + [Set device type, default is DANUBE] + ), + [ + if test "$withval" = yes; then +- AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9]); ++ AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9|FALCON]); + else + case $withval in + DANUBE) +@@ -986,8 +987,13 @@ AC_ARG_WITH(device, + AC_DEFINE([SYSTEM_VR9],[1],[enable VR9 specific code]) + AM_CONDITIONAL(VR9, true) + ;; ++ FALCON) ++ AC_MSG_RESULT(FALCON device is used); ++ AC_DEFINE([SYSTEM_FALCON],[1],[enable FALCON specific code]) ++ AM_CONDITIONAL(FALCON, true) ++ ;; + *) +- AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9]); ++ AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9|FALCON]); + ;; + esac + fi +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -70,6 +70,11 @@ drv_vmmc_SOURCES +=\ + mps/drv_mps_vmmc_ar9.c + endif + ++if FALCON ++drv_vmmc_SOURCES +=\ ++ mps/drv_mps_vmmc_falcon.c ++endif ++ + endif + + if PMC_SUPPORT +--- a/drv_version.h ++++ b/drv_version.h +@@ -36,6 +36,10 @@ + #define MIN_FW_MAJORSTEP 2 + #define MIN_FW_MINORSTEP 1 + #define MIN_FW_HOTFIXSTEP 0 ++#elif defined(SYSTEM_FALCON) ++#define MIN_FW_MAJORSTEP 0 ++#define MIN_FW_MINORSTEP 1 ++#define MIN_FW_HOTFIXSTEP 0 + #else + #error unknown system + #endif +--- a/src/drv_vmmc_bbd.c ++++ b/src/drv_vmmc_bbd.c +@@ -34,6 +34,7 @@ + #define VMMC_WL_SDD_BASIC_CFG 0x04000400 + #define VMMC_WL_SDD_RING_CFG 0x04000500 + #define VMMC_WL_SDD_DCDC_CFG 0x04000C00 ++#define VMMC_WL_SDD_MWI_CFG 0x04000600 + + #define IDLE_EXT_TOGGLE_SLEEP_MS 5 + +@@ -52,6 +53,8 @@ + #define BBD_VMMC_MAGIC 0x41523921 /* "AR9" */ + #elif defined(SYSTEM_VR9) + #define BBD_VMMC_MAGIC 0x56523921 /* "VR9" */ ++#elif defined(SYSTEM_FALCON) ++#define BBD_VMMC_MAGIC 0x46414C43 /* "FALC" */ + #else + #error system undefined + #endif +@@ -525,9 +528,6 @@ static IFX_int32_t VMMC_BBD_BlockHandler + IFX_uint16_t slic_val; + IFX_int32_t ret = IFX_SUCCESS; + +- TRACE(VMMC, DBG_LEVEL_LOW, +- ("bbd block with tag 0x%04X passed\n", pBBDblock->tag)); +- + /* for FXO line allowed blocks are FXO_CRAM and TRANSPARENT */ + if (pCh->pALM->line_type_fxs != IFX_TRUE) + { +@@ -686,6 +686,7 @@ static IFX_int32_t VMMC_BBD_BlockHandler + break; + } + } /* if */ ++ + return ret; + } + +@@ -1026,6 +1027,7 @@ static IFX_int32_t vmmc_BBD_WhiteListedC + } + case VMMC_WL_SDD_RING_CFG: + case VMMC_WL_SDD_DCDC_CFG: ++ case VMMC_WL_SDD_MWI_CFG: + ret = CmdWrite (pCh->pParent, Msg.val, Msg.cmd.LENGTH); + break; + +@@ -1068,7 +1070,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + IFX_uint32_t countWords; + IFX_uint32_t posBytes = 0; + IFX_uint8_t lenBytes, *pByte; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + IFX_uint8_t padBytes = 0; + #endif + IFX_uint16_t cram_offset, cram_crc, +@@ -1088,7 +1090,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + #ifdef SYSTEM_DANUBE + /* CMD1 is a COP command */ + pCmd[0] = (0x0200) | (pCh->nChannel - 1); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* SDD_Coef command */ + pCmd[0] = (0x0400) | (pCh->nChannel - 1); + pCmd[1] = (0x0D00); +@@ -1111,7 +1113,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + pCmd[1] = ((cram_offset + (posBytes >> 1)) << 8); + /* set CRAM data while taking care of endianess */ + cpb2w (&pCmd[2], &pByte[posBytes], lenBytes); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* calculate length to download (in words = 16bit), + maximum allowed length for this message is 56 Bytes = 28 Words */ + if (countWords > ((MAX_CMD_WORD - CMD_HDR_CNT - 1))) +@@ -1140,7 +1142,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + /* write Data */ + #if defined SYSTEM_DANUBE + ret = CmdWrite (pCh->pParent, (IFX_uint32_t *) pCmd, lenBytes); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + #if 1 + /* lenBytes + 2 bytes for block offset/length which are not calculated + in the download progress */ +--- a/src/mps/drv_mps_version.h ++++ b/src/mps/drv_mps_version.h +@@ -17,7 +17,7 @@ + #define VERSIONSTEP 2 + #define VERS_TYPE 5 + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + #define IFX_MPS_PLATFORM_NAME "MIPS34KEc" + #elif defined(SYSTEM_DANUBE) + #define IFX_MPS_PLATFORM_NAME "MIPS24KEc" +--- a/src/mps/drv_mps_vmmc_linux.c ++++ b/src/mps/drv_mps_vmmc_linux.c +@@ -2225,7 +2225,7 @@ IFX_int32_t __init ifx_mps_init_module ( + #if defined(CONFIG_MIPS) && !defined(CONFIG_MIPS_UNCACHED) + #if defined(SYSTEM_DANUBE) + bDoCacheOps = IFX_TRUE; /* on Danube always perform cache ops */ +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* on AR9/VR9 cache is configured by BSP; + here we check whether the D-cache is shared or partitioned; + 1) in case of shared D-cache all cache operations are omitted; +@@ -2255,7 +2255,8 @@ IFX_int32_t __init ifx_mps_init_module ( + + /* reset the device before initializing the device driver */ + ifx_mps_reset (); +- result = request_irq (INT_NUM_IM4_IRL18, ++ ++ result = request_irq (INT_NUM_IM4_IRL18, + #ifdef LINUX_2_6 + ifx_mps_ad0_irq, IRQF_DISABLED + #else /* */ +@@ -2396,7 +2397,7 @@ IFX_int32_t __init ifx_mps_init_module ( + if (result = ifx_mps_init_gpt_danube ()) + return result; + #endif /*DANUBE*/ +- TRACE (MPS, DBG_LEVEL_HIGH, ("Downloading Firmware...\n")); ++ TRACE (MPS, DBG_LEVEL_HIGH, ("Downloading Firmware...\n")); + ifx_mps_download_firmware (IFX_NULL, (mps_fw *) 0xa0a00000); + udelay (500); + TRACE (MPS, DBG_LEVEL_HIGH, ("Providing Buffers...\n")); +--- /dev/null ++++ b/src/mps/drv_mps_vmmc_falcon.c +@@ -0,0 +1,463 @@ ++/****************************************************************************** ++ ++ Copyright (c) 2009 ++ Lantiq Deutschland GmbH ++ Am Campeon 3; 85579 Neubiberg, Germany ++ ++ For licensing information, see the file 'LICENSE' in the root folder of ++ this software module. ++ ++**************************************************************************** ++ Module : drv_mps_vmmc_falcon.c ++ Description : This file contains the implementation of the FALC-ON specific ++ driver functions. ++*******************************************************************************/ ++ ++/* ============================= */ ++/* Includes */ ++/* ============================= */ ++#include "drv_config.h" ++ ++#if defined(SYSTEM_FALCON) /* defined in drv_config.h */ ++ ++/* lib_ifxos headers */ ++#include "ifx_types.h" ++#include "ifxos_linux_drv.h" ++#include "ifxos_copy_user_space.h" ++#include "ifxos_event.h" ++#include "ifxos_lock.h" ++#include "ifxos_select.h" ++#include "ifxos_interrupt.h" ++#include <linux/gpio.h> ++#include <sys1_reg.h> ++#include <falcon.h> ++#include <falcon_irq.h> ++#include <vpe.h> ++#include <sysctrl.h> ++void (*ifx_bsp_basic_mps_decrypt)(unsigned int addr, int n) = (void (*)(unsigned int, int))0xbf000290; ++ ++#define IFX_MPS_SRAM IFXMIPS_MPS_SRAM ++ ++/*#define USE_PLAIN_VOICE_FIRMWARE*/ ++/* board specific headers */ ++ ++/* device specific headers */ ++#include "drv_mps_vmmc.h" ++#include "drv_mps_vmmc_dbg.h" ++#include "drv_mps_vmmc_device.h" ++ ++/* ============================= */ ++/* Local Macros & Definitions */ ++/* ============================= */ ++/* Firmware watchdog timer counter address */ ++#define VPE1_WDOG_CTR_ADDR ((IFX_uint32_t)((IFX_uint8_t* )IFX_MPS_SRAM + 432)) ++ ++/* Firmware watchdog timeout range, values in ms */ ++#define VPE1_WDOG_TMOUT_MIN 20 ++#define VPE1_WDOG_TMOUT_MAX 5000 ++ ++/* ============================= */ ++/* Global variable definition */ ++/* ============================= */ ++extern mps_comm_dev *pMPSDev; ++ ++/* ============================= */ ++/* Global function declaration */ ++/* ============================= */ ++IFX_void_t ifx_mps_release (IFX_void_t); ++extern IFX_uint32_t ifx_mps_reset_structures (mps_comm_dev * pMPSDev); ++extern IFX_int32_t ifx_mps_bufman_close (IFX_void_t); ++IFX_int32_t ifx_mps_wdog_callback (IFX_uint32_t wdog_cleared_ok_count); ++extern IFXOS_event_t fw_ready_evt; ++/* ============================= */ ++/* Local function declaration */ ++/* ============================= */ ++static IFX_int32_t ifx_mps_fw_wdog_start_ar9(IFX_void_t); ++ ++/* ============================= */ ++/* Local variable definition */ ++/* ============================= */ ++static IFX_int32_t vpe1_started = 0; ++/* VMMC watchdog timer callback */ ++IFX_int32_t (*ifx_wdog_callback) (IFX_uint32_t flags) = IFX_NULL; ++ ++/* ============================= */ ++/* Local function definition */ ++/* ============================= */ ++ ++/****************************************************************************** ++ * AR9 Specific Routines ++ ******************************************************************************/ ++ ++/** ++ * Start AR9 EDSP firmware watchdog mechanism. ++ * Called after download and startup of VPE1. ++ * ++ * \param none ++ * \return 0 IFX_SUCCESS ++ * \return -1 IFX_ERROR ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_fw_wdog_start_ar9() ++{ ++ return IFX_SUCCESS; ++} ++ ++/** ++ * Firmware download to Voice CPU ++ * This function performs a firmware download to the coprocessor. ++ * ++ * \param pMBDev Pointer to mailbox device structure ++ * \param pFWDwnld Pointer to firmware structure ++ * \return 0 IFX_SUCCESS, firmware ready ++ * \return -1 IFX_ERROR, firmware not downloaded. ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_download_firmware (mps_mbx_dev *pMBDev, mps_fw *pFWDwnld) ++{ ++ IFX_uint32_t mem, cksum; ++ IFX_uint8_t crc; ++ IFX_boolean_t bMemReqNotPresent = IFX_FALSE; ++ ++ /* VCC register */ ++ /* dummy accesss on GTC for GPONC-55, otherwise upper bits are random on read */ ++ ltq_r32 ((u32 *)((KSEG1 | 0x1DC000B0))); ++ /* NTR Frequency Select 1536 kHz per default or take existing, ++ NTR Output Enable and NTR8K Output Enable */ ++ if ((ltq_r32 ((u32 *)(GPON_SYS_BASE + 0xBC)) & 7) == 0) ++ ltq_w32_mask (0x10187, 0x183, (u32 *)(GPON_SYS_BASE + 0xBC)); ++ else ++ ltq_w32_mask (0x10180, 0x180, (u32 *)(GPON_SYS_BASE + 0xBC)); ++#if 0 ++ /* BIU-ICU1-IM1_ISR - IM1:FSCT_CMP1=1 and FSC_ROOT=1 ++ (0x1f880328 = 0x00002800) */ ++ ltq_w32 (0x00002800, (u32 *)(GPON_ICU1_BASE + 0x30)); ++#endif ++ /* copy FW footer from user space */ ++ if (IFX_NULL == IFXOS_CpyFromUser(pFW_img_data, ++ pFWDwnld->data+pFWDwnld->length/4-sizeof(*pFW_img_data)/4, ++ sizeof(*pFW_img_data))) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "[%s %s %d]: copy_from_user error\r\n", ++ __FILE__, __func__, __LINE__)); ++ return IFX_ERROR; ++ } ++ ++ mem = pFW_img_data->mem; ++ ++ /* memory requirement sanity check */ ++ if ((crc = ~((mem >> 16) + (mem >> 8) + mem)) != (mem >> 24)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: warning, image does not contain size - assuming 1MB!\n", ++ __FILE__, __func__, __LINE__)); ++ mem = 1 * 1024 * 1024; ++ bMemReqNotPresent = IFX_TRUE; ++ } ++ else ++ { ++ mem &= 0x00FFFFFF; ++ } ++ ++ /* check if FW image fits in available memory space */ ++ if (mem > vpe1_get_max_mem(0)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n", ++ __FILE__, __func__, __LINE__, mem, vpe1_get_max_mem(0))); ++ return IFX_ERROR; ++ } ++ ++ /* reset the driver */ ++ ifx_mps_reset (); ++ ++ /* call BSP to get cpu1 base address */ ++ cpu1_base_addr = (IFX_uint32_t *)vpe1_get_load_addr(0); ++ ++ /* check if CPU1 base address is sane ++ \todo: check if address is 1MB aligned, ++ also make it visible in a /proc fs */ ++ if (!cpu1_base_addr) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "IFX_MPS: CPU1 base address is invalid!\r\n")); ++ return IFX_ERROR; ++ } ++ /* further use uncached value */ ++ cpu1_base_addr = (IFX_uint32_t *)KSEG1ADDR(cpu1_base_addr); ++ ++ /* free all data buffers that might be currently used by FW */ ++ if (IFX_NULL != ifx_mps_bufman_freeall) ++ { ++ ifx_mps_bufman_freeall(); ++ } ++ ++ if(FW_FORMAT_NEW) ++ { ++ /* adjust download length */ ++ pFWDwnld->length -= (sizeof(*pFW_img_data)-sizeof(IFX_uint32_t)); ++ } ++ else ++ { ++ pFWDwnld->length -= sizeof(IFX_uint32_t); ++ ++ /* handle unlikely case if FW image does not contain memory requirement - ++ assumed for old format only */ ++ if (IFX_TRUE == bMemReqNotPresent) ++ pFWDwnld->length += sizeof(IFX_uint32_t); ++ ++ /* in case of old FW format always assume that FW is encrypted; ++ use compile switch USE_PLAIN_VOICE_FIRMWARE for plain FW */ ++#ifndef USE_PLAIN_VOICE_FIRMWARE ++ pFW_img_data->enc = 1; ++#else ++#warning Using unencrypted firmware! ++ pFW_img_data->enc = 0; ++#endif /* USE_PLAIN_VOICE_FIRMWARE */ ++ /* initializations for the old format */ ++ pFW_img_data->st_addr_crc = 2*sizeof(IFX_uint32_t) + ++ FW_AR9_OLD_FMT_XCPT_AREA_SZ; ++ pFW_img_data->en_addr_crc = pFWDwnld->length; ++ pFW_img_data->fw_vers = 0; ++ pFW_img_data->magic = 0; ++ } ++ ++ /* copy FW image to base address of CPU1 */ ++ if (IFX_NULL == ++ IFXOS_CpyFromUser ((IFX_void_t *)cpu1_base_addr, ++ (IFX_void_t *)pFWDwnld->data, pFWDwnld->length)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "[%s %s %d]: copy_from_user error\r\n", __FILE__, ++ __func__, __LINE__)); ++ return IFX_ERROR; ++ } ++ ++ /* process firmware decryption */ ++ if (pFW_img_data->enc == 1) ++ { ++ if(FW_FORMAT_NEW) ++ { ++ /* adjust decryption length (avoid decrypting CRC32 checksum) */ ++ pFWDwnld->length -= sizeof(IFX_uint32_t); ++ } ++ /* BootROM actually decrypts n+4 bytes if n bytes were passed for ++ decryption. Subtract sizeof(u32) from length to avoid decryption ++ of data beyond the FW image code */ ++ pFWDwnld->length -= sizeof(IFX_uint32_t); ++ ifx_bsp_basic_mps_decrypt((unsigned int)cpu1_base_addr, pFWDwnld->length); ++ } ++ ++ /* calculate CRC32 checksum over downloaded image */ ++ cksum = ifx_mps_fw_crc32(cpu1_base_addr, pFW_img_data); ++ ++ /* verify the checksum */ ++ if(FW_FORMAT_NEW) ++ { ++ if (cksum != pFW_img_data->crc32) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("MPS: FW checksum error: img=0x%08x calc=0x%08x\r\n", ++ pFW_img_data->crc32, cksum)); ++ /*return IFX_ERROR;*/ ++ } ++ } ++ else ++ { ++ /* just store self-calculated checksum */ ++ pFW_img_data->crc32 = cksum; ++ } ++ ++ /* start VPE1 */ ++ ifx_mps_release (); ++#if 0 ++ /* start FW watchdog mechanism */ ++ ifx_mps_fw_wdog_start_ar9(); ++#endif ++ /* get FW version */ ++ return ifx_mps_get_fw_version (0); ++} ++ ++ ++/** ++ * Restart CPU1 ++ * This function restarts CPU1 by accessing the reset request register and ++ * reinitializes the mailbox. ++ * ++ * \return 0 IFX_SUCCESS, successful restart ++ * \return -1 IFX_ERROR, if reset failed ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_restart (IFX_void_t) ++{ ++ /* raise reset request for CPU1 and reset driver structures */ ++ ifx_mps_reset (); ++ /* Disable GPTC Interrupt to CPU1 */ ++ ifx_mps_shutdown_gpt (); ++ /* re-configure GPTC */ ++ ifx_mps_init_gpt (); ++ /* let CPU1 run */ ++ ifx_mps_release (); ++ /* start FW watchdog mechanism */ ++ ifx_mps_fw_wdog_start_ar9(); ++ TRACE (MPS, DBG_LEVEL_HIGH, ("IFX_MPS: Restarting firmware...")); ++ return ifx_mps_get_fw_version (0); ++} ++ ++/** ++ * Shutdown MPS - stop VPE1 ++ * This function stops VPE1 ++ * ++ * \ingroup Internal ++ */ ++IFX_void_t ifx_mps_shutdown (IFX_void_t) ++{ ++ if (vpe1_started) ++ { ++ /* stop software watchdog timer */ ++ vpe1_sw_wdog_stop (0); ++ /* clean up the BSP callback function */ ++ vpe1_sw_wdog_register_reset_handler (IFX_NULL); ++ /* stop VPE1 */ ++ vpe1_sw_stop (0); ++ vpe1_started = 0; ++ } ++ /* free GPTC */ ++ ifx_mps_shutdown_gpt (); ++} ++ ++/** ++ * Reset CPU1 ++ * This function causes a reset of CPU1 by clearing the CPU0 boot ready bit ++ * in the reset request register RCU_RST_REQ. ++ * It does not change the boot configuration registers for CPU0 or CPU1. ++ * ++ * \return 0 IFX_SUCCESS, cannot fail ++ * \ingroup Internal ++ */ ++IFX_void_t ifx_mps_reset (IFX_void_t) ++{ ++ /* if VPE1 is already started, stop it */ ++ if (vpe1_started) ++ { ++ /* stop software watchdog timer first */ ++ vpe1_sw_wdog_stop (0); ++ vpe1_sw_stop (0); ++ vpe1_started = 0; ++ } ++ ++ /* reset driver */ ++ ifx_mps_reset_structures (pMPSDev); ++ ifx_mps_bufman_close (); ++ return; ++} ++ ++/** ++ * Let CPU1 run ++ * This function starts VPE1 ++ * ++ * \return none ++ * \ingroup Internal ++ */ ++IFX_void_t ifx_mps_release (IFX_void_t) ++{ ++ IFX_int_t ret; ++ IFX_int32_t RetCode = 0; ++ ++ /* Start VPE1 */ ++ if (IFX_SUCCESS != ++ vpe1_sw_start ((IFX_void_t *)cpu1_base_addr, 0, 0)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, (KERN_ERR "Error starting VPE1\r\n")); ++ return; ++ } ++ vpe1_started = 1; ++ ++ /* sleep 3 seconds until FW is ready */ ++ ret = IFXOS_EventWait (&fw_ready_evt, 3000, &RetCode); ++ if ((ret == IFX_ERROR) && (RetCode == 1)) ++ { ++ /* timeout */ ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "[%s %s %d]: Timeout waiting for firmware ready.\r\n", ++ __FILE__, __func__, __LINE__)); ++ /* recalculate and compare the firmware checksum */ ++ ifx_mps_fw_crc_compare(cpu1_base_addr, pFW_img_data); ++ /* dump exception area on a console */ ++ ifx_mps_dump_fw_xcpt(cpu1_base_addr, pFW_img_data); ++ } ++} ++ ++/** ++ * WDT callback. ++ * This function is called by BSP (module softdog_vpe) in case if software ++ * watchdog timer expiration is detected by BSP. ++ * This function needs to be registered at BSP as WDT callback using ++ * vpe1_sw_wdog_register_reset_handler() API. ++ * ++ * \return 0 IFX_SUCCESS, cannot fail ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_wdog_callback (IFX_uint32_t wdog_cleared_ok_count) ++{ ++#ifdef DEBUG ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("MPS: watchdog callback! arg=0x%08x\r\n", wdog_cleared_ok_count)); ++#endif /* DEBUG */ ++ ++ /* reset SmartSLIC is done by FW */ ++ /* recalculate and compare the firmware checksum */ ++ ifx_mps_fw_crc_compare(cpu1_base_addr, pFW_img_data); ++ ++ /* dump exception area on a console */ ++ ifx_mps_dump_fw_xcpt(cpu1_base_addr, pFW_img_data); ++ ++ if (IFX_NULL != ifx_wdog_callback) ++ { ++ /* call VMMC driver */ ++ ifx_wdog_callback (wdog_cleared_ok_count); ++ } ++ else ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_WARNING "MPS: VMMC watchdog timer callback is NULL.\r\n")); ++ } ++ return 0; ++} ++ ++/** ++ * Register WDT callback. ++ * This function is called by VMMC driver to register its callback in ++ * the MPS driver. ++ * ++ * \return 0 IFX_SUCCESS, cannot fail ++ * \ingroup Internal ++ */ ++IFX_int32_t ++ifx_mps_register_wdog_callback (IFX_int32_t (*pfn) (IFX_uint32_t flags)) ++{ ++ ifx_wdog_callback = pfn; ++ return 0; ++} ++ ++/** ++ Hardware setup on FALC ON ++*/ ++void sys_hw_setup (void) ++{ ++ /* Set INFRAC register bit 1: clock enable of the GPE primary clock. */ ++ sys_gpe_hw_activate (0); ++ /* enable 1.5 V */ ++ ltq_w32_mask (0xf, 0x0b, (u32 *)(GPON_SYS1_BASE | 0xbc)); ++ /* SYS1-CLKEN:GPTC = 1 and MPS, no longer FSCT = 1 */ ++ sys1_hw_activate (ACTS_MPS | ACTS_GPTC); ++ /* GPTC:CLC:RMC = 1 */ ++ ltq_w32 (0x00000100, (u32 *)(KSEG1 | 0x1E100E00)); ++} ++ ++#ifndef VMMC_WITH_MPS ++EXPORT_SYMBOL (ifx_mps_register_wdog_callback); ++#endif /* !VMMC_WITH_MPS */ ++ ++#endif /* SYSTEM_FALCON */ +--- a/src/mps/drv_mps_vmmc_common.c ++++ b/src/mps/drv_mps_vmmc_common.c +@@ -66,6 +66,10 @@ static void inline bsp_mask_and_ack_irq( + # include <asm/ifx/ifx_regs.h> + # include <asm/ifx/ifx_gptu.h> + #endif ++#if defined(SYSTEM_FALCON) ++#include <sys1_reg.h> ++#include <sysctrl.h> ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -1156,7 +1160,12 @@ IFX_uint32_t ifx_mps_init_structures (mp + mailbox, * upstream and downstream direction. */ + memset ( + /* avoid to overwrite CPU boot registers */ ++#if defined(SYSTEM_FALCON) ++ (IFX_void_t *) MBX_Memory + ++ 2 * sizeof (mps_boot_cfg_reg), ++#else + (IFX_void_t *) MBX_Memory, ++#endif + 0, + sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg)); + MBX_Memory->MBX_UPSTR_CMD_BASE = +@@ -2651,7 +2660,6 @@ IFX_void_t ifx_mps_enable_mailbox_int () + #endif + + *IFX_MPS_AD0ENR = Ad0Reg.val; +- + } + + /** +@@ -2669,6 +2677,7 @@ IFX_void_t ifx_mps_disable_mailbox_int ( + Ad0Reg.fld.cu_mbx = 0; + Ad0Reg.fld.du_mbx = 0; + *IFX_MPS_AD0ENR = Ad0Reg.val; ++ + } + + /** +@@ -2766,11 +2775,13 @@ irqreturn_t ifx_mps_ad0_irq (IFX_int32_t + /* handle only enabled interrupts */ + MPS_Ad0StatusReg.val &= *IFX_MPS_AD0ENR; + ++#if !defined(SYSTEM_FALCON) + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++#endif /* !defined(SYSTEM_FALCON) */ + /* FW is up and ready to process commands */ + if (MPS_Ad0StatusReg.fld.dl_end) + { +@@ -2919,11 +2930,13 @@ irqreturn_t ifx_mps_ad1_irq (IFX_int32_t + /* handle only enabled interrupts */ + MPS_Ad1StatusReg.val &= *IFX_MPS_AD1ENR; + ++#if !defined(SYSTEM_FALCON) + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++#endif /* !defined(SYSTEM_FALCON) */ + pMPSDev->event.MPS_Ad1Reg.val = MPS_Ad1StatusReg.val; + + /* use callback function or queue wake up to notify about data reception */ +@@ -2977,11 +2990,13 @@ irqreturn_t ifx_mps_vc_irq (IFX_int32_t + IFX_MPS_CVC0SR[chan] = MPS_VCStatusReg.val; + /* handle only enabled interrupts */ + MPS_VCStatusReg.val &= IFX_MPS_VC0ENR[chan]; ++#if !defined(SYSTEM_FALCON) + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++#endif /* !defined(SYSTEM_FALCON) */ + + pMPSDev->event.MPS_VCStatReg[chan].val = MPS_VCStatusReg.val; + #ifdef PRINT_ON_ERR_INTERRUPT +@@ -3126,6 +3141,7 @@ IFX_int32_t ifx_mps_get_fw_version (IFX_ + */ + IFX_return_t ifx_mps_init_gpt () + { ++#if !defined(SYSTEM_FALCON) + unsigned long flags; + IFX_uint32_t timer_flags, timer, loops = 0; + IFX_ulong_t count; +@@ -3134,7 +3150,11 @@ IFX_return_t ifx_mps_init_gpt () + #else /* Danube */ + timer = TIMER1B; + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ ++#endif + ++#if defined(SYSTEM_FALCON) ++ sys_hw_setup (); ++#else + /* calibration loop - required to syncronize GPTC interrupt with falling + edge of FSC clock */ + timer_flags = +@@ -3179,7 +3199,7 @@ Probably already in use.\r\n", __FILE__, + #endif /* DEBUG */ + + IFXOS_UNLOCKINT (flags); +- ++#endif + return IFX_SUCCESS; + } + +@@ -3194,6 +3214,9 @@ Probably already in use.\r\n", __FILE__, + */ + IFX_void_t ifx_mps_shutdown_gpt (IFX_void_t) + { ++#if defined(SYSTEM_FALCON) ++ sys1_hw_deactivate (ACTS_MPS); ++#else + IFX_uint32_t timer; + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + timer = TIMER1A; +@@ -3202,6 +3225,7 @@ IFX_void_t ifx_mps_shutdown_gpt (IFX_voi + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ + + ifx_gptu_timer_free (timer); ++#endif + } + + /** +--- a/src/mps/drv_mps_vmmc_device.h ++++ b/src/mps/drv_mps_vmmc_device.h +@@ -22,7 +22,12 @@ + # include <lantiq_soc.h> + # include <gpio.h> + #define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000)) ++#if defined(SYSTEM_FALCON) ++#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1D004000) ++#else + #define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000) ++#endif ++ + #define IFXMIPS_MPS_CHIPID ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0344)) + #define IFXMIPS_MPS_VC0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0000)) + #define IFXMIPS_MPS_RVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0010)) +@@ -73,10 +78,11 @@ + /* MPS Common defines */ + /* ============================= */ + +-#define MPS_BASEADDRESS 0xBF107000 +-#define MPS_RAD0SR MPS_BASEADDRESS + 0x0004 +- ++#if defined(SYSTEM_FALCON) ++#define MBX_BASEADDRESS 0xBF200040 ++#else + #define MBX_BASEADDRESS 0xBF200000 ++#endif + #define VCPU_BASEADDRESS 0xBF208000 /* 0xBF108000 */ + /*---------------------------------------------------------------------------*/ + #if !defined(CONFIG_LANTIQ) +@@ -118,7 +124,6 @@ + /*---------------------------------------------------------------------------*/ + + #ifdef CONFIG_MPS_EVENT_MBX +- + #define MBX_CMD_FIFO_SIZE 64 /**< Size of command FIFO in bytes */ + #define MBX_DATA_UPSTRM_FIFO_SIZE 64 + #define MBX_DATA_DNSTRM_FIFO_SIZE 128 +@@ -294,6 +299,10 @@ typedef struct + #ifdef CONFIG_MPS_EVENT_MBX + typedef struct + { ++#if defined(SYSTEM_FALCON) ++ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ ++ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + volatile IFX_uint32_t *MBX_UPSTR_CMD_BASE; /**< Upstream Command FIFO Base Address */ + volatile IFX_uint32_t MBX_UPSTR_CMD_SIZE; /**< Upstream Command FIFO size in byte */ + volatile IFX_uint32_t *MBX_DNSTR_CMD_BASE; /**< Downstream Command FIFO Base Address */ +@@ -317,13 +326,19 @@ typedef struct + volatile IFX_uint32_t MBX_UPSTR_EVENT_WRITE; /**< Upstream Event FIFO Write Index */ + volatile IFX_uint32_t MBX_EVENT[MBX_EVENT_DATA_WORDS]; + volatile IFX_uint32_t reserved[4]; ++#if !defined(SYSTEM_FALCON) + mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ + mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + } mps_mbx_reg; + + #else /* */ + typedef struct + { ++#if defined(SYSTEM_FALCON) ++ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ ++ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + volatile IFX_uint32_t *MBX_UPSTR_CMD_BASE; /**< Upstream Command FIFO Base Address */ + volatile IFX_uint32_t MBX_UPSTR_CMD_SIZE; /**< Upstream Command FIFO size in byte */ + volatile IFX_uint32_t *MBX_DNSTR_CMD_BASE; /**< Downstream Command FIFO Base Address */ +@@ -341,8 +356,10 @@ typedef struct + volatile IFX_uint32_t MBX_DNSTR_DATA_READ; /**< Downstream Data FIFO Read Index */ + volatile IFX_uint32_t MBX_DNSTR_DATA_WRITE; /**< Downstream Data FIFO Write Index */ + volatile IFX_uint32_t MBX_DATA[MBX_DATA_WORDS]; ++#if !defined(SYSTEM_FALCON) + mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ + mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + } mps_mbx_reg; + #endif /* CONFIG_MPS_EVENT_MBX */ + +--- a/src/drv_api.h ++++ b/src/drv_api.h +@@ -183,7 +183,7 @@ + #endif + + /* TAPI FXS Phone Detection feature is not available for Danube platform */ +-#if defined(TAPI_PHONE_DETECTION) && (defined(SYSTEM_AR9) || defined(SYSTEM_VR9)) ++#if defined(TAPI_PHONE_DETECTION) && (defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)) + #define VMMC_CFG_ADD_FEAT_PHONE_DETECTION VMMC_FEAT_PHONE_DETECTION + #else + #define VMMC_CFG_ADD_FEAT_PHONE_DETECTION 0 +--- a/src/drv_vmmc_alm.c ++++ b/src/drv_vmmc_alm.c +@@ -800,7 +800,7 @@ IFX_void_t VMMC_ALM_Free_Ch_Structures ( + } + + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /** + Check whether SmartSLIC is connected + +@@ -836,7 +836,7 @@ IFX_boolean_t VMMC_ALM_SmartSLIC_IsConne + #endif /*SYSTEM_AR9 || SYSTEM_VR9*/ + + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /** + Read the number of channels on the SmartSLIC. + +@@ -1876,7 +1876,7 @@ IFX_int32_t VMMC_TAPI_LL_ALM_VMMC_Test_L + /* write updated message contents */ + ret = CmdWrite (pDev, (IFX_uint32_t *)((IFX_void_t *)&debugCfg), + DCCTL_CMD_LEN); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + IFX_uint32_t dcctrlLoop[2]; + IFX_uint32_t ch = (IFX_uint32_t)(pCh->nChannel - 1); + +--- a/src/drv_vmmc_alm.h ++++ b/src/drv_vmmc_alm.h +@@ -65,7 +65,7 @@ extern IFX_void_t irq_VMMC_ALM_LineDisab + extern IFX_void_t VMMC_ALM_CorrectLinemodeCache (VMMC_CHANNEL *pCh, + IFX_uint16_t lm); + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + extern IFX_boolean_t VMMC_ALM_SmartSLIC_IsConnected ( + VMMC_DEVICE *pDev); + +--- a/src/drv_vmmc_init.c ++++ b/src/drv_vmmc_init.c +@@ -52,15 +52,6 @@ + #include "ifx_pmu.h" + #endif /* PMU_SUPPORTED */ + +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) +-# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR +-# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR +-# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR +-# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR +-# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR +-# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR +-#endif +- + /* ============================= */ + /* Local Macros & Definitions */ + /* ============================= */ +@@ -820,7 +811,7 @@ static IFX_int32_t VMMC_TAPI_LL_FW_Init( + MIN_FW_HOTFIXSTEP}; + IFX_uint8_t tmp1, tmp2; + IFX_TAPI_RESOURCE nResource; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + IFX_uint8_t nChannels, nFXOChannels; + #endif /*SYSTEM_AR9 || SYSTEM_VR9*/ + IFX_int32_t ret = VMMC_statusOk; +@@ -874,7 +865,7 @@ static IFX_int32_t VMMC_TAPI_LL_FW_Init( + pDev->bSmartSlic = IFX_FALSE; + pDev->bSlicSupportsIdleMode = IFX_FALSE; + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + if (VMMC_SUCCESS(ret)) + { + /* Reduce the number of ALM channels in the capabilities if the SLIC +--- a/src/drv_vmmc_ioctl.c ++++ b/src/drv_vmmc_ioctl.c +@@ -273,7 +273,7 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP + case FIO_GET_VERS: + { + VMMC_IO_VERSION *pVers; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + VMMC_SDD_REVISION_READ_t *pSDDVersCmd = IFX_NULL; + #endif /*SYSTEM_AR9 || SYSTEM_VR9*/ + SYS_VER_t *pCmd; +@@ -322,7 +322,7 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP + pVers->nTapiVers = 3; + pVers->nDrvVers = MAJORSTEP << 24 | MINORSTEP << 16 | + VERSIONSTEP << 8 | VERS_TYPE; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* in case of SmartSLIC based systems, we can give some more + versions.*/ + if (VMMC_ALM_SmartSLIC_IsConnected(pDev)) |