static void nand_dma_write(const void *buf, int len)
{
	int offset = 0;
	int tmp_len = 0;
	int len_left = len;
	DMA_Handle_t hndl;

	if (buf == NULL)
		panic("nand_dma_write: buf == NULL\n");

	if (virtPtr == NULL)
		panic("nand_dma_write: virtPtr == NULL\n");

	if ((void *)physPtr == NULL)
		panic("nand_dma_write: physPtr == NULL\n");

	memcpy(virtPtr, buf, len);


	hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
	if (hndl < 0) {
		printk(KERN_ERR
		       "nand_dma_write: unable to allocate dma channel: %d\n",
		       (int)hndl);
		panic("\n");
	}

	while (len_left > 0) {
		if (len_left > DMA_MAX_LEN) {
			tmp_len = DMA_MAX_LEN;
			len_left -= DMA_MAX_LEN;
		} else {
			tmp_len = len_left;
			len_left = 0;
		}

		init_completion(&nand_comp);
		dma_transfer_mem_to_mem(hndl, physPtr + offset,
					REG_NAND_DATA_PADDR, tmp_len);
		wait_for_completion(&nand_comp);

		offset += tmp_len;
	}

	dma_free_channel(hndl);
}
Beispiel #2
0
/*
 * Kernel thread that processes the update requests
 */
