Added 6657 support for pcie linux loader
[keystone-rtos/mcsdk-tools.git] / boot_loader / examples / pcie / linux_host_loader / pciedemo.c
1 /******************************************************************************
2  * Copyright (c) 2011 Texas Instruments Incorporated - http://www.ti.com
3  * 
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as 
6  * published by the Free Software Foundation version 2.
7  *
8  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9  * kind, whether express or implied; without even the implied warranty
10  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *****************************************************************************/
14 /**************************************************************************************
15  * FILE NAME: pciedemo.c
16  *
17  * DESCRIPTION: A sample code to load DSP boot image from a Linux machine into DSP.
18  *
19  * Revision History:
20  *    - 1.0:  Initial version (6678 little endian PCIE boot POST demo)
21  *    - 1.1:  Add a new PCIE boot demo for HelloWorld
22  *    - 1.2:  support 6670 boot
23  *    - 1.3:  support big endian boot for 6670/6678; support 32-bit/64-bit Linux;         
24  *            support EDMA; support interrupt between host and DSP; 
25  *            added PCIE over EDMA throughput measurement
26  *    - 1.4:  Add a DSP local reset demo; fix pushData() to handle cases when 
27  *            sections within different memory regions in a header file
28  *    - 1.5:  Support 6657 boot
29  ***************************************************************************************/
31 #include <linux/module.h>
32 #include <linux/types.h>
33 #include <linux/kernel.h>
34 #include <linux/pci.h>
35 #include <linux/delay.h>
36 #include <linux/fs.h>
37 #include <linux/init.h>
38 #include <linux/ioport.h>
39 #include <linux/interrupt.h>
40 #include <asm/uaccess.h>
41 #include <asm/dma-mapping.h>
42 #include <linux/time.h>
44 MODULE_LICENSE("GPL v2");
46 /* Must select the endianess */
47 #define BIG_ENDIAN          0
49 /* Must select which demo to run */ 
50 #define HELLO_WORLD_DEMO    1
51 #define POST_DEMO           0 
52 #define EDMA_INTC_DEMO      0 
53 #define LOCAL_RESET         0
55 /* Must select a platform */
56 #define EVMC6678L           1
57 #define EVMC6670L           0
58 #define EVMC6657L           0
59  
60 #if BIG_ENDIAN
61 #define myIoread32  ioread32be
62 #define myIowrite32 iowrite32be
63 #else
64 #define myIoread32  ioread32 
65 #define myIowrite32 iowrite32
66 #endif
68 #if EVMC6678L
69 #define MAGIC_ADDR          0x0087FFFC
70 #endif
72 #if EVMC6670L
73 #define MAGIC_ADDR          0x008FFFFC
74 #endif
76 #if EVMC6657L
77 #define MAGIC_ADDR          0x008FFFFC
78 #endif
80 /* Include header array */
81 #if HELLO_WORLD_DEMO
83 #if EVMC6678L
84 #include "pcieDdrInit_6678.h"     /* DDR init */
85 #include "pcieBootCode_6678.h"    /* "Hello world" boot example */  
86 #endif
88 #if EVMC6670L
89 #include "pcieDdrInit_6670.h"     /* DDR init */
90 #include "pcieBootCode_6670.h"    /* "Hello world" boot example */
91 #endif
93 #if EVMC6657L
94 #include "pcieDdrInit_6657.h"     /* DDR init */
95 #include "pcieBootCode_6657.h"    /* "Hello world" boot example */
96 #endif
98 #endif
100 #if POST_DEMO
102 #if EVMC6678L
103 #include "post_6678.h"            /* POST boot example */
104 #endif
106 #if EVMC6670L
107 #include "post_6670.h"            /* POST boot example */
108 #endif
110 #if EVMC6657L
111 #include "post_6657.h"            /* POST boot example */
112 #endif
114 #endif
116 #if EDMA_INTC_DEMO
118 #if EVMC6678L
119 #include "pcieInterrupt_6678.h"   /* EDMA-Interrupt boot example */
120 #endif
122 #if EVMC6670L
123 #include "pcieInterrupt_6670.h"   /* EDMA-Interrupt boot example */
124 #endif
126 #endif
128 #if LOCAL_RESET
130 #if EVMC6678L
131 #include "pcieLocalReset_6678.h"
132 #endif
134 #if EVMC6670L
135 #include "pcieLocalReset_6670.h"
136 #endif
138 #endif
140 /* PCIE registers */
141 #define PCIE_BASE_ADDRESS            0x21800000
142 #define OB_SIZE                      0x30
143 #define PRIORITY                     0x3C
144 #define EP_IRQ_CLR                   0x68
145 #define EP_IRQ_STATUS                0x6C
146 #define LEGACY_A_IRQ_STATUS_RAW      0x180
147 #define LEGACY_A_IRQ_ENABLE_SET      0x188
148 #define LEGACY_A_IRQ_ENABLE_CLR      0x18C
149 #define OB_OFFSET_INDEX(n)           (0x200 + (8 * (n)))
150 #define OB_OFFSET_HI(n)              (0x204 + (8 * (n)))
151 #define IB_BAR(n)                    (0x300 + (0x10 * (n)))
152 #define IB_START_LO(n)               (0x304 + (0x10 * (n)))
153 #define IB_START_HI(n)               (0x308 + (0x10 * (n)))
154 #define IB_OFFSET(n)                 (0x30C + (0x10 * (n)))
156 #define PCIE_TI_VENDOR               0x104C
157 #define PCIE_TI_DEVICE               0xB005
159 /* PSC registers */
160 #define PSC_BASE_ADDRESS             0x02350000
161 #define PTCMD                        0x120
162 #define PTSTAT                       0x128
163 #define PDSTAT(n)                    (0x200 + (4 * (n)))
164 #define PDCTL(n)                     (0x300 + (4 * (n)))
165 #define MDSTAT(n)                    (0x800 + (4 * (n)))
166 #define MDCTL(n)                     (0xA00 + (4 * (n))) 
168 /* EDMA registers */
169 #define EDMA_TPCC0_BASE_ADDRESS      0x02700000
170 #define DMAQNUM0                     0x0240  
171 #define ESR                          0x1010 
172 #define EESR                         0x1030                 
173 #define IESR                         0x1060
174 #define IPR                          0x1068 
175 #define ICR                          0x1070 
176 #define PARAM_0_OPT                  0x4000
177 #define PARAM_0_SRC                  0x4004
178 #define PARAM_0_A_B_CNT              0x4008
179 #define PARAM_0_DST                  0x400C
180 #define PARAM_0_SRC_DST_BIDX         0x4010
181 #define PARAM_0_LINK_BCNTRLD         0x4014
182 #define PARAM_0_SRC_DST_CIDX         0x4018
183 #define PARAM_0_CCNT                 0x401C
185 /* Chip level registers */
186 #define CHIP_LEVEL_BASE_ADDRESS      0x02620000
187 #define KICK0                        0x38    
188 #define KICK1                        0x3C
189 #define KICK0_UNLOCK                 0x83E70B13
190 #define KICK1_UNLOCK                 0x95A4F1E0 
191 #define KICK_LOCK                    0x0
192 #define DSP_BOOT_ADDR(n)             (0x040 + (4 * (n)))
193 #define IPCGR(n)                     (0x240 + (4 * (n)))
196 #define LL2_START                    0x00800000
197 #define MSMC_START                   0x0C000000  /* Shared L2 */
198 #define DDR_START                    0x80000000
199 #define PCIE_DATA                    0x60000000  
201 /* Block size in bytes when r/w data between GPP and DSP via DSP CPU */
202 #define BLOCK_TRANSFER_SIZE          0x100      
204 /* Data size in bytes when r/w data bewteen GPP and DSP via EDMA:
205    GPP----PCIE link----PCIE data space----EDMA----DSP device memory (L2, DDR, ...) */
206 #define DMA_TRANSFER_SIZE            0x400000   /* 4MB */
208 /* Payload size in bytes over PCIE link. PCIe module supports 
209    outbound payload size of 128 bytes and inbound payload size of 256 bytes */
210 #define PCIE_TRANSFER_SIZE           0x80               
212 /* For 1MB outbound translation window size */
213 #define PCIE_ADLEN_1MB               0x00100000
214 #define PCIE_1MB_BITMASK             0xFFF00000
216 #define PSC_SWRSTDISABLE             0x0
217 #define PSC_ENABLE                   0x3
219 #define LOC_RST_ASSERT               0x0
220 #define LOC_RST_DEASSERT             0x1
222 /* Power domains definitions */
223 #define PD0         0     // Power Domain-0
224 #define PD1         1     // Power Domain-1
225 #define PD2         2     // Power Domain-2
226 #define PD3         3     // Power Domain-3
227 #define PD4         4     // Power Domain-4
228 #define PD5         5     // Power Domain-5
229 #define PD6         6     // Power Domain-6
230 #define PD7         7     // Power Domain-7
231 #define PD8         8     // Power Domain-8
232 #define PD9         9     // Power Domain-9
233 #define PD10        10    // Power Domain-10
234 #define PD11        11    // Power Domain-11
235 #define PD12        12    // Power Domain-12
236 #define PD13        13    // Power Domain-13
237 #define PD14        14    // Power Domain-14
238 #define PD15        15    // Power Domain-15
239 #define PD16        16    // Power Domain-16
240 #define PD17        17    // Power Domain-17
242 #if EVMC6670L
243 /* Modules on power domain 0 */
244 #define LPSC_TCP3E     3
245 #define LPSC_VCP2A     4
247 /* Modules on power domain 1 */
248 #define LPSC_DEBUG     5
249 #define LPSC_TETB      6
251 /* Modules on power domain 2 */
252 #define LPSC_PA        7
253 #define LPSC_SGMII     8
254 #define LPSC_SA        9
256 /* Modules on power domain 3 */
257 #define LPSC_PCIE      10
259 /* Modules on power domain 4 */
260 #define LPSC_SRIO      11
262 /* Modules on power domain 5 */
263 #define LPSC_HYPER     12
265 /* Modules on power domain 6 */
266 #define LPSC_RESERV    13
268 /* Modules on power domain 7 */
269 #define LPSC_MSMCRAM   14
271 /* Modules on power domain 8 */
272 #define LPSC_RACA_RACB 15
273 #define LPSC_TAC       16
275 /* Modules on power domain 9 */
276 #define LPSC_FFTCA_FFTCB 17
278 /* Modules on power domain 10 */
279 #define LPSC_AIF2      18
281 /* Modules on power domain 11 */
282 #define LPSC_TCP3DA    19
284 /* Modules on power domain 12 */
285 #define LPSC_VCP2B     20
286 #define LPSC_VCP2C     21
287 #define LPSC_VCP2D     22
289 /* Modules on power domain 13 */
290 #define LPSC_C0_TIM0   23
292 /* Modules on power domain 14 */
293 #define LPSC_C1_TIM1   24
294 #define LPSC_C1_RSA    25
296 /* Modules on power domain 15 */
297 #define LPSC_C2_TIM2   26
298 #define LPSC_C2_RSA    27
300 /* Modules on power domain 16 */
301 #define LPSC_C3_TIM3   28
303 /* Modules on power domain 17 */
304 #define LPSC_TCP3dB    29
306 #endif
308 #if EVMC6678L
309 /* Modules on power domain 0 */
310 #define LPSC_EMIF16_SPI  3  
311 #define LPSC_TSIP        4
313 /* Modules on power domain 1 */
314 #define LPSC_DEBUG       5
315 #define LPSC_TETB_TRC    6
317 /* Modules on power domain 2 */
318 #define LPSC_PA          7  
319 #define LPSC_SGMII       8  
320 #define LPSC_SA          9  
322 /* Modules on power domain 3 */
323 #define LPSC_PCIE        10
325 /* Modules on power domain 4 */
326 #define LPSC_SRIO        11
328 /* Modules on power domain 5 */
329 #define LPSC_HYPER       12
331 /* Modules on power domain 6 */
332 #define LPSC_RESERV      13
334 /* Modules on power domain 7 */
335 #define LPSC_MSMCRAM     14
337 /* Modules on power domain 8 */
338 #define LPSC_C0_TIM0     15
340 /* Modules on power domain 9 */
341 #define LPSC_C1_TIM1     16
343 /* Modules on power domain 10 */
344 #define LPSC_C2_TIM2     17
346 /* Modules on power domain 11 */
347 #define LPSC_C3_TIM3     18
349 /* Modules on power domain 12 */
350 #define LPSC_C4_TIM4     19
352 /* Modules on power domain 13 */
353 #define LPSC_C5_TIM5     20
355 /* Modules on power domain 14 */
356 #define LPSC_C6_TIM6     21
358 /* Modules on power domain 15 */
359 #define LPSC_C7_TIM7     22
361 #endif
363 /* 
364 reg:  PCIE application registers
365 mem:  Local L2
366 msmc: Shared L2 memory
367 ddr:  DDR3   
368  */
370 uint8_t *wDataVirt, *rDataVirt;          /* Virtue address for CPU */
371 dma_addr_t wData, rData;                 /* Physical PCIE bus address */
374 /***********************************************
375  * uncomment following line on very old kernels:
376  * typedef unsigned long resource_size_t;
377  **********************************************/
378 resource_size_t regBase = 0;
379 resource_size_t memBase = 0;
380 resource_size_t msmcBase = 0;
381 resource_size_t ddrBase = 0;
383 uint32_t *regVirt = NULL;
384 uint32_t *memVirt = NULL;
385 uint32_t *msmcVirt = NULL;
386 uint32_t *ddrVirt = NULL;
388 resource_size_t memLen = 0;
389 resource_size_t regLen = 0;
390 resource_size_t msmcLen = 0;
391 resource_size_t ddrLen = 0;
393 uint32_t *ptrReg = 0; 
394 int32_t  irqNo;
395 uint32_t dummy;
396 struct pci_dev *PCIE_DEV = NULL;
398 struct timeval test_time1;
399 struct timeval test_time2;
400 struct timeval test_time3;
401 struct timeval test_time4;
403 /* ============================================================================
404  *  @func   PCI_FindPciDevices
405  *
406  *  @desc   This function locates 6670/6678 PCIE cards on system.
407  *
408  *  @modif  None.
409  *  ============================================================================
410  */
411 void PCI_FindPciDevices(void)
413         struct pci_dev *dev = NULL;
415         while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
416         {
417                 if ((dev->vendor == PCIE_TI_VENDOR) && (dev->device == PCIE_TI_DEVICE)) {
418                         printk("Found TI device\n");
419                         irqNo = dev->irq;
420                         PCIE_DEV = dev;
421                         printk("TI device: vendor=0x%04x, dev=0x%04x, irq=0x%08x\n", dev->vendor, dev->device, dev->irq);
422                         break;
423                 }
424         }
427 /* ============================================================================
428  *  @func   PCI_readBAR
429  *
430  *  @desc   This function reads config.
431  *
432  *  @modif  None.
433  *  ============================================================================
434  */
435 void PCI_readBAR(void)
437         resource_size_t  barStart[4];
438         resource_size_t  barLen[4];
439         resource_size_t  barFlags[4];
441         barStart [0] = pci_resource_start (PCIE_DEV, 0);   /* BAR0 4K for PCIE application registers */
442         barLen   [0] = pci_resource_len   (PCIE_DEV, 0);
443         barFlags [0] = pci_resource_flags (PCIE_DEV, 0);
444         barStart [1] = pci_resource_start (PCIE_DEV, 1);   /* BAR1 512K/1024K for 6678/6670 Local L2 */
445         barLen   [1] = pci_resource_len   (PCIE_DEV, 1);
446         barFlags [1] = pci_resource_flags (PCIE_DEV, 1);
447         barStart [2] = pci_resource_start (PCIE_DEV, 2);   /* BAR2 4M/2M for 6678/6670 Shared L2 */
448         barLen   [2] = pci_resource_len   (PCIE_DEV, 2);
449         barFlags [2] = pci_resource_flags (PCIE_DEV, 2);
450         barStart [3] = pci_resource_start (PCIE_DEV, 3);   /* BAR3 16M for DDR3 */
451         barLen   [3] = pci_resource_len   (PCIE_DEV, 3);
452         barFlags [3] = pci_resource_flags (PCIE_DEV, 3);
454         /* ---------------------------------------------------------------------
455          * Map the REG memory region
456          * ---------------------------------------------------------------------
457          */
458         if (barFlags[0] & IORESOURCE_MEM) {
459                 regBase = barStart[0];
460                 /* Map the memory region. */
461                 request_mem_region(regBase, barLen[0], "DSPLINK");
462         }
463         else {
464                 /* Map the memory region. */
465                 request_region(regBase, barLen[0], "DSPLINK");
466         }
468         if (regBase > 0) {
469                 regVirt = ioremap(barStart[0], barLen[0]);
470         }
472         /* ---------------------------------------------------------------------
473          * Map the LL2RAM memory region
474          * ---------------------------------------------------------------------
475          */
476         if (barFlags[1] & IORESOURCE_MEM) {
477                 memBase = barStart[1];
478                 /* Map the memory region. */
479                 request_mem_region(memBase, barLen[1], "DSPLINK");
480         }
481         else {
482                 /* Map the memory region. */
483                 request_region(memBase, barLen[1], "DSPLINK");
484         }
486         if (memBase > 0) {
487                 memVirt = ioremap(barStart[1], barLen[1]);
488         }
490         /* ---------------------------------------------------------------------
491          * Map the MSMC memory region
492          * ---------------------------------------------------------------------
493          */
494         if (barFlags[2] & IORESOURCE_MEM) {
495                 msmcBase = barStart[2];
496                 /* Map the memory region. */
497                 request_mem_region(msmcBase, barLen[2], "DSPLINK");
498         }
499         else {
500                 /* Map the memory region. */
501                 request_region(msmcBase, barLen[2], "DSPLINK");
502         }
504         if (msmcBase > 0) {
505                 msmcVirt = ioremap(barStart[2], barLen[2]);
506         }
508         /* ---------------------------------------------------------------------
509          * Map the DDR memory region
510          * ---------------------------------------------------------------------
511          */
512         if (barFlags[3] & IORESOURCE_MEM) {
513                 ddrBase = barStart[3];
514                 /* Map the memory region. */
515                 request_mem_region(ddrBase, barLen[3], "DSPLINK");
516         }
517         else {
518                 /* Map the memory region. */
519                 request_region(ddrBase, barLen[3], "DSPLINK");
520         }
522         if (ddrBase > 0) {
523                 ddrVirt = ioremap(barStart[3], barLen[3]);
524         }
526         regLen  = barLen[0];
527         memLen  = barLen[1];
528         msmcLen = barLen[2];
529         ddrLen  = barLen[3];
533 /* =============================================================================
534  *  @func   PCI_setMaster
535  *
536  *  @desc   This function makes the given device to be master.
537  *
538  *  @modif  None.
539  *  ============================================================================
540  */
541 void PCI_setMaster(void)
543         int32_t  retVal;
544         uint16_t cmdVal;
545         struct pci_dev *dev;
547         dev = PCIE_DEV;
549         /* set the DMA mask */
550         if (pci_set_dma_mask(dev, 0xfffffff0ULL)) {
551         }
553         /* set the desired PCI dev to be master, this internally sets the latency timer */
554         pci_set_master(dev);
555         pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
557         /* Add support memory write invalidate */
558         retVal = pci_set_mwi(dev);
560         pci_read_config_word(dev, PCI_COMMAND, (u16 *)&cmdVal);
561         /* and set the master bit in command register. */
562         cmdVal |= PCI_COMMAND_MEMORY
563                 | PCI_COMMAND_MASTER
564                 | PCI_COMMAND_SERR;
565         /* and clear the interrupt disable bit in command register. */
566         cmdVal &= ~PCI_COMMAND_INTX_DISABLE;
567         pci_write_config_word(dev, PCI_COMMAND, cmdVal);
570 /* =============================================================================
571  *  @func   HAL_CheckPciInterrupt
572  *
573  *  @desc   This function check whether interrupt is generated by C667x or not.
574  *
575  *  @modif  None.
576  *  ============================================================================
577  */
578 bool HAL_CheckPciInterrupt(void)
580         uint32_t *pReg = (uint32_t *)regVirt;
581         return ioread32(pReg + EP_IRQ_STATUS/4);
584 /** ============================================================================
585  *  @func   HAL_PciClearDspInterrupt
586  *
587  *  @desc   Clear pending interrupt from DSP to Host.
588  *
589  *  @modif  None.
590  *  ============================================================================
591  */
592 void HAL_PciClearDspInterrupt(void)
594         uint32_t *pReg = (uint32_t *)regVirt;
595         iowrite32(1, pReg+EP_IRQ_CLR/4);
598 /** ============================================================================
599  *  @func   HAL_PciEnableDspInterrupt
600  *
601  *  @desc   Allow the DSP to generate interrupts to the Host.
602  *
603  *  @modif  None.
604  *  ============================================================================
605  */
606 void HAL_PciEnableDspInterrupt(void)
608         uint32_t *pReg = (uint32_t *)regVirt;
609         iowrite32(1, pReg+LEGACY_A_IRQ_ENABLE_SET/4);
612 /** ============================================================================
613  *  @func   HAL_PciDisableDspInterrupt
614  *
615  *  @desc   Disable the DSP to generate interrupts to the Host.
616  *
617  *  @modif  None.
618  *  ============================================================================
619  */
620 void HAL_PciDisableDspInterrupt(void)
622         uint32_t *pReg = (uint32_t *)regVirt;
623         iowrite32(1, pReg+LEGACY_A_IRQ_ENABLE_CLR/4);
627 /* ============================================================================
628  *  @func   HAL_readDMA
629  *
630  *  @desc   Move DMAs contents from DSP memory to GPP Memory. For DSP this is
631  *          outbound write. 
632  *  flag:   0: Move data inside DSP; 1: Move data between GPP and DSP
633  *  
634  *  @modif  None.
635  *  ============================================================================
636  */
637 void HAL_readDMA(uint32_t srcAddr, uint32_t dstAddr, uint32_t size, uint32_t flag)
639         uint32_t *pReg, tmp, pageBase, i, tSize;
641         pReg = (uint32_t *)regVirt;     /* Point to PCIE application registers */
643         /* Move data between GPP and DSP, need to program PCIE OB registers */
644         if (flag) { 
645                 iowrite32(0x0, pReg + OB_SIZE/4); /* 1MB outbound translation size */
647                 if (size <= PCIE_ADLEN_1MB) {
648                         pageBase = dstAddr & PCIE_1MB_BITMASK;
649                         iowrite32(pageBase|0x1, pReg + OB_OFFSET_INDEX(0)/4);
650                         iowrite32(0x0, pReg + OB_OFFSET_HI(0)/4);  
651                 }
652                 else {
653                         for (tmp = size, i = 0; tmp > 0; tmp -= PCIE_ADLEN_1MB, i++) {
654                                 pageBase = (dstAddr + (PCIE_ADLEN_1MB * i)) & PCIE_1MB_BITMASK;
655                                 iowrite32(pageBase|0x1, pReg + OB_OFFSET_INDEX(i)/4);
656                                 iowrite32(0x0, pReg + OB_OFFSET_HI(i)/4);
657                         }
658                 }
659         }
661         /* Temporarily re-map IB region 3 from DDR memory to EDMA registers */
662         iowrite32(EDMA_TPCC0_BASE_ADDRESS, pReg + IB_OFFSET(3)/4);  
664         pReg = (uint32_t*)ddrVirt;   /* Now it points to the start of EDMA_TPCC0_BASE_ADDRESS */
666         while (true) {
667                 /* Use TC0 for DBS = 128 bytes */
668                 myIowrite32(0x0, pReg + DMAQNUM0/4);                
670                 /* Set the interrupt enable for 1st Channel (IER). */
671                 myIowrite32(0x1, pReg + IESR/4);
673                 /* Clear any pending interrupt (IPR). */
674                 myIowrite32(0x1, pReg + ICR/4);
676                 /* Populate the Param entry. */
677                 myIowrite32(0x00100004, pReg + PARAM_0_OPT/4);    /* Enable SYNCDIM and TCINTEN, TCC = 0 */
679                 if (flag == 1) {
680                         /* Calculate the DSP PCI address for the PC address */
681                         tmp = PCIE_DATA + (dstAddr & ~PCIE_1MB_BITMASK);
682                         myIowrite32(tmp, pReg + PARAM_0_DST/4);
683                 } else {
684                         myIowrite32(dstAddr, pReg + PARAM_0_DST/4);
685                 }
687                 /* Calculate the A & B count */
688                 if (size > PCIE_TRANSFER_SIZE)  {
689                         tmp = size/PCIE_TRANSFER_SIZE;
690                         tSize = tmp*PCIE_TRANSFER_SIZE;
691                         size -= (tmp*PCIE_TRANSFER_SIZE);
692                         tmp <<= 16;
693                         tmp |= PCIE_TRANSFER_SIZE;
694                 }
695                 else {
696                         tmp = 0x10000|size;
697                         tSize = size;
698                         size = 0;
699                 }
701                 myIowrite32(tmp, pReg + PARAM_0_A_B_CNT/4);
702                 myIowrite32(srcAddr, pReg + PARAM_0_SRC/4);
704                 myIowrite32(((PCIE_TRANSFER_SIZE<<16)|PCIE_TRANSFER_SIZE), pReg + PARAM_0_SRC_DST_BIDX/4);
705                 myIowrite32(0xFFFF, pReg + PARAM_0_LINK_BCNTRLD/4);
706                 myIowrite32(0x0, pReg + PARAM_0_SRC_DST_CIDX/4);
708                 /* C Count is set to 1 since mostly size will not be more than 1.75GB */
709                 myIowrite32(0x1, pReg + PARAM_0_CCNT/4);
711                 /* Set the Event Enable Set Register. */
712                 myIowrite32(0x1, pReg + EESR/4);
714                 /* Set the event set register. */
715                 myIowrite32(0x1, pReg + ESR/4);
717                 /* wait for current DMA to finish. */
718                 while (true) {
719                         /* check in steps of 10 usec. */
720                         udelay(10);
721                         tmp = myIoread32(pReg + IPR/4);
722                         if ((tmp & 0x1) == 1) {
723                                 break;
724                         }
725                 }
727                 if (size != 0) {
728                         srcAddr += tSize;
729                         dstAddr += tSize;
730                 } else {
731                         break;
732                 }
733         } 
735         /* Clear any pending interrupt. */
736         myIowrite32(1, pReg + ICR/4);
738         /* Restore pointer */
739         pReg = (uint32_t *)regVirt;     /* Point to PCIE application registers */
740         iowrite32(DDR_START, pReg + IB_OFFSET(3)/4); 
743 /* ============================================================================
744  *  @func   HAL_writeDMA
745  *
746  *  @desc   Move DMAs contents from GPP memory to DSP Memory. For DSP this is
747  *          outbound read.
748  *  flag:   0: Move data inside DSP; 1: Move data between GPP and DSP
749  *
750  *  @modif  None.
751  *  ============================================================================
752  */
753 void HAL_writeDMA(uint32_t srcAddr, uint32_t dstAddr, uint32_t size, uint32_t flag)
755         uint32_t *pReg, tmp, pageBase, i, tSize;
757         pReg = (uint32_t *)regVirt;     /* Point to PCIE application registers */
759         /* Move data between GPP and DSP, need to program PCIE OB registers */
760         if (flag) { 
761                 iowrite32(0x0, pReg + OB_SIZE/4); /* 1MB outbound translation size */
763                 if (size <= PCIE_ADLEN_1MB) {
764                         pageBase = srcAddr & PCIE_1MB_BITMASK;
765                         iowrite32(pageBase|0x1, pReg + OB_OFFSET_INDEX(0)/4);
766                         iowrite32(0x0, pReg + OB_OFFSET_HI(0)/4);  
767                 }
768                 else {
769                         for (tmp = size, i = 0; tmp > 0; tmp -= PCIE_ADLEN_1MB, i++) {
770                                 pageBase = (srcAddr + (PCIE_ADLEN_1MB * i)) & PCIE_1MB_BITMASK;
771                                 iowrite32(pageBase|0x1, pReg + OB_OFFSET_INDEX(i)/4);
772                                 iowrite32(0x0, pReg + OB_OFFSET_HI(i)/4);
773                         }
774                 }
775         }
777         /* Temporarily re-map IB region 3 from DDR memory to EDMA registers */
778         iowrite32(EDMA_TPCC0_BASE_ADDRESS, pReg + IB_OFFSET(3)/4);  
780         pReg = (uint32_t*)ddrVirt;   /* Now it points to the start of EDMA_TPCC0_BASE_ADDRESS */
782         while (true) {
783                 /* Use TC0 for DBS = 128 bytes */
784                 myIowrite32(0x0, pReg + DMAQNUM0/4);                
786                 /* Set the interrupt enable for 1st Channel (IER). */
787                 myIowrite32(0x1, pReg + IESR/4);
789                 /* Clear any pending interrupt (IPR). */
790                 myIowrite32(0x1, pReg + ICR/4);
792                 /* Populate the Param entry. */
793                 myIowrite32(0x00100004, pReg + PARAM_0_OPT/4);    /* Enable SYNCDIM and TCINTEN, TCC = 0 */
795                 if (flag == 1) {
796                         /* Calculate the DSP PCI address for the PC address */
797                         tmp = PCIE_DATA + (srcAddr & ~PCIE_1MB_BITMASK);
798                         myIowrite32(tmp, pReg + PARAM_0_SRC/4);
799                 } else {
800                         myIowrite32(srcAddr, pReg + PARAM_0_SRC/4);
801                 }
803                 /* Calculate the A & B count */
804                 if (size > PCIE_TRANSFER_SIZE)  {
805                         tmp = size/PCIE_TRANSFER_SIZE;
806                         tSize = tmp*PCIE_TRANSFER_SIZE;
807                         size -= (tmp*PCIE_TRANSFER_SIZE);
808                         tmp <<= 16;
809                         tmp |= PCIE_TRANSFER_SIZE;
810                 }
811                 else {
812                         tmp = 0x10000|size;
813                         tSize = size;
814                         size = 0;
815                 }
817                 myIowrite32(tmp, pReg + PARAM_0_A_B_CNT/4);
818                 myIowrite32(dstAddr, pReg + PARAM_0_DST/4);
820                 myIowrite32(((PCIE_TRANSFER_SIZE<<16)|PCIE_TRANSFER_SIZE), pReg + PARAM_0_SRC_DST_BIDX/4);
821                 myIowrite32(0xFFFF, pReg + PARAM_0_LINK_BCNTRLD/4);
822                 myIowrite32(0x0, pReg + PARAM_0_SRC_DST_CIDX/4);
824                 /* C Count is set to 1 since mostly size will not be more than 1.75GB */
825                 myIowrite32(0x1, pReg + PARAM_0_CCNT/4);
827                 /* Set the Event Enable Set Register. */
828                 myIowrite32(0x1, pReg + EESR/4);
830                 /* Set the event set register. */
831                 myIowrite32(0x1, pReg + ESR/4);
833                 /* wait for current DMA to finish. */
834                 while (true) {
835                         /* check in steps of 10 usec. */
836                         udelay(10);
837                         tmp = myIoread32(pReg + IPR/4);
838                         if ((tmp & 0x1) == 1) {
839                                 break;
840                         }
841                 }
843                 if (size != 0) {
844                         srcAddr += tSize;
845                         dstAddr += tSize;
846                 } else {
847                         break;
848                 }
849         } 
851         /* Clear any pending interrupt. */
852         myIowrite32(1, pReg + ICR/4);
854         /* Restore pointer */
855         pReg = (uint32_t *)regVirt;     //Point to PCIE application registers
856         iowrite32(DDR_START, pReg + IB_OFFSET(3)/4);  
859 /** ============================================================================
860  *  @func   ISR_handler
861  *
862  *  @desc   ISR.
863  *
864  *  @modif  None.
865  *  ============================================================================
866  */
867 static irqreturn_t ISR_handler(int irq, void *arg) 
869         uint32_t i, dma_failure_flag = 0, counter = 0;
870         uint32_t status = HAL_CheckPciInterrupt();
872         if (status == 1) {
873                 printk("Interrupt %d received from DSP\n", irq);
874                 printk("Read DMA from DSP ...\n");
875                 do_gettimeofday(&test_time3);
876                 HAL_readDMA(DDR_START, rData, DMA_TRANSFER_SIZE, 1);     /* Move from DSP to GPP */
877                 do_gettimeofday(&test_time4);
879                 for (i = 0; i < DMA_TRANSFER_SIZE; i++) {
880                         if ((~(rDataVirt[i])&0xFF) != wDataVirt[i]) {
881                                 dma_failure_flag = 1;
882                                 counter++;
883                         }
884                 }
886                 if (dma_failure_flag) 
887                         printk("DMA test failed with %d locations !\n", counter);
888                 else 
889                         printk("DMA test passed!\n");
891                 HAL_PciClearDspInterrupt();
892                 return IRQ_HANDLED;
893         }
894         return IRQ_NONE;
897 /* ============================================================================
898  *  @func   byteto32bits 
899  *
900  *  @desc   Convert 4 bytes to 32 bits long word
901  *
902  *  @modif  None.
903  *  ============================================================================
904  */
905 uint32_t byteTo32bits(uint8_t *pDspCode)
907         uint32_t i, temp;
909         temp = *pDspCode++;
910         for(i = 0; i < 3;i++) {
911                 temp <<= 8;
912                 temp |= *pDspCode++;
913         }
914         return(temp);
917 /* ============================================================================
918  *  @func   swap4bytes
919  *
920  *  @desc   Endian swap: 0xA0B1C2D3 to 0xD3C2B1A0 
921  *
922  *  @modif  None.
923  *  ============================================================================
924  */
925 void swap4bytes(uint32_t *pDspCode, uint32_t size)
927         uint32_t i, temp;
929         for(i = 0; i < size; i += 4, pDspCode++) {
930                 temp = *pDspCode;
931                 temp = (temp>>24) |
932                         ((temp<<8) & 0x00FF0000) |
933                         ((temp>>8) & 0x0000FF00) |
934                         (temp<<24);
936                 *pDspCode = temp;
937         }
940 /* ============================================================================
941  *  @func   writeDSPMemory
942  *
943  *  @desc   Write a block of data into DSP memory from Linux host. 
944  *          Note the data buffer is in 32-bit format, unit of length is byte. 
945  *          coreNum: to write data: 0-7 for cores 0-7; 8 for MSMC; 9 for DDR.
946  *
947  *  @modif  None.
948  *  ============================================================================
949  */
950 uint32_t writeDSPMemory(uint32_t coreNum, uint32_t DSPMemAddr, uint32_t *buffer, uint32_t length) 
952         uint32_t i, offset, tempReg = 0;
953         uint32_t *ptr;
955         if (length == 0) {
956                 return 0;
957         }
959         switch (coreNum) {
960 #if EVMC6678L
961                 case 0:
962                 case 1:
963                 case 2:
964                 case 3:
965                 case 4:
966                 case 5:
967                 case 6:
968                 case 7: 
969 #endif
970 #if EVMC6670L
971                 case 0:
972                 case 1:
973                 case 2:
974                 case 3:
975 #endif
976 #if EVMC6657L
977                 case 0:
978                 case 1:
979 #endif
980                         DSPMemAddr &= 0x00FFFFFF;
981                         tempReg = ioread32(ptrReg + IB_OFFSET(1)/4);
982                         iowrite32(tempReg + coreNum*0x01000000, ptrReg + IB_OFFSET(1)/4); /* pointing to a different core */
984                         if (DSPMemAddr < LL2_START) {
985                                 return 0;
986                         } else {  
987                                 offset = DSPMemAddr - LL2_START;
988                                 ptr = (uint32_t *)memVirt + offset/4;
989                         }
990                         break;
991                 case 8:  /* this is for MSMC */
992                         if (DSPMemAddr < MSMC_START) {
993                                 return 0;
994                         } else {
995                                 offset = DSPMemAddr - MSMC_START;
996                                 ptr = (uint32_t *)msmcVirt + offset/4;
997                         }               
998                         break;   
999                 case 9:  /* this is for DDR */
1000                         if (DSPMemAddr < DDR_START) {
1001                                 return 0;
1002                         } else {  
1003                                 offset = DSPMemAddr - DDR_START;
1004                                 ptr = (uint32_t *)ddrVirt + offset/4;
1005                         }
1006                         break; 
1007                 default:
1008                         printk("Use coreNum 0-7 for core 0-7 of EVMC6678L, or coreNum 0-3 for core 0-3 of EVMC6670L; coreNum 8 for MSMC and coreNum 9 for DDR.\n");
1009                         return 0;
1010                         break;
1011         }     
1013         for (i = 0; i < length/4; i++) {
1014 #if BIG_ENDIAN
1015                 swap4bytes(&buffer[i], 4);
1016 #endif
1017                 *ptr = buffer[i];
1018                 ptr++; 
1019         }
1021         if ((coreNum >= 0)&&(coreNum <= 7)) {
1022                 iowrite32(tempReg, ptrReg + IB_OFFSET(1)/4);  /* Restore IB_OFFSET1 */
1023         }
1025         return length;
1028 /* ============================================================================
1029  *  @func   readDSPMemory
1030  *
1031  *  @desc   Read a block of DSP memory by Linux host. 
1032  *          Note the data buffer is in 32-bit format, unit of length is byte. 
1033  *          coreNum: to read data: 0-7 for cores 0-7; 8 for MSMC; 9 for DDR.
1034  *
1035  *  @modif  None.
1036  *  ============================================================================
1037  */
1038 uint32_t readDSPMemory(uint32_t coreNum, uint32_t DSPMemAddr, uint32_t *buffer, uint32_t length) 
1040         uint32_t i, offset, tempReg = 0;
1041         uint32_t *ptr;
1043         if (length == 0) {
1044                 return 0;
1045         }  
1047         switch (coreNum) {
1048 #if EVMC6678L
1049                 case 0:
1050                 case 1:
1051                 case 2:
1052                 case 3:
1053                 case 4:
1054                 case 5:
1055                 case 6:
1056                 case 7: 
1057 #endif
1058 #if EVMC6670L
1059                 case 0:
1060                 case 1:
1061                 case 2:
1062                 case 3:
1063 #endif
1064 #if EVMC6657L
1065                 case 0:
1066                 case 1:
1067 #endif
1068                         DSPMemAddr &= 0x00FFFFFF;
1069                         tempReg = ioread32(ptrReg + IB_OFFSET(1)/4);
1070                         iowrite32(tempReg + coreNum*0x1000000, ptrReg + IB_OFFSET(1)/4);        /* pointing to a different core */
1071                         if (DSPMemAddr < LL2_START) {
1072                                 return 0;
1073                         } else {  
1074                                 offset = DSPMemAddr - LL2_START;
1075                                 ptr = (uint32_t *)memVirt + offset/4;
1076                         }
1077                         break;
1078                 case 8:  /* this is for MSMC */
1079                         if (DSPMemAddr < MSMC_START) {
1080                                 return 0;
1081                         } else {                   
1082                                 offset = DSPMemAddr - MSMC_START;
1083                                 ptr = (uint32_t *)msmcVirt + offset/4;
1084                         }
1085                         break;   
1086                 case 9:  /* this is for DDR */
1087                         if (DSPMemAddr < DDR_START) {
1088                                 return 0;
1089                         } else {                   
1090                                 offset = DSPMemAddr - DDR_START;
1091                                 ptr = (uint32_t *)ddrVirt + offset/4;
1092                         }
1093                         break; 
1094                 default:
1095                         printk("Use coreNum 0-7 for core 0-7 of EVMC6678L, or coreNum 0-3 for core 0-3 of EVMC6670L; coreNum 8 for MSMC and coreNum 9 for DDR.\n");
1096                         return 0;
1097                         break;
1098         }     
1100         for (i = 0; i < length/4; i++) {
1101                 buffer[i] = *ptr;
1102 #if BIG_ENDIAN
1103                 swap4bytes(&buffer[i], 4);
1104 #endif
1105                 ptr++;
1106         }
1108         if ((coreNum >= 0)&&(coreNum <= 7)) {
1109                 iowrite32(tempReg, ptrReg + IB_OFFSET(1)/4);  /* Restore IB_OFFSET1 */
1110         }
1112         return length;
1115 /* ============================================================================
1116  *  @func   pushData
1117  *
1118  *  @desc   Parser function for DSP boot image array
1119  *
1120  *  @modif  None.
1121  *  ============================================================================
1122  */
1123 void pushData(uint8_t *pDspCode, uint8_t coreNum, uint32_t *bootEntryAddr)
1125         uint32_t i, j, tempArray[BLOCK_TRANSFER_SIZE/4];
1126         uint32_t size, section = 0, totalSize = 0;
1127         uint32_t count, remainder, startAddr, temp;
1128         uint8_t newCoreNum;
1130         /* Get the boot entry address */
1131         *bootEntryAddr = byteTo32bits(pDspCode);
1132         printk("Boot entry address is 0x%8x\n", *bootEntryAddr);
1133         pDspCode +=4;
1135         while(1) {
1137                 /* Get the size */
1138                 size = byteTo32bits(pDspCode);
1139                 if(size == 0) break;
1141                 if ((size/4)*4 != size) {
1142                         size = ((size/4)+1)*4;
1143                 }
1145                 totalSize += size;
1146                 section++;
1147                 pDspCode += 4;
1148                 startAddr = byteTo32bits(pDspCode);
1150                 /* In case there are several sections within different memory regions */
1151                 temp = (startAddr & 0xFF000000) >> 24;
1153                 if (temp == 0x00 || ((temp >> 4) == 0x1)) {
1154                         if (coreNum < 8) {
1155                                 /* Write address like 0x00800000 to core 1, 2, ... */
1156                                 newCoreNum = coreNum;
1157                         } else {
1158                                 newCoreNum = 0;
1159                         }
1160                 } else if (temp == 0x0C) {
1161                         newCoreNum = 8;
1162                 } else {
1163                         newCoreNum = 9;
1164                 }
1166                 pDspCode+= 4;
1167                 count = size/BLOCK_TRANSFER_SIZE;
1168                 remainder = size - count * BLOCK_TRANSFER_SIZE;
1170                 for(i = 0; i < count; i++) {
1171                         for (j = 0; j < BLOCK_TRANSFER_SIZE/4; j++) {
1172                                 tempArray[j] = byteTo32bits(pDspCode);
1173                                 pDspCode += 4;
1174                         }
1175                         /* Transfer boot tables to DSP */
1176                         writeDSPMemory(newCoreNum, startAddr, tempArray, BLOCK_TRANSFER_SIZE); 
1177                         startAddr += BLOCK_TRANSFER_SIZE;
1178                 }
1180                 for (j = 0; j < remainder/4; j++) {
1181                         tempArray[j] = byteTo32bits(pDspCode);
1182                         pDspCode += 4;
1183                 }
1184                 writeDSPMemory(newCoreNum, startAddr, tempArray, remainder); 
1185                 // printk("Section %d started at 0x%8x with size 0x%8x bytes written to core %d\n", section, startAddr, size, newCoreNum);
1186         }
1187         printk("Total %d sections, 0x%x bytes of data were written\n", section, totalSize);
1191 #if LOCAL_RESET
1192 /* ============================================================================
1193  *  @func   coreLocalReset
1194  *
1195  *  @desc   Reset a particular CorePac, 6678 Data Manual, section 7.4.4
1196  *          initiated by LPSC MMRs
1197  *
1198  *  @modif  None.
1199  *  ============================================================================
1200  */
1201 void coreLocalReset(uint32_t pid, uint32_t mid, uint32_t state) 
1203         uint32_t *pReg, temp, counter = 0;
1205         /* Point to PCIE application registers */
1206         pReg = (uint32_t *)regVirt; 
1207         /* Set MST_PRIV bit to access PSC via PCIE */
1208         iowrite32(((ioread32(pReg + PRIORITY/4))|0x00010000), pReg + PRIORITY/4);    
1210         /* Temporarily re-map IB region 3 from DDR memory to PSC registers */
1211         iowrite32(PSC_BASE_ADDRESS, pReg + IB_OFFSET(3)/4);  
1212         /* Now it points to the start of PSC_BASE_ADDRESS */
1213         pReg = (uint32_t*)ddrVirt;   
1215         temp = myIoread32(pReg + MDCTL(mid)/4);
1216         if (state == 0) {
1217                 /* Reset assert */
1218                 temp = ((temp & ~0x1F) | PSC_ENABLE) & (~0x100);
1219                 printk("Start local reset assert for core (module id): %d ...\n", mid);
1220         } else  {
1221                 /* Reset de-assert */
1222                 temp = (temp & ~0x1F) | PSC_ENABLE | (1 << 8);
1223                 printk("Start local reset de-assert for core (module id): %d ...\n", mid);
1224         }
1226         myIowrite32(temp, pReg + MDCTL(mid)/4);    /* Assert/De-assert local reset */
1228         /* No previous transition in progress */
1229         counter = 0;
1230         while (true) {
1231                 temp = myIoread32(pReg + PTSTAT/4);
1232                 if ((temp & (1 << pid)) == 0) break;
1233                 mdelay(1);
1234                 counter ++;
1235                 if (counter > 10) {
1236                         printk("Previous transition in progress pid %d mid %d state: %d\n", pid, mid, state);
1237                         break;
1238                 }
1239         }
1241         myIowrite32((1 << pid), pReg + PTCMD/4); 
1243         /* Current transition finished */
1244         counter = 0;
1245         while (true) {
1246                 temp = myIoread32(pReg + PTSTAT/4);
1247                 if ((temp & (1 << pid)) == 0) break;
1248                 mdelay(1);
1249                 counter ++;
1250                 if (counter > 10) {
1251                         printk("Current transition in progress pid %d mid %d state: %d\n", pid, mid, state);
1252                         break;
1253                 }
1254         }
1256         /* Verifying state change */
1257         counter = 0;
1258         while (true) {
1259                 temp = myIoread32(pReg + MDSTAT(mid)/4);
1260                 if ((temp & 0x1F) == 3) break;
1261                 mdelay(1);
1262                 counter ++;
1263                 if (counter > 10) {
1264                         printk("MD stat for pid %d mid %d state: %d timeout\n", pid, mid, state);
1265                         break;
1266                 }
1267         }
1269         /* Restore pointer */
1270         pReg = (uint32_t *)regVirt;     /* Point to PCIE application registers */
1271         iowrite32(DDR_START, pReg + IB_OFFSET(3)/4);  
1274 /* ============================================================================
1275  *  @func   setPscState
1276  *
1277  *  @desc   Set a new power state for the specified domain id in a power controler
1278  *          domain. Wait for the power transition to complete.
1279  *
1280  *      pid   -  power domain.
1281  *      mid   -  module id to use for module in the specified power domain
1282  *      state -  new state value to set (0 = RESET; 3 = ENABLE)
1283  *
1284  *  @modif  None.
1285  *  ============================================================================
1286  */
1287 void setPscState(uint32_t pid, uint32_t mid, uint32_t state)
1289         uint32_t *pReg, mdctl, pdctl, temp, counter = 0;
1291         /* Point to PCIE application registers */
1292         pReg = (uint32_t *)regVirt; 
1293         /* Set MST_PRIV bit to access PSC via PCIE */
1294         iowrite32(((ioread32(pReg + PRIORITY/4))|0x00010000), pReg + PRIORITY/4);    
1296         /* Temporarily re-map IB region 3 from DDR memory to PSC registers */
1297         iowrite32(PSC_BASE_ADDRESS, pReg + IB_OFFSET(3)/4);  
1298         /* Now it points to the start of PSC_BASE_ADDRESS */
1299         pReg = (uint32_t*)ddrVirt;   
1301         mdctl = myIoread32(pReg + MDCTL(mid)/4);
1302         pdctl = myIoread32(pReg + PDCTL(pid)/4);
1304         /* No previous transition in progress */
1305         counter = 0;
1306         while (true) {
1307                 temp = myIoread32(pReg + PTSTAT/4);
1308                 if ((temp & (1 << pid)) == 0) break;
1309                 mdelay(1);
1310                 counter ++;
1311                 if (counter > 10) {
1312                         printk("Previous transition in progress pid %d mid %d state: %d\n", pid, mid, state);
1313                         break;
1314                 }
1315         }
1317         /* Set power domain control */
1318         myIowrite32(pdctl | 0x1, pReg + PDCTL(pid)/4);
1320         /* Set MDCTL NEXT to new state */
1321         mdctl = ((mdctl) & ~(0x1f)) | state;
1322         myIowrite32(mdctl, pReg + MDCTL(mid)/4);
1324         /* Start power transition by setting PTCMD GO to 1 */
1325         temp = myIoread32(pReg + PTCMD/4);
1326         myIowrite32(temp | (0x1<<pid), pReg + PTCMD/4);
1328         /* Current transition finished */
1329         counter = 0;
1330         while (true) {
1331                 temp = myIoread32(pReg + PTSTAT/4);
1332                 if ((temp & (1 << pid)) == 0) break;
1333                 mdelay(1);
1334                 counter ++;
1335                 if (counter > 10) {
1336                         printk("Current transition in progress pid %d mid %d state: %d\n", pid, mid, state);
1337                         break;
1338                 }
1339         }
1341         /* Verifying state change */
1342         counter = 0;
1343         while (true) {
1344                 temp = myIoread32(pReg + MDSTAT(mid)/4);
1345                 if ((temp & 0x1F) == state) break;
1346                 mdelay(1);
1347                 counter ++;
1348                 if (counter > 10) {
1349                         printk("MD stat for pid %d mid %d state: %d timeout\n", pid, mid, state);
1350                         break;
1351                 }
1352         }
1354         /* Restore pointer */
1355         pReg = (uint32_t *)regVirt;     /* Point to PCIE application registers */
1356         iowrite32(DDR_START, pReg + IB_OFFSET(3)/4);  
1359 /* ============================================================================
1360  *  @func   setBootAddrIpcgr
1361  *
1362  *  @desc   Write boot entry point into DSP_BOOT_ADDR0 and the send an IPC
1363  *
1364  *  @modif  None.
1365  *  ============================================================================
1366  */
1367 uint32_t setBootAddrIpcgr(uint32_t core, uint32_t addr)  
1369         uint32_t *pReg;
1370         /* Point to PCIE application registers */
1371         pReg = (uint32_t *)regVirt; 
1372         /* Set MST_PRIV bit to access PSC via PCIE */
1373         iowrite32(((ioread32(pReg + PRIORITY/4))|0x00010000), pReg + PRIORITY/4);    
1375         /* Temporarily re-map IB region 3 from DDR memory to chip level registers */
1376         iowrite32(CHIP_LEVEL_BASE_ADDRESS, pReg + IB_OFFSET(3)/4);  
1377         /* Now it points to the start of CHIP_LEVEL_BASE_ADDRESS */
1378         pReg = (uint32_t*)ddrVirt; 
1380         /* Unlock KICK0, KICK1 */
1381         myIowrite32(KICK0_UNLOCK, pReg + KICK0/4); 
1382         myIowrite32(KICK1_UNLOCK, pReg + KICK1/4);
1384         /* Check if the last 10 bits of addr is 0 */
1385         if ((addr & 0x3f) != 0) {
1386                 printk("The address is not 1K aligned.\n");
1387                 return 0;
1388         }
1390         myIowrite32(addr, pReg + DSP_BOOT_ADDR(core)/4);
1391         myIowrite32(1, pReg + IPCGR(core)/4);  
1393         mdelay(1); 
1395         /* Restore pointer */
1396         pReg = (uint32_t *)regVirt;     /* Point to PCIE application registers */
1397         iowrite32(DDR_START, pReg + IB_OFFSET(3)/4);  
1399         return 1;
1402 /* ============================================================================
1403  *  @func   dspLocalReset
1404  *
1405  *  @desc   Perform DSP cores and periphrals reset
1406  *
1407  *  @modif  None.
1408  *  ============================================================================
1409  */
1410 void dspLocalReset(void) 
1412         uint32_t i, bootEntryAddr = 0;
1414 #if EVMC6670L
1415         /* Local reset of all cores */
1416         coreLocalReset(PD13, LPSC_C0_TIM0, LOC_RST_ASSERT);
1417         coreLocalReset(PD14, LPSC_C1_TIM1, LOC_RST_ASSERT);
1418         coreLocalReset(PD15, LPSC_C2_TIM2, LOC_RST_ASSERT);
1419         coreLocalReset(PD16, LPSC_C3_TIM3, LOC_RST_ASSERT);
1421         /* Disable all other modules */
1422         setPscState(PD0, LPSC_TCP3E, PSC_SWRSTDISABLE);
1423         setPscState(PD0, LPSC_VCP2A, PSC_SWRSTDISABLE);
1424         setPscState(PD1, LPSC_DEBUG, PSC_SWRSTDISABLE);
1425         setPscState(PD1, LPSC_TETB, PSC_SWRSTDISABLE);
1426         setPscState(PD2, LPSC_SA, PSC_SWRSTDISABLE);
1427         setPscState(PD2, LPSC_SGMII, PSC_SWRSTDISABLE);
1428         setPscState(PD2, LPSC_PA, PSC_SWRSTDISABLE);
1429         //setPscState(PD3, LPSC_PCIE, PSC_SWRSTDISABLE);
1430         setPscState(PD4, LPSC_SRIO, PSC_SWRSTDISABLE);
1431         setPscState(PD5, LPSC_HYPER, PSC_SWRSTDISABLE);
1432         //setPscState(PD6, LPSC_RESERV, PSC_SWRSTDISABLE);
1433         setPscState(PD7, LPSC_MSMCRAM, PSC_SWRSTDISABLE);
1434         setPscState(PD8, LPSC_RACA_RACB, PSC_SWRSTDISABLE);
1435         setPscState(PD8, LPSC_TAC, PSC_SWRSTDISABLE);
1436         setPscState(PD9, LPSC_FFTCA_FFTCB, PSC_SWRSTDISABLE);
1437         setPscState(PD10, LPSC_AIF2, PSC_SWRSTDISABLE);
1438         setPscState(PD11, LPSC_TCP3DA, PSC_SWRSTDISABLE);
1439         setPscState(PD12, LPSC_VCP2B, PSC_SWRSTDISABLE);
1440         setPscState(PD12, LPSC_VCP2C, PSC_SWRSTDISABLE);
1441         setPscState(PD12, LPSC_VCP2D, PSC_SWRSTDISABLE);
1442         setPscState(PD17, LPSC_TCP3dB, PSC_SWRSTDISABLE);
1444         for (i = 0; i < 4; i++) {
1445                 pushData(localResetCode, i, &bootEntryAddr);
1446                 if (setBootAddrIpcgr(i, bootEntryAddr) == 0) {
1447                         printk("Core %d is not ready !!! \n", i);
1448                 }
1449         }
1451         /* Enable all other modules */
1452         setPscState(PD0, LPSC_TCP3E, PSC_ENABLE);
1453         setPscState(PD0, LPSC_VCP2A, PSC_ENABLE);
1454         setPscState(PD1, LPSC_DEBUG, PSC_ENABLE);
1455         setPscState(PD1, LPSC_TETB, PSC_ENABLE);
1456         setPscState(PD2, LPSC_PA, PSC_ENABLE);
1457         setPscState(PD2, LPSC_SGMII, PSC_ENABLE);
1458         setPscState(PD2, LPSC_SA, PSC_ENABLE);
1459         //setPscState(PD3, LPSC_PCIE, PSC_ENABLE);
1460         setPscState(PD4, LPSC_SRIO, PSC_ENABLE);
1461         setPscState(PD5, LPSC_HYPER, PSC_ENABLE);
1462         //setPscState(PD6, LPSC_RESERV, PSC_ENABLE);
1463         setPscState(PD7, LPSC_MSMCRAM, PSC_ENABLE);
1464         setPscState(PD8, LPSC_RACA_RACB, PSC_ENABLE);
1465         setPscState(PD8, LPSC_TAC, PSC_ENABLE);
1466         setPscState(PD9, LPSC_FFTCA_FFTCB, PSC_ENABLE);
1467         setPscState(PD10, LPSC_AIF2, PSC_ENABLE);
1468         setPscState(PD11, LPSC_TCP3DA, PSC_ENABLE);
1469         setPscState(PD12, LPSC_VCP2B, PSC_ENABLE);
1470         setPscState(PD12, LPSC_VCP2C, PSC_ENABLE);
1471         setPscState(PD12, LPSC_VCP2D, PSC_ENABLE);
1472         setPscState(PD17, LPSC_TCP3dB, PSC_ENABLE);     
1474         /* Local out of reset of all cores */
1475         coreLocalReset(PD13, LPSC_C0_TIM0, LOC_RST_DEASSERT);
1476         coreLocalReset(PD14, LPSC_C1_TIM1, LOC_RST_DEASSERT);
1477         coreLocalReset(PD15, LPSC_C2_TIM2, LOC_RST_DEASSERT);
1478         coreLocalReset(PD16, LPSC_C3_TIM3, LOC_RST_DEASSERT);
1479 #endif
1481 #if EVMC6678L
1482         /* Local reset of all cores */
1483         coreLocalReset(PD8,  LPSC_C0_TIM0, LOC_RST_ASSERT);
1484         coreLocalReset(PD9,  LPSC_C1_TIM1, LOC_RST_ASSERT);
1485         coreLocalReset(PD10, LPSC_C2_TIM2, LOC_RST_ASSERT);
1486         coreLocalReset(PD11, LPSC_C3_TIM3, LOC_RST_ASSERT);
1487         coreLocalReset(PD12, LPSC_C4_TIM4, LOC_RST_ASSERT);
1488         coreLocalReset(PD13, LPSC_C5_TIM5, LOC_RST_ASSERT);
1489         coreLocalReset(PD14, LPSC_C6_TIM6, LOC_RST_ASSERT);
1490         coreLocalReset(PD15, LPSC_C7_TIM7, LOC_RST_ASSERT);
1492         /* Disable all other modules */
1493         setPscState(PD0, LPSC_EMIF16_SPI, PSC_SWRSTDISABLE);
1494         setPscState(PD0, LPSC_TSIP, PSC_SWRSTDISABLE);
1495         setPscState(PD1, LPSC_DEBUG, PSC_SWRSTDISABLE);
1496         setPscState(PD1, LPSC_TETB_TRC, PSC_SWRSTDISABLE);
1497         setPscState(PD2, LPSC_SA, PSC_SWRSTDISABLE);
1498         setPscState(PD2, LPSC_SGMII, PSC_SWRSTDISABLE);
1499         setPscState(PD2, LPSC_PA, PSC_SWRSTDISABLE);
1500         //setPscState(PD3, LPSC_PCIE, PSC_SWRSTDISABLE);
1501         setPscState(PD4, LPSC_SRIO, PSC_SWRSTDISABLE);
1502         setPscState(PD5, LPSC_HYPER, PSC_SWRSTDISABLE);
1503         //setPscState(PD6, LPSC_RESERV, PSC_SWRSTDISABLE);
1504         setPscState(PD7, LPSC_MSMCRAM, PSC_SWRSTDISABLE);
1506         for (i = 0; i < 8; i++) {
1507                 pushData(localResetCode, i, &bootEntryAddr);
1508                 if (setBootAddrIpcgr(i, bootEntryAddr) == 0) {
1509                         printk("Core %d is not ready !!! \n", i);
1510                 }
1511         }
1513         /* Enable all other modules */
1514         setPscState(PD0, LPSC_EMIF16_SPI, PSC_ENABLE);
1515         setPscState(PD0, LPSC_TSIP, PSC_ENABLE);
1516         setPscState(PD1, LPSC_DEBUG, PSC_ENABLE);
1517         setPscState(PD1, LPSC_TETB_TRC, PSC_ENABLE);
1518         setPscState(PD2, LPSC_PA, PSC_ENABLE);
1519         setPscState(PD2, LPSC_SGMII, PSC_ENABLE);
1520         setPscState(PD2, LPSC_SA, PSC_ENABLE);
1521         //setPscState(PD3, LPSC_PCIE, PSC_ENABLE);
1522         setPscState(PD4, LPSC_SRIO, PSC_ENABLE);
1523         setPscState(PD5, LPSC_HYPER, PSC_ENABLE);
1524         //setPscState(PD6, LPSC_RESERV, PSC_ENABLE);
1525         setPscState(PD7, LPSC_MSMCRAM, PSC_ENABLE);
1527         /* Local out of reset of all cores */
1528         coreLocalReset(PD8,  LPSC_C0_TIM0, LOC_RST_DEASSERT);
1529         coreLocalReset(PD9,  LPSC_C1_TIM1, LOC_RST_DEASSERT);
1530         coreLocalReset(PD10, LPSC_C2_TIM2, LOC_RST_DEASSERT);
1531         coreLocalReset(PD11, LPSC_C3_TIM3, LOC_RST_DEASSERT);
1532         coreLocalReset(PD12, LPSC_C4_TIM4, LOC_RST_DEASSERT);
1533         coreLocalReset(PD13, LPSC_C5_TIM5, LOC_RST_DEASSERT);
1534         coreLocalReset(PD14, LPSC_C6_TIM6, LOC_RST_DEASSERT);
1535         coreLocalReset(PD15, LPSC_C7_TIM7, LOC_RST_DEASSERT);
1536 #endif
1539 #endif   
1540 /* ============================================================================
1541  *  @func   init_module
1542  *
1543  *  @desc   Initialize a loadable module 
1544  *
1545  *  @modif  None.
1546  *  ============================================================================
1547  */
1548 int init_module(void)
1550         uint32_t i; 
1551         uint32_t bootEntryAddr = 0;              /* Store 32-bit boot entry address read from .h file */
1552 #if HELLO_WORLD_DEMO | EDMA_INTC_DEMO
1553         uint32_t buffer[BLOCK_TRANSFER_SIZE/4];  /* Store 32-bit DSP memory readback data */
1554 #endif 
1556 #if EDMA_INTC_DEMO
1557         uint32_t diff;
1558 #endif
1560         printk ("Finding the device....\n") ;
1561         PCI_FindPciDevices();
1562         if (!PCIE_DEV) {
1563                 printk ("No PCIE device found!!!\n") ;
1564         }
1566         if (PCIE_DEV != NULL) {
1568                 printk("Reading the BAR areas....\n");
1569                 PCI_readBAR();
1571                 printk("Enabling the device....\n");
1572                 /* Linux Function: Initialize device before it's used by a driver */
1573                 pci_enable_device(PCIE_DEV);
1575                 /* Linux Function: Associates the given data with the given pci_driver structure */
1576                 pci_set_drvdata(PCIE_DEV, memVirt);
1578                 PCI_setMaster();
1580                 printk("Access PCIE application register ....\n");
1581                 /* Pointing to the beginning of the application registers */
1582                 ptrReg = (uint32_t *)regVirt;
1584                 /* Configure IB_BAR0 to BAR0 for PCIE registers; Configure IB_BAR1 to BAR1 for LL2 for core 0
1585                    Configure IB_BAR2 to BAR2 for MSMC; Configure IB_BAR3 to BAR3 for DDR */
1586                 for (i = 0; i < 4; i++) {
1587                         iowrite32(i, ptrReg + IB_BAR(i)/4);     
1588                         iowrite32(PCIE_DEV->resource[i].start, ptrReg + IB_START_LO(i)/4);    
1589                         iowrite32(0, ptrReg + IB_START_HI(i)/4);
1590                 }     
1591                 iowrite32(PCIE_BASE_ADDRESS, ptrReg + IB_OFFSET(0)/4);    
1592                 iowrite32(LL2_START + (1 << 28), ptrReg + IB_OFFSET(1)/4);    
1593                 iowrite32(MSMC_START, ptrReg + IB_OFFSET(2)/4);  
1594                 iowrite32(DDR_START, ptrReg + IB_OFFSET(3)/4); 
1596                 printk("Registering the irq %d ...\n", irqNo);
1597                 request_irq(irqNo, ISR_handler, IRQF_SHARED, "TI 667x PCIE", &dummy);
1598                 HAL_PciEnableDspInterrupt();
1600 #if HELLO_WORLD_DEMO
1601                 /* Load DDR init code into DSP */
1602                 pushData(ddrInitCode, 0, &bootEntryAddr);
1604                 /* Write boot entry address into MAGIC_ADDR */
1605                 writeDSPMemory(0, MAGIC_ADDR, &bootEntryAddr, 4);       
1607                 while (1) {
1608                         readDSPMemory(0, MAGIC_ADDR, buffer, 4);
1609                         if (buffer[0] == 0)  break;
1610                         for (i = 0; i < 1000; i++) i++;
1611                 } 
1613                 /* Load "Hello World" demo into DSP */
1614                 pushData(bootCode, 9, &bootEntryAddr);
1616                 /* Write boot entry address into MAGIC_ADDR */
1617                 writeDSPMemory(0, MAGIC_ADDR, &bootEntryAddr, 4);
1618 #endif
1620 #if POST_DEMO
1621                 /* Load POST demo code into DSP */
1622                 pushData(post, 0, &bootEntryAddr);
1624                 /* Write boot entry address into MAGIC_ADDR */
1625                 writeDSPMemory(0, MAGIC_ADDR, &bootEntryAddr, 4);       
1626 #endif
1628 #if EDMA_INTC_DEMO
1630                 printk("Allocating consistent memory ...\n"); 
1631                 wDataVirt = (uint8_t*)dma_alloc_coherent(&PCIE_DEV->dev, DMA_TRANSFER_SIZE, &wData, GFP_KERNEL);
1632                 rDataVirt = (uint8_t*)dma_alloc_coherent(&PCIE_DEV->dev, DMA_TRANSFER_SIZE, &rData, GFP_KERNEL);
1634                 for (i = 0; i < DMA_TRANSFER_SIZE; i++) {
1635                         wDataVirt[i] = i;
1636                         rDataVirt[i] = 0;
1637                 }
1639                 /* Load Interrupt demo code into DSP */
1640                 pushData(pcieInterrupt, 0, &bootEntryAddr);
1642                 /* Write boot entry address into MAGIC_ADDR */
1643                 writeDSPMemory(0, MAGIC_ADDR, &bootEntryAddr, 4);       
1645                 while (1) {
1646                         readDSPMemory(0, MAGIC_ADDR, buffer, 4);
1647                         if (buffer[0] == 0)  break;
1648                         for (i = 0; i < 1000; i++) i++;
1649                 } 
1651                 /* Wait 2 second for DDR init */
1652                 mdelay(2000);
1654                 printk ("Write DMA to DSP ...\n");
1655                 do_gettimeofday(&test_time1);
1656                 HAL_writeDMA (wData, DDR_START, DMA_TRANSFER_SIZE, 1);   /* Move from GPP to DSP */ 
1657                 do_gettimeofday(&test_time2);
1659                 /* Note: From PCIE specification, legacy interrupts cannot be generated from RC and be passed downstream. 
1660                    The example below is just making use of the facility that RC can access EP side register to generate 
1661                    a generic interrupt on local (EP) side using one of the event inputs of Interrupt Controller (INTC). 
1662                    There is no real interrupt signal sent over the PCIe link */
1663                 printk ("Generating interrupt to DSP ...\n");
1664                 iowrite32(1, ptrReg + LEGACY_A_IRQ_STATUS_RAW/4); 
1666                 /* Waiting DSP ISR handler to process the interrupt from DSP and then generates an interrupt to host
1667                    Waiting for host ISR handler to process the interrupt from DSP before program exits */ 
1668                 mdelay(1000);
1670                 /* For demo how to move inside DSP purpose only, you can directly move between GPP and DSP using flag = 1 */
1671                 //      HAL_writeDMA (0x80000000, 0x11800000, 0x10000, 0);        
1672                 //      HAL_writeDMA (0x11800000, 0x0C000000, 0x10000, 0);
1674                 diff = (test_time2.tv_sec - test_time1.tv_sec)*1000000 + (test_time2.tv_usec - test_time1.tv_usec);
1675                 printk("DMA write throughput is: %d.%02d MB/s\n", DMA_TRANSFER_SIZE/(1024*1024)*1000*1000/diff, 
1676                                 ((DMA_TRANSFER_SIZE/(1024*1024)*1000*1000)%diff)*100/diff);
1678                 diff = (test_time4.tv_sec - test_time3.tv_sec)*1000000 + (test_time4.tv_usec - test_time3.tv_usec);
1679                 printk("DMA read throughput is: %d.%02d MB/s\n", DMA_TRANSFER_SIZE/(1024*1024)*1000*1000/diff, 
1680                                 ((DMA_TRANSFER_SIZE/(1024*1024)*1000*1000)%diff)*100/diff);
1682                 printk("Freeing consistent memory ...\n");
1683                 dma_free_coherent(&PCIE_DEV->dev, DMA_TRANSFER_SIZE, wDataVirt, wData);
1684                 dma_free_coherent(&PCIE_DEV->dev, DMA_TRANSFER_SIZE, rDataVirt, rData);
1685 #endif
1687 #if LOCAL_RESET
1688                 mdelay(10000);
1689                 dspLocalReset();
1690 #endif
1691         }
1692         else {
1693                 printk("No PCIE device found!!!\n");
1694         }
1695         return 0 ;
1698 /* ============================================================================
1699  *  @func   cleanup_module
1700  *
1701  *  @desc   Unregister a loadable module 
1702  *
1703  *  @modif  None.
1704  *  ============================================================================
1705  */
1707 void cleanup_module(void)
1710         if (PCIE_DEV != NULL) {
1711                 HAL_PciDisableDspInterrupt();
1712                 /* ---------------------------------------------------------------------
1713                  * Unmap baseRegs region & release the reg region.
1714                  * ---------------------------------------------------------------------
1715                  */
1716                 iounmap(regVirt);
1717                 if (pci_resource_flags(PCIE_DEV, 0) & IORESOURCE_MEM) {
1718                         /* Map the memory region. */
1719                         release_mem_region(regBase, regLen);
1720                 }
1721                 else {
1722                         /* Map the memory region. */
1723                         release_region(regBase, regLen);
1724                 }
1726                 /* ---------------------------------------------------------------------
1727                  * Unmap LL2 region & release the reg region.
1728                  * ---------------------------------------------------------------------
1729                  */
1730                 iounmap(memVirt);
1731                 if (pci_resource_flags(PCIE_DEV, 1) & IORESOURCE_MEM) {
1732                         /* Map the memory region. */
1733                         release_mem_region(memBase, memLen);
1734                 }
1735                 else {
1736                         /* Map the memory region. */
1737                         release_region(memBase, memLen);
1738                 }
1740                 /* ---------------------------------------------------------------------
1741                  * Unmap MSMC region & release the reg region.
1742                  * ---------------------------------------------------------------------
1743                  */
1744                 iounmap(msmcVirt);
1745                 if (pci_resource_flags(PCIE_DEV, 2) & IORESOURCE_MEM) {
1746                         /* Map the memory region. */
1747                         release_mem_region(msmcBase, msmcLen);
1748                 }
1749                 else {
1750                         /* Map the memory region. */
1751                         release_region(msmcBase, msmcLen);
1752                 }
1754                 /* ---------------------------------------------------------------------
1755                  * Unmap DDR region & release the reg region.
1756                  * ---------------------------------------------------------------------
1757                  */
1758                 iounmap(ddrVirt);
1759                 if (pci_resource_flags(PCIE_DEV, 3) & IORESOURCE_MEM) {
1760                         /* Map the memory region. */
1761                         release_mem_region(ddrBase, ddrLen);
1762                 }
1763                 else {
1764                         /* Map the memory region. */
1765                         release_region(ddrBase, ddrLen);
1766                 }
1768                 free_irq(irqNo, &dummy);
1769         }