summaryrefslogtreecommitdiff
path: root/package/kernel/lantiq/ltq-vmmc/patches/400-falcon.patch
blob: 490d6e5dc91f143ed3ba789114dd01319b5132e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
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))