Hello,

I´m trying to develop an SPI audio driver for a Phytec 5200b tiny platform. For 
this purpose, I´m reusing a working I2S driver that was working in a Lite5200b 
platform. This I2S driver was developed for 2.6.16 kernel, using the PPC arch. 
The kernel used by the new platform is a 2.6.20 version, using the powerpc arch.
This kernel does not include the gen_bd files for the BestComm to set up a 
generic task for the DMA, so I had to patch this kernel with the files from 
Sylvain 2.6.20 tree (gen_bd.h, gen_bd.c, sdma_gen_bd_rx_task.c and 
sdma_gen_bd_tx_task.c) and compile them so now, the functions are available. As 
it was working with the old platform, my main goal is to stablish two interrupt 
routines for the dma to read and copy data from the PSC1 configured as an SPI 
master device..
The question is: when I enable the sdma task (with sdma_enable() function), the 
system seems to halt for a while and then continue (so I guess it is doing 
something...) and I have also noticed that the interrupt routines that I 
requested for transmission and reception are not called (a simple printk with a 
character is not printed). May be a problem of setting up the interrupts? I 
have no clue, but the irq allocation seems to be a success
Any hint will be appreciated.

Here is the Setup function that configures the PSC and the DMA tasks:

static int SPI_setup(void) {

        int i;
        // CDM
        struct mpc52xx_cdm __iomem *cdm;
// 
//      /* GPIO Modification */
        struct mpc52xx_gpio __iomem *gpio;

//      /* END GPIO Modification */
// 
        cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
        gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
// 
        printk("psc_num %d\n", psc_num);

        /* Phytec, PSC1*/
        switch(psc_num) {
                case 1:
                        initiator_tx = SDMA_INITIATOR_PSC1_TX;
                        initiator_rx = SDMA_INITIATOR_PSC1_RX;
                        break;
                case 2:
                        initiator_tx = SDMA_INITIATOR_PSC2_TX;
                        initiator_rx = SDMA_INITIATOR_PSC2_RX;
                        break;
                default:
                        panic("snd-SPImgt.o: invalid value for psc_num 
(%i)\n",psc_num);
                        break;
        };

        /* 528MHz/(0x1f+1)=16.5 MHz */
        cdm->mclken_div_psc1 = 0x8001; // Mhz MCLK ( Khz * )
        psc->command = (MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
        /* PSC1 CODEC with Master Clock */
        printk("GPIO->port_config 0x%08x\n", gpio->port_config);
        gpio->port_config |= 0x00000007;
        printk("GPIO->port_config 0x%08x\n", gpio->port_config);
        /* PSC1 clock enable */
        cdm->clk_enables |= 0x20;

        // PSC reset
        psc->command = MPC52xx_PSC_RST_RX;
        psc->command = MPC52xx_PSC_RST_TX;
        psc->command = MPC52xx_PSC_SEL_MODE_REG_1;
        psc->command = MPC52xx_PSC_RST_ERR_STAT;


        // PSC setup SPI
        psc->mode = 0;
        psc->rfalarm = RX_ALARM;
        psc->tfalarm = TX_ALARM;
        psc->rfcntl = RX_GRAN;
        psc->tfcntl = TX_GRAN;
        psc->mpc52xx_psc_imr = 0x0000;
        
        psc->sicr = 0x0290E000;
        

        psc->ccr = 0x3f00; //LRCK  KHz, BitCLK  MHz  0x3f05!

        psc->command = MPC52xx_PSC_RST_RX;
        psc->command = MPC52xx_PSC_RST_TX;
        psc->command = MPC52xx_PSC_SEL_MODE_REG_1;
        psc->command = MPC52xx_PSC_RST_ERR_STAT;
// 
//      // setup the sdma tasks
        tx_sdma = sdma_alloc(PERIODS_HW+1);
        rx_sdma = sdma_alloc(PERIODS_HW+1);

        if (!tx_sdma || !rx_sdma) {
                printk("sdma_alloc failed\n");
                return -ENOMEM;
        }
// 
        sdma_gen_bd_rx_init(0, rx_sdma, (phys_addr_t)&(psc->rfdata), 
initiator_rx, 6, PERIODSIZE_HW);
        sdma_gen_bd_tx_init(1, tx_sdma, (phys_addr_t)&(psc->tfdata), 
initiator_tx, 6);

        printk("txtask is %d rxtask is %d\n", tx_sdma->tasknum, 
rx_sdma->tasknum);
// 
        // prepare the ring buffers
        for(i=0;itasknum %d\n", sdma_irq(rx_sdma), MPC52xx_SDMA_IRQ_BASE + 
rx_sdma->tasknum);
        if (request_irq(sdma_irq(rx_sdma), SPI_rx_irq, IRQF_DISABLED, "SPI rx 
dma", NULL)) {
                printk(KERN_ERR "SPI: SDMA rx irq allocation failed\n");
                return -EINVAL;
        } else printk("SPI: SDA rx irq allocation was a success\n");
        if (request_irq(sdma_irq(tx_sdma), SPI_tx_irq, IRQF_DISABLED, "SPI tx 
dma", NULL)) {
                printk(KERN_ERR "SPI: SDMA tx irq allocation failed\n");
                return -EINVAL;
        } else printk("SPI: SDA tx irq allocation was a success\n");
        
// 
//      // clear any pending interrupts
        sdma_clear_irq(tx_sdma);
        sdma_clear_irq(rx_sdma);
// 
        printk("Before activating the tasks\n");
//      // activate the tasks
        sdma_enable(tx_sdma);  /*Halts or gets stucked here for a while */
        sdma_enable(rx_sdma);  /*Halts or gets stucked here for a while */
// 
//      printk("about to enable SPI psc\n");
        udelay(100);
// 
//      // enable transmitter and receiver
        psc->command = MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE;

        return 0;
};

And here the interrupt routines:

static irqreturn_t SPI_tx_irq(int irq, void *dev_id) {

        if(psc->mpc52xx_psc_status&0x1800) {
                SPI_panic(__FUNCTION__);
                return 0;
        };
        printk("I");
        for (;;) {
                if (!sdma_buffer_done(tx_sdma)) {
                        break;
                }
                sdma_retrieve_buffer(tx_sdma, NULL);
                if(snd_SPImgt_running) {
                        sdma_submit_buffer(tx_sdma, NULL, (void 
*)(((u32)SPI_tx_bufs.pa) + (SPI_play*SAMPLESIZE)), PERIODSIZE_HW);
//                      printk("Ti %d ",SPI_play);
                        SPI_play += FPP_HW;
                        if(SPI_play == FPP*PERIODS) SPI_play=0;
                        if(snd_SPImgt_started) {
                                snd_SPImgt_started--;
                        }
                        else {
                                SPI_pos += FPP_HW;
                                if(SPI_pos == FPP*PERIODS) SPI_pos=0;
//                              snd_pcm_period_elapsed(snd_SPImgt_substream);
                        };
                }
                else {
                        sdma_submit_buffer(tx_sdma, NULL, (void 
*)SPI_tx_silence.pa, PERIODSIZE_HW);
                };
        };
        
        if(snd_SPImgt_running &&(!snd_SPImgt_started)){
                snd_pcm_period_elapsed(snd_SPImgt_substream);
        }
        return IRQ_HANDLED;
};


static irqreturn_t SPI_rx_irq(int irq, void *dev_id) {

        //SPI_print(__FUNCTION__);
        if(psc->mpc52xx_psc_status&0x1800) {
                SPI_panic(__FUNCTION__);
                return 0;
        };
        printk("R");            
        for (;;) {
                if (!sdma_buffer_done(rx_sdma)) {
                        break;
                }
                sdma_retrieve_buffer(rx_sdma, NULL);
                sdma_submit_buffer(rx_sdma, NULL, (void *)SPI_rx_bufs.pa, 
PERIODSIZE_HW);
        };
        return IRQ_HANDLED;
};

Regards,
Pedro.

_________________________________________________________________
Llama a tus amigos de PC a PC: ¡Es GRATIS!
http://get.live.com/messenger/overview
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Reply via email to