Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82770a2f authored by Vinod Koul's avatar Vinod Koul
Browse files

Merge branch 'topic/qcom' into for-linus

parents ba8b6cc0 42d236f8
Loading
Loading
Loading
Loading
+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.
+2 −0
Original line number Diff line number Diff line
@@ -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:

+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
+26 −12
Original line number Diff line number Diff line
@@ -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;
@@ -387,6 +387,7 @@ struct bam_device {

	/* execution environment ID, from DT */
	u32 ee;
	bool controlled_remotely;

	const struct reg_offset_data *layout;

@@ -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 */
@@ -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) +
@@ -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;
@@ -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;
}
@@ -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));
@@ -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);
@@ -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;
@@ -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);
+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
@@ -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;
@@ -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);
@@ -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);
@@ -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
@@ -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;
@@ -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);
@@ -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)
@@ -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);

@@ -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