MPC5200B SPI PSC3 Problem

John Rigby jcrigby at gmail.com
Fri Jun 9 02:04:52 EST 2006


There seems to be a conflict between two sections of the 5200 User manual.
In section 7.3 where port_config is documented the PSC3 configuration
bits (20:23)
defined as:

0000 = All PSC3 pins are GPIOs
0001 = USB2 on PSC3, no GPIOs available, see Note 3
001X = Reserved
0100 = UART functionality without CD
0101 = UARTe functionality with CD
0110 = CODEC3 functionality
0111 = CODEC3 functionality (with MCLK)
100X = SPI
101X = Reserved
1100 = SPI with UART3
1101 = SPI with UART3e
111X = SPI with CODEC3

but in the psc chapter in table 15-85 it says to set port config to
0x00000600 but
the description says "Select the Pin-Muxing for PSC3 Codec mode"

It appears that table 15-85 is wrong.

I have attached some spi code that is embedded in a touchscreen
driver.  It might be helpful.





On 6/7/06, Trueskew <trueskew at gmail.com> wrote:
>
>
> We have an AIC26 codec connected to our Lite5200B platform via J21.  I've
> used MPC5200BUG to configure PSC3 as an SPI master, along with some samples
> I've found online (including here) and some I received from Freescale.
> Although the transfers seem to be working as expected (please see the output
> file at the end of this message), I get only 0xffff back.  This occurs
> whether or not the device is attached to J21.  A scope shows that PSC3_8
> (SPI_SS) and PSC3_9 (SPI_CLK) are low at all times, and I'm concerned I'm
> still doing something wrong with respect to enabling SPI over PSC3.
>
> I'm including my driver initialization code, my write code, and output
> showing the write behavior.  If someone could comment on it, I would greatly
> appreciate it... or if someone flat out has code to do this, I'd be happy to
> take it from you.  I've seen a few variations, but whether I use them
> directly or modify them as I need to, I can't seem to get past this.  Of
> course, any other suggestions are welcome.
>
> Thanks.
> Sal
>
> ---------------------------------------------------------------------------
> Initialization Code
> ---------------------------------------------------------------------------
> #define GPIO_PSC3_PORT_CONFIG_MASK 0x00000f00
> #ifdef SPI_USE_MCLK
>    #define      GPIO_PSC3_PORT_CONFIG 0x00000700  /* PSC3 mode with mclk */
> #else  /* SPI_USE_MCLK */
>    #define      GPIO_PSC3_PORT_CONFIG 0x00000600  /* PSC3 mode */
> #endif /* SPI_USE_MCLK */
>
> #define       CDM_PSC3_MCLK_ENABLE 0x00000080
> #define       CDM_PSC3_MCLK_CONFIG 0x8020      /* Divide Fvco ftom 528 to
>                                                   16Mhz */
>
> #define        PSC3_SICR_REG_VALUE 0x0280f000  /* 16-bit select Codec SPI
>                                                   master
> mode, msb first,
>                                                   UseEOF=1.
> GenClk=1, SIM,
>                                                   CPOL and
> CPHA are
>                                                   function
> input */
> ...
>    /* Select the Pin-Muxing for PSC3 Codec mode */
>    gpio = (struct mpc52xx_gpio *) ioremap(MPC52xx_GPIO,
>      sizeof(struct mpc52xx_gpio));
>    if(gpio)
>    {
>       port_config = gpio->port_config;
>       port_config &= ~GPIO_PSC3_PORT_CONFIG_MASK;
>       port_config |= GPIO_PSC3_PORT_CONFIG;
>       gpio->port_config = port_config;
>       iounmap(gpio);
>    }
>    else
>    {
>       return(-1);
>    }
>
> #ifdef SPI_USE_MCLK
>    /* PSC clock enable */
>    g_pCDM->clk_enables |= CDM_PSC3_MCLK_ENABLE;
>    g_pCDM->mclken_div_psc3 = CDM_PSC3_MCLK_CONFIG;
> #endif /* SPI_USE_MCLK */
>
>    /* Disable rx and tx */
>    g_pPSC->command = MPC52xx_PSC_RST_RX;
>    g_pPSC->command = MPC52xx_PSC_RST_TX;
>    g_pPSC->command = MPC52xx_PSC_SEL_MODE_REG_1;
>    g_pPSC->command = MPC52xx_PSC_RST_ERR_STAT;
>    g_pPSC->command = MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_DISABLE;
>
>    g_pPSC->mode = 0;
>    g_pPSC->sicr = PSC3_SICR_REG_VALUE;
>
>    #ifdef SPI_USE_MCLK
>    g_pPSC->ccr=0x0703;       /* set SCK and DSCKL delay */
>    #else  /* SPI_USE_MCLK */
>    g_pPSC->ccr=0x0003;       /* set SCK and DSCKL delay must be > 2 */
>    #endif /* SPI_USE_MCLK */
>
>    g_pPSC->ctur=0x00;        /* Set DTL delay 2us */
>    g_pPSC->ctlr=0x84;
>
>    g_pPSC->rfalarm=100;      /* Alarm values taken from SPI example sample
> */
>    g_pPSC->tfalarm=1;
>
>    g_pPSC->rfcntl &= 0xf8;       /* 0 byte granularity */
>    g_pPSC->tfcntl = 1;
>
>    /* Enable rx & tx */
>    g_pPSC->command = MPC52xx_PSC_RST_RX;
>    g_pPSC->command = MPC52xx_PSC_RST_TX;
>    g_pPSC->command = MPC52xx_PSC_SEL_MODE_REG_1;
>    g_pPSC->command = MPC52xx_PSC_RST_ERR_STAT;
>    g_pPSC->command = MPC52xx_PSC_RX_ENABLE | MPC52xx_PSC_TX_ENABLE;
>
> ---------------------------------------------------------------------------
> Write code
> ---------------------------------------------------------------------------
> static int mpc52xx_spi_transfer(u16 *p_usBuffer, u16 p_usCount)
> {
>    u16 usIndex, usTemp;
>
>
> printk("------------------------------------------------------\n");
>    printk("Entry:         psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>      g_pPSC->tfnum, g_pPSC->rfnum);
>    g_pPSC->command = MPC52xx_PSC_RST_RX;
>    g_pPSC->command = MPC52xx_PSC_RST_TX;
>    g_pPSC->command = MPC52xx_PSC_SEL_MODE_REG_1;
>    g_pPSC->command = MPC52xx_PSC_RST_ERR_STAT;
>    g_pPSC->command = MPC52xx_PSC_RX_ENABLE | MPC52xx_PSC_TX_ENABLE;
>    printk("TX-RX Enable:  psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>      g_pPSC->tfnum, g_pPSC->rfnum);
>
>    /* Clean out the read FIFO */
>    usIndex = 0;
>    while(g_pPSC->mpc52xx_psc_status & MPC52xx_PSC_SR_RXRDY)
>    {
>       usTemp = g_pPSC->mpc52xx_psc_buffer_16;
>       printk("Flushing Rx FIFO: psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>         g_pPSC->tfnum, g_pPSC->rfnum);
>       udelay(100000);
>       udelay(100000);
>       udelay(100000);
>       udelay(100000);
>       udelay(100000);
>       usIndex++;
>       if(usIndex == 10) return(-1);
>    }
>
>    /* Send out the buffer */
>    g_pPSC->command = MPC52xx_PSC_RX_ENABLE | MPC52xx_PSC_TX_DISABLE;
>    for(usIndex=0; usIndex<p_usCount; usIndex++)
>    {
>       printk("Sending %04x:  psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>         p_usBuffer[usIndex],
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>         g_pPSC->tfnum, g_pPSC->rfnum);
>       g_pPSC->mpc52xx_psc_buffer_16 = p_usBuffer[usIndex];
>       printk("Sent:          psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>         g_pPSC->tfnum, g_pPSC->rfnum);
>    }
>    g_pPSC->command = MPC52xx_PSC_RX_ENABLE | MPC52xx_PSC_TX_ENABLE;
>    usTemp = 0;
>    while(g_pPSC->tfnum)
>    {
>       printk("TFNUM Wait:   psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>         g_pPSC->tfnum, g_pPSC->rfnum);
>       udelay(100000);
>       udelay(100000);
>       udelay(100000);
>       udelay(100000);
>       udelay(100000);
>       usTemp++;
>       if(usTemp == 10) return(-1);
>    };
>    printk("TxRDY:         psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>      g_pPSC->tfnum, g_pPSC->rfnum);
>    for(usIndex=0; usIndex<p_usCount; usIndex++)
>    {
>       usTemp = 0;
>       while(!(g_pPSC->mpc52xx_psc_status &
> MPC52xx_PSC_SR_RXRDY))
>       {
>          printk("RxRDY Wait:    psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>            g_pPSC->tfnum, g_pPSC->rfnum);
>          udelay(100000);
>          udelay(100000);
>          udelay(100000);
>          udelay(100000);
>          udelay(100000);
>          usTemp++;
>          if(usTemp == 10) return(-1);
>       };
>       printk("RxRDY:         psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>         g_pPSC->tfnum, g_pPSC->rfnum);
>       p_usBuffer[usIndex] = g_pPSC->mpc52xx_psc_buffer_16;
>       printk("  Received %04x\n", p_usBuffer[usIndex]);
>    }
>
>    printk("EXIT:          psc=%x status=%04x tfstat=%04x rfstat=%04x
> mode=%02x\n   tfnum %3d  rfnum %3d\n",
>
> (int)g_pPSC,g_pPSC->mpc52xx_psc_status,g_pPSC->tfstat,g_pPSC->tfstat,g_pPSC->mode,
>      g_pPSC->tfnum, g_pPSC->rfnum);
>    return(usIndex);
> }
>
>
> ---------------------------------------------------------------------------
> Output
> ---------------------------------------------------------------------------
> The lines below are a capture of register settings from my driver,
> along with output lines when trying to write 16 bit words to our
> device.  This output is consistent whether the device is connected
> or not (via J21).  Basic operation, delimited by "------...---":
>
>   - Disable TX, Enable RX (despite the "TX-RX Enable" heading)
>   - Send word 1
>   - Send word 2
>   - Enable TX, Enable RX
>   - Wait for tfnum == 0
>   - Receive data
>
> port_config=91051624 sicr=0280f000 clk_enables=00ffffff div_psc3=800f
> ------------------------------------------------------
> Entry:         psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=33
>    tfnum   0  rfnum   0
> TX-RX Enable:  psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=33
>    tfnum   0  rfnum   0
> Sending 0880:  psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   0
> Sent:          psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   2  rfnum   0
> Sending bb00:  psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   2  rfnum   0
> Sent:          psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   4  rfnum   0
> TFNUM Wait:   psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   2  rfnum   0
> TxRDY:         psc=f0002400 status=0500 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   4
> RxRDY:         psc=f0002400 status=0500 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   4
>   Received ffff
> RxRDY:         psc=f0002400 status=0500 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   2
>   Received ffff
> EXIT:          psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   0
> ------------------------------------------------------
> Entry:         psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   0
> TX-RX Enable:  psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=33
>    tfnum   0  rfnum   0
> Sending 8820:  psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   0
> Sent:          psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   2  rfnum   0
> Sending 0000:  psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   2  rfnum   0
> Sent:          psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   4  rfnum   0
> TFNUM Wait:   psc=f0002400 status=0000 tfstat=0002 rfstat=0002 mode=07
>    tfnum   2  rfnum   0
> TxRDY:         psc=f0002400 status=0500 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   4
> RxRDY:         psc=f0002400 status=0500 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   4
>   Received ffff
> RxRDY:         psc=f0002400 status=0500 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   2
>   Received ffff
> EXIT:          psc=f0002400 status=0400 tfstat=0003 rfstat=0003 mode=07
>    tfnum   0  rfnum   0
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
-------------- next part --------------
/*
 * Media5200 touchscreen driver
 *
 * Copyright (c) 2006 Freescale
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 */

/*
	File : mpc5200_ts_spi.c
	Summary : touchscreen spi driver
*/

#include "mpc5200_ts_spi.h"
#include "asm/io.h"


/**************** Public functions ****************/

/* 
	Initialize and configure spi 
	- configure mux port on psc3
	- configure spi mode
	- configure spi baud rate
	
*/
int spi_init (void) 
{
	struct mpc52xx_gpio __iomem *gpio;
	struct mpc52xx_intr __iomem *intr;

	/* Map zones */
	gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);

	if (!gpio || !intr) {
		printk(KERN_ERR __FILE__ ": "
				"Error while mapping GPIO/INTR during "
				"spi_init\n");
		goto unmap_regs;
	}

	SPI_Config_T 	spi_config; /* spi configuration */

	PDEBUG3("spin_init: initializing SPI in spi_init()\n");

	/* enable interrupt */
	intr->per_mask &= INTR_PER_MASK_SPI_OFF;


	/* initialize mux port PSC3 to SPI */
	gpio->port_config |= GPIO_CONFIG_PORT_SPI_MASK;

	/* initialze data structure */	
	SPI_Regs = (SPI_Regs_T *)(SPI_BASE_ADDRESS);
	memset(&spi_config, 0, sizeof(SPI_Config_T)); 

	/* set spi config attributes */
	spi_config.SPI_Master = SPI_MASTER_DEFAULT;
	spi_config.ClockPolarity = SPI_CPOL_DEFAULT;
	spi_config.ClockPhase = SPI_CPHA_DEFAULT;
	spi_config.WiredOR = SPI_WOR_DEFAULT;
	spi_config.SSoutput = SPI_SSOE_DEFAULT;

	spi_config.SPI_Enable = SPI_SPE_DEFAULT;
	spi_config.BaudRate = SPI_BAUD_DEFAULT;    

	/* modify according to touchscreen driver spi config */   
	spi_config.ClockPolarity = 0;
	spi_config.ClockPhase = 0 ;
	spi_config.WiredOR = 0;


	/*Set the SS pin to low by set SPIPORT register*/ 
	SPI_Regs->SPIPORT = 0x00;

	/* now initialize the spi hardware */
	SPI_SetConfig(&spi_config);

	/* Unmap reg zone */
unmap_regs:
	if (gpio) iounmap(gpio);
	if (intr) iounmap(intr);

	return (TS_OK);
}







/* assume *buffer already alocated to be at least nbytes long */
int read_spi(u8 *buffer, u32 nbytes)
{
    int i;

	for (i = 0; i < nbytes; i++) {
	    buffer[i] = ReadRegister(SPI_Regs->SPIDR);
    } /* for */

	return (nbytes);
} /* read_spi */












int write_spi( u8 *buffer, u32 nbytes)
{
    u32 len;
    u8 reg_value;
    

    // Move this to one devctl command 
    // SPI_Regs->SPIPORT = 0x00;   
     
    for ( len = 0; len < nbytes; len++ )
    {
     

	    PDEBUG9("in write_spi: buffer = %x\n", *buffer);

        WriteRegister(SPI_Regs->SPIDR,*buffer);

        /* Wait several nanoseconds and then check the WCOL flag in status 
         * register.  WeiWei systest replace it with the for-loop directly
         */
        //  WAIT(NANOSECS_PER_WRITE);
        while(1)
        {
             reg_value = ReadRegister(SPI_Regs->SPISR); 
             if (reg_value & SPI_WCOL) 
             {
                WriteRegister(SPI_Regs->SPIDR,*buffer);
                continue;
             }
             if ( reg_value & SPI_SPIF )       
                 break;
	    }

        //SPI_Isr();
        buffer++;
    }
    /* WeiWei add : hardware team suggestion, but it is optional  */
    // SPI_Regs->SPIPORT = 0x08;   
    return len;
}





/*************** Private functions ********************/
static int SPI_SetConfig(SPI_Config_T * Config_Ptr )
{
    u8 control_reg = 0x00;

       
	/* initialize direction register for SPI */
    WriteRegister ( SPI_Regs->SPIDDR, 0x0e );   
      
    /* Set Baud Rate */
    if(SPI_SetBaudrate( Config_Ptr -> BaudRate) == TS_ERROR )
    {
        PDEBUG3("SPI_SetConfig: Error in Set baudrate \n");
        
        WriteRegister(SPI_Regs->SPICR1, control_reg | SPI_SPE);
        return TS_ERROR;
    }   

	/* aways master */     
	control_reg |= SPI_MASTER_MODE;
	/* The SSOE for master mode */          
	control_reg &= ~SPI_SSOE;     
       
	if(Config_Ptr -> ClockPolarity)
	    control_reg |= SPI_CPOL;
	else 
	    control_reg &= ~SPI_CPOL;
	    
	if(Config_Ptr -> ClockPhase)
	    control_reg |= SPI_CPHA;
	else 
	    control_reg &= ~SPI_CPHA;
	    
	if(Config_Ptr -> WiredOR)
	    control_reg |= SPI_SPWOM;
	else 
	    control_reg &= ~SPI_SPWOM;
        
    /* always enable SPI */    
    control_reg |= SPI_SPE;        
      

    /* Enable the interrupt and set the register : WeiWei systest */
    WriteRegister(SPI_Regs->SPICR1, control_reg | SPI_SPIE );
  
    PDEBUG3("SPI_SetCconfig : SPICR1 =%x \n",SPI_Regs->SPICR1);


    return TS_OK ;

}



static int SPI_SetBaudrate(u32 BaudRate)
{
    int i;
    u16 clockdivisor;

    /* Compute the Clock Divisor from module clock divided by BaudRate */ 
    clockdivisor = SPI_MODULE_CLOCK/BaudRate;
 
    /* Find the value of the Baud Rate Register from the array. 
     * If no accurate value can be found, select the closest one 
     */  
    for (i = 0; i < SPI_DIVISOR_NUM-1; i++)
    {
        if(( clockdivisor >= Clock_Divisor[i].clockdivisor ) && \
           ( clockdivisor < Clock_Divisor[i+1].clockdivisor))
        {      
            u16 middle;
            middle = (Clock_Divisor[i].clockdivisor + \
                   Clock_Divisor[i+1].clockdivisor)/2;
            if ( clockdivisor <= middle ) {
                WriteRegister(SPI_Regs->SPIBR,  \
                          Clock_Divisor[i].reg_value);
                PDEBUG3("SPI_SetBaudrate: Baudrate %d\n", SPI_MODULE_CLOCK/Clock_Divisor[i].clockdivisor); 
            } else {
                WriteRegister(SPI_Regs->SPIBR, \
                          Clock_Divisor[i+1].reg_value);
				PDEBUG3("SPI_SetBaudrate: Baudrate %d\n", SPI_MODULE_CLOCK/Clock_Divisor[i+1].clockdivisor);                          
            }
    
            return TS_OK;
        }
    }
    if ( clockdivisor == Clock_Divisor[i].clockdivisor )
    {     
       
        WriteRegister(SPI_Regs->SPIBR, Clock_Divisor[i].reg_value);   
        PDEBUG3("SPI_SetBaudrate: Exact Baudrate %d\n", SPI_MODULE_CLOCK/clockdivisor);
         
        return TS_OK;
    }
    else 
        return TS_ERROR;
}



More information about the Linuxppc-embedded mailing list