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); } }
/* 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; }
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; }
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); } }
static inline void pxa250_dma_stop(int ch) { __ECHO_IN; DCSR(ch) &= ~DCSR_RUN; __ECHO_OUT; }
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; }
/* 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); }
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); }
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; }
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; }
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); }
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; }
/* * 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); }
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; }
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; }
/* 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; }
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; }
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; }
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; }
/* * 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; }
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; } }
/* * 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; }
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; }
/* * 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; }