This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem with uPP module on OMAP-L138

Other Parts Discussed in Thread: OMAP-L138, OMAPL138

Hi, everybody! i am working with omap-l138 recently! i have written an uPP driver under linux-2.6.33-rc4, which is used for sending data to  the external FPGA. So we use channel A only , and set it to be in transmition mode, single data rate and 8-bit width.  when the application called the uPP driver,  at first the uPP peripheral can transfer the data block correctly, but an internal bus error will occur very soon(the 2nd bit was set in UPISR). On our own board, the chip number is omapl138B, which means that its silicon version is 2.0. However, if I run the same driver on a demo board, on which the chip number is omapl138A(and it's silicon version is 1.1), then the uPP module will work properly.From both the datasheet and the user's guide of uPP module, i couldn't find more information about the error, except the following sentence " This event occurs when the uPP peripheral or its internal DMA controller encounters an internal bus error.
After encountering this error, the uPP peripheral should be reset to avoid further problem.
"(on P28 of uer's guide of uPP) .

I suspect that there mayabe some difference between the two silicon version, which causes the difference. Is there anyone can tell me more   about the error condition and what caused it? can you give me some suggestion on how to make the uPP module work as expected on omapl138B?  thansk a lot!

  • Xisheng, 

     

     

    xisheng liu said:
    I suspect that there mayabe some difference between the two silicon version, which causes the difference. Is there anyone can tell me more   about the error condition and what caused it? can you give me some suggestion on how to make the uPP module work as expected on omapl138B?

     

       You can find the differences between the silicon revisions in the OMAP-L138 Errata. Have you verified that the internal DMA can make the transfer sucessfully more than once?

     

     

  • Xisheng Liu,


    Can you share your uPP driver with us?  Are you planning to push the driver upstream?

    Todd

     

  • I'm also working on a Linux side UPP driver and getting failed transfers with reported bus errors (ERRI and ERRQ bits set in UPISR).  EOW and EOL bits are also set, and DMA start addresses (UPIS0 and UPQS0) appear to be increasing as expected, but receive buffer does not get updated with new data.  The driver is currently part of a user space application (file contents copied below), but will probably be converted to kernel module after initial transfer success.  The test setup is via external hardware loopback (tx on A, rx on B)- the same bus errors were observed trying to perform internal loopback test.  The UPP manual does not provide enough information on what may cause ERRI/Q bus errors.  Any information to aid troubleshooting would be greatly appreciated.

    Thanks.

     

    /*
     * upp.c
     */

    // OS Headers
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <time.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/mman.h>

    // Application Headers
    #include <gpp/Linux/upp.h>
    #include <gpp/Linux/pin_mux.h>
    #include <gpp/Linux/debug.h>
    #include <omap/omapl138_upp.h>
    #include <omap/omapl138_psc.h>
    #include <omap/omapl138_intc.h>

    #define INTERNAL_LOOPBACK_B2A    0
    #define PRINT_PINMUX            0

    #define UPP_BUF_SIZE    (4096*10)
    void *rx_buf, *tx_buf;
    //int rx_buf[UPP_BUF_SIZE], tx_buf[UPP_BUF_SIZE];

    static int upp_mmap_size, psc1_mmap_size, intc_mmap_size;
    static uintptr_t upp_base, psc1_base, intc_base;


    static int upp_mmap_init( void );
    static int upp_mmap_deinit( void );
    static int upp_pin_mux_init( void );
    static int upp_pwr_init( void );
    static int upp_clk_init( void );
    static int upp_reset( void );
    static int upp_reg_init( void );
    static int upp_dma_init( void );
    static int upp_intc_init( void );
    static int upp_buff_init( void );


    int upp_init( void )
    {
        upp_pin_mux_init();

        upp_mmap_init();

        //TODO - review
        // for some reason, this needs to be called twice to take effect
        upp_pwr_init();
        upp_pwr_init();

        upp_reg_init();

        upp_mmap_deinit();

        return 0;
    }


    static int upp_pin_mux_init( void )
    {

        pin_mux_set( 13, 0x44440000, 0xffff0000 );
        pin_mux_set( 14, 0x44444400, 0xffffff00 );
        pin_mux_set( 15, 0x44444444, 0xffffffff );
        pin_mux_set( 16, 0x44444444, 0xffffffff );
        pin_mux_set( 17, 0x44444444, 0xffffffff );
        pin_mux_set( 18, 0x00444444, 0x00ffffff );

    #if PRINT_PINMUX
        pin_mux_print();
    #endif

        return 0;
    }


    /*
     * see Power and Sleep Controller (PSC), Chapter 9 in Sys Ref Guide
     */
    static int upp_pwr_init( void )
    {
        int reg_stat;

        reg_stat = *(uint32_t *)(psc1_base + PSC_REVID);
    //    dbg_printf_fl("PSC1_REVID = 0x%08x\n", reg_stat);


        // wait for GOSTAT[0] in PSTAT to clear to 0
        while ( *(uint32_t *)(psc1_base + PSC_PTSTAT) & 0x00000001 )
            ;

        // set NEXT bit in MDCTL19 to Enable(3h)
        reg_stat = *(uint32_t *)(psc1_base + PSC1_MDCTL_OFFSET(19));
    //    dbg_printf_fl("PSC1_MDCTL19 = 0x%08x\n", PSC1_MDCTL_OFFSET(19));
    //    dbg_printf_fl("PSC1_MDCTL19 = 0x%08x\n", reg_stat);
        reg_stat &= 0xfffffffc;
        reg_stat |= 0x00000003;
        *(uint32_t *)(psc1_base + PSC1_MDCTL_OFFSET(19)) = reg_stat;
        reg_stat = *(uint32_t *)(psc1_base + PSC1_MDCTL_OFFSET(19));
    //    dbg_printf_fl("PSC1_MDCTL19 = 0x%08x\n", reg_stat);

        // set the GO[0] bit in PTCMD to 1 to initiate transition
        reg_stat = *(uint32_t *)(psc1_base + PSC_PTCMD);
        reg_stat &= 0xfffffffe;
        reg_stat |= 0x00000001;
        *(uint32_t *)(psc1_base + PSC_PTCMD) = reg_stat;

        // wait for GOSTAT[0] in PSTAT to clear to 0
        while ( *(uint32_t *)(psc1_base + PSC_PTSTAT) & 0x00000001 )
            ;

        return 0;
    }


    static int upp_clk_init( void )
    {

        return 0;
    }


    static int upp_reset( void )
    {

        return 0;
    }

    static int upp_reg_init( void )
    {
        int reg_stat;

        // wait for UPPID to become valid after enabling module in upp_pwr_init()
        dbg_printf_fl("\nChecking UPPID...\n");
        while ( *(uint32_t *)(upp_base + UPPID) != 0x44231100 )
            ;
        reg_stat = *(uint32_t *)(upp_base + UPPID);
        dbg_printf_fl("UPPID = 0x%08x\n", reg_stat);


        //==========================================================================
        // SWRST
        //==========================================================================
        dbg_printf_fl("\nPerforming SWRST...\n");

        // clear EN bit of UPPCR
        reg_stat = *(uint32_t *)(upp_base + UPPCR);
    //    reg_stat &= 0xfffffff7;
        reg_stat = 0x00000000;
        *(uint32_t *)(upp_base + UPPCR) = reg_stat;

        // poll DB bit of UPPCR to ensure DMA is idle
        while ( *(uint32_t *)(upp_base + UPPCR) & 0x00000000 )
            ;

        // assert SWRST bit (bit 4) of UPPCR
        reg_stat = *(uint32_t *)(upp_base + UPPCR);
        reg_stat &= 0xfffffff7;
        reg_stat |= 0x00000008;
        *(uint32_t *)(upp_base + UPPCR) = reg_stat;
        reg_stat = *(uint32_t *)(upp_base + UPPCR);

        // wait at least 200 clock cycles
        usleep( 100000 );

        // clear SWRST bit (bit 4) of UPPCR
        reg_stat &= 0xfffffff7;
        *(uint32_t *)(upp_base + UPPCR) = reg_stat;
        reg_stat = *(uint32_t *)(upp_base + UPPCR);

        *(uint32_t *)(upp_base + UPIER) = 0xffffffff;
        reg_stat = *(uint32_t *)(upp_base + UPIER);
        dbg_printf_fl("UPIER = 0x%08x\n", reg_stat);

        *(uint32_t *)(upp_base + UPEOI) = 0x00000000;
        reg_stat = *(uint32_t *)(upp_base + UPEOI);
        dbg_printf_fl("UPEOI = 0x%08x\n", reg_stat);

        reg_stat = *(uint32_t *)(upp_base + UPPCR);
        dbg_printf_fl("UPPCR = 0x%08x\n", reg_stat);


        //==========================================================================
        // Program UPP Config Reg's
        //==========================================================================
        //TODO - work out with Doug use of Wait/Enable/Start signals
        dbg_printf_fl("\nProgramming UPP config reg's...\n");

        //--------------------------------------------------------------------------
        // UPPCTL - tx/rx selection, data width, data format, data rate,
        //            data interleave enable
        //--------------------------------------------------------------------------
        // 0000 0001 0000 00010 0000 0000 0000 0111
         *(uint32_t *)(upp_base + UPCTL) = 0x01020007;
        reg_stat = *(uint32_t *)(upp_base + UPCTL);
        dbg_printf_fl("UPCTL = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPPICR - signal enable, signal inversion, clk div (tx only)
        //--------------------------------------------------------------------------
        // 0010 0000 0011 1000 0010 0000 0011 1000
        // 0010 1000 0011 1000 0010 1000 0011 1000
        // 0010 1000 0001 0000 0010 1000 0001 0000
        *(uint32_t *)(upp_base + UPICR) = 0x28102810;
        reg_stat = *(uint32_t *)(upp_base + UPICR);
        dbg_printf_fl("UPICR = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPPIVR - idle value (tx only)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPIVR) = 0x00000000;
        reg_stat = *(uint32_t *)(upp_base + UPIVR);
        dbg_printf_fl("UPIVR = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPPTCR - i/o tx thresh (tx only), dma read burst size
        //--------------------------------------------------------------------------
        // 0000 0011 0000 0011 0000 0011 0000 0011
    //     *(uint32_t *)(upp_base + UPTCR) = 0x03030303;
         *(uint32_t *)(upp_base + UPTCR) = 0x00000000;
        reg_stat = *(uint32_t *)(upp_base + UPTCR);
        dbg_printf_fl("UPTCR = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPPDLB - digital loopback
        //--------------------------------------------------------------------------
        // 0000 0000 0000 0000 0001 0000 0000 0000
    #if INTERNAL_LOOPBACK_B2A
         *(uint32_t *)(upp_base + UPDLB) = 0x00001000;
    #else
         *(uint32_t *)(upp_base + UPDLB) = 0x00000000;
    #endif
        reg_stat = *(uint32_t *)(upp_base + UPDLB);
        dbg_printf_fl("UPDLB = 0x%08x\n", reg_stat);


        //==========================================================================
        // Program UPP Interrupt Event
        //==========================================================================
        dbg_printf_fl("\nProgramming UPP Interrupt Event...\n");

        //--------------------------------------------------------------------------
        // UPIEC
        //--------------------------------------------------------------------------
        *(uint32_t *)(upp_base + UPIEC) = 0xffffffff;
        reg_stat = *(uint32_t *)(upp_base + UPIEC);
        dbg_printf_fl("UPIEC = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPIES
        //--------------------------------------------------------------------------
        // 0000 0000 0000 0000 0000 1111 0000 1111
    //     *(uint32_t *)(upp_base + UPIES) = 0x00000f0f;
         *(uint32_t *)(upp_base + UPIES) = 0x0000000f;
        reg_stat = *(uint32_t *)(upp_base + UPIES);
        dbg_printf_fl("UPIES = 0x%08x\n", reg_stat);

        reg_stat = *(uint32_t *)(upp_base + UPISR);
        dbg_printf_fl("UPISR = 0x%08x\n", reg_stat);

        // register ISR
    //    upp_intc_init();


        //--------------------------------------------------------------------------
        // Enable UPP
        //--------------------------------------------------------------------------
        dbg_printf_fl("\nEnabling UPP...\n");

        // set EN bit in UPPCR
        reg_stat = *(uint32_t *)(upp_base + UPPCR);
        reg_stat &= 0xfffffff7;
        reg_stat |= 0x00000008;
        *(uint32_t *)(upp_base + UPPCR) = reg_stat;
        dbg_printf_fl("UPPCR = 0x%08x\n", reg_stat);


        //--------------------------------------------------------------------------
        // allocate/init buffers
        //--------------------------------------------------------------------------
        dbg_printf_fl("\nInitializing UPP buffers...\n");
        upp_buff_init();


        //==========================================================================
        // Program DMA channel desc. reg's
        //   - UPID0-2 and/or UPQD0-2.
        //==========================================================================
            // UPIS0
            *(uint32_t *)(upp_base + UPIS0) = 0x00;
            reg_stat = *(uint32_t *)(upp_base + UPIS0);
            dbg_printf_fl("UPIS0 = 0x%08x\n", reg_stat);

            // UPIS1
            *(uint32_t *)(upp_base + UPIS1) = 0x00;
            reg_stat = *(uint32_t *)(upp_base + UPIS1);
            dbg_printf_fl("UPIS1 = 0x%08x\n", reg_stat);

            // UPIS2
            *(uint32_t *)(upp_base + UPIS2) = 0x00;
            reg_stat = *(uint32_t *)(upp_base + UPIS2);
            dbg_printf_fl("UPIS2 = 0x%08x\n", reg_stat);

            // UPQS0
            *(uint32_t *)(upp_base + UPQS0) = 0x00;
            reg_stat = *(uint32_t *)(upp_base + UPQS0);
            dbg_printf_fl("UPQS0 = 0x%08x\n", reg_stat);

            // UPQS1
            *(uint32_t *)(upp_base + UPQS1) = 0x00;
            reg_stat = *(uint32_t *)(upp_base + UPQS1);
            dbg_printf_fl("UPQS1 = 0x%08x\n", reg_stat);

            // UPQS2
            *(uint32_t *)(upp_base + UPQS2) = 0x00;
            reg_stat = *(uint32_t *)(upp_base + UPQS2);
            dbg_printf_fl("UPQS2 = 0x%08x\n", reg_stat);
        dbg_printf_fl("\nProgramming DMA channel desc. reg's...\n");

        //--------------------------------------------------------------------------
        // UPID0 - Channel A (Rx)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPID0) = rx_buf;
        reg_stat = *(uint32_t *)(upp_base + UPID0);
        dbg_printf_fl("UPID0 = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPID1 - Channel A (Rx)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPID1) = (0x4 << 16 | 0x400);
        reg_stat = *(uint32_t *)(upp_base + UPID1);
        dbg_printf_fl("UPID1 = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPID2 - Channel A (Rx)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPID2) = 0x00000400;
        reg_stat = *(uint32_t *)(upp_base + UPID2);
        dbg_printf_fl("UPID2 = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPQD0 - Channel B (Tx)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPQD0) = tx_buf;
        reg_stat = *(uint32_t *)(upp_base + UPQD0);
        dbg_printf_fl("UPQD0 = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPQD1 - Channel B (Tx)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPQD1) = (0x4 << 16 | 0x400);
        reg_stat = *(uint32_t *)(upp_base + UPQD1);
        dbg_printf_fl("UPQD1 = 0x%08x\n", reg_stat);

        //--------------------------------------------------------------------------
        // UPQD2 - Channel B (Tx)
        //--------------------------------------------------------------------------
         *(uint32_t *)(upp_base + UPQD2) = 0x00000400;
        reg_stat = *(uint32_t *)(upp_base + UPQD2);
        dbg_printf_fl("UPQD2 = 0x%08x\n", reg_stat);


        //==========================================================================
        // watch for interrupts...
        //==========================================================================
        dbg_printf_fl("\nWaiting for UPP INT...\n");
        while ( !(*(uint32_t *)(upp_base + UPIER)) && !(*(uint32_t *)(upp_base + UPISR)) )
            ;
        reg_stat = *(uint32_t *)(upp_base + UPIER);
        dbg_printf_fl("UPIER = 0x%08x\n", reg_stat);
        reg_stat = *(uint32_t *)(upp_base + UPISR);
        dbg_printf_fl("UPISR = 0x%08x\n", reg_stat);

    //    sleep(1);

        int i = 0;
        dbg_printf_fl("\nRx Buf:\n");
    //    for ( i = 0; i < UPP_BUF_SIZE; i+=4 )
        {
            dbg_printf_fl("0x%08x ", *(int *)(rx_buf + i));
            dbg_printf_fl("0x%08x ", *(int *)(rx_buf + 4));
            dbg_printf_fl("0x%08x ", *(int *)(rx_buf + 8));
            dbg_printf_fl("0x%08x ", *(int *)(rx_buf + 12));
        }
        dbg_printf_fl("\nTx Buf:\n");
        dbg_printf_fl("0x%08x ", *(int *)(tx_buf + i));
        dbg_printf_fl("0x%08x ", *(int *)(tx_buf + 4));
        dbg_printf_fl("0x%08x ", *(int *)(tx_buf + 8));
        dbg_printf_fl("0x%08x ", *(int *)(tx_buf + 12));
        dbg_printf_fl("\n");

        // UPPCR
        reg_stat = *(uint32_t *)(upp_base + UPPCR);
        dbg_printf_fl("UPPCR = 0x%08x\n", reg_stat);

        // UPIS0
        reg_stat = *(uint32_t *)(upp_base + UPIS0);
        dbg_printf_fl("UPIS0 = 0x%08x\n", reg_stat);

        // UPIS1
        reg_stat = *(uint32_t *)(upp_base + UPIS1);
        dbg_printf_fl("UPIS1 = 0x%08x\n", reg_stat);

        // UPIS2
        reg_stat = *(uint32_t *)(upp_base + UPIS2);
        dbg_printf_fl("UPIS2 = 0x%08x\n", reg_stat);

        // UPQS0
        reg_stat = *(uint32_t *)(upp_base + UPQS0);
        dbg_printf_fl("UPQS0 = 0x%08x\n", reg_stat);

        // UPQS1
        reg_stat = *(uint32_t *)(upp_base + UPQS1);
        dbg_printf_fl("UPQS1 = 0x%08x\n", reg_stat);

        // UPQS2
        reg_stat = *(uint32_t *)(upp_base + UPQS2);
        dbg_printf_fl("UPQS2 = 0x%08x\n", reg_stat);

        return 0;
    }


    static int upp_buff_init( void )
    {
        int ret;
        int ps = getpagesize();

        if ( (ret = posix_memalign( &rx_buf, ps, UPP_BUF_SIZE) ) ) {
            perror("Memalign failed");
            return -1;
        }

        if ( (ret = posix_memalign( &tx_buf, ps, UPP_BUF_SIZE) ) ) {
            perror("Memalign failed");
            return -1;
        }

        memset( (void *)tx_buf, 0xab, UPP_BUF_SIZE );
        memset( (void *)rx_buf, 0x00, UPP_BUF_SIZE );

        dbg_printf_fl("Tx buf addr = 0x%08x (0x%08x)\n", (void *)tx_buf, *(int *)tx_buf);
        dbg_printf_fl("Rx buf addr = 0x%08x (0x%08x)\n", (void *)rx_buf, *(int *)rx_buf);


        return 0;
    }

    static int upp_dma_init( void )
    {

        return 0;
    }

    static int upp_intc_init( void )
    {
        int reg_stat;

        reg_stat = *(uint32_t *)(intc_base + INTC_REVID);
        dbg_printf_fl("INTC_REVID = 0x%08x\n", reg_stat);

        reg_stat = *(uint32_t *)(intc_base + INTC_GER);
        dbg_printf_fl("INTC_GER = 0x%08x\n", reg_stat);

        reg_stat = *(uint32_t *)(intc_base + INTC_HIER);
        dbg_printf_fl("INTC_HIER = 0x%08x\n", reg_stat);

        return 0;
    }


    /*
     * see Section 2.6 of uPP User's Guide
     */
    static int upp_mmap_init( void )
    {
        int mem_fd;
        int reg_stat;

        mem_fd = open("/dev/mem", O_RDWR);
        if ( mem_fd < 0 ) {
            dbg_printf_fl("failed to open /dev/mem");
            return mem_fd;
        }

        // UPP Reg Base
        upp_mmap_size = getpagesize();
        upp_base = (uintptr_t)mmap( 0, upp_mmap_size, PROT_READ|PROT_WRITE,
                                         MAP_SHARED, mem_fd, UPP_BASE_ADDR );
        if ( upp_base == (uintptr_t)MAP_FAILED ) {
            perror("mmap failed");
            dbg_printf_fl("\n\nupp_base mmap fail!\n\n");
            return -1;
        }

        // PSC1
        psc1_mmap_size = getpagesize();
        psc1_base = (uintptr_t)mmap( 0, psc1_mmap_size, PROT_READ|PROT_WRITE,
                                         MAP_SHARED, mem_fd, PSC1_BASE_ADDR );
        if ( psc1_base == (uintptr_t)MAP_FAILED ) {
            perror("mmap failed");
            dbg_printf_fl("\n\npsc1_base mmap fail!\n\n");
            return -1;
        }

        // INTC
        intc_mmap_size = getpagesize() * 2;
        intc_base = (uintptr_t)mmap( 0, intc_mmap_size, PROT_READ|PROT_WRITE,
                                         MAP_SHARED, mem_fd, INTC_BASE_ADDR );
        if ( intc_base == (uintptr_t)MAP_FAILED ) {
            perror("mmap failed");
            dbg_printf_fl("\n\nintc_base mmap fail!\n\n");
            return -1;
        }


        close( mem_fd );


        return 0;
    }

    static int upp_mmap_deinit( void )
    {
        if ( munmap( (void *)upp_base, upp_mmap_size ) == -1 ) {
            dbg_printf_fl("\n%s(%d) - munmap fail!\n", __FUNCTION__, __LINE__);
            return -1;
        }

        if ( munmap( (void *)psc1_base, psc1_mmap_size ) == -1 ) {
            dbg_printf_fl("\n%s(%d) - munmap fail!\n", __FUNCTION__, __LINE__);
            return -1;
        }

        if ( munmap( (void *)intc_base, intc_mmap_size ) == -1 ) {
            dbg_printf_fl("\n%s(%d) - munmap fail!\n", __FUNCTION__, __LINE__);
            return -1;
        }


        return 0;
    }


  • Rick Rogers,

                  hi!I found that the bus error problem of upp communication was in connection with the frequency of upp module clock and cpu clock. In our previous setting, CPU was running at 300MHz, but the DDR and uPP module were running at 110MHz, and the bus error occurred after transmiting a few data.  However after we set DDR and uPP moulde clock to be 150MHz(CPU clock is still 300M), the bus error problem never occured. So I suggest that you should check your clock settings of different modules, and hope it will help. (PS: you should notice that the init code of linux2.6.33.rc4( from TI's dvsdk) will move upp's clk source from PLL0 to PLL1, so it has the same clk frequency with DDR module)

  • Hi Rick Rogers.

    I am also trying to write an UPP driver for the OMAPL138 and I have the same problem as you. Have you found a solution for this problem????

    As xisheng liu suggests, I verify my UPP transmit input clock (PLL1_SYSCLK2) : this clock is at 150MHz.

    Best regards

    Armand  

  • Armand,

    Yes, I was able to solve the issue I was having.  As it turned out, it didn't appear to have anything to do with PLL configuration (2.6.33-rc4).  I think my main problem was improper reset of the UPP peripheral, as well as improper sequence for reloading dma parameters.  The functions below provide a consolidated example of how I got successful UPP transfers (there are some blanks to fill in, but hopefully it helps a little).  This of course assumes that the peripheral has been enabled via PSC1 and the pinmux's have been configured via SYSCFG.

    -Rick


    int upp_periph_config( upp_dev_t *dev )
    {
        //==========================================================================
        // Peripheral config
        //==========================================================================

        // SW Reset
        upp_swrst();

        // Control Reg's
        upp_ctl_config( dev );

        // IER
        upp_ier_config( dev );

        // Enable UPP
        upp_enable();

        // DMA params (size, src, dst)
        upp_rxdma_reload( dev );

        return 0;
    }


    static int upp_swrst( void )
    {
        int32_t reg_val;
        int32_t i;

        //--------------------------------------------------------------------------
        // SWRST
        //--------------------------------------------------------------------------
        dbg_printk(ID_STR "Performing SWRST...\n");

        // clear EN bit of UPPCR
        reg_val = ioread32( (void *)(upp_base + UPPCR) );
        reg_val &= 0xfffffff7;
        iowrite32( reg_val, (void *)(upp_base + UPPCR) );

        // poll DB bit of UPPCR to ensure DMA is idle
        while ( ioread32( (void *)(upp_base + UPPCR) ) & 0x00000080 )
            ;

        // assert SWRST bit (bit 4) of UPPCR
        reg_val = ioread32( (void *)(upp_base + UPPCR) );
        reg_val &= 0xffffffef;
        reg_val |= 0x00000010;
        iowrite32( reg_val, (void *)(upp_base + UPPCR) );

        // wait at least 200 clock cycles
        mdelay( 200 );  // abitrary choice of 200ms

        // clear SWRST bit (bit 4) of UPPCR
        reg_val = ioread32( (void *)(upp_base + UPPCR) );
        reg_val &= 0xffffffef;
        iowrite32( reg_val, (void *)(upp_base + UPPCR) );

        return 0;
    }


    static int upp_enable( void )
    {
        int32_t reg_val;

        //--------------------------------------------------------------------------
        // Enable UPP
        //--------------------------------------------------------------------------
        dbg_printk( ID_STR "Enabling UPP...\n");

        // set EN bit in UPPCR
        reg_val = ioread32( (void *)(upp_base + UPPCR) );
        reg_val &= 0xfffffff7;
        reg_val |= 0x00000008;
        iowrite32( reg_val, (void *)(upp_base + UPPCR) );
        dbg_printk( ID_STR "UPPCR = 0x%08x\n", reg_val);

        mdelay( 200 );

        return 0;
    }


    static int upp_ctl_config( upp_dev_t *dev )
    {
        int32_t reg_val;

        //==========================================================================
        // Program UPP Config Reg's
        //==========================================================================
        dbg_printk( ID_STR "Programming UPP config reg's...\n");

        //--------------------------------------------------------------------------
        // UPPCTL - tx/rx selection, data width, data format, data rate,
        //            data interleave enable
        //--------------------------------------------------------------------------
        iowrite32( 0x02020007, (void *)(upp_base + UPCTL) );
        reg_val = ioread32( (void *)(upp_base + UPCTL) );
        dbg_printk( ID_STR "UPCTL = 0x%08x\n", reg_val);

        //--------------------------------------------------------------------------
        // UPPICR - signal enable, signal inversion, clk div (tx only)
        //--------------------------------------------------------------------------
        iowrite32( 0x00100010, (void *)(upp_base + UPICR) );
        reg_val = ioread32( (void *)(upp_base + UPICR) );
        dbg_printk( ID_STR "UPICR = 0x%08x\n", reg_val);

        //--------------------------------------------------------------------------
        // UPPIVR - idle value (tx only)
        //--------------------------------------------------------------------------
        iowrite32( 0x5b5b5a5a, (void *)(upp_base + UPIVR) );
        reg_val = ioread32( (void *)(upp_base + UPIVR) );
        dbg_printk( ID_STR "UPIVR = 0x%08x\n", reg_val);

        //--------------------------------------------------------------------------
        // UPPTCR - i/o tx thresh (tx only), dma read burst size
        //--------------------------------------------------------------------------
        iowrite32( 0x03030303, (void *)(upp_base + UPTCR) );
        reg_val = ioread32( (void *)(upp_base + UPTCR) );
        dbg_printk( ID_STR "UPTCR = 0x%08x\n", reg_val);

        //--------------------------------------------------------------------------
        // UPPDLB - digital loopback
        //--------------------------------------------------------------------------
        if ( UPP_CFG_DOLOOPBACK )
        {
            iowrite32( 0x00001000, (void *)(upp_base + UPDLB) );
        }
        else
        {
            iowrite32( 0x00000000, (void *)(upp_base + UPDLB) );
        }
        reg_val = ioread32( (void *)(upp_base + UPDLB) );
        dbg_printk( ID_STR "UPDLB = 0x%08x\n", reg_val);

        return 0;
    }


    static int upp_rxdma_config( upp_dev_t *dev )
    {
        //TODO - add check for dma pend bit?


        //==========================================================================
        // Program DMA channel desc. reg's
        //   - UPID0-2 and/or UPQD0-2.
        //==========================================================================

        //--------------------------------------------------------------------------
        // UPQD0 - Channel B (Rx)
        //--------------------------------------------------------------------------
        iowrite32( rx_start_addr, (void *)(upp_base + UPQD0) );
        dbg_printk( ID_STR "UPQD0 = 0x%08x\n", *(int32_t *)(upp_base + UPQD0));

        //--------------------------------------------------------------------------
        // UPQD1 - Channel B (Rx)
        //--------------------------------------------------------------------------
        iowrite32( (rxdma_line_count << 16 | rxdma->line_size),
                (void *)(upp_base + UPQD1) );
        dbg_printk( ID_STR "UPQD1 = 0x%08x\n", *(int32_t *)(upp_base + UPQD1));

        //--------------------------------------------------------------------------
        // UPQD2 - Channel B (Rx)
        //--------------------------------------------------------------------------
        iowrite32( rxdma_line_size, (void *)(upp_base + UPQD2) );
        dbg_printk( ID_STR "UPQD2 = 0x%08x\n", *(int32_t *)(upp_base + UPQD2));


        return 0;
    }


    static int upp_txdma_config( upp_dev_t *dev )
    {
        int32_t reg_val;

        // wait for dma active/pending bits to clear
        while ( ioread32( upp_base + UPIS2 ) & 0x00000002 )
            ;


        //==========================================================================
        // Program DMA channel desc. reg's
        //   - UPID0-2 and/or UPQD0-2.
        //==========================================================================

        //--------------------------------------------------------------------------
        // UPID0 - Channel A (Tx)
        //--------------------------------------------------------------------------
        iowrite32( tx_start_addr, (void *)(upp_base + UPID0) );
        dbg_printk( ID_STR "UPID0 = 0x%08x\n", *(int32_t *)(upp_base + UPID0));

        //--------------------------------------------------------------------------
        // UPID1 - Channel A (Tx)
        //--------------------------------------------------------------------------
        iowrite32( (txdma_line_count << 16 | txdma->line_size),
                (void *)(upp_base + UPID1) );
        dbg_printk( ID_STR "UPID1 = 0x%08x\n", *(int32t *)(upp_base + UPID1));

        //--------------------------------------------------------------------------
        // UPID2 - Channel A (Tx)
        //--------------------------------------------------------------------------
        iowrite32( txdma_line_size, (void *)(upp_base + UPID2) );
        dbg_printk( ID_STR "UPID2 = 0x%08x\n", *(int32_t *)(upp_base + UPID2));


        return 0;
    }


    static int upp_ier_config( upp_dev_t *dev )
    {
        int32_t reg_val;
        int32_t status;

        //==========================================================================
        // Program UPP Interrupt Event
        //==========================================================================
        dbg_printk( ID_STR "Programming UPP Interrupt Event...\n");

        //--------------------------------------------------------------------------
        // UPIEC
        //--------------------------------------------------------------------------
        // clear all interrupt triggers
        iowrite32( 0xffffffff, (void *)(upp_base + UPIEC) );
        reg_val = ioread32( (void *)(upp_base + UPIEC) );
        dbg_printk( ID_STR "UPIEC = 0x%08x\n", reg_val);

        // clear ier
        iowrite32( 0xffffffff, upp_base +  UPIER );
        reg_val = ioread32( (void *)(upp_base + UPIER) );
        dbg_printk( ID_STR "UPIER = 0x%08x\n", reg_val);

        // register ISR
        status = request_irq( UPP_INTERRUPT, upp_rx_handler, 0, "upp_combined", dev );
        if( status < 0 ) {
            printk( ID_STR "error %d requesting UPP IRQ %d\n", status,
                    UPP_INTERRUPT);
            return status;
        }

        // clear interrupts
        iowrite32( 0x00000000, (void *)(upp_base + UPEOI) );
        reg_val = ioread32( (void *)(upp_base + UPEOI) );
        dbg_printk( ID_STR "UPEOI = 0x%08x\n", reg_val);


        return 0;
    }


    int upp_rxdma_reload( upp_dev_t *dev )
    {
        // wait for dma active/pending bits to clear
        while ( ioread32( upp_base + UPQS2 ) & 0x00000002 )
            ;


        //--------------------------------------------------------------------------
        // reset interrupt enables
        //--------------------------------------------------------------------------

        // clear all enables
        iowrite32( 0x00001f1f, (void *)(upp_base + UPIEC) );

        // set desired interrupts
        iowrite32( 0x00000f00, (void *)(upp_base + UPIES) );

        //--------------------------------------------------------------------------
        // reload dma params
        //--------------------------------------------------------------------------
        upp_rxdma_config( dev );

        return 0;
    }



  • Have you ever deal with this problem? recently i also have to write the driver of upp in the uboot side,it's used to test upp.I have just finished the initial progress of the upp,but don't know how to start a upp transfer. Do we have to initial the EDMA? if have to,how can we initial it ?

  • void do_upp_test (cmd_tbl_t *cmdtp, int argc, char *argv[])

    {

    //    psc_init();

    // clocks_init();

     

    syscfg_kick_unlock();

     

    //set upp clock source,use PLL1_SYSCLK2 //600/2/2 = 150M

    SETBIT(SYSCFG_0_CFGCHIP3_ADDR, ASYNC3_CLKSRC);

    CLRBIT(SYSCFG_0_CFGCHIP3_ADDR, UPP_TX_CLKSRC);

    syscfg_kick_lock(); 

    upp_pinmux_init();

    emif_init();

    edma_init();

    upp_init();

    upp_test();

    }

    void upp_tx(unsigned int * pSrc,unsigned short uByteNum)
    {      
    UPP_UPID0_ADDR = (UINT32)pSrc; // DMA channel I, 64bit alignment
    UPP_UPID1_ADDR = (0x0001 << 16) | uByteNum; // line count in MSB16; Byte count in LSB16, 16bit alignment
    UPP_UPID2_ADDR = uByteNum;
    }
    if this upp_tx() program can work ?