Loading Documentation/ABI/testing/sysfs-platform-hidma 0 → 100644 +9 −0 Original line number Diff line number Diff line What: /sys/devices/platform/hidma-*/chid /sys/devices/platform/QCOM8061:*/chid Date: Dec 2015 KernelVersion: 4.4 Contact: "Sinan Kaya <okaya@cudeaurora.org>" Description: Contains the ID of the channel within the HIDMA instance. It is used to associate a given HIDMA channel with the priority and weight calls in the management interface. Documentation/devicetree/bindings/dma/qcom_bam_dma.txt +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ Required properties: - clock-names: must contain "bam_clk" entry - qcom,ee : indicates the active Execution Environment identifier (0-7) used in the secure world. - qcom,controlled-remotely : optional, indicates that the bam is controlled by remote proccessor i.e. execution environment. Example: Loading drivers/dma/qcom/Makefile +2 −0 Original line number Diff line number Diff line obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mgmt.o hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o obj-$(CONFIG_QCOM_HIDMA) += hdma.o hdma-objs := hidma_ll.o hidma.o hidma_dbg.o drivers/dma/qcom/bam_dma.c +26 −12 Original line number Diff line number Diff line Loading @@ -342,7 +342,7 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { #define BAM_DESC_FIFO_SIZE SZ_32K #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) #define BAM_MAX_DATA_SIZE (SZ_32K - 8) #define BAM_FIFO_SIZE (SZ_32K - 8) struct bam_chan { struct virt_dma_chan vc; Loading Loading @@ -387,6 +387,7 @@ struct bam_device { /* execution environment ID, from DT */ u32 ee; bool controlled_remotely; const struct reg_offset_data *layout; Loading Loading @@ -458,7 +459,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan, */ writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR)); writel_relaxed(BAM_DESC_FIFO_SIZE, writel_relaxed(BAM_FIFO_SIZE, bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES)); /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ Loading Loading @@ -604,7 +605,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, /* calculate number of required entries */ for_each_sg(sgl, sg, sg_len, i) num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_MAX_DATA_SIZE); num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_FIFO_SIZE); /* allocate enough room to accomodate the number of entries */ async_desc = kzalloc(sizeof(*async_desc) + Loading Loading @@ -635,10 +636,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, desc->addr = cpu_to_le32(sg_dma_address(sg) + curr_offset); if (remainder > BAM_MAX_DATA_SIZE) { desc->size = cpu_to_le16(BAM_MAX_DATA_SIZE); remainder -= BAM_MAX_DATA_SIZE; curr_offset += BAM_MAX_DATA_SIZE; if (remainder > BAM_FIFO_SIZE) { desc->size = cpu_to_le16(BAM_FIFO_SIZE); remainder -= BAM_FIFO_SIZE; curr_offset += BAM_FIFO_SIZE; } else { desc->size = cpu_to_le16(remainder); remainder = 0; Loading Loading @@ -801,13 +802,17 @@ static irqreturn_t bam_dma_irq(int irq, void *data) if (srcs & P_IRQ) tasklet_schedule(&bdev->task); if (srcs & BAM_IRQ) if (srcs & BAM_IRQ) { clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS)); /* don't allow reorder of the various accesses to the BAM registers */ /* * don't allow reorder of the various accesses to the BAM * registers */ mb(); writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR)); } return IRQ_HANDLED; } Loading Loading @@ -1038,6 +1043,9 @@ static int bam_init(struct bam_device *bdev) val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); bdev->num_channels = val & BAM_NUM_PIPES_MASK; if (bdev->controlled_remotely) return 0; /* s/w reset bam */ /* after reset all pipes are disabled and idle */ val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL)); Loading Loading @@ -1125,6 +1133,9 @@ static int bam_dma_probe(struct platform_device *pdev) return ret; } bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, "qcom,controlled-remotely"); bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); if (IS_ERR(bdev->bamclk)) return PTR_ERR(bdev->bamclk); Loading Loading @@ -1163,7 +1174,7 @@ static int bam_dma_probe(struct platform_device *pdev) /* set max dma segment size */ bdev->common.dev = bdev->dev; bdev->common.dev->dma_parms = &bdev->dma_parms; ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE); ret = dma_set_max_seg_size(bdev->common.dev, BAM_FIFO_SIZE); if (ret) { dev_err(bdev->dev, "cannot set maximum segment size\n"); goto err_bam_channel_exit; Loading Loading @@ -1234,6 +1245,9 @@ static int bam_dma_remove(struct platform_device *pdev) bam_dma_terminate_all(&bdev->channels[i].vc.chan); tasklet_kill(&bdev->channels[i].vc.task); if (!bdev->channels[i].fifo_virt) continue; dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bdev->channels[i].fifo_virt, bdev->channels[i].fifo_phys); Loading drivers/dma/qcom/hidma.c +46 −6 Original line number Diff line number Diff line /* * Qualcomm Technologies HIDMA DMA engine interface * * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -404,7 +404,7 @@ static int hidma_terminate_channel(struct dma_chan *chan) spin_unlock_irqrestore(&mchan->lock, irqflags); /* this suspends the existing transfer */ rc = hidma_ll_pause(dmadev->lldev); rc = hidma_ll_disable(dmadev->lldev); if (rc) { dev_err(dmadev->ddev.dev, "channel did not pause\n"); goto out; Loading @@ -427,7 +427,7 @@ static int hidma_terminate_channel(struct dma_chan *chan) list_move(&mdesc->node, &mchan->free); } rc = hidma_ll_resume(dmadev->lldev); rc = hidma_ll_enable(dmadev->lldev); out: pm_runtime_mark_last_busy(dmadev->ddev.dev); pm_runtime_put_autosuspend(dmadev->ddev.dev); Loading Loading @@ -488,7 +488,7 @@ static int hidma_pause(struct dma_chan *chan) dmadev = to_hidma_dev(mchan->chan.device); if (!mchan->paused) { pm_runtime_get_sync(dmadev->ddev.dev); if (hidma_ll_pause(dmadev->lldev)) if (hidma_ll_disable(dmadev->lldev)) dev_warn(dmadev->ddev.dev, "channel did not stop\n"); mchan->paused = true; pm_runtime_mark_last_busy(dmadev->ddev.dev); Loading @@ -507,7 +507,7 @@ static int hidma_resume(struct dma_chan *chan) dmadev = to_hidma_dev(mchan->chan.device); if (mchan->paused) { pm_runtime_get_sync(dmadev->ddev.dev); rc = hidma_ll_resume(dmadev->lldev); rc = hidma_ll_enable(dmadev->lldev); if (!rc) mchan->paused = false; else Loading @@ -530,6 +530,43 @@ static irqreturn_t hidma_chirq_handler(int chirq, void *arg) return hidma_ll_inthandler(chirq, lldev); } static ssize_t hidma_show_values(struct device *dev, struct device_attribute *attr, char *buf) { struct platform_device *pdev = to_platform_device(dev); struct hidma_dev *mdev = platform_get_drvdata(pdev); buf[0] = 0; if (strcmp(attr->attr.name, "chid") == 0) sprintf(buf, "%d\n", mdev->chidx); return strlen(buf); } static int hidma_create_sysfs_entry(struct hidma_dev *dev, char *name, int mode) { struct device_attribute *attrs; char *name_copy; attrs = devm_kmalloc(dev->ddev.dev, sizeof(struct device_attribute), GFP_KERNEL); if (!attrs) return -ENOMEM; name_copy = devm_kstrdup(dev->ddev.dev, name, GFP_KERNEL); if (!name_copy) return -ENOMEM; attrs->attr.name = name_copy; attrs->attr.mode = mode; attrs->show = hidma_show_values; sysfs_attr_init(&attrs->attr); return device_create_file(dev->ddev.dev, attrs); } static int hidma_probe(struct platform_device *pdev) { struct hidma_dev *dmadev; Loading Loading @@ -644,6 +681,8 @@ static int hidma_probe(struct platform_device *pdev) dmadev->irq = chirq; tasklet_init(&dmadev->task, hidma_issue_task, (unsigned long)dmadev); hidma_debug_init(dmadev); hidma_create_sysfs_entry(dmadev, "chid", S_IRUGO); dev_info(&pdev->dev, "HI-DMA engine driver registration complete\n"); platform_set_drvdata(pdev, dmadev); pm_runtime_mark_last_busy(dmadev->ddev.dev); Loading @@ -651,6 +690,7 @@ static int hidma_probe(struct platform_device *pdev) return 0; uninit: hidma_debug_uninit(dmadev); hidma_ll_uninit(dmadev->lldev); dmafree: if (dmadev) Loading @@ -668,6 +708,7 @@ static int hidma_remove(struct platform_device *pdev) pm_runtime_get_sync(dmadev->ddev.dev); dma_async_device_unregister(&dmadev->ddev); devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev); hidma_debug_uninit(dmadev); hidma_ll_uninit(dmadev->lldev); hidma_free(dmadev); Loading @@ -689,7 +730,6 @@ static const struct of_device_id hidma_match[] = { {.compatible = "qcom,hidma-1.0",}, {}, }; MODULE_DEVICE_TABLE(of, hidma_match); static struct platform_driver hidma_driver = { Loading Loading
Documentation/ABI/testing/sysfs-platform-hidma 0 → 100644 +9 −0 Original line number Diff line number Diff line What: /sys/devices/platform/hidma-*/chid /sys/devices/platform/QCOM8061:*/chid Date: Dec 2015 KernelVersion: 4.4 Contact: "Sinan Kaya <okaya@cudeaurora.org>" Description: Contains the ID of the channel within the HIDMA instance. It is used to associate a given HIDMA channel with the priority and weight calls in the management interface.
Documentation/devicetree/bindings/dma/qcom_bam_dma.txt +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ Required properties: - clock-names: must contain "bam_clk" entry - qcom,ee : indicates the active Execution Environment identifier (0-7) used in the secure world. - qcom,controlled-remotely : optional, indicates that the bam is controlled by remote proccessor i.e. execution environment. Example: Loading
drivers/dma/qcom/Makefile +2 −0 Original line number Diff line number Diff line obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mgmt.o hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o obj-$(CONFIG_QCOM_HIDMA) += hdma.o hdma-objs := hidma_ll.o hidma.o hidma_dbg.o
drivers/dma/qcom/bam_dma.c +26 −12 Original line number Diff line number Diff line Loading @@ -342,7 +342,7 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { #define BAM_DESC_FIFO_SIZE SZ_32K #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) #define BAM_MAX_DATA_SIZE (SZ_32K - 8) #define BAM_FIFO_SIZE (SZ_32K - 8) struct bam_chan { struct virt_dma_chan vc; Loading Loading @@ -387,6 +387,7 @@ struct bam_device { /* execution environment ID, from DT */ u32 ee; bool controlled_remotely; const struct reg_offset_data *layout; Loading Loading @@ -458,7 +459,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan, */ writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR)); writel_relaxed(BAM_DESC_FIFO_SIZE, writel_relaxed(BAM_FIFO_SIZE, bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES)); /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ Loading Loading @@ -604,7 +605,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, /* calculate number of required entries */ for_each_sg(sgl, sg, sg_len, i) num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_MAX_DATA_SIZE); num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_FIFO_SIZE); /* allocate enough room to accomodate the number of entries */ async_desc = kzalloc(sizeof(*async_desc) + Loading Loading @@ -635,10 +636,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, desc->addr = cpu_to_le32(sg_dma_address(sg) + curr_offset); if (remainder > BAM_MAX_DATA_SIZE) { desc->size = cpu_to_le16(BAM_MAX_DATA_SIZE); remainder -= BAM_MAX_DATA_SIZE; curr_offset += BAM_MAX_DATA_SIZE; if (remainder > BAM_FIFO_SIZE) { desc->size = cpu_to_le16(BAM_FIFO_SIZE); remainder -= BAM_FIFO_SIZE; curr_offset += BAM_FIFO_SIZE; } else { desc->size = cpu_to_le16(remainder); remainder = 0; Loading Loading @@ -801,13 +802,17 @@ static irqreturn_t bam_dma_irq(int irq, void *data) if (srcs & P_IRQ) tasklet_schedule(&bdev->task); if (srcs & BAM_IRQ) if (srcs & BAM_IRQ) { clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS)); /* don't allow reorder of the various accesses to the BAM registers */ /* * don't allow reorder of the various accesses to the BAM * registers */ mb(); writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR)); } return IRQ_HANDLED; } Loading Loading @@ -1038,6 +1043,9 @@ static int bam_init(struct bam_device *bdev) val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); bdev->num_channels = val & BAM_NUM_PIPES_MASK; if (bdev->controlled_remotely) return 0; /* s/w reset bam */ /* after reset all pipes are disabled and idle */ val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL)); Loading Loading @@ -1125,6 +1133,9 @@ static int bam_dma_probe(struct platform_device *pdev) return ret; } bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, "qcom,controlled-remotely"); bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); if (IS_ERR(bdev->bamclk)) return PTR_ERR(bdev->bamclk); Loading Loading @@ -1163,7 +1174,7 @@ static int bam_dma_probe(struct platform_device *pdev) /* set max dma segment size */ bdev->common.dev = bdev->dev; bdev->common.dev->dma_parms = &bdev->dma_parms; ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE); ret = dma_set_max_seg_size(bdev->common.dev, BAM_FIFO_SIZE); if (ret) { dev_err(bdev->dev, "cannot set maximum segment size\n"); goto err_bam_channel_exit; Loading Loading @@ -1234,6 +1245,9 @@ static int bam_dma_remove(struct platform_device *pdev) bam_dma_terminate_all(&bdev->channels[i].vc.chan); tasklet_kill(&bdev->channels[i].vc.task); if (!bdev->channels[i].fifo_virt) continue; dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bdev->channels[i].fifo_virt, bdev->channels[i].fifo_phys); Loading
drivers/dma/qcom/hidma.c +46 −6 Original line number Diff line number Diff line /* * Qualcomm Technologies HIDMA DMA engine interface * * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -404,7 +404,7 @@ static int hidma_terminate_channel(struct dma_chan *chan) spin_unlock_irqrestore(&mchan->lock, irqflags); /* this suspends the existing transfer */ rc = hidma_ll_pause(dmadev->lldev); rc = hidma_ll_disable(dmadev->lldev); if (rc) { dev_err(dmadev->ddev.dev, "channel did not pause\n"); goto out; Loading @@ -427,7 +427,7 @@ static int hidma_terminate_channel(struct dma_chan *chan) list_move(&mdesc->node, &mchan->free); } rc = hidma_ll_resume(dmadev->lldev); rc = hidma_ll_enable(dmadev->lldev); out: pm_runtime_mark_last_busy(dmadev->ddev.dev); pm_runtime_put_autosuspend(dmadev->ddev.dev); Loading Loading @@ -488,7 +488,7 @@ static int hidma_pause(struct dma_chan *chan) dmadev = to_hidma_dev(mchan->chan.device); if (!mchan->paused) { pm_runtime_get_sync(dmadev->ddev.dev); if (hidma_ll_pause(dmadev->lldev)) if (hidma_ll_disable(dmadev->lldev)) dev_warn(dmadev->ddev.dev, "channel did not stop\n"); mchan->paused = true; pm_runtime_mark_last_busy(dmadev->ddev.dev); Loading @@ -507,7 +507,7 @@ static int hidma_resume(struct dma_chan *chan) dmadev = to_hidma_dev(mchan->chan.device); if (mchan->paused) { pm_runtime_get_sync(dmadev->ddev.dev); rc = hidma_ll_resume(dmadev->lldev); rc = hidma_ll_enable(dmadev->lldev); if (!rc) mchan->paused = false; else Loading @@ -530,6 +530,43 @@ static irqreturn_t hidma_chirq_handler(int chirq, void *arg) return hidma_ll_inthandler(chirq, lldev); } static ssize_t hidma_show_values(struct device *dev, struct device_attribute *attr, char *buf) { struct platform_device *pdev = to_platform_device(dev); struct hidma_dev *mdev = platform_get_drvdata(pdev); buf[0] = 0; if (strcmp(attr->attr.name, "chid") == 0) sprintf(buf, "%d\n", mdev->chidx); return strlen(buf); } static int hidma_create_sysfs_entry(struct hidma_dev *dev, char *name, int mode) { struct device_attribute *attrs; char *name_copy; attrs = devm_kmalloc(dev->ddev.dev, sizeof(struct device_attribute), GFP_KERNEL); if (!attrs) return -ENOMEM; name_copy = devm_kstrdup(dev->ddev.dev, name, GFP_KERNEL); if (!name_copy) return -ENOMEM; attrs->attr.name = name_copy; attrs->attr.mode = mode; attrs->show = hidma_show_values; sysfs_attr_init(&attrs->attr); return device_create_file(dev->ddev.dev, attrs); } static int hidma_probe(struct platform_device *pdev) { struct hidma_dev *dmadev; Loading Loading @@ -644,6 +681,8 @@ static int hidma_probe(struct platform_device *pdev) dmadev->irq = chirq; tasklet_init(&dmadev->task, hidma_issue_task, (unsigned long)dmadev); hidma_debug_init(dmadev); hidma_create_sysfs_entry(dmadev, "chid", S_IRUGO); dev_info(&pdev->dev, "HI-DMA engine driver registration complete\n"); platform_set_drvdata(pdev, dmadev); pm_runtime_mark_last_busy(dmadev->ddev.dev); Loading @@ -651,6 +690,7 @@ static int hidma_probe(struct platform_device *pdev) return 0; uninit: hidma_debug_uninit(dmadev); hidma_ll_uninit(dmadev->lldev); dmafree: if (dmadev) Loading @@ -668,6 +708,7 @@ static int hidma_remove(struct platform_device *pdev) pm_runtime_get_sync(dmadev->ddev.dev); dma_async_device_unregister(&dmadev->ddev); devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev); hidma_debug_uninit(dmadev); hidma_ll_uninit(dmadev->lldev); hidma_free(dmadev); Loading @@ -689,7 +730,6 @@ static const struct of_device_id hidma_match[] = { {.compatible = "qcom,hidma-1.0",}, {}, }; MODULE_DEVICE_TABLE(of, hidma_match); static struct platform_driver hidma_driver = { Loading