From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from wr-out-0506.google.com (wr-out-0506.google.com [64.233.184.230]) by ozlabs.org (Postfix) with ESMTP id D5C21DDFA8 for ; Tue, 27 Feb 2007 03:43:16 +1100 (EST) Received: by wr-out-0506.google.com with SMTP id i30so1446909wra for ; Mon, 26 Feb 2007 08:43:14 -0800 (PST) Message-ID: Date: Mon, 26 Feb 2007 10:43:13 -0600 From: "Greg Lopp" Sender: greg.lopp@gmail.com To: linuxppc-embedded@ozlabs.org Subject: Re: SPI controller hangs in 2.6 and not in 2.4 In-Reply-To: MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_95270_24660034.1172508193706" References: List-Id: Linux on Embedded PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , ------=_Part_95270_24660034.1172508193706 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 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 > #include > #include > > #include // for udelay() > #include > #include > #include > > #include > #include // for request_mem_region > #include // 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 > ------=_Part_95270_24660034.1172508193706 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline 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

------=_Part_95270_24660034.1172508193706--