static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
{
	struct snd_pcm_substream *substream = dev_id;
	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
	int dcsr;

	dcsr = DCSR(dma_ch);
	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;

	if (dcsr & DCSR_ENDINTR) {
		snd_pcm_period_elapsed(substream);
	} else {
		printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
			rtd->params->name, dma_ch, dcsr );
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
	}
}
Пример #2
0
/* hard_xmit interface of irda device */
static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct pxa_irda *si = netdev_priv(dev);
	int speed = irda_get_next_speed(skb);

	/*
	 * Does this packet contain a request to change the interface
	 * speed?  If so, remember it until we complete the transmission
	 * of this frame.
	 */
	if (speed != si->speed && speed != -1)
		si->newspeed = speed;

	/*
	 * If this is an empty frame, we can bypass a lot.
	 */
	if (skb->len == 0) {
		if (si->newspeed) {
			si->newspeed = 0;
			pxa_irda_set_speed(si, speed);
		}
		dev_kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	netif_stop_queue(dev);

	if (!IS_FIR(si)) {
		si->tx_buff.data = si->tx_buff.head;
		si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);

		/* Disable STUART interrupts and switch to transmit mode. */
		STIER = 0;
		STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;

		/* enable STUART and transmit interrupts */
		STIER = IER_UUE | IER_TIE;
	} else {
		unsigned long mtt = irda_get_mtt(skb);

		si->dma_tx_buff_len = skb->len;
		skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len);

		if (mtt)
			while ((unsigned)(OSCR - si->last_oscr)/4 < mtt)
				cpu_relax();

		/* stop RX DMA,  disable FICP */
		DCSR(si->rxdma) &= ~DCSR_RUN;
		ICCR0 = 0;

		pxa_irda_fir_dma_tx_start(si);
		ICCR0 = ICCR0_ITR | ICCR0_TXE;
	}

	dev_kfree_skb(skb);
	return NETDEV_TX_OK;
}
Пример #3
0
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data)
{
	struct spi_message *msg = drv_data->cur_msg;

	/* Clear and disable interrupts on SSP and DMA channels*/
	pxa2xx_spi_write(drv_data, SSCR1,
			 pxa2xx_spi_read(drv_data, SSCR1)
			 & ~drv_data->dma_cr1);
	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);
}
static int wait_dma_channel_stop(int channel)
{
    unsigned long limit = loops_per_jiffy << 1;

    while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
        cpu_relax();

    return limit;
}
Пример #5
0
void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
{
	struct snd_pcm_substream *substream = dev_id;
	int dcsr;

	dcsr = DCSR(dma_ch);
	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;

	if (dcsr & DCSR_ENDINTR) {
		snd_pcm_period_elapsed(substream);
	} else {
		printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
			dma_ch, dcsr);
		snd_pcm_stream_lock(substream);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(substream);
	}
}
Пример #6
0
static inline void pxa250_dma_stop(int ch)
{
   __ECHO_IN;

   DCSR(ch) &= ~DCSR_RUN;

   __ECHO_OUT;
   
}
Пример #7
0
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
	unsigned long req;

	if (!prtd || !prtd->params)
		return 0;

	if (prtd->dma_ch == -1)
		return -EINVAL;

	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
	DCSR(prtd->dma_ch) = 0;
	DCMD(prtd->dma_ch) = 0;
	req = *(unsigned long *) prtd->params->filter_data;
	DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;

	return 0;
}
Пример #8
0
/* FIR Transmit DMA interrupt handler */
static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
{
	struct net_device *dev = data;
	struct pxa_irda *si = netdev_priv(dev);
	int dcsr;

	dcsr = DCSR(channel);
	DCSR(channel) = dcsr & ~DCSR_RUN;

	if (dcsr & DCSR_ENDINTR)  {
		si->stats.tx_packets++;
		si->stats.tx_bytes += si->dma_tx_buff_len;
	} else {
		si->stats.tx_errors++;
	}

	while (ICSR1 & ICSR1_TBY)
		cpu_relax();
	si->last_oscr = OSCR;

	/*
	 * HACK: It looks like the TBY bit is dropped too soon.
	 * Without this delay things break.
	 */
	udelay(120);

	if (si->newspeed) {
		pxa_irda_set_speed(si, si->newspeed);
		si->newspeed = 0;
	} else {
		int i = 64;

		ICCR0 = 0;
		pxa_irda_fir_dma_rx_start(si);
		while ((ICSR1 & ICSR1_RNE) && i--)
			(void)ICDR;
		ICCR0 = ICCR0_ITR | ICCR0_RXE;

		if (i < 0)
			printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
	}
	netif_wake_queue(dev);
}
Пример #9
0
static int pxa250_get_rx_len(struct pxa250_irda *si)
{
   /*
    * DMA have to be stoped here
    */

   if ( ! (DCSR(si->rxdma_ch) & DCSR_STOPSTATE) )
      printk("warning dma have to be stoped befor counting len\n");
   
   return ( HPSIR_MAX_RXLEN - ( DCMD(si->rxdma_ch) & DCMD_LENGTH ) );
   
}
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);
}
Пример #11
0
static unsigned int audio_poll(struct file *file,
			       struct poll_table_struct *wait)
{
	audio_state_t *state = file->private_data;
	audio_stream_t *is = state->input_stream;
	audio_stream_t *os = state->output_stream;
	unsigned int mask = 0;

