static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, struct mmc_data *data, struct scatterlist *sgl) { int blksz, nblk, dma_ch; dma_ch = host->dma_ch; if (data->flags & MMC_DATA_WRITE) { omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, (host->mapbase + OMAP_HSMMC_DATA), 0, 0); omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, sg_dma_address(sgl), 0, 0); } else { omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, (host->mapbase + OMAP_HSMMC_DATA), 0, 0); omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, sg_dma_address(sgl), 0, 0); } blksz = host->data->blksz; nblk = sg_dma_len(sgl) / blksz; omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, blksz / 4, nblk, OMAP_DMA_SYNC_FRAME, omap_hsmmc_get_dma_sync_dev(host, data), !(data->flags & MMC_DATA_WRITE)); omap_start_dma(dma_ch); }
static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr, u_int dma_size) { int dt = 0x1; /* data type 16 */ int cen = 16; /* mono */ int cfn = dma_size / (2 * cen); unsigned long src_start; int src_port = 0; int sync_dev = 0; int src_sync = 0; FN_IN; if (cpu_is_omap16xx()) { src_start = (OMAP1610_MCBSP1_BASE + 0x802); src_port = OMAP_DMA_PORT_MPUI; } if (cpu_is_omap24xx()) { src_start = AUDIO_MCBSP_DATAREAD; sync_dev = AUDIO_DMA_RX; src_sync = 1; } omap_set_dma_src_params(channel, src_port, OMAP_DMA_AMODE_CONSTANT, src_start, 0, 0); omap_set_dma_dest_params(channel, 0, OMAP_DMA_AMODE_POST_INC, dma_ptr, 0, 0); omap_set_dma_transfer_params(channel, dt, cen, cfn, OMAP_DMA_SYNC_ELEMENT, sync_dev, src_sync); FN_OUT(0); return 0; }
static int serial_omap_start_rxdma(struct uart_omap_port *up) { int ret = 0; if (up->uart_dma.rx_dma_channel == -1) { pm_runtime_get_sync(&up->pdev->dev); ret = omap_request_dma(up->uart_dma.uart_dma_rx, "UART Rx DMA", (void *)uart_rx_dma_callback, up, &(up->uart_dma.rx_dma_channel)); if (ret < 0) return ret; omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, up->uart_dma.rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.rx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_rx, 0); } up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; omap_start_dma(up->uart_dma.rx_dma_channel); mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_poll_rate)); up->uart_dma.rx_dma_used = true; return ret; }
static void serial_omap_continue_tx(struct uart_omap_port *up) { struct circ_buf *xmit = &up->port.state->xmit; unsigned int start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); if (uart_circ_empty(xmit)) return; up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); /* * It is a circular buffer. See if the buffer has wounded back. * If yes it will have to be transferred in two separate dma * transfers */ if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_tx, 0); /* FIXME: Cache maintenance needed here? */ omap_start_dma(up->uart_dma.tx_dma_channel); }
static void serial_omap_continue_tx(struct uart_omap_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); if (uart_circ_empty(xmit)) { return; } up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); /* It is a circular buffer. See if the buffer has wounded back. * If yes it will have to be transferred in two separate dma * transfers */ if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, UART_BASE(up->pdev->id - 1), 0,0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0,0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_tx[(up->pdev->id)-1], 0); omap_start_dma(up->uart_dma.tx_dma_channel); }
static void serial_omap_continue_tx(struct uart_omap_port *up) { struct circ_buf *xmit = &up->port.state->xmit; unsigned int start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); if (uart_circ_empty(xmit)) return; up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_tx, 0); omap_start_dma(up->uart_dma.tx_dma_channel); }
static void serial_omap_start_rxdma(struct uart_omap_port *up) { #ifdef CONFIG_OMAP3_PM /* Disallow OCP bus idle. UART TX irqs are not seen during * bus idle. Alternative is to set kernel timer at fifo * drain rate. */ unsigned int tmp; tmp = (serial_in(up, UART_OMAP_SYSC) & 0x7) | (1 << 3); serial_out(up, UART_OMAP_SYSC, tmp); /* no-idle */ #endif if (up->uart_dma.rx_dma_channel == 0xFF) { omap_request_dma(uart_dma_rx[up->pdev->id-1],"UART Rx DMA", (void *)uart_rx_dma_callback,up, &(up->uart_dma.rx_dma_channel)); omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, UART_BASE(up->pdev->id - 1), 0, 0); omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, up->uart_dma.rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.rx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_rx[up->pdev->id-1], 0); } up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; omap_writel(0, OMAP34XX_DMA4_BASE + OMAP_DMA4_CDAC(up->uart_dma.rx_dma_channel)); omap_start_dma(up->uart_dma.rx_dma_channel); mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_timeout)); up->uart_dma.rx_dma_state = 1; }
static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; struct circ_buf *xmit; unsigned int start; int ret = 0; if (!up->use_dma) { serial_omap_enable_ier_thri(up); return; } if (up->uart_dma.tx_dma_used) return; xmit = &up->port.state->xmit; if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { ret = omap_request_dma(up->uart_dma.uart_dma_tx, "UART Tx DMA", (void *)uart_tx_dma_callback, up, &(up->uart_dma.tx_dma_channel)); if (ret < 0) { serial_omap_enable_ier_thri(up); return; } } spin_lock(&(up->uart_dma.tx_lock)); up->uart_dma.tx_dma_used = true; spin_unlock(&(up->uart_dma.tx_lock)); start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); /* * It is a circular buffer. See if the buffer has wounded back. * If yes it will have to be transferred in two separate dma * transfers */ if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_tx, 0); /* FIXME: Cache maintenance needed here? */ omap_start_dma(up->uart_dma.tx_dma_channel); }
/*************************************************************************************** * * DMA related functions * **************************************************************************************/ static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr, u_int dma_size) { int dt = 0x1; /* data type 16 */ int cen = 32; /* Stereo */ int cfn = dma_size / (2 * cen); unsigned long dest_start; int dest_port = 0; int sync_dev = 0; FN_IN; if (cpu_is_omap16xx()) { dest_start = (OMAP1610_MCBSP1_BASE + 0x806); dest_port = OMAP_DMA_PORT_MPUI; } if (cpu_is_omap24xx()) { dest_start = AUDIO_MCBSP_DATAWRITE; sync_dev = AUDIO_DMA_TX; } omap_set_dma_dest_params(channel, dest_port, OMAP_DMA_AMODE_CONSTANT, dest_start, 0, 0); omap_set_dma_src_params(channel, 0, OMAP_DMA_AMODE_POST_INC, dma_ptr, 0, 0); omap_set_dma_transfer_params(channel, dt, cen, cfn, OMAP_DMA_SYNC_ELEMENT, sync_dev, 0); FN_OUT(0); return 0; }
static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; #ifdef CONFIG_OMAP3_PM /* Disallow OCP bus idle. UART TX irqs are not seen during * bus idle. Alternative is to set kernel timer at fifo * drain rate. */ unsigned int tmp; tmp = (serial_in(up, UART_OMAP_SYSC) & 0x7) | (1 << 3); serial_out(up, UART_OMAP_SYSC, tmp); /* no-idle */ #endif if (up->use_dma && !(up->port.x_char)) { struct circ_buf *xmit = &up->port.info->xmit; unsigned int start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); if (uart_circ_empty(xmit) || up->uart_dma.tx_dma_state) return; spin_lock(&(up->uart_dma.tx_lock)); up->uart_dma.tx_dma_state = 1; spin_unlock(&(up->uart_dma.tx_lock)); up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); /* It is a circular buffer. See if the buffer has wounded back. * If yes it will have to be transferred in two separate dma * transfers */ if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; if (up->uart_dma.tx_dma_channel == 0xFF) omap_request_dma(uart_dma_tx[up->pdev->id-1], "UART Tx DMA", (void *)uart_tx_dma_callback, up, &(up->uart_dma.tx_dma_channel)); omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, UART_BASE(up->pdev->id - 1), 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_tx[(up->pdev->id)-1], 0); omap_start_dma(up->uart_dma.tx_dma_channel); } else if (!(up->ier & UART_IER_THRI)) { up->ier |= UART_IER_THRI; serial_out(up, UART_IER, up->ier); } }
/* * Configure dma src and destination parameters */ static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host, struct mmc_data *data) { if (sync_dir == 0) { omap_set_dma_dest_params(host->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, (host->mapbase + OMAP_HSMMC_DATA), 0, 0); omap_set_dma_src_params(host->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, sg_dma_address(&data->sg[0]), 0, 0); } else { omap_set_dma_src_params(host->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, (host->mapbase + OMAP_HSMMC_DATA), 0, 0); omap_set_dma_dest_params(host->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, sg_dma_address(&data->sg[0]), 0, 0); } return 0; }
static void omap1610_irda_start_rx_dma(struct omap1610_irda *si) { /* Configure DMA */ omap_set_dma_src_params(si->rx_dma_channel, 0x3, 0x0, (unsigned long)UART3_RHR); omap_enable_dma_irq(si->rx_dma_channel, 0x01); omap_set_dma_dest_params(si->rx_dma_channel, 0x0, 0x1, si->rx_buf_dma_phys); omap_set_dma_transfer_params(si->rx_dma_channel, 0x0, 4096, 0x1, 0x0); omap_start_dma(si->rx_dma_channel); }
static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr, u_int dma_size) { int dt = 0x1; /* data type 16 */ int cen = 32; /* stereo */ int cfn = dma_size / (2 * cen); FN_IN; omap_set_dma_src_params(channel, 0x05, 0x00, (OMAP1510_MCBSP1_BASE + 0x02), 0, 0); omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr, 0, 0); omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0); FN_OUT(0); return 0; }
void omap_set_dma_params(int lch, struct omap_dma_channel_params *params) { omap_set_dma_transfer_params(lch, params->data_type, params->elem_count, params->frame_count, params->sync_mode, params->trigger, params->src_or_dst_synch); omap_set_dma_src_params(lch, params->src_port, params->src_amode, params->src_start, params->src_ei, params->src_fi); omap_set_dma_dest_params(lch, params->dst_port, params->dst_amode, params->dst_start, params->dst_ei, params->dst_fi); if (params->read_prio || params->write_prio) omap_dma_set_prio_lch(lch, params->read_prio, params->write_prio); }
static void omap_start_tx_dma(struct omap_irda *omap_ir, int size) { /* Configure DMA */ omap_set_dma_dest_params(omap_ir->tx_dma_channel, 0x03, 0x0, omap_ir->pdata->dest_start, 0, 0); omap_enable_dma_irq(omap_ir->tx_dma_channel, 0x01); omap_set_dma_src_params(omap_ir->tx_dma_channel, 0x0, 0x1, omap_ir->tx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(omap_ir->tx_dma_channel, 0x0, size, 0x1, 0x0, omap_ir->pdata->tx_trigger, 0); /* Start DMA */ omap_start_dma(omap_ir->tx_dma_channel); }
static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area, const unsigned char *buffer, int offset, size_t count) { struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); struct onenand_chip *this = mtd->priv; dma_addr_t dma_src, dma_dst; int bram_offset; bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset; /* DMA is not used. Revisit PM requirements before enabling it. */ if (1 || (c->dma_channel < 0) || ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) || (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) { memcpy((__force void *)(this->base + bram_offset), buffer, count); return 0; } dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count, DMA_TO_DEVICE); dma_dst = c->phys_base + bram_offset; if (dma_mapping_error(&c->pdev->dev, dma_src)) { dev_err(&c->pdev->dev, "Couldn't DMA map a %d byte buffer\n", count); return -1; } omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S16, count / 2, 1, 0, 0, 0); omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_src, 0, 0); omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_dst, 0, 0); INIT_COMPLETION(c->dma_done); omap_start_dma(c->dma_channel); wait_for_completion(&c->dma_done); dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE); return 0; }
static void omap_irda_start_rx_dma(struct omap_irda *omap_ir) { /* Configure DMA */ omap_set_dma_src_params(omap_ir->rx_dma_channel, 0x3, 0x0, omap_ir->pdata->src_start, 0, 0); omap_enable_dma_irq(omap_ir->rx_dma_channel, 0x01); omap_set_dma_dest_params(omap_ir->rx_dma_channel, 0x0, 0x1, omap_ir->rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(omap_ir->rx_dma_channel, 0x0, IRDA_SKB_MAX_MTU, 0x1, 0x0, omap_ir->pdata->rx_trigger, 0); omap_start_dma(omap_ir->rx_dma_channel); }
/* * ======== SCPY_configure ======== * Configure a transfer on the SDMA handle */ void SCPY_configure(IRES_SDMA_Handle handle, SCPY_Params * params) { /* SCPY_configure should be called with only one logicalChannel */ int logicalChannel = handle->channel->chanNum; unsigned int dmaAddr = (unsigned int)(handle->channel->addr); CMEM_init(); omap_set_dma_transfer_params(logicalChannel, dmaAddr, params->transfer->dataType, params->transfer->elemCount, params->transfer->frameCount); omap_set_dma_src_params(logicalChannel, dmaAddr, params->src->addr_mode, CMEM_getPhys((void *)(params->src->addr)), params->src->elem_index, params->src->frame_index); omap_set_dma_dest_params(logicalChannel, dmaAddr, params->dst->addr_mode, CMEM_getPhys((void *)(params->dst->addr)), params->dst->elem_index, params->dst->frame_index); CMEM_exit(); }
static void omap1610_start_tx_dma(struct omap1610_irda *si, int size) { __ECHO_IN; /* Configure DMA */ omap_set_dma_dest_params(si->tx_dma_channel, 0x03, 0x0, (unsigned long)UART3_THR); omap_enable_dma_irq(si->tx_dma_channel, 0x01); omap_set_dma_src_params(si->tx_dma_channel, 0x0, 0x1, si->tx_buf_dma_phys); omap_set_dma_transfer_params(si->tx_dma_channel, 0x0, size, 0x1, 0x0); HDBG1(1); /* Start DMA */ omap_start_dma(si->tx_dma_channel); HDBG1(1); __ECHO_OUT; }
static int serial_omap_start_rxdma(struct uart_omap_port *up) { int ret = 0; if (up->uart_dma.rx_dma_channel == -1) { ret = omap_request_dma(up->uart_dma.uart_dma_rx, "UART Rx DMA", (void *)uart_rx_dma_callback, up, &(up->uart_dma.rx_dma_channel)); if (ret < 0) return ret; omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, up->uart_dma.rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.rx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_rx, 0); } up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; /* FIXME: Cache maintenance needed here? */ omap_start_dma(up->uart_dma.rx_dma_channel); mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_poll_rate)); up->uart_dma.rx_dma_used = true; if (up->plat_hold_wakelock) (up->plat_hold_wakelock(up, WAKELK_RX)); return ret; }
/* Prepare to transfer the next segment of a scatterlist */ static void mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) { int dma_ch = host->dma_ch; unsigned long data_addr; u16 buf, frame; u32 count; struct scatterlist *sg = &data->sg[host->sg_idx]; int src_port = 0; int dst_port = 0; int sync_dev = 0; data_addr = host->phys_base + OMAP_MMC_REG_DATA; frame = data->blksz; count = sg_dma_len(sg); if ((data->blocks == 1) && (count > data->blksz)) count = frame; host->dma_len = count; /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx. * Use 16 or 32 word frames when the blocksize is at least that large. * Blocksize is usually 512 bytes; but not for some SD reads. */ if (cpu_is_omap15xx() && frame > 32) frame = 32; else if (frame > 64) frame = 64; count /= frame; frame >>= 1; if (!(data->flags & MMC_DATA_WRITE)) { buf = 0x800f | ((frame - 1) << 8); if (cpu_class_is_omap1()) { src_port = OMAP_DMA_PORT_TIPB; dst_port = OMAP_DMA_PORT_EMIFF; } if (cpu_is_omap24xx()) sync_dev = OMAP24XX_DMA_MMC1_RX; omap_set_dma_src_params(dma_ch, src_port, OMAP_DMA_AMODE_CONSTANT, data_addr, 0, 0); omap_set_dma_dest_params(dma_ch, dst_port, OMAP_DMA_AMODE_POST_INC, sg_dma_address(sg), 0, 0); omap_set_dma_dest_data_pack(dma_ch, 1); omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); } else { buf = 0x0f80 | ((frame - 1) << 0); if (cpu_class_is_omap1()) { src_port = OMAP_DMA_PORT_EMIFF; dst_port = OMAP_DMA_PORT_TIPB; } if (cpu_is_omap24xx()) sync_dev = OMAP24XX_DMA_MMC1_TX; omap_set_dma_dest_params(dma_ch, dst_port, OMAP_DMA_AMODE_CONSTANT, data_addr, 0, 0); omap_set_dma_src_params(dma_ch, src_port, OMAP_DMA_AMODE_POST_INC, sg_dma_address(sg), 0, 0); omap_set_dma_src_data_pack(dma_ch, 1); omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); } /* Max limit for DMA frame count is 0xffff */ BUG_ON(count > 0xffff); OMAP_MMC_WRITE(host, BUF, buf); omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, frame, count, OMAP_DMA_SYNC_FRAME, sync_dev, 0); }
static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; struct omap_uart_port_info *pdata = up->pdev->dev.platform_data; struct circ_buf *xmit; unsigned int start; int ret = 0; if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); serial_omap_enable_ier_thri(up); if (pdata && pdata->set_noidle) pdata->set_noidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); return; } if (up->uart_dma.tx_dma_used) return; xmit = &up->port.state->xmit; if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { pm_runtime_get_sync(&up->pdev->dev); ret = omap_request_dma(up->uart_dma.uart_dma_tx, "UART Tx DMA", (void *)uart_tx_dma_callback, up, &(up->uart_dma.tx_dma_channel)); if (ret < 0) { serial_omap_enable_ier_thri(up); return; } } spin_lock(&(up->uart_dma.tx_lock)); up->uart_dma.tx_dma_used = true; spin_unlock(&(up->uart_dma.tx_lock)); start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_tx, 0); omap_start_dma(up->uart_dma.tx_dma_channel); }
int omap_vout_prepare_vrfb(struct omap_vout_device *vout, struct videobuf_buffer *vb) { dma_addr_t dmabuf; struct vid_vrfb_dma *tx; enum dss_rotation rotation; u32 dest_frame_index = 0, src_element_index = 0; u32 dest_element_index = 0, src_frame_index = 0; u32 elem_count = 0, frame_count = 0, pixsize = 2; if (!is_rotation_enabled(vout)) return 0; dmabuf = vout->buf_phy_addr[vb->i]; /* If rotation is enabled, copy input buffer into VRFB * memory space using DMA. We are copying input buffer * into VRFB memory space of desired angle and DSS will * read image VRFB memory for 0 degree angle */ pixsize = vout->bpp * vout->vrfb_bpp; /* * DMA transfer in double index mode */ /* Frame index */ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - (vout->pix.width * vout->bpp)) + 1; /* Source and destination parameters */ src_element_index = 0; src_frame_index = 0; dest_element_index = 1; /* Number of elements per frame */ elem_count = vout->pix.width * vout->bpp; frame_count = vout->pix.height; tx = &vout->vrfb_dma_tx; tx->tx_status = 0; omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, tx->dev_id, 0x0); /* src_port required only for OMAP1 */ omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, dmabuf, src_element_index, src_frame_index); /*set dma source burst mode for VRFB */ omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); rotation = calc_rotation(vout); /* dest_port required only for OMAP1 */ omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, vout->vrfb_context[vb->i].paddr[0], dest_element_index, dest_frame_index); /*set dma dest burst mode for VRFB */ omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); omap_start_dma(tx->dma_ch); wait_event_interruptible_timeout(tx->wait, tx->tx_status == 1, VRFB_TX_TIMEOUT); if (tx->tx_status == 0) { omap_stop_dma(tx->dma_ch); return -EINVAL; } /* Store buffers physical address into an array. Addresses * from this array will be used to configure DSS */ vout->queued_buf_addr[vb->i] = (u8 *) vout->vrfb_context[vb->i].paddr[rotation]; return 0; }
static void musb_sdma_channel_program(struct musb *musb, struct musb_dma_channel *musb_channel, dma_addr_t dma_addr, u32 len) { u16 frame = len; int data_type = OMAP_DMA_DATA_TYPE_S8; switch (dma_addr & 0x3) { case 0: if ((len % 4) == 0) { data_type = OMAP_DMA_DATA_TYPE_S32; frame = len / 4; break; } case 2: if ((len % 2) == 0) { data_type = OMAP_DMA_DATA_TYPE_S16; frame = len / 2; break; } case 1: case 3: default: data_type = OMAP_DMA_DATA_TYPE_S8; frame = len; break; } /* set transfer parameters */ omap_set_dma_transfer_params(musb_channel->sysdma_channel, data_type, len ? frame : 1, 1, /* One frame */ OMAP_DMA_SYNC_FRAME, OMAP24XX_DMA_NO_DEVICE, 0); /* Src Sync */ if (!musb_channel->transmit) { /* RX: set src = FIFO */ omap_set_dma_src_params(musb_channel->sysdma_channel, 0, OMAP_DMA_AMODE_CONSTANT, MUSB_FIFO_ADDRESS(musb->ctrl_phys_base, musb_channel->epnum), 0, 0); omap_set_dma_dest_params(musb_channel->sysdma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_addr, 0, 0); omap_set_dma_dest_data_pack(musb_channel->sysdma_channel, 1); omap_set_dma_dest_burst_mode(musb_channel->sysdma_channel, OMAP_DMA_DATA_BURST_16); } else if (musb_channel->transmit) { /* TX: set dst = FIFO */ omap_set_dma_src_params(musb_channel->sysdma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_addr, 0, 0); omap_set_dma_dest_params(musb_channel->sysdma_channel, 0, OMAP_DMA_AMODE_CONSTANT, MUSB_FIFO_ADDRESS(musb->ctrl_phys_base, musb_channel->epnum), 0, 0); omap_set_dma_dest_data_pack(musb_channel->sysdma_channel, 0); omap_set_dma_dest_burst_mode(musb_channel->sysdma_channel, OMAP_DMA_DATA_BURST_DIS); } /* start the system dma */ omap_start_dma(musb_channel->sysdma_channel); }
static void OMAPLFBFliepNoLock_HDMI(OMAPLFB_SWAPCHAIN *psSwapChain, OMAPLFB_DEVINFO *psDevInfo, struct omapfb_info *ofbi, struct fb_info *framebuffer, unsigned long fb_offset) { struct omap_overlay *ovl_hdmi; struct omap_overlay_info info; struct omap_overlay *hdmi; struct omap_overlay_manager *manager; bool overlay_change_requested = false; enum omap_dss_overlay_s3d_type s3d_type_in_video_hdmi = omap_dss_overlay_s3d_none; ovl_hdmi = omap_dss_get_overlay(3); if(ovl_hdmi->info.enabled) s3d_type_in_video_hdmi = ovl_hdmi->info.s3d_type; hdmi = psSwapChain->stHdmiTiler.overlay; manager = hdmi->manager; hdmi->get_overlay_info(hdmi, &info); //not good... if ( omap_overlay_info_req[hdmi->id].status==2 ) { info.enabled = omap_overlay_info_req[hdmi->id].enabled; info.rotation = omap_overlay_info_req[hdmi->id].rotation; info.pos_x = omap_overlay_info_req[hdmi->id].pos_x; info.pos_y = omap_overlay_info_req[hdmi->id].pos_y; info.out_width = omap_overlay_info_req[hdmi->id].out_width; info.out_height = omap_overlay_info_req[hdmi->id].out_height; info.global_alpha = omap_overlay_info_req[hdmi->id].global_alpha; info.zorder = omap_overlay_info_req[hdmi->id].zorder; printk("GUI HDMI layer change requested. req_enabled(%d)\n", omap_overlay_info_req[hdmi->id].enabled); omap_overlay_info_req[hdmi->id].status = 0; overlay_change_requested = true; } if ( info.enabled ) { mutex_lock(&psSwapChain->stHdmiTiler.lock); if ( !psSwapChain->stHdmiTiler.alloc ) { // if ( AllocTilerForHdmi(psSwapChain, psDevInfo) ) { ERROR_PRINTK("Tiler memory for HDMI GUI cloning is not allocated\n"); mutex_unlock(&psSwapChain->stHdmiTiler.lock); return; // } } if ( psSwapChain->stHdmiTiler.alloc ) //if Tiler memory is allocated { unsigned long line_offset; unsigned long w, h; unsigned long src_stride, dst_stride; unsigned long i; unsigned char *dst, *src; unsigned long pStride; u32 j, *src_4, *dst_4, *dst1_4; int ch; src_stride = psDevInfo->sFBInfo.ulByteStride; dst_stride = psSwapChain->stHdmiTiler.vStride; line_offset = fb_offset / src_stride; h = psDevInfo->sFBInfo.ulHeight; w = psDevInfo->sFBInfo.ulWidth; pStride = psSwapChain->stHdmiTiler.pStride; //Copy dst = (unsigned char*)psSwapChain->stHdmiTiler.vAddr + (line_offset * dst_stride); src = (unsigned char*)framebuffer->screen_base + fb_offset; DEBUG_PRINTK("Copy Start h:%d, src:0x%p src_stride:%d, dst:0x%p dst_stride:%d, line offset:%d, pStride:%d\n", h, src, src_stride, dst, dst_stride, line_offset, pStride); if( psSwapChain->s3d_type==omap_dss_overlay_s3d_side_by_side && s3d_type_in_video_hdmi == omap_dss_overlay_s3d_top_bottom) { for(j=0; j<h/2; j++) { src_4 = (u32 *)(src + src_stride*j); dst_4 = (u32 *)(dst + dst_stride*2*j); dst1_4 = (u32 *)(dst + dst_stride*2*j + w*2); for(i=0;i<w/2;i++) { *dst_4++ = *src_4; *dst1_4++ = *src_4++; src_4++; } src_4 = (u32 *)(src + src_stride*j); dst_4 = (u32 *)(dst + dst_stride*(2*j+1)); dst1_4 = (u32 *)(dst + dst_stride*(2*j+1) + w*2); for(i=0;i<w/2;i++) { *dst_4++ = *src_4; *dst1_4++ = *src_4++; src_4++; } } info.s3d_type = omap_dss_overlay_s3d_top_bottom; } else { if(hdmi_dma.state == HDMI_DMA_DONE) { ch = hdmi_dma.frame_pos; hdmi->get_overlay_info(hdmi, &hdmi_dma.info[ch]); hdmi_dma.hdmi = hdmi; printk("S:%x\n", psSwapChain->stHdmiTiler.pAddr + (h * pStride * ch)); omap_set_dma_transfer_params(hdmi_dma.lch, OMAP_DMA_DATA_TYPE_S32, src_stride>>2, h, 0, 0, 0); omap_set_dma_src_params(hdmi_dma.lch, 0, OMAP_DMA_AMODE_POST_INC, framebuffer->fix.smem_start + fb_offset, 1, 1); omap_set_dma_dest_params(hdmi_dma.lch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, psSwapChain->stHdmiTiler.pAddr + (h * pStride * ch), 1, pStride - src_stride + 1 ); omap_dma_set_prio_lch(hdmi_dma.lch, DMA_CH_PRIO_HIGH, DMA_CH_PRIO_HIGH); omap_set_dma_src_burst_mode(hdmi_dma.lch, OMAP_DMA_DATA_BURST_16); omap_set_dma_dest_burst_mode(hdmi_dma.lch, OMAP_DMA_DATA_BURST_16); omap_start_dma(hdmi_dma.lch); hdmi_dma.state = HDMI_DMA_TRANSFERRING; if ( omap_overlay_info_req[hdmi->id].status==2 ) { hdmi_dma.info[ch].enabled = omap_overlay_info_req[hdmi->id].enabled; hdmi_dma.info[ch].rotation = omap_overlay_info_req[hdmi->id].rotation; hdmi_dma.info[ch].pos_x = omap_overlay_info_req[hdmi->id].pos_x; hdmi_dma.info[ch].pos_y = omap_overlay_info_req[hdmi->id].pos_y; hdmi_dma.info[ch].out_width = omap_overlay_info_req[hdmi->id].out_width; hdmi_dma.info[ch].out_height = omap_overlay_info_req[hdmi->id].out_height; hdmi_dma.info[ch].global_alpha = omap_overlay_info_req[hdmi->id].global_alpha; hdmi_dma.info[ch].zorder = omap_overlay_info_req[hdmi->id].zorder; } //fill info //@todo not good find another way later hdmi_dma.info[ch].color_mode = ofbi->overlays[0]->info.color_mode; hdmi_dma.info[ch].paddr = psSwapChain->stHdmiTiler.pAddr + (h * pStride * ch); hdmi_dma.info[ch].vaddr = NULL; //no need if ( hdmi_dma.info[ch].rotation==OMAP_DSS_ROT_90 || hdmi_dma.info[ch].rotation==OMAP_DSS_ROT_270 ) { hdmi_dma.info[ch].width = h; hdmi_dma.info[ch].height = w; hdmi_dma.info[ch].screen_width = h; } else { hdmi_dma.info[ch].width =w; hdmi_dma.info[ch].height = h; hdmi_dma.info[ch].screen_width = w; } hdmi_dma.info[ch].rotation_type = OMAP_DSS_ROT_TILER; hdmi_dma.info[ch].s3d_type = psSwapChain->s3d_type; hdmi_dma.curr_frame = hdmi_dma.frame_pos; if( ++hdmi_dma.frame_pos >= HDMI_DMA_MAX ) hdmi_dma.frame_pos = 0; if( omap_overlay_info_req[hdmi->id].status == 2) { omap_overlay_info_req[hdmi->id].status = 0; } } else printk("DOLCOM : DMA busy!!!!!!!!!!!!!!!!!\n");
static void makeinterlave(struct fb_info *fbi, struct omapfb_info *ofbi, struct omap_overlay *overlay, struct omap_overlay_info *pInfo) { struct InterleaveBuffer* IB; struct omap_overlay_info overlay_info = *pInfo; IB = findInterleaveBuffer(fbi, &overlay_info); if ( IB!=NULL ) { #ifdef CONFIG_GFX_DMA_COPY //LGE_CHANGE_S [[email protected]] 2010-12-27, P920 : For GFX dma copy. if (wait_for_completion_timeout(&gfx_dma[0].compl, msecs_to_jiffies(1000)) == 0) { omap_stop_dma(gfx_dma[0].lch); DEBUG_PRINTK("GFX DMA: dma timeout while transferring\n"); } omap_set_dma_transfer_params(gfx_dma[0].lch, OMAP_DMA_DATA_TYPE_S32, (fbi->fix.line_length>>2), (fbi->var.yres)>>1, 0, 0, 0); omap_set_dma_src_params(gfx_dma[0].lch, 0, OMAP_DMA_AMODE_POST_INC, overlay_info.paddr, 1, 1); omap_set_dma_dest_params(gfx_dma[0].lch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, IB->paddr + fbi->fix.line_length, 1, (fbi->fix.line_length) + 1); omap_start_dma(gfx_dma[0].lch); #if 0 if (wait_for_completion_timeout(&gfx_dma[0].compl, msecs_to_jiffies(1000)) == 0) { omap_stop_dma(gfx_dma[0].lch); DEBUG_PRINTK("GFX DMA: dma timeout while transferring\n"); } if (wait_for_completion_timeout(&gfx_dma[1].compl, msecs_to_jiffies(1000)) == 0) { omap_stop_dma(gfx_dma[1].lch); DEBUG_PRINTK("GFX DMA: dma timeout while transferring\n"); } omap_set_dma_transfer_params(gfx_dma[0].lch, OMAP_DMA_DATA_TYPE_S32, (fbi->fix.line_length>>2), (fbi->var.yres)>>1, 0, 0, 0); omap_set_dma_src_params(gfx_dma[0].lch, 0, OMAP_DMA_AMODE_POST_INC, overlay_info.paddr, 1, 1); omap_set_dma_dest_params(gfx_dma[0].lch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, IB->paddr + fbi->fix.line_length, 1, (fbi->fix.line_length) + 1); omap_set_dma_transfer_params(gfx_dma[1].lch, OMAP_DMA_DATA_TYPE_S32, (fbi->fix.line_length>>2), (fbi->var.yres)>>1, 0, 0, 0); omap_set_dma_src_params(gfx_dma[1].lch, 0, OMAP_DMA_AMODE_POST_INC, overlay_info.paddr + (fbi->fix.line_length * (fbi->var.yres>>1)), 1, 1); omap_set_dma_dest_params(gfx_dma[1].lch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, IB->paddr, 1, (fbi->fix.line_length) + 1); omap_start_dma(gfx_dma[0].lch); omap_start_dma(gfx_dma[1].lch); #endif //LGE_CHANGE_E [[email protected]] #else // memcpy(IB->buffer, overlay_info.vaddr, IB->size); { //copy interleave int stride; int height; unsigned char *src, *dst; int i; stride = fbi->fix.line_length; height = fbi->var.yres; src = overlay_info.vaddr; dst = IB->buffer; // printk("Interleave Copy line %d address:%p\n", height, IB->buffer); // printk("overlay->roation_type : %d\n", overlay_info.rotation_type); for(i=0;i<height;i++) { if ( i < (height/2) ) { //left frame copy to odd line unsigned char *odd_line; odd_line = dst + stride * (i*2 + 1); memcpy(odd_line, src, stride); } else { //right frame copy to even line unsigned char *even_line; even_line = dst + stride * ( (i-height/2) * 2 + 1 -1 ); memcpy(even_line, src, stride); } src += stride; } } #endif // flush_cache_all(); overlay_info.paddr = IB->paddr; overlay_info.vaddr = IB->buffer; // printk("S3D : set oerlay paddr:0x%x vaddr 0x%x", // overlay_info.paddr, // overlay_info.vaddr ); // if ( cacheflush(IB->buffer, IB->size, DCACHE ) ) // printk("Interleave buffer flush failed\n"); // overlay->set_overlay_info(overlay, &overlay_info); // return; } overlay_info.s3d_type = omap_dss_overlay_s3d_interlaced; overlay->set_overlay_info(overlay, &overlay_info); }
static void configure_channel(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_controller *controller = musb_channel->controller; void __iomem *mbase = controller->base; u8 bchannel = musb_channel->idx; u16 csr = 0; DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", channel, packet_sz, dma_addr, len, mode); if (musb_channel->sysdma_channel != -1) { /* System DMA */ /* RX: set src = FIFO */ omap_set_dma_transfer_params(musb_channel->sysdma_channel, OMAP_DMA_DATA_TYPE_S8, len ? len : 1, 1, /* One frame */ OMAP_DMA_SYNC_ELEMENT, OMAP24XX_DMA_NO_DEVICE, 0); /* Src Sync */ omap_set_dma_src_params(musb_channel->sysdma_channel, 0, OMAP_DMA_AMODE_CONSTANT, MUSB_FIFO_ADDRESS(musb_channel->epnum), 0, 0); omap_set_dma_dest_params(musb_channel->sysdma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_addr, 0, 0); omap_set_dma_dest_data_pack(musb_channel->sysdma_channel, 1); omap_set_dma_dest_burst_mode(musb_channel->sysdma_channel, OMAP_DMA_DATA_BURST_16); omap_start_dma(musb_channel->sysdma_channel); } else { /* Mentor DMA */ if (mode) { csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; BUG_ON(len < packet_sz); if (packet_sz >= 64) { csr |= MUSB_HSDMA_BURSTMODE_INCR16 << MUSB_HSDMA_BURSTMODE_SHIFT; } else if (packet_sz >= 32) { csr |= MUSB_HSDMA_BURSTMODE_INCR8 << MUSB_HSDMA_BURSTMODE_SHIFT; } else if (packet_sz >= 16) { csr |= MUSB_HSDMA_BURSTMODE_INCR4 << MUSB_HSDMA_BURSTMODE_SHIFT; } } csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) | (1 << MUSB_HSDMA_ENABLE_SHIFT) | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) | (musb_channel->transmit ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) : 0); /* address/count */ musb_write_hsdma_addr(mbase, bchannel, dma_addr); musb_write_hsdma_count(mbase, bchannel, len); /* control (this should start things) */ musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), csr); } }
static int __init omap1_cam_probe(struct platform_device *pdev) { struct omap1_cam_dev *pcdev; struct resource *res; struct clk *clk; void __iomem *base; unsigned int irq; int err = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (!res || (int)irq <= 0) { err = -ENODEV; goto exit; } clk = clk_get(&pdev->dev, "armper_ck"); if (IS_ERR(clk)) { err = PTR_ERR(clk); goto exit; } pcdev = kzalloc(sizeof(*pcdev) + resource_size(res), GFP_KERNEL); if (!pcdev) { dev_err(&pdev->dev, "Could not allocate pcdev\n"); err = -ENOMEM; goto exit_put_clk; } pcdev->res = res; pcdev->clk = clk; pcdev->pdata = pdev->dev.platform_data; pcdev->pflags = pcdev->pdata->flags; if (pcdev->pdata) pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000; switch (pcdev->camexclk) { case 6000000: case 8000000: case 9600000: case 12000000: case 24000000: break; default: dev_warn(&pdev->dev, "Incorrect sensor clock frequency %ld kHz, " "should be one of 0, 6, 8, 9.6, 12 or 24 MHz, " "please correct your platform data\n", pcdev->pdata->camexclk_khz); pcdev->camexclk = 0; case 0: dev_info(&pdev->dev, "Not providing sensor clock\n"); } INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); /* * Request the region. */ if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) { err = -EBUSY; goto exit_kfree; } base = ioremap(res->start, resource_size(res)); if (!base) { err = -ENOMEM; goto exit_release; } pcdev->irq = irq; pcdev->base = base; sensor_reset(pcdev, true); err = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, DRIVER_NAME, dma_isr, (void *)pcdev, &pcdev->dma_ch); if (err < 0) { dev_err(&pdev->dev, "Can't request DMA for OMAP1 Camera\n"); err = -EBUSY; goto exit_iounmap; } dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_ch); /* preconfigure DMA */ omap_set_dma_src_params(pcdev->dma_ch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, res->start + REG_CAMDATA, 0, 0); omap_set_dma_dest_burst_mode(pcdev->dma_ch, OMAP_DMA_DATA_BURST_4); /* setup DMA autoinitialization */ omap_dma_link_lch(pcdev->dma_ch, pcdev->dma_ch); err = request_irq(pcdev->irq, cam_isr, 0, DRIVER_NAME, pcdev); if (err) { dev_err(&pdev->dev, "Camera interrupt register failed\n"); goto exit_free_dma; } pcdev->soc_host.drv_name = DRIVER_NAME; pcdev->soc_host.ops = &omap1_host_ops; pcdev->soc_host.priv = pcdev; pcdev->soc_host.v4l2_dev.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); if (err) goto exit_free_irq; dev_info(&pdev->dev, "OMAP1 Camera Interface driver loaded\n"); return 0; exit_free_irq: free_irq(pcdev->irq, pcdev); exit_free_dma: omap_free_dma(pcdev->dma_ch); exit_iounmap: iounmap(base); exit_release: release_mem_region(res->start, resource_size(res)); exit_kfree: kfree(pcdev); exit_put_clk: clk_put(clk); exit: return err; }
static void omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, unsigned int u32_count, int is_write) { const int block_size = 16; unsigned int block_count, len; int dma_ch; unsigned long fifo_reg, timeout, jiffies_before, jiffies_spent; static unsigned long max_jiffies = 0; dma_ch = omap_nand_dma_ch; block_count = u32_count * 4 / block_size; nand_write_reg(NND_STATUS, 0x0f); nand_write_reg(NND_FIFOCTRL, (block_size << 24) | block_count); fifo_reg = NAND_BASE + NND_FIFO; if (is_write) { omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, fifo_reg, 0, 0); omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, virt_to_phys(addr), 0, 0); // omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); /* Set POSTWRITE bit */ nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 16)); } else { omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, fifo_reg, 0, 0); omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, virt_to_phys(addr), 0, 0); // omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_8); /* Set PREFETCH bit */ nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17)); } omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, block_size / 4, block_count, OMAP_DMA_SYNC_FRAME, 0, 0); init_completion(&omap_nand_dma_comp); len = u32_count << 2; dma_cache_maint(addr, len, DMA_TO_DEVICE); omap_start_dma(dma_ch); jiffies_before = jiffies; timeout = wait_for_completion_timeout(&omap_nand_dma_comp, msecs_to_jiffies(1000)); jiffies_spent = (unsigned long)((long)jiffies - (long)jiffies_before); if (jiffies_spent > max_jiffies) max_jiffies = jiffies_spent; if (timeout == 0) { printk(KERN_WARNING "omap-hw-nand: DMA timeout after %u ms, max. seen latency %u ms\n", jiffies_to_msecs(jiffies_spent), jiffies_to_msecs(max_jiffies)); } if (!is_write) dma_cache_maint(addr, len, DMA_FROM_DEVICE); nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) & ~((1 << 16) | (1 << 17))); }
static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area, const unsigned char *buffer, int offset, size_t count) { struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); struct onenand_chip *this = mtd->priv; dma_addr_t dma_src, dma_dst; int bram_offset; unsigned long timeout; void *buf = (void *)buffer; volatile unsigned *done; bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset; if (bram_offset & 3 || (size_t)buf & 3 || count < 384) goto out_copy; /* panic_write() may be in an interrupt context */ if (in_interrupt() || oops_in_progress) goto out_copy; if (buf >= high_memory) { struct page *p1; if (((size_t)buf & PAGE_MASK) != ((size_t)(buf + count - 1) & PAGE_MASK)) goto out_copy; p1 = vmalloc_to_page(buf); if (!p1) goto out_copy; buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK); } dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE); dma_dst = c->phys_base + bram_offset; if (dma_mapping_error(&c->pdev->dev, dma_src)) { dev_err(&c->pdev->dev, "Couldn't DMA map a %d byte buffer\n", count); return -1; } omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32, count >> 2, 1, 0, 0, 0); omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_src, 0, 0); omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC, dma_dst, 0, 0); INIT_COMPLETION(c->dma_done); omap_start_dma(c->dma_channel); timeout = jiffies + msecs_to_jiffies(20); done = &c->dma_done.done; while (time_before(jiffies, timeout)) if (*done) break; dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE); if (!*done) { dev_err(&c->pdev->dev, "timeout waiting for DMA\n"); goto out_copy; } return 0; out_copy: memcpy(this->base + bram_offset, buf, count); return 0; }