int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
{
    struct device *dev = &drv_data->pdev->dev;
    struct ssp_device *ssp = drv_data->ssp;

    /* Get two DMA channels	(rx and tx) */
    drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
                                           DMA_PRIO_HIGH,
                                           pxa2xx_spi_dma_handler,
                                           drv_data);
    if (drv_data->rx_channel < 0) {
        dev_err(dev, "problem (%d) requesting rx channel\n",
                drv_data->rx_channel);
        return -ENODEV;
    }
    drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
                                           DMA_PRIO_MEDIUM,
                                           pxa2xx_spi_dma_handler,
                                           drv_data);
    if (drv_data->tx_channel < 0) {
        dev_err(dev, "problem (%d) requesting tx channel\n",
                drv_data->tx_channel);
        pxa_free_dma(drv_data->rx_channel);
        return -ENODEV;
    }

    DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
    DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;

    return 0;
}
Пример #2
0
static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct pxa2xx_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
	int ret;

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!dma)
		return 0;

	/* this may get called several times by oss emulation
	 * with different params */
	if (prtd->params == NULL) {
		prtd->params = dma;
		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
			      pxa2xx_pcm_dma_irq, substream);
		if (ret < 0)
			return ret;
		prtd->dma_ch = ret;
	} else if (prtd->params != dma) {
		pxa_free_dma(prtd->dma_ch);
		prtd->params = dma;
		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
			      pxa2xx_pcm_dma_irq, substream);
		if (ret < 0)
			return ret;
		prtd->dma_ch = ret;
	}

	return __pxa2xx_pcm_hw_params(substream, params);
}
static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
	struct pxa2xx_pcm_client *client = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct pxa2xx_runtime_data *rtd;
	int ret;

	ret = __pxa2xx_pcm_open(substream);
	if (ret)
		goto out;

	rtd = runtime->private_data;

	rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
		      client->playback_params : client->capture_params;
	ret = pxa_request_dma("dma", DMA_PRIO_LOW,
			      pxa2xx_pcm_dma_irq, substream);
	if (ret < 0)
		goto err2;
	rtd->dma_ch = ret;

	ret = client->startup(substream);
	if (!ret)
		goto out;

	pxa_free_dma(rtd->dma_ch);
 err2:
	__pxa2xx_pcm_close(substream);
 out:
	return ret;
}
Пример #4
0
static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
	struct pxa2xx_pcm_client *client = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct pxa2xx_runtime_data *rtd;
	int ret;

	runtime->hw = pxa2xx_pcm_hardware;

	/*
	 * For mysterious reasons (and despite what the manual says)
	 * playback samples are lost if the DMA count is not a multiple
	 * of the DMA burst size.  Let's add a rule to enforce that.
	 */
	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
				  pxa2xx_pcm_hw_rule_mult32, NULL,
				  SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1);
	if (ret)
		goto out;
	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
				  pxa2xx_pcm_hw_rule_mult32, NULL,
				  SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
	if (ret)
		goto out;

	ret = -ENOMEM;
	rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
	if (!rtd)
		goto out;
	rtd->dma_desc_array =
		dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
				       &rtd->dma_desc_array_phys, GFP_KERNEL);
	if (!rtd->dma_desc_array)
		goto err1;

	rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
		      client->playback_params : client->capture_params;
	ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
			      pxa2xx_pcm_dma_irq, substream);
	if (ret < 0)
		goto err2;
	rtd->dma_ch = ret;

	runtime->private_data = rtd;
	ret = client->startup(substream);
	if (!ret)
		goto out;

	pxa_free_dma(rtd->dma_ch);
 err2:
	dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
			      rtd->dma_desc_array, rtd->dma_desc_array_phys);
 err1:
	kfree(rtd);
 out:
	return ret;
}
Пример #5
0
static void serial_pxa_dma_init(struct pxa_uart *up)
{
	up->rxdma =
		pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_receive_dma, up);
	if (up->rxdma < 0)
		goto out;
	up->txdma =
		pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_transmit_dma, up);
	if (up->txdma < 0)
		goto err_txdma;
	up->dmadesc = kmalloc(4 * sizeof(pxa_dma_desc), GFP_KERNEL);
	if (!up->dmadesc)
		goto err_alloc;

	/* ... */
err_alloc:
	pxa_free_dma(up->txdma);
err_rxdma:
	pxa_free_dma(up->rxdma);