	if (file->f_mode & FMODE_READ) {
		/* Start audio input if not already active */
		if (!is->buffers && audio_setup_buf(is))
			return -ENOMEM;
		if (DCSR(is->dma_ch) & DCSR_STOPSTATE) {
			DDADR(is->dma_ch) = 
				is->buffers[is->dma_frag].dma_desc->ddadr;
			DCSR(is->dma_ch) = DCSR_RUN;
		}
		poll_wait(file, &is->frag_wq, wait);
	}

	if (file->f_mode & FMODE_WRITE) {
		if (!os->buffers && audio_setup_buf(os))
			return -ENOMEM;
		poll_wait(file, &os->frag_wq, wait);
	}

	if (file->f_mode & FMODE_READ)
		if (( is->mapped && is->bytecount > 0) ||
		    (!is->mapped && atomic_read(&is->sem.count) > 0))
			mask |= POLLIN | POLLRDNORM;

	if (file->f_mode & FMODE_WRITE)
		if (( os->mapped && os->bytecount > 0) ||
		    (!os->mapped && atomic_read(&os->sem.count) > 0))
			mask |= POLLOUT | POLLWRNORM;

	return mask;
}
Пример #12
0
static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
				      const char *msg)
{
	/* 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);
	pxa2xx_spi_write(drv_data, SSCR1,
			 pxa2xx_spi_read(drv_data, SSCR1)
			 & ~drv_data->dma_cr1);
	if (!pxa25x_ssp_comp(drv_data))
		pxa2xx_spi_write(drv_data, SSTO, 0);
	pxa2xx_spi_flush(drv_data);
	pxa2xx_spi_write(drv_data, SSCR0,
			 pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);

	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);
}
static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct pxa_irda *si = netdev_priv(dev);
	int speed = irda_get_next_speed(skb);

	if (speed != si->speed && speed != -1)
		si->newspeed = speed;

	if (skb->len == 0) {
		if (si->newspeed) {
			si->newspeed = 0;
			pxa_irda_set_speed(si, speed);
		}
		dev_kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	netif_stop_queue(dev);

	if (!IS_FIR(si)) {
		si->tx_buff.data = si->tx_buff.head;
		si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);

		
		STIER = 0;
		STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;

		
		STIER = IER_UUE | IER_TIE;
	} else {
		unsigned long mtt = irda_get_mtt(skb);

		si->dma_tx_buff_len = skb->len;
		skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len);

		if (mtt)
			while ((unsigned)(OSCR - si->last_oscr)/4 < mtt)
				cpu_relax();

		
		DCSR(si->rxdma) &= ~DCSR_RUN;
		ICCR0 = 0;

		pxa_irda_fir_dma_tx_start(si);
		ICCR0 = ICCR0_ITR | ICCR0_TXE;
	}

	dev_kfree_skb(skb);
	return NETDEV_TX_OK;
}
Пример #14
0
Файл: dma.c Проект: 274914765/C
void pxa_free_dma (int dma_ch)
{
    unsigned long flags;

    if (!dma_channels[dma_ch].name) {
        printk (KERN_CRIT
            "%s: trying to free channel %d which is already freed\n",
            __func__, dma_ch);
        return;
    }

    local_irq_save(flags);
    DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
    dma_channels[dma_ch].name = NULL;
    local_irq_restore(flags);
}
Пример #15
0
int pxa_request_dma (char *name, pxa_dma_prio prio,
			 void (*irq_handler)(int, void *, struct pt_regs *),
		 	 void *data)
{
	unsigned long flags;
	int i, found = 0;

	/* basic sanity checks */
	if (!name || !irq_handler)
		return -EINVAL;

	local_irq_save(flags);

	/* try grabbing a DMA channel with the requested priority */
	for (i = prio; i < prio + PXA_DMA_NBCH(prio); i++) {
		if (!dma_channels[i].name) {
			found = 1;
			break;
		}
	}

	if (!found) {
		/* requested prio group is full, try hier priorities */
		for (i = prio-1; i >= 0; i--) {
			if (!dma_channels[i].name) {
				found = 1;
				break;
			}
		}
	}

	if (found) {
		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
		dma_channels[i].name = name;
		dma_channels[i].irq_handler = irq_handler;
		dma_channels[i].data = data;
	} else {
		printk (KERN_WARNING "No more available DMA channels for %s\n", name);
		i = -ENODEV;
	}

	local_irq_restore(flags);
	return i;
}
Пример #16
0
/*
 * Validate and sets up buffer fragments, etc.
 */
