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; }