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);
}
Exemplo n.º 2
0
/*
 * 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);
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
/**
 * 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;
}