static int audio_set_fragments(audio_stream_t *s, int val)
{
	if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN)
		return -EBUSY;
	if (s->buffers)
		audio_clear_buf(s);
	s->nbfrags = (val >> 16) & 0x7FFF;
	val &= 0xffff;
	if (val < 5)
		val = 5;
	if (val > 15)
		val = 15;
	s->fragsize = 1 << val;
	if (s->nbfrags < 2)
		s->nbfrags = 2;
	if (s->nbfrags * s->fragsize > 256 * 1024)
		s->nbfrags = 256 * 1024 / s->fragsize;
	if (audio_setup_buf(s))
		return -ENOMEM;
	return val|(s->nbfrags << 16);
}
Пример #17
0
Файл: dma.c Проект: 274914765/C
static irqreturn_t dma_irq_handler(int irq, void *dev_id)
{
    int i, dint = DINT;

    for (i = 0; i < num_dma_channels; i++) {
        if (dint & (1 << i)) {
            struct dma_channel *channel = &dma_channels[i];
            if (channel->name && channel->irq_handler) {
                channel->irq_handler(i, channel->data);
            } else {
                /*
                 * IRQ for an unregistered DMA channel:
                 * let's clear the interrupts and disable it.
                 */
                printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
                DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
            }
        }
    }
    return IRQ_HANDLED;
}
Пример #18
0
Файл: dma.c Проект: 274914765/C
int pxa_request_dma (char *name, pxa_dma_prio prio,
             void (*irq_handler)(int, void *),
              void *data)
{
    unsigned long flags;
    int i, found = 0;

    /* basic sanity checks */
    if (!name || !irq_handler)
        return -EINVAL;

    local_irq_save(flags);

    do {
        /* try grabbing a DMA channel with the requested priority */
        for (i = 0; i < num_dma_channels; i++) {
            if ((dma_channels[i].prio == prio) &&
                !dma_channels[i].name) {
                found = 1;
                break;
            }
        }
        /* if requested prio group is full, try a hier priority */
    } while (!found && prio--);

    if (found) {
        DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
        dma_channels[i].name = name;
        dma_channels[i].irq_handler = irq_handler;
        dma_channels[i].data = data;
    } else {
        printk (KERN_WARNING "No more available DMA channels for %s\n", name);
        i = -ENODEV;
    }

    local_irq_restore(flags);
    return i;
}
Пример #19
0
/* FIR interrupt handler */
static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct pxa_irda *si = netdev_priv(dev);
	int icsr0, i = 64;

	/* stop RX DMA */
	DCSR(si->rxdma) &= ~DCSR_RUN;
	si->last_oscr = OSCR;
	icsr0 = ICSR0;

	if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
		if (icsr0 & ICSR0_FRE) {
		        printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
			si->stats.rx_frame_errors++;
		} else {
			printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
			si->stats.rx_errors++;
		}
		ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
	}

	if (icsr0 & ICSR0_EIF) {
		/* An error in FIFO occured, or there is a end of frame */
		pxa_irda_fir_irq_eif(si, dev, icsr0);
	}

	ICCR0 = 0;
	pxa_irda_fir_dma_rx_start(si);
	while ((ICSR1 & ICSR1_RNE) && i--)
		(void)ICDR;
	ICCR0 = ICCR0_ITR | ICCR0_RXE;

	if (i < 0)
		printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");

	return IRQ_HANDLED;
}
Пример #20
0
static int audio_ioctl( struct inode *inode, struct file *file,
			uint cmd, ulong arg)
{
	audio_state_t *state = file->private_data;
	audio_stream_t *os = state->output_stream;
	audio_stream_t *is = state->input_stream;
	long val;

	switch (cmd) {
	case OSS_GETVERSION:
		return put_user(SOUND_VERSION, (int *)arg);

	case SNDCTL_DSP_GETBLKSIZE:
		if (file->f_mode & FMODE_WRITE)
			return put_user(os->fragsize, (int *)arg);
		else
			return put_user(is->fragsize, (int *)arg);

	case SNDCTL_DSP_GETCAPS:
		val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
		if (is && os)
			val |= DSP_CAP_DUPLEX;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETFRAGMENT:
		if (get_user(val, (long *) arg))
			return -EFAULT;
		if (file->f_mode & FMODE_READ) {
			int ret = audio_set_fragments(is, val);
			if (ret < 0)
				return ret;
			ret = put_user(ret, (int *)arg);
			if (ret)
				return ret;
		}
		if (file->f_mode & FMODE_WRITE) {
			int ret = audio_set_fragments(os, val);
			if (ret < 0)
				return ret;
			ret = put_user(ret, (int *)arg);
			if (ret)
				return ret;
		}
		return 0;

	case SNDCTL_DSP_SYNC:
		return audio_sync(file);

	case SNDCTL_DSP_SETDUPLEX:
		return 0;

	case SNDCTL_DSP_POST:
		return 0;

	case SNDCTL_DSP_GETTRIGGER:
		val = 0;
		if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN)
			val |= PCM_ENABLE_INPUT;
		if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN)
			val |= PCM_ENABLE_OUTPUT;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETTRIGGER:
		if (get_user(val, (int *)arg))
			return -EFAULT;
		if (file->f_mode & FMODE_READ) {
			if (val & PCM_ENABLE_INPUT) {
				if (!is->buffers && audio_setup_buf(is))
					return -ENOMEM;
				if (!(DCSR(is->dma_ch) & DCSR_RUN)) {
					audio_buf_t *b = &is->buffers[is->dma_frag];
					DDADR(is->dma_ch) = b->dma_desc->ddadr;
					DCSR(is->dma_ch) = DCSR_RUN;
				}
			} else {
				DCSR(is->dma_ch) = 0;
			}
		}
		if (file->f_mode & FMODE_WRITE) {
			if (val & PCM_ENABLE_OUTPUT) {
				if (!os->buffers && audio_setup_buf(os))
					return -ENOMEM;
				if (!(DCSR(os->dma_ch) & DCSR_RUN)) {
					audio_buf_t *b = &os->buffers[os->dma_frag];
					DDADR(os->dma_ch) = b->dma_desc->ddadr;
					DCSR(os->dma_ch) = DCSR_RUN;
				}
			} else {
				DCSR(os->dma_ch) = 0;
			}
		}
		return 0;

	case SNDCTL_DSP_GETOSPACE:
	case SNDCTL_DSP_GETISPACE:
	    {
		audio_buf_info inf = { 0, };
		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;

		if ((s == is && !(file->f_mode & FMODE_READ)) ||
		    (s == os && !(file->f_mode & FMODE_WRITE)))
			return -EINVAL;
		if (!s->buffers && audio_setup_buf(s))
			return -ENOMEM;
		inf.bytes = atomic_read(&s->sem.count) * s->fragsize;
		inf.bytes -= s->buffers[s->usr_frag].offset;
		inf.fragments = inf.bytes / s->fragsize;
		inf.fragsize = s->fragsize;
		inf.fragstotal = s->nbfrags;
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_GETOPTR:
	case SNDCTL_DSP_GETIPTR:
	    {
		count_info inf = { 0, };
		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
		dma_addr_t ptr;
		int bytecount, offset, flags;

		if ((s == is && !(file->f_mode & FMODE_READ)) ||
		    (s == os && !(file->f_mode & FMODE_WRITE)))
			return -EINVAL;
		if (DCSR(s->dma_ch) & DCSR_RUN) {
			audio_buf_t *b;
			save_flags_cli(flags);
			ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch);
			b = &s->buffers[s->dma_frag];
			offset = ptr - b->dma_desc->dsadr;
			if (offset >= s->fragsize)
				offset = s->fragsize - 4;
		} else {
			save_flags(flags);
			offset = 0;
		}
		inf.ptr = s->dma_frag * s->fragsize + offset;
		bytecount = s->bytecount + offset;
		s->bytecount = -offset;
		inf.blocks = s->fragcount;
		s->fragcount = 0;
		restore_flags(flags);
		if (bytecount < 0)
			bytecount = 0;
		inf.bytes = bytecount;
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_NONBLOCK:
		file->f_flags |= O_NONBLOCK;
		return 0;

	case SNDCTL_DSP_RESET:
		if (file->f_mode & FMODE_WRITE) 
			audio_clear_buf(os);
		if (file->f_mode & FMODE_READ)
			audio_clear_buf(is);
		return 0;

	default:
		return state->client_ioctl(inode, file, cmd, arg);
	}

	return 0;
}
Пример #21
0
static int audio_read(struct file *file, char *buffer,
		      size_t count, loff_t * ppos)
{
	char *buffer0 = buffer;
	audio_state_t *state = file->private_data;
	audio_stream_t *s = state->input_stream;
	int chunksize, ret = 0;

	if (ppos != &file->f_pos)
		return -ESPIPE;
	if (s->mapped)
		return -ENXIO;
	if (!s->buffers && audio_setup_buf(s))
		return -ENOMEM;

	while (count > 0) {
		audio_buf_t *b = &s->buffers[s->usr_frag];

		/* prime DMA */
		if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
			DDADR(s->dma_ch) = 
				s->buffers[s->dma_frag].dma_desc->ddadr;
			DCSR(s->dma_ch) = DCSR_RUN;
		}

		/* Wait for a buffer to become full */
		if (file->f_flags & O_NONBLOCK) {
			ret = -EAGAIN;
			if (down_trylock(&s->sem))
				break;
		} else {
			ret = -ERESTARTSYS;
			if (down_interruptible(&s->sem))
				break;
		}

		/* Grab data from current buffer */
		chunksize = s->fragsize - b->offset;
		if (chunksize > count)
			chunksize = count;
		if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
			up(&s->sem);
			return -EFAULT;
		}
		b->offset += chunksize;
		buffer += chunksize;
		count -= chunksize;
		if (b->offset < s->fragsize) {
			up(&s->sem);
			break;
		}

		/* 
		 * Make this buffer available for DMA again.
		 * We unlock this fragment's checkpoint descriptor and
		 * kick DMA if it is idle.  Using checkpoint descriptors
		 * allows for control operations without the need for 
		 * stopping the DMA channel if it is already running.
		 */
		b->offset = 0;
		b->dma_desc->ddadr &= ~DDADR_STOP;

		/* move the index to the next fragment */
		if (++s->usr_frag >= s->nbfrags)
			s->usr_frag = 0;
	}

	if ((buffer - buffer0))
		ret = buffer - buffer0;
	return ret;
}
Пример #22
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;
}
Пример #23
0
/*
 * Set the IrDA communications speed.
 */