out:
	return;
}
Пример #6
0
static int pxa_irda_start(struct net_device *dev)
{
	struct pxa_irda *si = netdev_priv(dev);
	int err;

	si->speed = 9600;

	err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev);
	if (err)
		goto err_irq1;

	err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev);
	if (err)
		goto err_irq2;

	/*
	 * The interrupt must remain disabled for now.
	 */
	disable_irq(IRQ_STUART);
	disable_irq(IRQ_ICP);

	err = -EBUSY;
	si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
	if (si->rxdma < 0)
		goto err_rx_dma;

	si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
	if (si->txdma < 0)
		goto err_tx_dma;

	err = -ENOMEM;
	si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
					     &si->dma_rx_buff_phy, GFP_KERNEL );
	if (!si->dma_rx_buff)
		goto err_dma_rx_buff;

	si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
					     &si->dma_tx_buff_phy, GFP_KERNEL );
	if (!si->dma_tx_buff)
		goto err_dma_tx_buff;

	/* Setup the serial port for the initial speed. */
	pxa_irda_startup(si);

	/*
	 * Open a new IrLAP layer instance.
	 */
	si->irlap = irlap_open(dev, &si->qos, "pxa");
	err = -ENOMEM;
	if (!si->irlap)
		goto err_irlap;

	/*
	 * Now enable the interrupt and start the queue
	 */
	enable_irq(IRQ_STUART);
	enable_irq(IRQ_ICP);
	netif_start_queue(dev);

	printk(KERN_DEBUG "pxa_ir: irda driver opened\n");

	return 0;

err_irlap:
	pxa_irda_shutdown(si);
	dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
err_dma_tx_buff:
	dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
err_dma_rx_buff:
	pxa_free_dma(si->txdma);
err_tx_dma:
	pxa_free_dma(si->rxdma);
err_rx_dma:
	free_irq(IRQ_ICP, dev);
err_irq2:
	free_irq(IRQ_STUART, dev);
