I see that your code enables interrupts in the CPM and <font size="2">sets BD</font><font size="2">_SC_INTRPT, but you do not claim the IRQ anywhere in this sample. </font><br><br>It doesn't explain the 2.4 vs 2.6 issues,
<font size="2"> but where is the request_irq() ?</font><br><br><br><div><span class="gmail_quote">On 2/25/07, <b class="gmail_sendername">DI BACCO ANTONIO - technolabs</b> <<a href="mailto:Antonio.DiBacco@technolabs.it">
Antonio.DiBacco@technolabs.it</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div>
<p><font size="2">Hi all,<br>
<br>
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.
<br>
<br>
#include <linux/init.h><br>
#include <linux/module.h><br>
#include <linux/kernel.h><br>
<br>
#include <linux/delay.h> // for udelay()<br>
#include <linux/interrupt.h><br>
#include <asm/io.h><br>
#include <asm/semaphore.h><br>
<br>
#include <asm/commproc.h><br>
#include <linux/ioport.h> // for request_mem_region<br>
#include <asm/irq.h> // for SIU_IRQ1<br>
<br>
#define SPI_MAX_BUFFER_SIZE 8<br>
#define BD_SC_ME ((ushort)0x0001) /* Multi Master Error */<br>
#define SPCOM_STR 0x80 /* Start transmission command */<br>
<br>
<br>
volatile car8xx_t *carp;<br>
volatile spi_t *spi; <br>
volatile immap_t *immap;<br>
volatile cpic8xx_t *cpi; <br>
volatile cpm8xx_t *cp; <br>
volatile iop8xx_t *iop; <br>
<br>
static cbd_t *tbdf, *rbdf;<br>
<br>
static u8* txbuffer;<br>
static u8* rxbuffer;<br>
static u16 r_tbase, r_rbase;<br>
u8 txbuf[32];<br>
u8 rxbuf[32];<br>
<br>
static int transmit_data()<br>
{<br>
int result = 0; // default is no error<br>
<br>
// BD status/control register<br>
tbdf->cbd_sc = BD_SC_READY | BD_SC_WRAP | BD_SC_LAST;<br>
rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT;<br>
<br>
cp->cp_spmode = 0x0778 | SPMODE_LOOP; // spi mode setting<br>
cp->cp_spmode |= 0x0100; // enable SPI<br>
cp->cp_spie = 0xff; // clear all spi events<br>
cp->cp_spim = 0x37; // mask all SPI events<br>
<br>
udelay(5); // Wait 5 microsecs<br>
<br>
cp->cp_spcom = SPCOM_STR; // start the transfer<br>
<br>
printk("after spcom\n");<br>
udelay(100);<br>
// go on and clear chip select befor looking at the result<br>
<br>
// wait 2 character times before writing to SPI bus again !!! ?????<br>
<br>
cp->cp_spmode = 0x00; // reset spi mode<br>
<br>
<br>
// test receive and transmit buffer descriptor for errors<br>
if (rbdf->cbd_sc & (BD_SC_EMPTY | BD_SC_OV | BD_SC_ME))<br>
{<br>
result = -EIO;<br>
}<br>
if (tbdf->cbd_sc & (BD_SC_READY | BD_SC_UN | BD_SC_ME))<br>
{<br>
result = -EIO;<br>
}<br>
<br>
return result;<br>
} // int transmit_data<br>
<br>
<br>
static int hello_init(void)<br>
{<br>
u32 dp_addr;<br>
// get pointer to processors internal memory map<br>
immap = (immap_t *)IMAP_ADDR;<br>
// printk("*** spi_read: immap = 0x%08x ***\n",(unsigned int)immap);<br>
<br>
// get pointer to cpm interrupt controller<br>
cpi = (cpic8xx_t*)&(((volatile immap_t*)IMAP_ADDR)->im_cpic);<br>
// printk("*** spi_read: cpi = 0x%08x ***\n",(unsigned int)cpi);<br>
<br>
// get pointer to input/output port<br>
iop = (iop8xx_t *)&(((volatile immap_t *)IMAP_ADDR)->im_ioport);<br>
// printk("*** spi_read: iop = 0x%08x ***\n",(unsigned int)iop);<br>
<br>
// get pointer to communication processor<br>
cp = (cpm8xx_t *)&(((volatile immap_t *)IMAP_ADDR)->im_cpm);<br>
// printk("*** spi_init: cp = 0x%08x ***\n",(unsigned int)cp);<br>
<br>
// get pointer to Serial Peripheral Interface parameter RAM<br>
spi = (spi_t *)&cp->cp_dparam[PROFF_SPI];<br>
// printk("*** spi_init: spi = 0x%08x ***\n",(unsigned int)spi);<br>
<br>
// get pointer to clocks and reset<br>
carp = (car8xx_t *)&((volatile immap_t *)IMAP_ADDR)->im_clkrst;<br>
// printk("*** spi_init: carp = 0x%08x ***\n",(unsigned int)carp);<br>
<br>
// ------------------------------------------<br>
// SCCR[DFBRG] = 0 --> BRGCLK = vcoout/1 ### verwenden nicht auch andere in ioDriver ????<br>
// ------------------------------------------<br>
carp->car_sccr &= 0xFFFFE7FF;<br>
<br>
// initialize the parameter ram<br>
// we need to make sure many things are initialized to zero<br>
spi->spi_rstate = 0;<br>
spi->spi_rdp = 0;<br>
spi->spi_rbptr = 0;<br>
spi->spi_rbc = 0;<br>
spi->spi_rxtmp = 0;<br>
spi->spi_tstate = 0;<br>
spi->spi_tdp = 0;<br>
spi->spi_tbptr = 0;<br>
spi->spi_tbc = 0;<br>
spi->spi_txtmp = 0;<br>
<br>
// allocate space for one transmit and one receive buffer descriptor in the DP ram<br>
dp_addr = cpm_dpalloc(sizeof(cbd_t) * 2, 8);<br>
// printk("*** spi_init: dp_addr = 0x%08x ***\n",(unsigned int)dp_addr);<br>
<br>
// Set up the SPI parameters in the parameter ram<br>
spi->spi_rbase = r_rbase = dp_addr;<br>
spi->spi_tbase = r_tbase = dp_addr + sizeof(cbd_t);<br>
<br>
// ***********IMPORTANT******************<br>
// setting transmit and receive buffer descriptor<br>
// pointers initially to rbase and tbase. Only the<br>
// microcode patches documentation talks about initializing<br>
// this pointer. This is missing from the sample I2C driver.<br>
// If you dont initialize these pointers, the kernel hangs.<br>
spi->spi_rbptr = spi->spi_rbase;<br>
spi->spi_tbptr = spi->spi_tbase;<br>
<br>
// Set to big endian<br>
spi->spi_tfcr = SMC_EB;<br>
spi->spi_rfcr = SMC_EB;<br>
<br>
spi->spi_mrblr = SPI_MAX_BUFFER_SIZE; // Set maximum receive size<br>
// printk("*** spi_init: spi->spi_mrblr = 0x%04x ***\n",spi->spi_mrblr);<br>
<br>
cp->cp_cpcr |= 0x51; // Setting CPCR<br>
<br>
immap->im_siu_conf.sc_sdcr = 0x0001; // sets SDMA configuration register<br>
cpi->cpic_cicr |= 0x00000580; // enable cpm interrupts, spi has highest priority<br>
cpi->cpic_cimr |= 0x00000020; // enable spi interrupts<br>
<br>
cp->cp_spie = 0xff; // clear all spi events<br>
<br>
// printk("*** spi_init: iop->iop_pcdat = 0x%04x ***\n", iop->iop_pcdat);<br>
<br>
// ------------------------------------------------<br>
// initialize Port B SPI pins -> page 34-8 MPC860UM<br>
// (we are only in master mode !)<br>
// ------------------------------------------------<br>
<br>
// --------------------------------------------<br>
// GPIO or per. function<br>
// PBPAR[28] = 1 -> PERI: (SPIMISO)<br>
// PBPAR[29] = 1 -> PERI: (SPIMOSI)<br>
// PBPAR[30] = 1 -> PERI: (SPICLK)<br>
// --------------------------------------------<br>
cp->cp_pbpar |= 0x0000000E; // set bits<br>
// printk("*** spi_init: cp->cp_pbpar\n ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbpar, cp->cp_pbpar);<br>
<br>
// ----------------------------------------------<br>
// In/Out or per. function 0/1<br>
// PBDIR[28] = 1 -> PERI1: SPIMISO<br>
// PBDIR[29] = 1 -> PERI1: SPIMOSI<br>
// PBDIR[30] = 1 -> PERI1: SPICLK<br>
// ----------------------------------------------<br>
cp->cp_pbdir |= 0x0000000E;<br>
//printk("*** spi_init: cp->cp_pbdir\n ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbdir, cp->cp_pbdir);<br>
<br>
// -------------------------------------------------------------<br>
// attention: PBODR is a 32-bit-register,<br>
// but in the memory-map-struct it is handled as<br>
// 16-bit-register because lower 16 bit are always 0<br>
//<br>
// open drain or active output<br>
// PBODR[28] = 1 -> open drain: SPIMISO<br>
// PBODR[29] = 0 -> active output SPIMOSI<br>
// PBODR[30] = 0 -> active output: SPICLK<br>
// -------------------------------------------------------------<br>
// printk("\n*** cp->cp_pbodr = 0x%08x ***\n",cp->cp_pbodr);<br>
cp->cp_pbodr |= 0x0008; // set bits<br>
cp->cp_pbodr &= 0xFFF9; // reset bits<br>
// printk("*** spi_init: cp->cp_pbodr\n ADR=0x%08x\n VAL=0x%04x\n",(unsigned int)&cp->cp_pbodr, cp->cp_pbodr);<br>
<br>
// printk("*** spi_init: cp->cp_pbdat\n ADR=0x%08x\n VAL=0x%08x\n",(unsigned int)&cp->cp_pbdat, cp->cp_pbdat);<br>
<br>
// tx and rx buffer descriptors<br>
tbdf = (cbd_t *)&cp->cp_dpmem[r_tbase];<br>
rbdf = (cbd_t *)&cp->cp_dpmem[r_rbase];<br>
<br>
// initialize tx and tx bd's<br>
tbdf->cbd_sc &= ~BD_SC_READY;<br>
rbdf->cbd_sc &= ~BD_SC_EMPTY;<br>
<br>
// Allocate memory as required<br>
rxbuffer = (u8*)m8xx_cpm_hostalloc(SPI_MAX_BUFFER_SIZE); // Memory alloc for receive buffer<br>
txbuffer = (u8*)m8xx_cpm_hostalloc(SPI_MAX_BUFFER_SIZE); // Memory alloc for transmit buffer<br>
<br>
// Set the bd's rx and tx buffer address pointers<br>
rbdf->cbd_bufaddr = virt_to_bus((void *)rxbuffer); <br>
tbdf->cbd_bufaddr = virt_to_bus((void *)txbuffer); <br>
<br>
<br>
transmit_data();<br>
<br>
return 0;<br>
}<br>
<br>
<br>
static void hello_exit(void)<br>
{<br>
}<br>
<br>
module_init(hello_init);<br>
module_exit(hello_exit);<br>
<br>
MODULE_LICENSE("Dual BSD/GPL");<br>
</font>
</p>
</div>
<br>_______________________________________________<br>Linuxppc-embedded mailing list<br><a onclick="return top.js.OpenExtLink(window,event,this)" href="mailto:Linuxppc-embedded@ozlabs.org">Linuxppc-embedded@ozlabs.org</a>
<br><a onclick="return top.js.OpenExtLink(window,event,this)" href="https://ozlabs.org/mailman/listinfo/linuxppc-embedded" target="_blank">https://ozlabs.org/mailman/listinfo/linuxppc-embedded</a><br></blockquote></div><br>