static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
{
	unsigned long flags;
	unsigned int divisor;

	switch (speed) {
	case 9600:	case 19200:	case 38400:
	case 57600:	case 115200:

		/* refer to PXA250/210 Developer's Manual 10-7 */
		/*  BaudRate = 14.7456 MHz / (16*Divisor) */
		divisor = 14745600 / (16 * speed);

		local_irq_save(flags);

		if (IS_FIR(si)) {
			/* stop RX DMA */
			DCSR(si->rxdma) &= ~DCSR_RUN;
			/* disable FICP */
			ICCR0 = 0;
			pxa_irda_disable_clk(si);

			/* set board transceiver to SIR mode */
			si->pdata->transceiver_mode(si->dev, IR_SIRMODE);

			/* enable the STUART clock */
			pxa_irda_enable_sirclk(si);
		}

		/* disable STUART first */
		STIER = 0;

		/* access DLL & DLH */
		STLCR |= LCR_DLAB;
		STDLL = divisor & 0xff;
		STDLH = divisor >> 8;
		STLCR &= ~LCR_DLAB;

		si->speed = speed;
		STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
		STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;

		local_irq_restore(flags);
		break;

	case 4000000:
		local_irq_save(flags);

		/* disable STUART */
		STIER = 0;
		STISR = 0;
		pxa_irda_disable_clk(si);

		/* disable FICP first */
		ICCR0 = 0;

		/* set board transceiver to FIR mode */
		si->pdata->transceiver_mode(si->dev, IR_FIRMODE);

		/* enable the FICP clock */
		pxa_irda_enable_firclk(si);

		si->speed = speed;
		pxa_irda_fir_dma_rx_start(si);
		ICCR0 = ICCR0_ITR | ICCR0_RXE;

		local_irq_restore(flags);
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
Пример #24
0
static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct pxa250_irda *si = dev->priv;
	int speed = irda_get_next_speed(skb);
	int mtt;
	
  	__ECHO_IN; 

	/*
	 * Does this packet contain a request to change the interface
	 * speed?  If so, remember it until we complete the transmission
	 * of this frame.
	 */
	if (speed != si->speed && speed != -1)
		si->newspeed = speed;

	/*
	 * If this is an empty frame, we can bypass a lot.
	 */
	if (skb->len == 0) {
		if (si->newspeed) {
			si->newspeed = 0;
			pxa250_irda_set_speed(dev, speed);
		}
		dev_kfree_skb(skb);
		return 0;
	}


  	DBG("stop queue\n"); 
	netif_stop_queue(dev);

	if(!IS_FIR(si))
	{
	   
	   si->tx_buff.data = si->tx_buff.head;
	   si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data,
						  si->tx_buff.truesize);

        
	   pxa250_sir_transmit(dev);

	
	
	   dev_kfree_skb(skb);

	   dev->trans_start = jiffies;

	   return 0;
	}
	else /* FIR */
	{
	   DBG("Enter FIR transmit\n");
	   /*
	    * We must not be transmitting...
	    */
	   if (si->txskb)
	      BUG();

      	   disable_irq(si->fir_irq); 
	   
	   netif_stop_queue(dev);
	   DBG("queue stoped\n");
	   si->txskb = skb;

	   /* we could not just map so we'll need some triks */
	   /* skb->data may be not DMA capable -Sed- */


	   if (skb->len > TXBUFF_MAX_SIZE)
	   {
	      printk (KERN_ERR "skb data too large\n");
	      printk (KERN_ERR "len=%d",skb->len);
	      BUG();
	   }
		

	   DBG("gonna copy %d bytes to txbuf\n",skb->len);

	   memcpy (si->txbuf_dma_virt, skb->data , skb->len);
	   
	   /* Actual sending ;must not be receiving !!! */
	   /* Write data and source address */

	   DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 );

	   /*Disable receiver and enable transifer */
  	   ICCR0 &= ~ICCR0_RXE;      
	   
	   if (ICSR1 & ICSR1_TBY)
	      BUG();

    	   ICCR0 |= ICCR0_TXE;  
		
	   DBG("FICP status %x\n",ICSR0);

	   if (0){
	      int i;
		   
	      DBG("sending packet\n");
	      for (i=0;i<skb->len;i++)
		 (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ;
	      DBG(" done\n");
   
	   }
	   /*
	    * If we have a mean turn-around time, impose the specified
	    * specified delay.  We could shorten this by timing from
	    * the point we received the packet.
	    */
	   
	   mtt = irda_get_mtt(skb); 
	   if(mtt)    
	      udelay(mtt);    
	   
	   DCSR(si->txdma_ch)=0;
	   DCSR(si->txdma_ch)=DCSR_NODESC;
	   DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */
	   DTADR(si->txdma_ch) = __PREG(ICDR);
		
	   DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len;

	   DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR;
	   DCSR(si->txdma_ch) = DCSR_RUN | DCSR_NODESC ;

	   DBG("FICP status %x\n",ICSR0);

	   return 0;
	}
	
}
Пример #25
0
/*
 * Execute the DMA transfer.
 */