err_irq1:

	return err;
}
Пример #7
0
static int pxa_ata_probe(struct platform_device *pdev)
{
	struct ata_host *host;
	struct ata_port *ap;
	struct pata_pxa_data *data;
	struct resource *cmd_res;
	struct resource *ctl_res;
	struct resource *dma_res;
	struct resource *irq_res;
	struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev);
	int ret = 0;

	/*
	 * Resource validation, three resources are needed:
	 *  - CMD port base address
	 *  - CTL port base address
	 *  - DMA port base address
	 *  - IRQ pin
	 */
	if (pdev->num_resources != 4) {
		dev_err(&pdev->dev, "invalid number of resources\n");
		return -EINVAL;
	}

	/*
	 * CMD port base address
	 */
	cmd_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (unlikely(cmd_res == NULL))
		return -EINVAL;

	/*
	 * CTL port base address
	 */
	ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (unlikely(ctl_res == NULL))
		return -EINVAL;

	/*
	 * DMA port base address
	 */
	dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
	if (unlikely(dma_res == NULL))
		return -EINVAL;

	/*
	 * IRQ pin
	 */
	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (unlikely(irq_res == NULL))
		return -EINVAL;

	/*
	 * Allocate the host
	 */
	host = ata_host_alloc(&pdev->dev, 1);
	if (!host)
		return -ENOMEM;

	ap		= host->ports[0];
	ap->ops		= &pxa_ata_port_ops;
	ap->pio_mask	= ATA_PIO4;
	ap->mwdma_mask	= ATA_MWDMA2;

	ap->ioaddr.cmd_addr	= devm_ioremap(&pdev->dev, cmd_res->start,
						resource_size(cmd_res));
	ap->ioaddr.ctl_addr	= devm_ioremap(&pdev->dev, ctl_res->start,
						resource_size(ctl_res));
	ap->ioaddr.bmdma_addr	= devm_ioremap(&pdev->dev, dma_res->start,
						resource_size(dma_res));

	/*
	 * Adjust register offsets
	 */
	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
	ap->ioaddr.data_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_DATA << pdata->reg_shift);
	ap->ioaddr.error_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_ERR << pdata->reg_shift);
	ap->ioaddr.feature_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_FEATURE << pdata->reg_shift);
	ap->ioaddr.nsect_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_NSECT << pdata->reg_shift);
	ap->ioaddr.lbal_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_LBAL << pdata->reg_shift);
	ap->ioaddr.lbam_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_LBAM << pdata->reg_shift);
	ap->ioaddr.lbah_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_LBAH << pdata->reg_shift);
	ap->ioaddr.device_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_DEVICE << pdata->reg_shift);
	ap->ioaddr.status_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_STATUS << pdata->reg_shift);
	ap->ioaddr.command_addr	= ap->ioaddr.cmd_addr +
					(ATA_REG_CMD << pdata->reg_shift);

	/*
	 * Allocate and load driver's internal data structure
	 */
	data = devm_kzalloc(&pdev->dev, sizeof(struct pata_pxa_data),
								GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	ap->private_data = data;
	data->dma_dreq = pdata->dma_dreq;
	data->dma_io_addr = dma_res->start;

	/*
	 * Allocate space for the DMA descriptors
	 */
	data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE,
					&data->dma_desc_addr, GFP_KERNEL);
	if (!data->dma_desc)
		return -EINVAL;

	/*
	 * Request the DMA channel
	 */
	data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW,
						pxa_ata_dma_irq, ap);
	if (data->dma_channel < 0)
		return -EBUSY;

	/*
	 * Stop and clear the DMA channel
	 */
	DCSR(data->dma_channel) = 0;

	/*
	 * Activate the ATA host
	 */
	ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt,
				pdata->irq_flags, &pxa_ata_sht);
	if (ret)
		pxa_free_dma(data->dma_channel);

	return ret;
}
Пример #8
0
static int pxa250_irda_start(struct net_device *dev)
{
	struct pxa250_irda *si = dev->priv;
	int err;
	unsigned int flags;
	

	MOD_INC_USE_COUNT;

	__ECHO_IN;
	si->speed = 9600;

	local_irq_save(flags);
	
	err = request_irq(si->fir_irq, pxa250_irda_fir_irq, 0,  dev->name, dev);
	if (err)
		goto err_fir_irq;

	err = request_irq(dev->irq, pxa250_irda_irq, 0, dev->name, dev);
	if (err)
		goto err_irq;

	/*
	 * The interrupt must remain disabled for now.
	 */
	
	disable_irq(dev->irq);
  	disable_irq(si->fir_irq);

	local_irq_restore(flags);


	/* Allocate DMA channel for receiver (not used) */
	err = pxa_request_dma("IrDA receive", DMA_PRIO_LOW, pxa250_irda_rxdma_irq, dev);
	if (err < 0 )
	   goto err_rx_dma;
	si->rxdma_ch=err;

	DRCMRRXICDR = DRCMR_MAPVLD | si->rxdma_ch;
	

	/* Allocate DMA channel for transmit */
	err = pxa_request_dma("IrDA transmit", DMA_PRIO_LOW, pxa250_irda_txdma_irq , dev);
	if (err < 0 )
	   goto err_tx_dma;

	si->txdma_ch=err;

	/*
	 * Make sure that ICP will be able 
	 * to assert the transmit dma request bit
	 * through the peripherals request bus (PREQ)
	 */
	
	DRCMRTXICDR = DRCMR_MAPVLD | si->txdma_ch;

	DBG("rx(not used) channel=%d tx channel=%d\n",si->rxdma_ch,si->txdma_ch);
	
	/* allocate consistent buffers for dma access
	 * buffers have to be aligned and situated in dma capable memory region;
	 */
	si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma);
	if (! si->rxbuf_dma_virt )
		goto err_rxbuf_dma;

	si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN,  &si->txbuf_dma); 
	if (! si->txbuf_dma_virt )
		goto err_txbuf_dma;

	/* Alocate skb for receiver */
	err=pxa250_irda_rx_alloc(si);
	if (err)
	   goto err_rx_alloc;
	
	/*
	 * Setup the serial port for the specified config.
	 */
	err = pxa250_irda_startup(dev);
	if (err)
		goto err_startup;

	pxa250_irda_set_speed(dev,si->speed = 9600);


	/*
	 * Open a new IrLAP layer instance.
	 */
	si->irlap = irlap_open(dev, &si->qos, "pxa250");
	err = -ENOMEM;
	if (!si->irlap)
		goto err_irlap;

	/*
	 * Now enable the interrupt and start the queue
	 */
	si->open = 1;
	enable_irq(dev->irq);
	netif_start_queue(dev);
	return 0;

err_irlap:
	si->open = 0;
	pxa250_sir_irda_shutdown(si);
err_startup:
	dev_kfree_skb(si->rxskb);
err_rx_alloc:	
	consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
err_txbuf_dma:
	consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
