/* * Initializes the NFC hardware. */ int mxs_nand_init(struct mxs_nand_info *info) { struct mxs_gpmi_regs *gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE; struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; int i = 0, j, ret = 0; info->desc = malloc(sizeof(struct mxs_dma_desc *) * MXS_NAND_DMA_DESCRIPTOR_COUNT); if (!info->desc) { ret = -ENOMEM; goto err1; } /* Allocate the DMA descriptors. */ for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) { info->desc[i] = mxs_dma_desc_alloc(); if (!info->desc[i]) { ret = -ENOMEM; goto err2; } } /* Init the DMA controller. */ mxs_dma_init(); for (j = MXS_DMA_CHANNEL_AHB_APBH_GPMI0; j <= MXS_DMA_CHANNEL_AHB_APBH_GPMI7; j++) { ret = mxs_dma_init_channel(j); if (ret) goto err3; } /* Reset the GPMI block. */ mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg); mxs_reset_block(&bch_regs->hw_bch_ctrl_reg); /* * Choose NAND mode, set IRQ polarity, disable write protection and * select BCH ECC. */ clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1, GPMI_CTRL1_GPMI_MODE, GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET | GPMI_CTRL1_BCH_MODE); return 0; err3: for (--j; j >= MXS_DMA_CHANNEL_AHB_APBH_GPMI0; j--) mxs_dma_release(j); err2: for (--i; i >= 0; i--) mxs_dma_desc_free(info->desc[i]); free(info->desc); err1: if (ret == -ENOMEM) printf("MXS NAND: Unable to allocate DMA descriptors\n"); return ret; }
static int mxs_pcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxs_runtime_data *prtd = runtime->private_data; int desc_num = mxs_pcm_hardware.periods_max; int desc; int timeo = 20; static LIST_HEAD(list); mxs_dma_disable(prtd->dma_ch); /* Wait until the DMA chain is finished. */ while (mxs_dma_read_semaphore(prtd->dma_ch)) { if (!timeo--) break; pr_debug("The sema is not zero now\n"); msleep(10); } if (timeo <= 0) pr_warn("Is the DMA channel dead?\n"); /* Free DMA irq */ free_irq(prtd->params->irq, substream); mxs_dma_get_cooked(prtd->dma_ch, &list); /* Free DMA channel*/ for (desc = 0; desc < desc_num; desc++) mxs_dma_free_desc(prtd->dma_desc_array[desc]); mxs_dma_release(prtd->dma_ch, mxs_pcm_dev); /* Free private runtime data */ kfree(prtd); return 0; }
static int mxs_pcm_dma_request(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct mxs_runtime_data *prtd = runtime->private_data; struct mxs_pcm_dma_params *dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); int desc_num = mxs_pcm_hardware.periods_max; int desc; int ret; if (!dma_data) return -ENODEV; prtd->params = dma_data; prtd->dma_ch = dma_data->dma_ch; ret = mxs_dma_request(prtd->dma_ch, mxs_pcm_dev, prtd->params->name); if (ret) { printk(KERN_ERR "%s: Failed to request DMA channel (%d:%d)\n", __func__, dma_data->dma_bus, dma_data->dma_ch); return ret; } /* Allocate memory for data and pio DMA descriptors */ for (desc = 0; desc < desc_num; desc++) { prtd->dma_desc_array[desc] = mxs_dma_alloc_desc(); if (prtd->dma_desc_array[desc] == NULL) { printk(KERN_ERR"%s Unable to allocate DMA command %d\n", __func__, desc); goto err; } } ret = request_irq(prtd->params->irq, mxs_pcm_dma_irq, 0, "MXS PCM DMA", substream); if (ret) { printk(KERN_ERR "%s: Unable to request DMA irq %d\n", __func__, prtd->params->irq); goto err; } /* Enable completion interrupt */ mxs_dma_ack_irq(prtd->dma_ch); mxs_dma_enable_irq(prtd->dma_ch, 1); return 0; err: while (--desc >= 0) mxs_dma_free_desc(prtd->dma_desc_array[desc]); mxs_dma_release(prtd->dma_ch, mxs_pcm_dev); return ret; }
/* * Initializes the NFC hardware. */ int mxs_nand_init(struct mxs_nand_info *info) { int ret; int i; info->desc = malloc(sizeof(struct mxs_dma_desc *) * MXS_NAND_DMA_DESCRIPTOR_COUNT); if (!info->desc) { printf("MXS NAND: Unable to allocate DMA descriptor table\n"); ret = -ENOMEM; goto err1; } mxs_dma_init(); /* Allocate the DMA descriptors. */ for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) { info->desc[i] = mxs_dma_desc_alloc(); if (!info->desc[i]) { printf("MXS NAND: Unable to allocate DMA descriptors\n"); ret = -ENOMEM; goto err2; } } /* Init the DMA controller. */ for (i = 0; i < CONFIG_SYS_NAND_MAX_CHIPS; i++) { const int chan = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + i; ret = mxs_dma_init_channel(chan); if (ret) { printf("Failed to initialize DMA channel %d\n", chan); goto err3; } } ret = mxs_nand_gpmi_init(); if (ret) goto err3; return 0; err3: for (--i; i >= 0; i--) mxs_dma_release(i + MXS_DMA_CHANNEL_AHB_APBH_GPMI0); i = MXS_NAND_DMA_DESCRIPTOR_COUNT - 1; err2: free(info->desc); for (--i; i >= 0; i--) mxs_dma_desc_free(info->desc[i]); err1: return ret; }
static int __devexit mxs_hsadc_remove(struct platform_device *pdev) { struct mxs_hsadc_data *pd = platform_get_drvdata(pdev); u32 ctrl = 0; hsadc_cleanup_cdev(pd); // clean cdev interface if (pd->buf_phy) dma_free_coherent(NULL, DMA_BUF_SIZE, pd->buf, pd->buf_phy); if (pd->desc) mxs_dma_free_desc(pd->desc); mxs_dma_enable_irq(pd->dma_ch, 0); ctrl = readl(pd->hsadc_base + HSADC_CTRL1); ctrl &= ~(1<<31 | 1<<30 | 1<<29); // disable irq writel(ctrl, pd->hsadc_base + HSADC_CTRL1); mxs_dma_disable(pd->dma_ch); mxs_dma_release(pd->dma_ch, pd->dev); free_irq(pd->dev_irq, pd); free_irq(pd->dma_irq, pd); clk_disable(pd->hsadc_clk); clk_disable(pd->pwm_clk); clk_disable(pd->ref_hsadc_clk); clk_put(pd->hsadc_clk); clk_put(pd->pwm_clk); clk_put(pd->ref_hsadc_clk); iounmap(pd->pwm_base); iounmap(pd->hsadc_base); platform_set_drvdata(pdev, NULL); kfree(pd); #if HSADC_DEBUG printk(KERN_INFO "%s> driver removed.\n", HSADC_DEVICE_NAME); #endif return 0; }
static int mxs_pcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxs_runtime_data *prtd = runtime->private_data; int desc_num = mxs_pcm_hardware.periods_max; int desc; static LIST_HEAD(list); mxs_dma_disable(prtd->dma_ch); /* Free DMA irq */ free_irq(prtd->params->irq, substream); mxs_dma_get_cooked(prtd->dma_ch, &list); /* Free DMA channel*/ for (desc = 0; desc < desc_num; desc++) mxs_dma_free_desc(prtd->dma_desc_array[desc]); mxs_dma_release(prtd->dma_ch, mxs_pcm_dev); /* Free private runtime data */ kfree(prtd); return 0; }
static int __devinit mxs_hsadc_probe(struct platform_device *pdev) { struct mxs_hsadc_data *pd; struct resource *res; int rlevel = 0; pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (pd) rlevel++; else goto quit; pd->dev = &pdev->dev; platform_set_drvdata(pdev, pd); pd->pdev = pdev; rlevel++; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) goto quit; pd->hsadc_base = ioremap(res->start, res->end - res->start); if (pd->hsadc_base) rlevel++; else goto quit; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res == NULL) goto quit; pd->pwm_base = ioremap(res->start, res->end - res->start); if (pd->pwm_base) rlevel++; else goto quit; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res) pd->dev_irq = res->start; else goto quit; res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (res) pd->dma_irq = res->start; else goto quit; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) pd->dma_ch = res->start; else goto quit; pd->ref_hsadc_clk = clk_get(NULL, "ref_hsadc"); if (pd->ref_hsadc_clk) rlevel++; else goto quit; pd->hsadc_clk = clk_get(NULL, "hsadc"); if (pd->hsadc_clk) rlevel++; else goto quit; pd->pwm_clk = clk_get(NULL, "pwm"); if (pd->pwm_clk) rlevel++; else goto quit; clk_enable(pd->ref_hsadc_clk); clk_enable(pd->hsadc_clk); clk_enable(pd->pwm_clk); rlevel++; clk_set_rate(pd->ref_hsadc_clk, REF_HSADC_FREQ); clk_set_rate(pd->hsadc_clk, HSADC_FREQ); if (request_irq(pd->dma_irq, hsadc_dma_isr, 0, "hsadc dma", pd)) goto quit; else rlevel++; if (request_irq(pd->dev_irq, hsadc_isr, 0, "hsadc irq", pd)) goto quit; else rlevel++; if (mxs_dma_request(pd->dma_ch, pd->dev, "hsadc")) goto quit; else rlevel++; mxs_dma_disable(pd->dma_ch); pd->desc = mxs_dma_alloc_desc(); if (pd->desc==NULL) goto quit; memset(&pd->desc->cmd, 0, sizeof(pd->desc->cmd)); rlevel++; pd->buf = dma_alloc_coherent(NULL, DMA_BUF_SIZE, &pd->buf_phy, GFP_KERNEL); if(!pd->buf) goto quit; rlevel++; if(hsadc_init_cdev(pd)) goto quit; #if HSADC_DEBUG printk(KERN_INFO "%s> probe successed.\n", HSADC_DEVICE_NAME); #endif return 0; quit: pr_err("%s quit at rlevel %d\n", __func__, rlevel); switch (rlevel) { case 14: hsadc_cleanup_cdev(pd); case 13: if (pd->buf_phy) dma_free_coherent(NULL, DMA_BUF_SIZE, pd->buf, pd->buf_phy); case 12: if (pd->desc) mxs_dma_free_desc(pd->desc); case 11: mxs_dma_release(pd->dma_ch, pd->dev); case 10: free_irq(pd->dev_irq, pd); case 9: free_irq(pd->dma_irq, pd); case 8: clk_disable(pd->pwm_clk); clk_disable(pd->hsadc_clk); clk_disable(pd->ref_hsadc_clk); case 7: clk_put(pd->pwm_clk); case 6: clk_put(pd->hsadc_clk); case 5: clk_put(pd->ref_hsadc_clk); case 4: iounmap(pd->pwm_base); case 3: iounmap(pd->hsadc_base); case 2: platform_set_drvdata(pdev, NULL); case 1: kfree(pd); case 0: default: return -ENODEV; } }