static void pxa_bmdma_start(struct ata_queued_cmd *qc)
{
	struct pata_pxa_data *pd = qc->ap->private_data;
	init_completion(&pd->dma_done);
	DCSR(pd->dma_channel) = DCSR_RUN;
}
static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
{
	unsigned long flags;
	unsigned int divisor;

	switch (speed) {
	case 9600:	case 19200:	case 38400:
	case 57600:	case 115200:

		
		
		divisor = 14745600 / (16 * speed);

		local_irq_save(flags);

		if (IS_FIR(si)) {
			
			DCSR(si->rxdma) &= ~DCSR_RUN;
			
			ICCR0 = 0;
			pxa_irda_disable_clk(si);

			
			pxa_irda_set_mode(si, IR_SIRMODE);

			
			pxa_irda_enable_sirclk(si);
		}

		
		STIER = 0;

		
		STLCR |= LCR_DLAB;
		STDLL = divisor & 0xff;
		STDLH = divisor >> 8;
		STLCR &= ~LCR_DLAB;

		si->speed = speed;
		STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
		STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;

		local_irq_restore(flags);
		break;

	case 4000000:
		local_irq_save(flags);

		
		STIER = 0;
		STISR = 0;
		pxa_irda_disable_clk(si);

		
		ICCR0 = 0;

		
		pxa_irda_set_mode(si, IR_FIRMODE);

		
		pxa_irda_enable_firclk(si);

		si->speed = speed;
		pxa_irda_fir_dma_rx_start(si);
		ICCR0 = ICCR0_ITR | ICCR0_RXE;

		local_irq_restore(flags);
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
Пример #27
0
static void pxa250_irda_txdma_irq(int ch, void *id , struct pt_regs *regs)
{
   struct net_device *dev=id;
   struct pxa250_irda *si=dev->priv;
   struct sk_buff *skb = si->txskb;
   u_int dcsr;


   __ECHO_IN;
   DBG_IRQ("transmit\n"); 
   
     
   /* 
    * Make sure that irq is our.
    */

   if ( ch != si->txdma_ch )
      /*just*/ return;


   /*
    * Check status 
    */
   dcsr = DCSR(ch);

   DBG("DCSR=%x",dcsr);

   if (dcsr &  DCSR_STOPSTATE )
   {
      DBG("Chanel %d in stop state\n",ch);
   }

   if (dcsr &  DCSR_BUSERR )
   {
      DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
      DCSR(ch) |= DCSR_BUSERR;
      si->txskb = NULL;
   }

   if (dcsr &  DCSR_ENDINTR )
   {
      DBG("PXA IrDA: Normal end of dma channel %d\n", ch);
      DCSR(ch) |= DCSR_ENDINTR;
      si->txskb = NULL;
   }

   /*
    * Account and free the packet.
    */
   if (skb)
   {
      si->stats.tx_packets ++;
      si->stats.tx_bytes += skb->len;
      dev_kfree_skb_irq(skb);
   }

	/*Disable transceiver and enable receiver*/

	if (si->newspeed) {
	   pxa250_irda_set_speed(dev, si->newspeed);
	   si->newspeed = 0;
	}

	while (ICSR1 & ICSR1_TBY)
	   udelay(1);
	
     	ICCR0 &= ~ICCR0_TXE;

	
	enable_irq(si->fir_irq);

  	ICCR0 |= ICCR0_RXE; 

	/*
	 * Make sure that the TX queue is available for sending
	 * (for retries).  TX has priority over RX at all times.
	 */
	netif_wake_queue(dev);
	
	__ECHO_OUT;
}
Пример #28
0
/*
 * Our DMA interrupt handler
 */
static void audio_dma_irq(int ch, void *dev_id, struct pt_regs *regs)
{
	audio_stream_t *s = dev_id;
	u_int dcsr;

	dcsr = DCSR(ch);
	DCSR(ch) = dcsr & ~DCSR_STOPIRQEN;

	if (!s->buffers) {
		printk("AC97 DMA: wow... received IRQ for channel %d but no buffer exists\n", ch);
		return;
	}

	if (dcsr & DCSR_BUSERR)
		printk("AC97 DMA: bus error interrupt on channel %d\n", ch);

	if (dcsr & DCSR_ENDINTR) {
		u_long cur_dma_desc;
		u_int cur_dma_frag;

		/* 
		 * Find out which DMA desc is current.  Note that DDADR
		 * points to the next desc, not the current one.
		 */
		cur_dma_desc = DDADR(ch) - s->dma_desc_phys - DMA_DESC_SIZE;

		/*
		 * Let the compiler nicely optimize constant divisors into
		 * multiplications for the common cases which is much faster.
		 * Common cases: x = 1 + (1 << y) for y = [0..3]
		 */
		switch (s->descs_per_frag) {
		case 2:  cur_dma_frag = cur_dma_desc / (2*DMA_DESC_SIZE); break;
		case 3:  cur_dma_frag = cur_dma_desc / (3*DMA_DESC_SIZE); break;
		case 5:  cur_dma_frag = cur_dma_desc / (5*DMA_DESC_SIZE); break;
		case 9:  cur_dma_frag = cur_dma_desc / (9*DMA_DESC_SIZE); break;
		default: cur_dma_frag =
			    cur_dma_desc / (s->descs_per_frag * DMA_DESC_SIZE);
		}

		/* Account for possible wrap back of cur_dma_desc above */
		if (cur_dma_frag >= s->nbfrags)
			cur_dma_frag = s->nbfrags - 1;

		while (s->dma_frag != cur_dma_frag) {
			if (!s->mapped) {
				/* 
				 * This fragment is done - set the checkpoint
				 * descriptor to STOP until it is gets
				 * processed by the read or write function.
				 */
				s->buffers[s->dma_frag].dma_desc->ddadr |= DDADR_STOP;
				up(&s->sem);
			}
			if (++s->dma_frag >= s->nbfrags)
				s->dma_frag = 0;

			/* Accounting */
			s->bytecount += s->fragsize;
			s->fragcount++;
		}

		/* ... and for polling processes */
		wake_up(&s->frag_wq);
	}

	if ((dcsr & DCSR_STOPIRQEN) && (dcsr & DCSR_STOPSTATE))
		wake_up(&s->stop_wq);
}
int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
{
    u32 dma_width;

    switch (drv_data->n_bytes) {
    case 1:
        dma_width = DCMD_WIDTH1;
        break;
    case 2:
        dma_width = DCMD_WIDTH2;
        break;
    default:
        dma_width = DCMD_WIDTH4;
        break;
    }

    /* Setup rx DMA Channel */
    DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
    DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
    DTADR(drv_data->rx_channel) = drv_data->rx_dma;
    if (!drv_data->spi_inc_mode) {
        if (drv_data->rx == drv_data->null_dma_buf)
            /* No target address increment */
            DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
                                         | dma_width
                                         | dma_burst
                                         | drv_data->len;
        else
            DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
                                         | DCMD_FLOWSRC
                                         | dma_width
                                         | dma_burst
                                         | drv_data->len;
    } else
        DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
                                     | DCMD_FLOWSRC
                                     | dma_width
                                     | dma_burst
                                     | drv_data->len;

    /* Setup tx DMA Channel */
    DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
    DSADR(drv_data->tx_channel) = drv_data->tx_dma;
    DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
    if (!drv_data->spi_inc_mode) {
        if (drv_data->tx == drv_data->null_dma_buf)
            /* No source address increment */
            DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
                                         | dma_width
                                         | dma_burst
                                         | drv_data->len;
        else
            DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
                                         | DCMD_FLOWTRG
                                         | dma_width
                                         | dma_burst
                                         | drv_data->len;
    } else
        DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
                                     | DCMD_FLOWTRG
                                     | dma_width
                                     | dma_burst
                                     | drv_data->len;

    /* Enable dma end irqs on SSP to detect end of transfer */
    if (drv_data->ssp_type == PXA25x_SSP)
        DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;

    return 0;
}
void pxa2xx_spi_dma_start(struct driver_data *drv_data)
{
    DCSR(drv_data->rx_channel) |= DCSR_RUN;
    DCSR(drv_data->tx_channel) |= DCSR_RUN;
}