err_rxbuf_dma:
	pxa_free_dma(si->txdma_ch);
err_tx_dma:
	pxa_free_dma(si->rxdma_ch);
err_rx_dma:
	free_irq(dev->irq, dev);
err_irq:
	free_irq(si->fir_irq, dev);
err_fir_irq:	
	MOD_DEC_USE_COUNT;
	return err;
}
Пример #9
0
static int pxa3xx_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct pxa3xx_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct pxa3xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
	size_t totsize = params_buffer_bytes(params);
	size_t period = params_period_bytes(params);
	pxa_dma_desc *dma_desc;
	dma_addr_t dma_buff_phys, next_desc_phys;
	int ret;

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	 if (!dma)
		return 0;

	/* this may get called several times by oss emulation
	 * with different params */
	if (prtd->params == NULL) {
		prtd->params = dma;
		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
			      pxa3xx_pcm_dma_irq, substream);
		if (ret < 0)
			return ret;
		prtd->dma_ch = ret;
	} else if (prtd->params != dma) {
		pxa_free_dma(prtd->dma_ch);
		prtd->params = dma;
		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
			      pxa3xx_pcm_dma_irq, substream);
		if (ret < 0)
			return ret;
		prtd->dma_ch = ret;
	}

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
	runtime->dma_bytes = totsize;

	dma_desc = prtd->dma_desc_array;
	next_desc_phys = prtd->dma_desc_array_phys;
	dma_buff_phys = runtime->dma_addr;
	do {
		next_desc_phys += sizeof(pxa_dma_desc);
		dma_desc->ddadr = next_desc_phys;
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			dma_desc->dsadr = dma_buff_phys;
			dma_desc->dtadr = prtd->params->dev_addr;
		} else {
			dma_desc->dsadr = prtd->params->dev_addr;
			dma_desc->dtadr = dma_buff_phys;
		}
		if (period > totsize)
			period = totsize;
		dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN;
		dma_desc++;
		dma_buff_phys += period;
	} while (totsize -= period);
	dma_desc[-1].ddadr = prtd->dma_desc_array_phys;

	return 0;
}
Пример #10
0
int pxa_audio_attach(struct inode *inode, struct file *file,
			 audio_state_t *state)
{
	audio_stream_t *is = state->input_stream;
	audio_stream_t *os = state->output_stream;
	int err;

	down(&state->sem);

	/* access control */
	err = -ENODEV;
	if ((file->f_mode & FMODE_WRITE) && !os)
		goto out;
	if ((file->f_mode & FMODE_READ) && !is)
		goto out;
	err = -EBUSY;
	if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
		goto out;
	if ((file->f_mode & FMODE_READ) && state->rd_ref)
		goto out;

	/* request DMA channels */
	if (file->f_mode & FMODE_WRITE) {
		err = pxa_request_dma(os->name, DMA_PRIO_LOW, 
					  audio_dma_irq, os);
		if (err < 0)
			goto out;
		os->dma_ch = err;
	}
	if (file->f_mode & FMODE_READ) {
		err = pxa_request_dma(is->name, DMA_PRIO_LOW,
					  audio_dma_irq, is);
		if (err < 0) {
			if (file->f_mode & FMODE_WRITE) {
				DRCMRTXPCDR = 0;
				pxa_free_dma(os->dma_ch);
			}
			goto out;
		}
		is->dma_ch = err;
	}

	file->private_data	= state;
	file->f_op->release	= audio_release;
	file->f_op->write	= audio_write;
	file->f_op->read	= audio_read;
	file->f_op->mmap	= audio_mmap;
	file->f_op->poll	= audio_poll;
	file->f_op->ioctl	= audio_ioctl;
	file->f_op->llseek	= no_llseek;

	if ((file->f_mode & FMODE_WRITE)) {
		state->wr_ref = 1;
		os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
		os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
		os->output = 1;
		os->mapped = 0;
		init_waitqueue_head(&os->frag_wq);
		init_waitqueue_head(&os->stop_wq);
		*os->drcmr = os->dma_ch | DRCMR_MAPVLD;
	}
	if (file->f_mode & FMODE_READ) {
		state->rd_ref = 1;
		is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
		is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
		is->output = 0;
		is->mapped = 0;
		init_waitqueue_head(&is->frag_wq);
		init_waitqueue_head(&is->stop_wq);
		*is->drcmr = is->dma_ch | DRCMR_MAPVLD;
	}

	err = 0;

out:
	up(&state->sem);
	return err;
}