예제 #1
0
int s3c6410_dmac_request(struct dma_data *dmadata, void *id)
{
    unsigned int 				channel = MAX_DMA_CHANNELS;
    unsigned int 				flow_ctrl = 0;
    unsigned int				val;

    if(dmadata->active == DMA_USED) {
        printk(KERN_WARNING "%s: Already allocated dma channel\n", DRIVER_NAME);
        return -EBUSY;
    }

    channel = get_dma_channel(dmadata->dma_port);
    DBG("%s: allocated dma channel[%d] for %s\n", DRIVER_NAME, channel, pdev->name);
    if(channel == MAX_DMA_CHANNELS) {
        printk(KERN_ERR "%s: Can't get dma channel\n", DRIVER_NAME);
        return -EBUSY;
    }

    dmadata->active = DMA_USED;
    dmadata->chan_num = channel;
    dmadata->private_data = id;

    /* Get the dmadata for the device which requested DMA */
    dport[dmadata->dma_port].dmac[channel]->dmadata = dmadata;

    dmac_writel(INTTC_CLR_CH(channel), 	 dmadata->dma_port, DMACINTTCCLR);
    dmac_writel(ERR_INT_CLR_CH(channel), dmadata->dma_port, DMACINTERRCLR);

    val = dmac_readl(dmadata->dma_port, DMACCFG);
    if(!(val && DMAC_ENABLE)) {
        val |= DMAC_ENABLE;
        dmac_writel(val, dmadata->dma_port, DMACCFG);
    }

    /* Configuration SRC/DST Addr, LLI Register */
    flow_ctrl = (dmadata->dmac_cfg & 0x3800);

    if(flow_ctrl == FCTL_DMA_M2P)
        dmac_writel(dmadata->dst_addr, dmadata->dma_port, DMACCxDSTADDR(dmadata->chan_num));

    else if(flow_ctrl == FCTL_DMA_P2M)
        dmac_writel(dmadata->src_addr, dmadata->dma_port, DMACCxSRCADDR(dmadata->chan_num));

    dmac_writel(dmadata->lli_addr, dmadata->dma_port, DMACCxLLI	   (dmadata->chan_num));

    DBG("%s: Pass dmac_request()\n", DRIVER_NAME);

    return 0;
}
예제 #2
0
static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
{
	ssize_t len = 0;
	int i;

	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
		struct dma_info *info = get_dma_info(i);
		struct dma_channel *channel = get_dma_channel(i);

		if (unlikely(!info) || !channel)
			continue;

		len += sprintf(buf + len, "%2d: %14s    %s\n",
			       channel->chan, info->name,
			       channel->dev_id);
	}

	return len;
}
예제 #3
0
static ssize_t dma_show_devices(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	ssize_t len = 0;
	int i;

	for (i = 0; get_dma_info(i) != NULL; i++) {
		struct dma_info *info = get_dma_info(i);
		struct dma_channel *channel = get_dma_channel(i);

		if (unlikely(!info) || !channel)
			continue;

		len += sprintf(buf + len, "%2d: %14s    %s\n",
			       channel->chan, info->name,
			       channel->dev_id);
	}

	return len;
}
예제 #4
0
static int __init fdma_driver_probe(struct platform_device *pdev)
{
	static __initdata char *fdma_clks_n[FDMA_CLKS_NR] = {
		[FDMA_SLIM_CLK] = "fdma_slim_clk",
		[FDMA_HI_CLK] = "fdma_hi_clk",
		[FDMA_LOW_CLK] = "fdma_low_clk",
		[FDMA_IC_CLK] = "fdma_ic_clk",
	};
	struct stm_plat_fdma_data *plat_data;
	struct fdma *fdma = NULL;
	struct resource *res;
	int chan_num, i;
	int err = 0;

	plat_data = pdev->dev.platform_data;

	fdma = kzalloc(sizeof(struct fdma), GFP_KERNEL);
	if (fdma == NULL)
		return -ENOMEM;

	for (i = 0; i < FDMA_CLKS_NR; ++i) {
		fdma->clks[i] = clk_get(&pdev->dev, fdma_clks_n[i]);
		if (!fdma->clks[i] || IS_ERR(fdma->clks[i]))
			pr_warning("%s: clk %s not found\n",
				dev_name(&pdev->dev), fdma_clks_n[i]);
	}

	stm_fdma_clk_enable(fdma);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENODEV;

	fdma->phys_mem = request_mem_region(res->start,
			res->end - res->start + 1, pdev->name);
	if (fdma->phys_mem == NULL)
		return -EBUSY;

	fdma->io_base = ioremap_nocache(res->start, res->end - res->start + 1);
	if (fdma->io_base == NULL)
		return -EINVAL;

	fdma->pdev = pdev;
	fdma->fdma_num = (pdev->id != -1 ? pdev->id : 0);
	fdma_channels_parse(fdma);

	fdma->ch_status_mask = ((1ULL << ((fdma->ch_max + 1) * 2)) - 1ULL) ^
			((1 << (fdma->ch_min * 2)) - 1);

	fdma->fw = plat_data->fw;
	fdma->hw = plat_data->hw;

	fdma->regs.id = fdma->hw->slim_regs.id;
	fdma->regs.ver = fdma->hw->slim_regs.ver;
	fdma->regs.en = fdma->hw->slim_regs.en;
	fdma->regs.clk_gate = fdma->hw->slim_regs.clk_gate;
	fdma->regs.rev_id = fdma->fw->rev_id;
	fdma->regs.cmd_statn = fdma->fw->cmd_statn;
	fdma->regs.req_ctln = fdma->fw->req_ctln;
	fdma->regs.ptrn = fdma->fw->ptrn;
	fdma->regs.cntn = fdma->fw->cntn;
	fdma->regs.saddrn = fdma->fw->saddrn;
	fdma->regs.daddrn = fdma->fw->daddrn;
	fdma->regs.sync_reg = fdma->hw->periph_regs.sync_reg;
	fdma->regs.cmd_sta = fdma->hw->periph_regs.cmd_sta;
	fdma->regs.cmd_set = fdma->hw->periph_regs.cmd_set;
	fdma->regs.cmd_clr = fdma->hw->periph_regs.cmd_clr;
	fdma->regs.cmd_mask = fdma->hw->periph_regs.cmd_mask;
	fdma->regs.int_sta = fdma->hw->periph_regs.int_sta;
	fdma->regs.int_set = fdma->hw->periph_regs.int_set;
	fdma->regs.int_clr = fdma->hw->periph_regs.int_clr;
	fdma->regs.int_mask = fdma->hw->periph_regs.int_mask;

	/* Req lines 0 and 31 are basically unusable */
	fdma->reqs_used_mask = (1 << 31) | (1 << 0);
	spin_lock_init(&fdma->reqs_lock);

	spin_lock_init(&fdma->channels_lock);
	init_waitqueue_head(&fdma->fw_load_q);

	fdma->dma_info.nr_channels = fdma->ch_max - fdma->ch_min + 1;
	fdma->dma_info.ops = &fdma_ops;
	fdma->dma_info.flags = DMAC_CHANNELS_TEI_CAPABLE;
	strlcpy(fdma->name, STM_DMAC_ID, FDMA_NAME_LEN);
	if (pdev->id != -1) {
		int len = strlen(fdma->name);
		snprintf(fdma->name + len, FDMA_NAME_LEN - len, ".%d",
				pdev->id);
	}
	fdma->dma_info.name = fdma->name;

	if (register_dmac(&fdma->dma_info) != 0)
		printk(KERN_ERR "%s(): Error Registering DMAC\n", __func__);

	for (chan_num = fdma->ch_min; chan_num <= fdma->ch_max; chan_num++) {
		struct fdma_channel *channel = &fdma->channels[chan_num];
		struct dma_channel *dma_chan;

		channel->chan_num = chan_num;
		channel->fdma = fdma;

		dma_chan = get_dma_channel(chan_num - fdma->ch_min +
					   fdma->dma_info.first_vchannel_nr);

		dma_chan->priv_data = channel;
		channel->dma_chan = dma_chan;
	}

	fdma->irq = platform_get_irq(pdev, 0);
	err = request_irq(fdma->irq, fdma_irq,
			 IRQF_DISABLED | IRQF_SHARED, fdma->name, fdma);
	if (err < 0)
		panic("Cant Register irq %d for FDMA engine err %d\n",
				fdma->irq, err);

	fdma_register_caps(fdma);

	fdma_check_firmware_state(fdma);

	platform_set_drvdata(pdev, fdma);

	return 0;
}