Exemplo n.º 1
0
static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
		unsigned long arg)
{
	struct sdma_channel *sdmac = to_sdma_chan(chan);
	struct dma_slave_config *dmaengine_cfg = (void *)arg;

	switch (cmd) {
	case DMA_TERMINATE_ALL:
		sdma_disable_channel(sdmac);
		return 0;
	case DMA_SLAVE_CONFIG:
		if (dmaengine_cfg->direction == DMA_FROM_DEVICE) {
			sdmac->per_address = dmaengine_cfg->src_addr;
			sdmac->watermark_level = dmaengine_cfg->src_maxburst;
			sdmac->word_size = dmaengine_cfg->src_addr_width;
		} else {
			sdmac->per_address = dmaengine_cfg->dst_addr;
			sdmac->watermark_level = dmaengine_cfg->dst_maxburst;
			sdmac->word_size = dmaengine_cfg->dst_addr_width;
		}
		return sdma_config_channel(sdmac);
	default:
		return -ENOSYS;
	}

	return -EINVAL;
}
Exemplo n.º 2
0
static int setup_fpga_interface(struct sdma_engine *sdma)
{
	const int channel = 1;

	struct sdma_channel *sdmac = &sdma->channel[channel];
	const u32 sdma_code[24] = {
		0x6c20672b, 0x07647d02, 0x04007cfa, 0x612b622b, 0x662b0762, 0x7d0e6900, 0x6d0406da, 0x7d056e18,
		0x000002a6, 0x0e087cf8, 0x6a186c14, 0x6c2b7ce8, 0x7de7632b, 0x6904008f, 0x38037802, 0x6b290312,
		0x4a007d09, 0x6d0006da, 0x7d056e18, 0x000002a6, 0x0e087cf8, 0x6a180763, 0x7ce80300, 0x7de60000,
	};

	const int origin = 0xe00; /* In data space terms (32 bits/address) */

	struct sdma_context_data *context = sdma->context;

	int ret;

	ret = eim_init();

	if (ret) {
		printk(KERN_ERR THIS "Failed to initialize EIM bus\n");
		return ret;
	}

	sdma_write_datamem(sdma, (void *) sdma_code, sizeof(sdma_code), origin);

	ret = sdma_request_channel(sdmac);

	if (ret) {
		printk(KERN_ERR "Failed to request channel\n");
		return ret;
	}
  
	sdma_disable_channel(sdmac);

	/* Don't let events run yet: */
	sdma_config_ownership(sdmac, true, true, false);

	memset(context, 0, sizeof(*context));

	context->channel_state.pc = origin * 2; /* In program space addressing */
	context->gReg[4] = MX51_CS2_BASE_ADDR + 0x80;  /* Request region */
	context->gReg[5] = MX51_CS2_BASE_ADDR + 0x8000; /* Data region */

	ret = sdma_write_datamem(sdma, (void *) context, sizeof(*context),
				 0x800 + (sizeof(*context) / 4) * channel);
  
	if (ret) {
		printk(KERN_ERR "Failed to load context\n");
		return ret;
	}

	sdmac->desc.callback = sdma_irq_callback;
	sdmac->desc.callback_param = NULL;

	xillybus_sdmac = sdmac;
  
	return 0; /* Success! */
}
Exemplo n.º 3
0
static int sdma_config_channel(struct sdma_channel *sdmac)
{
	int ret;

	sdma_disable_channel(sdmac);

	sdmac->event_mask0 = 0;
	sdmac->event_mask1 = 0;
	sdmac->shp_addr = 0;
	sdmac->per_addr = 0;

	if (sdmac->event_id0) {
		if (sdmac->event_id0 > 32)
			return -EINVAL;
		sdma_event_enable(sdmac, sdmac->event_id0);
	}

	switch (sdmac->peripheral_type) {
	case IMX_DMATYPE_DSP:
		sdma_config_ownership(sdmac, false, true, true);
		break;
	case IMX_DMATYPE_MEMORY:
		sdma_config_ownership(sdmac, false, true, false);
		break;
	default:
		sdma_config_ownership(sdmac, true, true, false);
		break;
	}

	sdma_get_pc(sdmac, sdmac->peripheral_type);

	if ((sdmac->peripheral_type != IMX_DMATYPE_MEMORY) &&
			(sdmac->peripheral_type != IMX_DMATYPE_DSP)) {
		/* Handle multiple event channels differently */
		if (sdmac->event_id1) {
			sdmac->event_mask1 = 1 << (sdmac->event_id1 % 32);
			if (sdmac->event_id1 > 31)
				sdmac->watermark_level |= 1 << 31;
			sdmac->event_mask0 = 1 << (sdmac->event_id0 % 32);
			if (sdmac->event_id0 > 31)
				sdmac->watermark_level |= 1 << 30;
		} else {
			sdmac->event_mask0 = 1 << sdmac->event_id0;
			sdmac->event_mask1 = 1 << (sdmac->event_id0 - 32);
		}
		/* Watermark Level */
		sdmac->watermark_level |= sdmac->watermark_level;
		/* Address */
		sdmac->shp_addr = sdmac->per_address;
	} else {
		sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
	}

	ret = sdma_load_context(sdmac);

	return ret;
}
Exemplo n.º 4
0
static void sdma_free_chan_resources(struct dma_chan *chan)
{
	struct sdma_channel *sdmac = to_sdma_chan(chan);
	struct sdma_engine *sdma = sdmac->sdma;

	sdma_disable_channel(sdmac);

	if (sdmac->event_id0)
		sdma_event_disable(sdmac, sdmac->event_id0);
	if (sdmac->event_id1)
		sdma_event_disable(sdmac, sdmac->event_id1);

	sdmac->event_id0 = 0;
	sdmac->event_id1 = 0;

	sdma_set_channel_priority(sdmac, 0);

	dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);

	clk_disable(sdma->clk);
}
Exemplo n.º 5
0
static int sdma_config_channel(struct sdma_channel *sdmac)
{
	int ret;

	sdma_disable_channel(sdmac);

	sdmac->event_mask0 = 0;
	sdmac->event_mask1 = 0;
	sdmac->shp_addr = 0;
	sdmac->per_addr = 0;

	if (sdmac->event_id0)
		sdma_event_enable(sdmac, sdmac->event_id0);

	if (sdmac->event_id1)
		sdma_event_enable(sdmac, sdmac->event_id1);

	switch (sdmac->peripheral_type) {
	case IMX_DMATYPE_DSP:
		sdma_config_ownership(sdmac, false, true, true);
		break;
	case IMX_DMATYPE_MEMORY:
		sdma_config_ownership(sdmac, false, true, false);
		break;
	default:
		sdma_config_ownership(sdmac, true, true, false);
		break;
	}

	sdma_get_pc(sdmac, sdmac->peripheral_type);

	if ((sdmac->peripheral_type != IMX_DMATYPE_MEMORY) &&
			(sdmac->peripheral_type != IMX_DMATYPE_DSP)) {
		/* Handle multiple event channels differently */
		if (sdmac->event_id1) {
			if (sdmac->event_id0 > 31) {
				sdmac->watermark_level |= 1 << 28;
				sdmac->event_mask0 |= 0;
				sdmac->event_mask1 |=
					1 << ((sdmac->event_id0)%32);
			} else {
				sdmac->event_mask0 |=
					1 << ((sdmac->event_id0)%32);
				sdmac->event_mask1 |= 0;
			}
			if (sdmac->event_id1 > 31) {
				sdmac->watermark_level |= 1 << 29;
				sdmac->event_mask0 |= 0;
				sdmac->event_mask1 |=
					1 << ((sdmac->event_id1)%32);
			} else {
				sdmac->event_mask0 |=
					1 << ((sdmac->event_id1)%32);
				sdmac->event_mask1 |= 0;
			}
			sdmac->watermark_level |= (unsigned int)(3<<11);
			sdmac->watermark_level |= (unsigned int)(1<<31);
			sdmac->watermark_level |= (unsigned int)(2<<24);
		} else {
			if (sdmac->event_id0 > 31) {
				sdmac->event_mask0 = 0;
				sdmac->event_mask1 =
					1 << ((sdmac->event_id0)%32);
			} else {
				sdmac->event_mask0 =
					1 << ((sdmac->event_id0)%32);
				sdmac->event_mask1 = 0;
			}
		}
		/* Watermark Level */
		sdmac->watermark_level |= sdmac->watermark_level;
		/* Address */
		switch (sdmac->direction) {
		case DMA_DEV_TO_DEV:
			sdmac->per_addr = sdmac->per_address;
			sdmac->shp_addr = sdmac->per_address2;
			break;
		default:
		sdmac->shp_addr = sdmac->per_address;
			break;
		}
	} else {
		sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
	}

	ret = sdma_load_context(sdmac);

	return ret;
}
Exemplo n.º 6
0
void sdma_xillybus_remove(void)
{
	sdma_event_disable(xillybus_sdmac, 15); /* Connect to channel 15 */
	sdma_disable_channel(xillybus_sdmac);
	xillybus_handler = NULL;
}