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; }
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; }
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; }
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; }