static void test_thread(void)
{
	struct test_cfg *cfg = &gCfg;
	unsigned int i;
	int rc;
	void *virt_addr;
	enum dma_data_direction dir;
	dma_addr_t devPhysAddr;
	unsigned long time_left;
	unsigned long trials = 0;

	if (!cfg->setup_is_done) {
		printk(KERN_ERR
		       "Need to set up parameters before running the test\n");
		return;
	}

	cfg->kill_thread = 0;
	cfg->in_use = 1;

	/* allocate memory for dstination and source */
	cfg->src_ptr = alloc_mem(&cfg->src_addr, cfg->len, cfg->src_type);
	if (cfg->src_ptr == NULL) {
		printk(KERN_ERR "alloc_mem for src failed\n");
		goto exit_free_mem;
	}

	cfg->dst_ptr = alloc_mem(&cfg->dst_addr, cfg->len, cfg->dst_type);
	if (cfg->dst_ptr == NULL) {
		printk(KERN_ERR "alloc_mem for dst failed\n");
		goto exit_free_mem;
	}

	/* init mmap */
	rc = dma_mmap_init_map(&cfg->mmap_cfg);
	if (rc < 0) {
		printk(KERN_ERR "dma_mmap_init_map failed\n");
		goto exit_free_mem;
	}

	if (cfg->dir) {		/* mem-to-dev, map src memory */
		virt_addr = cfg->src_ptr;
		dir = DMA_TO_DEVICE;
		devPhysAddr = cfg->dst_addr;
	} else {		/* dev-to-mem, map dst memory */

		virt_addr = cfg->dst_ptr;
		dir = DMA_FROM_DEVICE;
		devPhysAddr = cfg->src_addr;
	}

	daemonize(MODULE_NAME);
	allow_signal(SIGKILL);

	for (;;) {
		/* driver shutting down... let's quit the kthread */
		if (cfg->kill_thread)
			goto exit_term_mmap;

		if (signal_pending(current))
			goto exit_term_mmap;

		/* write some values into the source buffer */
		for (i = 0; i < cfg->len; i++) {
			((unsigned char *)cfg->src_ptr)[i] = cnt++;
		}

		/* clear the destination buffer */
		memset(cfg->dst_ptr, 0, cfg->len);

		/* map memories */
		rc = dma_mmap_map(&cfg->mmap_cfg, virt_addr, cfg->len, dir);
		if (rc < 0) {
			printk(KERN_ERR "dma_mmap_map failed\n");
			goto exit_term_mmap;
		}

		/* reserve the DMA channel and set up descriptors */
		if (cfg->dma_type == DMA_TYPE_SDMA) {
			cfg->sdma_hdl = sdma_request_channel(cfg->device);
			if (cfg->sdma_hdl < 0) {
				printk(KERN_ERR
				       "sdma_request_channel failed\n");
				goto exit_unmap;
			}

			rc = sdma_map_create_descriptor_ring(cfg->sdma_hdl,
							     &cfg->mmap_cfg,
							     devPhysAddr,
							     DMA_UPDATE_MODE_INC);
			if (rc < 0) {
				printk(KERN_ERR "create desc ring failed\n");
				goto exit_free_dma_channel;
			}
		} else {
			printk(KERN_ERR "only support SDMA for now\n");
			rc = -EINVAL;
			goto exit_unmap;
#if 0
			cfg->dma_hdl = dma_request_channel(cfg->device);
			if (cfg->dma_hdl < 0) {
				printk(KERN_ERR "dma_request_channel failed\n");
				goto exit_unmap;
			}

			rc = dma_map_create_descriptor_ring(cfg->device,
							    &cfg->mmap_cfg,
							    devPhysAddr,
							    DMA_UPDATE_MODE_INC);
			if (rc < 0) {
				printk(KERN_ERR "create desc ring failed\n");
				goto exit_free_dma_channel;
			}
#endif
		}

		/* set DMA interrupt handler */
		rc = set_dev_handler(cfg);
		if (rc < 0) {
			printk(KERN_ERR "set_dev_handler failed\n");
			goto exit_free_dma_channel;
		}

		INIT_COMPLETION(cfg->dma_done);

		if (cfg->dma_type == DMA_TYPE_SDMA) {
			rc = sdma_start_transfer(cfg->sdma_hdl);
			if (rc < 0) {
				printk(KERN_ERR "sdma_transfer failed\n");
				goto exit_free_dma_channel;
			}
		}
#if 0
		else {		/* synopsys DMA */

			rc = dma_start_transfer(cfg->dma_hdl, cfg->len);
			if (rc < 0) {
				printk(KERN_ERR "dma_start_transfer failed\n");
				goto exit_free_dma_channel;
			}
		}
#endif

		time_left =
		    wait_for_completion_timeout(&cfg->dma_done, TIMEOUT_TIME);
		if (time_left == 0) {
			printk(KERN_ERR
			       "DMA MMAP test timeout after %lu trials\n",
			       trials);
			goto exit_free_dma_channel;
		}

		/* free DMA channel and unmap memory */
		if (cfg->dma_type == DMA_TYPE_SDMA)
			sdma_free_channel(cfg->sdma_hdl);
#if 0
		else
			dma_free_channel(cfg->dma_hdl);
#endif

		dma_mmap_unmap(&cfg->mmap_cfg, 0);

		/* verify the result */
		for (i = 0; i < cfg->len; i++) {
			if (((unsigned char *)cfg->src_ptr)[i] !=
			    ((unsigned char *)cfg->dst_ptr)[i]) {
				printk(KERN_ERR
				       "src[%u]=%u != dst[%u]=%u trials=%lu\n",
				       i, ((unsigned char *)cfg->src_ptr)[i], i,
				       ((unsigned char *)cfg->dst_ptr)[i],
				       trials);
				goto exit_term_mmap;
			}
		}

		trials++;
	}

exit_free_dma_channel:
	if (cfg->dma_type == DMA_TYPE_SDMA)
		sdma_free_channel(cfg->sdma_hdl);
#if 0
	else
		dma_free_channel(cfg->dma_hdl);
#endif

exit_unmap:
	dma_mmap_unmap(&cfg->mmap_cfg, 0);

exit_term_mmap:
	dma_mmap_term_map(&cfg->mmap_cfg);

exit_free_mem:
	if (cfg->src_ptr) {
		free_mem(cfg->src_ptr, cfg->src_addr, cfg->len, cfg->src_type);
		cfg->src_ptr = NULL;
	}

	if (cfg->dst_ptr) {
		free_mem(cfg->dst_ptr, cfg->dst_addr, cfg->len, cfg->dst_type);
		cfg->dst_ptr = NULL;
	}

	cfg->thread = NULL;
	cfg->in_use = 0;
	cfg->kill_thread = 0;

	printk(KERN_INFO "Quitted test thread\n");
}
/***********************************************************************
 *
 * Function: sd_dma_disable
 *
 * Purpose: Disable and return the SD card controller DMA channel
 *
 * Processing:
 *     Free (and disable) the DMA channel allocated to this driver.
 *
 * Parameters: None
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
static void sd_dma_disable(void)
{
  sdcarddat.regptr->sd_dctrl &= ~SD_DMA_EN;
  dma_free_channel(sdcarddat.dmact.dmach);
}