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