static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data) { void __iomem *reg = drv_data->ioaddr; struct spi_message *msg = drv_data->cur_msg; /* Clear and disable interrupts on SSP and DMA channels*/ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); write_SSSR_CS(drv_data, drv_data->clear_sr); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; if (wait_dma_channel_stop(drv_data->rx_channel) == 0) dev_err(&drv_data->pdev->dev, "dma_handler: dma rx channel stop failed\n"); if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) dev_err(&drv_data->pdev->dev, "dma_transfer: ssp rx stall failed\n"); pxa2xx_spi_unmap_dma_buffers(drv_data); /* update the buffer pointer for the amount completed in dma */ drv_data->rx += drv_data->len - (DCMD(drv_data->rx_channel) & DCMD_LENGTH); /* read trailing data from fifo, it does not matter how many * bytes are in the fifo just read until buffer is full * or fifo is empty, which ever occurs first */ drv_data->read(drv_data); /* return count of what was actually read */ msg->actual_length += drv_data->len - (drv_data->rx_end - drv_data->rx); /* Transfer delays and chip select release are * handled in pump_transfers or giveback */ /* Move to next transfer */ msg->state = pxa2xx_spi_next_transfer(drv_data); /* Schedule transfer tasklet */ tasklet_schedule(&drv_data->pump_transfers); }
/* * set_ssp_i2s_hw - Configure SSP driver according to settings. * @regs: pointer to registers * @shim: pointer to shim registers * @settings: config settings * @bps: bits per sample * * Configure SSP driver according to settings. */ static void set_ssp_i2s_hw(AplI2sRegs *regs, AplI2sRegs *shim, const AplI2sSettings *settings, int bps) { uint32_t sscr0; uint32_t sscr1; uint32_t sscr2; uint32_t sscr3; uint32_t sstsa; uint32_t ssrsa; uint32_t sspsp; uint32_t sspsp2 = 0; uint32_t sssr = 0; uint32_t ssioc; sscr0 = calculate_sscr0(settings, bps); sscr1 = calculate_sscr1(settings); sscr2 = calculate_sscr2(); sscr3 = 0; sspsp = calculate_sspsp(settings); sstsa = SSTSA_reg(TTSA, settings->ssp_active_tx_slots_map); ssrsa = SSRSA_reg(RTSA, settings->ssp_active_rx_slots_map); ssioc = calculate_ssioc(); write_SSCR0(sscr0, regs); write_SSCR1(sscr1, regs); write_SSCR2(sscr2, regs); write_SSCR3(sscr3, regs); write_SSPSP(sspsp, regs); write_SSPSP2(sspsp2, regs); write_SSTSA(sstsa, regs); write_SSRSA(ssrsa, regs); write_SSIOC(ssioc, regs); /* Clear status */ write_SSSR(sssr, regs); /* set the time out for the reception */ write_SSTO(SSP_TIMEOUT, regs); }
static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data, const char *msg) { void __iomem *reg = drv_data->ioaddr; /* Stop and reset */ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; write_SSSR_CS(drv_data, drv_data->clear_sr); write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (!pxa25x_ssp_comp(drv_data)) write_SSTO(0, reg); pxa2xx_spi_flush(drv_data); write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); pxa2xx_spi_unmap_dma_buffers(drv_data); dev_err(&drv_data->pdev->dev, "%s\n", msg); drv_data->cur_msg->state = ERROR_STATE; tasklet_schedule(&drv_data->pump_transfers); }
/** * intel_mid_i2s_probe - probing function for the pci selected * @pdev : pci_dev pointer that is probed * @ent : pci_device_id * * Output parameters * NA */ static int intel_mid_i2s_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_mid_i2s_hdl *drv_data; int status = 0; enum intel_mid_i2s_ssp_usage usage; drv_data = kzalloc(sizeof(struct intel_mid_i2s_hdl), GFP_KERNEL); dev_dbg(&(pdev->dev), "%s Probe, drv_data =%p\n", DRIVER_NAME, drv_data); if (!drv_data) { dev_err((&pdev->dev), "Can't alloc driver data in probe\n"); status = -ENOMEM; goto leave; } dev_info((&pdev->dev), "Detected PCI SSP (ID: %04x:%04x)\n", pdev->vendor, pdev->device); status = intel_mid_i2s_find_usage(pdev, drv_data, &usage); if (status) goto err_i2s_probe0; mutex_init(&drv_data->mutex); drv_data->pdev = pdev; drv_data->usage = usage; /* * Get basic io resource and map it for SSP1 [BAR=0] */ if ((pdev->device == MFLD_SSP1_DEVICE_ID) || (pdev->device == MFLD_SSP0_DEVICE_ID)) { drv_data->paddr = pci_resource_start(pdev, MRST_SSP_BAR); drv_data->iolen = pci_resource_len(pdev, MRST_SSP_BAR); status = pci_request_region(pdev, MRST_SSP_BAR, dev_name(&pdev->dev)); /* map bus memory into CPU space */ drv_data->ioaddr = pci_ioremap_bar(pdev, MRST_SSP_BAR); } else { dev_err(&pdev->dev, "Don't know which BAR to usefor this SSP PCDID=%x\n", pdev->device); status = -ENODEV; goto err_i2s_probe1; } dev_dbg(&(pdev->dev), "paddr = : %x\n", (unsigned int) drv_data->paddr); dev_dbg(&(pdev->dev), "iolen = : %d\n", drv_data->iolen); if (status) { dev_err((&pdev->dev), "Can't request region. err=%d\n", status); goto err_i2s_probe1; } if (!drv_data->ioaddr) { dev_err((&pdev->dev), "ioremap_nocache error\n"); status = -ENOMEM; goto err_i2s_probe2; } dev_dbg(&(pdev->dev), "ioaddr = : %p\n", drv_data->ioaddr); /* prepare for DMA channel allocation */ /* get the pci_dev structure pointer */ /* Check the SSP, if SSP3, then another DMA is used (GPDMA..) */ if ((pdev->device == MFLD_SSP1_DEVICE_ID) || (pdev->device == MFLD_SSP0_DEVICE_ID)) { drv_data->dmac1 = pci_get_device(PCI_VENDOR_ID_INTEL, MFLD_LPE_DMA_DEVICE_ID, NULL); } else { dev_err(&pdev->dev, "Don't know dma device ID for this SSP PCDID=%x\n", pdev->device); goto err_i2s_probe3; } /* in case the stop dma have to wait for end of callbacks */ /* This will be removed when TERMINATE_ALL available in DMA */ init_waitqueue_head(&drv_data->wq_chan_closing); if (!drv_data->dmac1) { dev_err(&(drv_data->pdev->dev), "Can't find DMAC1, dma init failed\n"); status = -ENODEV; goto err_i2s_probe3; } /* increment ref count of pci device structure already done by */ /* pci_get_device. will do a pci_dev_put when exiting the module */ pci_set_drvdata(pdev, drv_data); /* set SSP FrameSync and CLK direction in INPUT mode in order * to avoid disturbing peripherals */ write_SSCR1((SSCR1_SFRMDIR_MASK<<SSCR1_SFRMDIR_SHIFT) | (SSCR1_SCLKDIR_MASK<<SSCR1_SCLKDIR_SHIFT), drv_data->ioaddr); /* Attach to IRQ */ drv_data->irq = pdev->irq; dev_dbg(&(pdev->dev), "attaching to IRQ: %04x\n", pdev->irq); status = request_irq(drv_data->irq, i2s_int, IRQF_SHARED, "i2s ssp", drv_data); if (status < 0) { dev_err(&pdev->dev, "can not get IRQ. status err=%d\n", status); goto err_i2s_probe3; } pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&(drv_data->pdev->dev)); goto leave; err_i2s_probe3: iounmap(drv_data->ioaddr); err_i2s_probe2: pci_release_region(pdev, MRST_SSP_BAR); err_i2s_probe1: pci_disable_device(pdev); err_i2s_probe0: kfree(drv_data); leave: return status; }
/** * set_ssp_i2s_hw - configure the SSP driver according to the ps_settings * @drv_data : structure that contains all details about the SSP Driver * @ps_settings : structure that contains SSP Hardware settings * * it also store ps_settings the drv_data * * Output parameters * NA */ static void set_ssp_i2s_hw(struct intel_mid_i2s_hdl *drv_data, const struct intel_mid_i2s_settings *ps_settings) { u32 sscr0 = 0; u32 sscr1 = 0; u32 sstsa = 0; u32 ssrsa = 0; u32 sspsp = 0; u32 sssr = 0; /* Get the SSP Settings */ u16 l_ssp_clk_frm_mode = 0xFF; void __iomem *reg = drv_data->ioaddr; struct device *ddbg = &(drv_data->pdev->dev); dev_dbg(ddbg, "setup SSP I2S PCM1 configuration\n"); if ((ps_settings->sspsfrm_direction == SSPSFRM_MASTER_MODE) && (ps_settings->sspslclk_direction == SSPSCLK_MASTER_MODE)) { l_ssp_clk_frm_mode = SSP_IN_MASTER_MODE; } else if ((ps_settings->sspsfrm_direction == SSPSFRM_SLAVE_MODE) && (ps_settings->sspslclk_direction == SSPSCLK_SLAVE_MODE)) { l_ssp_clk_frm_mode = SSP_IN_SLAVE_MODE; } else { dev_err(ddbg, "Unsupported I2S PCM1 configuration\n"); goto leave; } dev_dbg(ddbg, "SSPSFRM_DIRECTION:%d:\n", ps_settings->sspsfrm_direction); dev_dbg(ddbg, "SSPSCLK_DIRECTION:%d:\n", ps_settings->sspslclk_direction); if (ps_settings->frame_format != PSP_FORMAT) { dev_err(ddbg, "UNSUPPORTED FRAME FORMAT:%d:\n", ps_settings->frame_format); goto leave; } if ((ps_settings->ssp_tx_dma != SSP_TX_DMA_ENABLE) || (ps_settings->ssp_rx_dma != SSP_RX_DMA_ENABLE)) { dev_err(ddbg, "ONLY DMA MODE IS SUPPORTED"); goto leave; } /*********** DMA Transfer Mode ***********/ dev_dbg(ddbg, "FORMAT :%d:\n", ps_settings->frame_format); sscr0 = calculate_sscr0_psp(ps_settings); dev_dbg(ddbg, " sscr0 :0x%08X\n", sscr0); sscr1 = calculate_sscr1_psp(ps_settings); dev_dbg(ddbg, " sscr1 :0x%08X\n", sscr1); if (ps_settings->mode == SSP_IN_NETWORK_MODE) { dev_dbg(ddbg, "MODE :%d:\n", ps_settings->mode); sscr0 |= SSCR0_reg(FRDC, SSCR0_SlotsPerFrm(ps_settings-> frame_rate_divider_control)); dev_dbg(ddbg, "sscr0 :0x%08X\n", sscr0); sspsp = calculate_sspsp_psp(ps_settings); dev_dbg(ddbg, "sspsp :0x%08X\n", sspsp); /* set the active TX time slot (bitmap) */ sstsa = SSTSA_reg(TTSA, ps_settings->ssp_active_tx_slots_map); /* set the active RX time slot (bitmap) */ ssrsa = SSRSA_reg(RTSA, ps_settings->ssp_active_rx_slots_map); if (l_ssp_clk_frm_mode == SSP_IN_MASTER_MODE) { switch (ps_settings->master_mode_clk_selection) { case SSP_ONCHIP_CLOCK: break; case SSP_NETWORK_CLOCK: sscr0 |= SSCR0_reg(NCS, 1); break; case SSP_EXTERNAL_CLOCK: sscr0 |= SSCR0_reg(ECS, 1); break; case SSP_ONCHIP_AUDIO_CLOCK: sscr0 |= SSCR0_reg(ACS, 1); break; default: dev_err(ddbg, "Master Mode clk selection UNKNOWN"); break; } sspsp |= SSPSP_reg(STRTDLY, ps_settings->ssp_psp_T1) |SSPSP_reg(DMYSTRT, ps_settings->ssp_psp_T2); } else { /* Set the Slave Clock Free Running Status */ sscr1 |= SSCR1_reg(SCFR, ps_settings->slave_clk_free_running_status); } } else { /* SSP_IN_NORMAL_MODE */ dev_err(ddbg, "UNSUPPORTED MODE"); goto leave; } /* Clear status */ sssr = (SSSR_BCE_MASK << SSSR_BCE_SHIFT) | (SSSR_TUR_MASK << SSSR_TUR_SHIFT) | (SSSR_TINT_MASK << SSSR_TINT_SHIFT) | (SSSR_PINT_MASK << SSSR_PINT_SHIFT) | (SSSR_ROR_MASK << SSSR_ROR_SHIFT); /* disable SSP */ clear_SSCR0_reg(reg, SSE); dev_dbg(ddbg, "WRITE SSCR0 DISABLE\n"); /* Clear status */ write_SSSR(sssr, reg); dev_dbg(ddbg, "WRITE SSSR: 0x%08X\n", sssr); write_SSCR0(sscr0, reg); dev_dbg(ddbg, "WRITE SSCR0\n"); /* first set CR1 without interrupt and service enables */ write_SSCR1(sscr1, reg); write_SSPSP(sspsp, reg); write_SSTSA(sstsa, reg); write_SSRSA(ssrsa, reg); /* set the time out for the reception */ write_SSTO(0, reg); ssp1_dump_registers(drv_data); leave: return; }