* SPI controller hangs in 2.6 and not in 2.4
@ 2007-02-25 13:41 DI BACCO ANTONIO - technolabs
2007-02-26 16:43 ` Greg Lopp
0 siblings, 1 reply; 2+ messages in thread
From: DI BACCO ANTONIO - technolabs @ 2007-02-25 13:41 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 8795 bytes --]
Hi all,
strange problem with SPI 8xx controller. I attach a litte code snippet that I use to produce the hang, just when giving the start command to the controller, the kernel hangs. START command is given in transmit_data called directly in init.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h> // for udelay()
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/commproc.h>
#include <linux/ioport.h> // for request_mem_region
#include <asm/irq.h> // for SIU_IRQ1
#define SPI_MAX_BUFFER_SIZE 8
#define BD_SC_ME ((ushort)0x0001) /* Multi Master Error */
#define SPCOM_STR 0x80 /* Start transmission command */
volatile car8xx_t *carp;
volatile spi_t *spi;
volatile immap_t *immap;
volatile cpic8xx_t *cpi;
volatile cpm8xx_t *cp;
volatile iop8xx_t *iop;
static cbd_t *tbdf, *rbdf;
static u8* txbuffer;
static u8* rxbuffer;
static u16 r_tbase, r_rbase;
u8 txbuf[32];
u8 rxbuf[32];
static int transmit_data()
{
int result = 0; // default is no error
// BD status/control register
tbdf->cbd_sc = BD_SC_READY | BD_SC_WRAP | BD_SC_LAST;
rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT;
cp->cp_spmode = 0x0778 | SPMODE_LOOP; // spi mode setting
cp->cp_spmode |= 0x0100; // enable SPI
cp->cp_spie = 0xff; // clear all spi events
cp->cp_spim = 0x37; // mask all SPI events
udelay(5); // Wait 5 microsecs
cp->cp_spcom = SPCOM_STR; // start the transfer
printk("after spcom\n");
udelay(100);
// go on and clear chip select befor looking at the result
// wait 2 character times before writing to SPI bus again !!! ?????
cp->cp_spmode = 0x00; // reset spi mode
// test receive and transmit buffer descriptor for errors
if (rbdf->cbd_sc & (BD_SC_EMPTY | BD_SC_OV | BD_SC_ME))
{
result = -EIO;
}
if (tbdf->cbd_sc & (BD_SC_READY | BD_SC_UN | BD_SC_ME))
{
result = -EIO;
}
return result;
} // int transmit_data
static int hello_init(void)
{
u32 dp_addr;
// get pointer to processors internal memory map
immap = (immap_t *)IMAP_ADDR;
// printk("*** spi_read: immap = 0x%08x ***\n",(unsigned int)immap);
// get pointer to cpm interrupt controller
cpi = (cpic8xx_t*)&(((volatile immap_t*)IMAP_ADDR)->im_cpic);
// printk("*** spi_read: cpi = 0x%08x ***\n",(unsigned int)cpi);
// get pointer to input/output port
iop = (iop8xx_t *)&(((volatile immap_t *)IMAP_ADDR)->im_ioport);
// printk("*** spi_read: iop = 0x%08x ***\n",(unsigned int)iop);
// get pointer to communication processor
cp = (cpm8xx_t *)&(((volatile immap_t *)IMAP_ADDR)->im_cpm);
// printk("*** spi_init: cp = 0x%08x ***\n",(unsigned int)cp);
// get pointer to Serial Peripheral Interface parameter RAM
spi = (spi_t *)&cp->cp_dparam[PROFF_SPI];
// printk("*** spi_init: spi = 0x%08x ***\n",(unsigned int)spi);
// get pointer to clocks and reset
carp = (car8xx_t *)&((volatile immap_t *)IMAP_ADDR)->im_clkrst;
// printk("*** spi_init: carp = 0x%08x ***\n",(unsigned int)carp);
// ------------------------------------------
// SCCR[DFBRG] = 0 --> BRGCLK = vcoout/1 ### verwenden nicht auch andere in ioDriver ????
// ------------------------------------------
carp->car_sccr &= 0xFFFFE7FF;
// initialize the parameter ram
// we need to make sure many things are initialized to zero
spi->spi_rstate = 0;
spi->spi_rdp = 0;
spi->spi_rbptr = 0;
spi->spi_rbc = 0;
spi->spi_rxtmp = 0;
spi->spi_tstate = 0;
spi->spi_tdp = 0;
spi->spi_tbptr = 0;
spi->spi_tbc = 0;
spi->spi_txtmp = 0;
// allocate space for one transmit and one receive buffer descriptor in the DP ram
dp_addr = cpm_dpalloc(sizeof(cbd_t) * 2, 8);
// printk("*** spi_init: dp_addr = 0x%08x ***\n",(unsigned int)dp_addr);
// Set up the SPI parameters in the parameter ram
spi->spi_rbase = r_rbase = dp_addr;
spi->spi_tbase = r_tbase = dp_addr + sizeof(cbd_t);
// ***********IMPORTANT******************
// setting transmit and receive buffer descriptor
// pointers initially to rbase and tbase. Only the
// microcode patches documentation talks about initializing
// this pointer. This is missing from the sample I2C driver.
// If you dont initialize these pointers, the kernel hangs.
spi->spi_rbptr = spi->spi_rbase;
spi->spi_tbptr = spi->spi_tbase;
// Set to big endian
spi->spi_tfcr = SMC_EB;
spi->spi_rfcr = SMC_EB;
spi->spi_mrblr = SPI_MAX_BUFFER_SIZE; // Set maximum receive size
// printk("*** spi_init: spi->spi_mrblr = 0x%04x ***\n",spi->spi_mrblr);
cp->cp_cpcr |= 0x51; // Setting CPCR
immap->im_siu_conf.sc_sdcr = 0x0001; // sets SDMA configuration register
cpi->cpic_cicr |= 0x00000580; // enable cpm interrupts, spi has highest priority
cpi->cpic_cimr |= 0x00000020; // enable spi interrupts
cp->cp_spie = 0xff; // clear all spi events
// printk("*** spi_init: iop->iop_pcdat = 0x%04x ***\n", iop->iop_pcdat);
// ------------------------------------------------
// initialize Port B SPI pins -> page 34-8 MPC860UM
// (we are only in master mode !)
// ------------------------------------------------
// --------------------------------------------
// GPIO or per. function
// PBPAR[28] = 1 -> PERI: (SPIMISO)
// PBPAR[29] = 1 -> PERI: (SPIMOSI)
// PBPAR[30] = 1 -> PERI: (SPICLK)
// --------------------------------------------
cp->cp_pbpar |= 0x0000000E; // set bits
// printk("*** spi_init: cp->cp_pbpar\n ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbpar, cp->cp_pbpar);
// ----------------------------------------------
// In/Out or per. function 0/1
// PBDIR[28] = 1 -> PERI1: SPIMISO
// PBDIR[29] = 1 -> PERI1: SPIMOSI
// PBDIR[30] = 1 -> PERI1: SPICLK
// ----------------------------------------------
cp->cp_pbdir |= 0x0000000E;
//printk("*** spi_init: cp->cp_pbdir\n ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbdir, cp->cp_pbdir);
// -------------------------------------------------------------
// attention: PBODR is a 32-bit-register,
// but in the memory-map-struct it is handled as
// 16-bit-register because lower 16 bit are always 0
//
// open drain or active output
// PBODR[28] = 1 -> open drain: SPIMISO
// PBODR[29] = 0 -> active output SPIMOSI
// PBODR[30] = 0 -> active output: SPICLK
// -------------------------------------------------------------
// printk("\n*** cp->cp_pbodr = 0x%08x ***\n",cp->cp_pbodr);
cp->cp_pbodr |= 0x0008; // set bits
cp->cp_pbodr &= 0xFFF9; // reset bits
// printk("*** spi_init: cp->cp_pbodr\n ADR=0x%08x\n VAL=0x%04x\n",(unsigned int)&cp->cp_pbodr, cp->cp_pbodr);
// printk("*** spi_init: cp->cp_pbdat\n ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbdat, cp->cp_pbdat);
// tx and rx buffer descriptors
tbdf = (cbd_t *)&cp->cp_dpmem[r_tbase];
rbdf = (cbd_t *)&cp->cp_dpmem[r_rbase];
// initialize tx and tx bd's
tbdf->cbd_sc &= ~BD_SC_READY;
rbdf->cbd_sc &= ~BD_SC_EMPTY;
// Allocate memory as required
rxbuffer = (u8*)m8xx_cpm_hostalloc(SPI_MAX_BUFFER_SIZE); // Memory alloc for receive buffer
txbuffer = (u8*)m8xx_cpm_hostalloc(SPI_MAX_BUFFER_SIZE); // Memory alloc for transmit buffer
// Set the bd's rx and tx buffer address pointers
rbdf->cbd_bufaddr = virt_to_bus((void *)rxbuffer);
tbdf->cbd_bufaddr = virt_to_bus((void *)txbuffer);
transmit_data();
return 0;
}
static void hello_exit(void)
{
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");
[-- Attachment #2: Type: text/html, Size: 16909 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: SPI controller hangs in 2.6 and not in 2.4
2007-02-25 13:41 SPI controller hangs in 2.6 and not in 2.4 DI BACCO ANTONIO - technolabs
@ 2007-02-26 16:43 ` Greg Lopp
0 siblings, 0 replies; 2+ messages in thread
From: Greg Lopp @ 2007-02-26 16:43 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 9392 bytes --]
I see that your code enables interrupts in the CPM and sets BD_SC_INTRPT,
but you do not claim the IRQ anywhere in this sample.
It doesn't explain the 2.4 vs 2.6 issues, but where is the request_irq() ?
On 2/25/07, DI BACCO ANTONIO - technolabs <Antonio.DiBacco@technolabs.it>
wrote:
>
> Hi all,
>
> strange problem with SPI 8xx controller. I attach a litte code snippet
> that I use to produce the hang, just when giving the start command to the
> controller, the kernel hangs. START command is given in transmit_data called
> directly in init.
>
> #include <linux/init.h>
> #include <linux/module.h>
> #include <linux/kernel.h>
>
> #include <linux/delay.h> // for udelay()
> #include <linux/interrupt.h>
> #include <asm/io.h>
> #include <asm/semaphore.h>
>
> #include <asm/commproc.h>
> #include <linux/ioport.h> // for request_mem_region
> #include <asm/irq.h> // for SIU_IRQ1
>
> #define SPI_MAX_BUFFER_SIZE 8
> #define BD_SC_ME ((ushort)0x0001) /* Multi Master Error */
> #define SPCOM_STR 0x80 /* Start transmission command */
>
>
> volatile car8xx_t *carp;
> volatile spi_t *spi;
> volatile immap_t *immap;
> volatile cpic8xx_t *cpi;
> volatile cpm8xx_t *cp;
> volatile iop8xx_t *iop;
>
> static cbd_t *tbdf, *rbdf;
>
> static u8* txbuffer;
> static u8* rxbuffer;
> static u16 r_tbase, r_rbase;
> u8 txbuf[32];
> u8 rxbuf[32];
>
> static int transmit_data()
> {
> int result = 0; // default is no error
>
> // BD status/control register
> tbdf->cbd_sc = BD_SC_READY | BD_SC_WRAP | BD_SC_LAST;
> rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT;
>
> cp->cp_spmode = 0x0778 | SPMODE_LOOP; // spi mode
> setting
> cp->cp_spmode |= 0x0100; // enable SPI
> cp->cp_spie = 0xff; // clear all spi events
> cp->cp_spim = 0x37; // mask all SPI events
>
> udelay(5); // Wait 5 microsecs
>
> cp->cp_spcom = SPCOM_STR; // start the transfer
>
> printk("after spcom\n");
> udelay(100);
> // go on and clear chip select befor looking at the result
>
> // wait 2 character times before writing to SPI bus again !!! ?????
>
> cp->cp_spmode = 0x00; // reset spi mode
>
>
> // test receive and transmit buffer descriptor for errors
> if (rbdf->cbd_sc & (BD_SC_EMPTY | BD_SC_OV | BD_SC_ME))
> {
> result = -EIO;
> }
> if (tbdf->cbd_sc & (BD_SC_READY | BD_SC_UN | BD_SC_ME))
> {
> result = -EIO;
> }
>
> return result;
> } // int transmit_data
>
>
> static int hello_init(void)
> {
> u32 dp_addr;
> // get pointer to processors internal memory map
> immap = (immap_t *)IMAP_ADDR;
> // printk("*** spi_read: immap = 0x%08x ***\n",(unsigned
> int)immap);
>
> // get pointer to cpm interrupt controller
> cpi = (cpic8xx_t*)&(((volatile immap_t*)IMAP_ADDR)->im_cpic);
> // printk("*** spi_read: cpi = 0x%08x ***\n",(unsigned int)cpi);
>
> // get pointer to input/output port
> iop = (iop8xx_t *)&(((volatile immap_t *)IMAP_ADDR)->im_ioport);
> // printk("*** spi_read: iop = 0x%08x ***\n",(unsigned int)iop);
>
> // get pointer to communication processor
> cp = (cpm8xx_t *)&(((volatile immap_t *)IMAP_ADDR)->im_cpm);
> // printk("*** spi_init: cp = 0x%08x ***\n",(unsigned int)cp);
>
> // get pointer to Serial Peripheral Interface parameter RAM
> spi = (spi_t *)&cp->cp_dparam[PROFF_SPI];
> // printk("*** spi_init: spi = 0x%08x ***\n",(unsigned int)spi);
>
> // get pointer to clocks and reset
> carp = (car8xx_t *)&((volatile immap_t *)IMAP_ADDR)->im_clkrst;
> // printk("*** spi_init: carp = 0x%08x ***\n",(unsigned
> int)carp);
>
> // ------------------------------------------
> // SCCR[DFBRG] = 0 --> BRGCLK = vcoout/1 ### verwenden
> nicht auch andere in ioDriver ????
> // ------------------------------------------
> carp->car_sccr &= 0xFFFFE7FF;
>
> // initialize the parameter ram
> // we need to make sure many things are initialized to zero
> spi->spi_rstate = 0;
> spi->spi_rdp = 0;
> spi->spi_rbptr = 0;
> spi->spi_rbc = 0;
> spi->spi_rxtmp = 0;
> spi->spi_tstate = 0;
> spi->spi_tdp = 0;
> spi->spi_tbptr = 0;
> spi->spi_tbc = 0;
> spi->spi_txtmp = 0;
>
> // allocate space for one transmit and one receive buffer
> descriptor in the DP ram
> dp_addr = cpm_dpalloc(sizeof(cbd_t) * 2, 8);
> // printk("*** spi_init: dp_addr = 0x%08x ***\n",(unsigned
> int)dp_addr);
>
> // Set up the SPI parameters in the parameter ram
> spi->spi_rbase = r_rbase = dp_addr;
> spi->spi_tbase = r_tbase = dp_addr + sizeof(cbd_t);
>
> // ***********IMPORTANT******************
> // setting transmit and receive buffer descriptor
> // pointers initially to rbase and tbase. Only the
> // microcode patches documentation talks about initializing
> // this pointer. This is missing from the sample I2C driver.
> // If you dont initialize these pointers, the kernel hangs.
> spi->spi_rbptr = spi->spi_rbase;
> spi->spi_tbptr = spi->spi_tbase;
>
> // Set to big endian
> spi->spi_tfcr = SMC_EB;
> spi->spi_rfcr = SMC_EB;
>
> spi->spi_mrblr = SPI_MAX_BUFFER_SIZE; // Set maximum receive
> size
> // printk("*** spi_init: spi->spi_mrblr = 0x%04x
> ***\n",spi->spi_mrblr);
>
> cp->cp_cpcr |= 0x51; // Setting CPCR
>
> immap->im_siu_conf.sc_sdcr = 0x0001; // sets SDMA configuration
> register
> cpi->cpic_cicr |= 0x00000580; // enable cpm interrupts,
> spi has highest priority
> cpi->cpic_cimr |= 0x00000020; // enable spi interrupts
>
> cp->cp_spie = 0xff; // clear all spi events
>
> // printk("*** spi_init: iop->iop_pcdat = 0x%04x ***\n",
> iop->iop_pcdat);
>
> // ------------------------------------------------
> // initialize Port B SPI pins -> page 34-8 MPC860UM
> // (we are only in master mode !)
> // ------------------------------------------------
>
> // --------------------------------------------
> // GPIO or per. function
> // PBPAR[28] = 1 -> PERI: (SPIMISO)
> // PBPAR[29] = 1 -> PERI: (SPIMOSI)
> // PBPAR[30] = 1 -> PERI: (SPICLK)
> // --------------------------------------------
> cp->cp_pbpar |= 0x0000000E; // set bits
> // printk("*** spi_init: cp->cp_pbpar\n
> ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbpar,
> cp->cp_pbpar);
>
> // ----------------------------------------------
> // In/Out or per. function 0/1
> // PBDIR[28] = 1 -> PERI1: SPIMISO
> // PBDIR[29] = 1 -> PERI1: SPIMOSI
> // PBDIR[30] = 1 -> PERI1: SPICLK
> // ----------------------------------------------
> cp->cp_pbdir |= 0x0000000E;
> //printk("*** spi_init: cp->cp_pbdir\n
> ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbdir,
> cp->cp_pbdir);
>
> // -------------------------------------------------------------
> // attention: PBODR is a 32-bit-register,
> // but in the memory-map-struct it is handled as
> // 16-bit-register because lower 16 bit are always 0
> //
> // open drain or active output
> // PBODR[28] = 1 -> open drain: SPIMISO
> // PBODR[29] = 0 -> active output SPIMOSI
> // PBODR[30] = 0 -> active output: SPICLK
> // -------------------------------------------------------------
> // printk("\n*** cp->cp_pbodr = 0x%08x ***\n",cp->cp_pbodr);
> cp->cp_pbodr |= 0x0008; // set bits
> cp->cp_pbodr &= 0xFFF9; // reset bits
> // printk("*** spi_init: cp->cp_pbodr\n
> ADR=0x%08x\n VAL=0x%04x\n",(unsigned int)&cp->cp_pbodr,
> cp->cp_pbodr);
>
> // printk("*** spi_init: cp->cp_pbdat\n
> ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbdat,
> cp->cp_pbdat);
>
> // tx and rx buffer descriptors
> tbdf = (cbd_t *)&cp->cp_dpmem[r_tbase];
> rbdf = (cbd_t *)&cp->cp_dpmem[r_rbase];
>
> // initialize tx and tx bd's
> tbdf->cbd_sc &= ~BD_SC_READY;
> rbdf->cbd_sc &= ~BD_SC_EMPTY;
>
> // Allocate memory as required
> rxbuffer = (u8*)m8xx_cpm_hostalloc(SPI_MAX_BUFFER_SIZE); //
> Memory alloc for receive buffer
> txbuffer = (u8*)m8xx_cpm_hostalloc(SPI_MAX_BUFFER_SIZE); //
> Memory alloc for transmit buffer
>
> // Set the bd's rx and tx buffer address pointers
> rbdf->cbd_bufaddr = virt_to_bus((void
> *)rxbuffer);
> tbdf->cbd_bufaddr = virt_to_bus((void *)txbuffer);
>
>
> transmit_data();
>
> return 0;
> }
>
>
> static void hello_exit(void)
> {
> }
>
> module_init(hello_init);
> module_exit(hello_exit);
>
> MODULE_LICENSE("Dual BSD/GPL");
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
[-- Attachment #2: Type: text/html, Size: 17438 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-02-26 16:43 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-25 13:41 SPI controller hangs in 2.6 and not in 2.4 DI BACCO ANTONIO - technolabs
2007-02-26 16:43 ` Greg Lopp
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.