diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
new file mode 100644
index 0000000..b906170
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
@@ -0,0 +1,62 @@
+Qualcomm Technologies HIDMA Management interface
+
+The Qualcomm Technologies HIDMA device has been designed
+to support virtualization technology. The driver has been
+divided into two to follow the hardware design. The management
+driver is executed in hypervisor context and is the main
+management entity for all channels provided by the device.
+
+Each HIDMA HW consists of multiple channels. These channels
+share some set of common parameters. These parameters are
+initialized by the management driver during power up.
+Same management driver is used for monitoring the execution
+of the channels. Management driver can change the performance
+behavior dynamically such as bandwidth allocation and
+prioritization.
+
+All channel devices get probed in the hypervisor
+context during power up. They show up as DMA engine
+DMA channels. Then, before starting the virtualization; each
+channel device is unbound from the hypervisor by VFIO
+and assign to the guest machine for control.
+
+This management driver will  be used by the system
+admin to monitor/reset the execution state of the DMA
+channels. This will be the management interface.
+
+
+Required properties:
+- compatible: must contain one of these.
+  "qcom,hidma-mgmt-1.1", "qcom,hidma-mgmt-1.0", "qcom,hidma-mgmt";
+- reg: Address range for DMA device
+- dma-channels: Number of channels supported by this DMA controller.
+- max-write-burst-bytes: Maximum write burst in bytes. A memcpy requested is
+  fragmented to multiples of this amount.
+- max-read-burst-bytes: Maximum read burst in bytes. A memcpy request is
+  fragmented to multiples of this amount.
+- max-write-transactions: Maximum write transactions to perform in a burst
+- max-read-transactions: Maximum read transactions to perform in a burst
+- channel-reset-timeout-cycles: Channel reset timeout in cycles for this SOC.
+- channel-priority: Priority of the channel.
+  Each dma channel share the same HW bandwidth with other dma channels.
+  If two requests reach to the HW at the same time from a low priority and
+  high priority channel, high priority channel will claim the bus.
+  0=low priority, 1=high priority
+- channel-weight: Round robin weight of the channel
+  Since there are only two priority levels supported, scheduling among
+  the equal priority channels is done via weights.
+
+Example:
+
+	hidma-mgmt@f9984000 = {
+		compatible = "qcom,hidma-mgmt-1.0";
+		reg = <0xf9984000 0x15000>;
+		dma-channels = 6;
+		max-write-burst-bytes = 1024;
+		max-read-burst-bytes = 1024;
+		max-write-transactions = 31;
+		max-read-transactions = 31;
+		channel-reset-timeout-cycles = 0x500;
+		channel-priority = < 1 1 0 0 0 0>;
+		channel-weight = < 1 13 10 3 4 5>;
+	};
diff --git a/drivers/dma/qcom/Kconfig b/drivers/dma/qcom/Kconfig
index 17545df..f3e2d4c 100644
--- a/drivers/dma/qcom/Kconfig
+++ b/drivers/dma/qcom/Kconfig
@@ -7,3 +7,14 @@ config QCOM_BAM_DMA
 	  Enable support for the QCOM BAM DMA controller.  This controller
 	  provides DMA capabilities for a variety of on-chip devices.
 
+config QCOM_HIDMA_MGMT
+	tristate "Qualcomm Technologies HIDMA Management support"
+	select DMA_ENGINE
+	help
+	  Enable support for the Qualcomm Technologies HIDMA Management.
+	  Each DMA device requires one management interface driver
+	  for basic initialization before QCOM_HIDMA channel driver can
+	  start managing the channels. In a virtualized environment,
+	  the guest OS would run QCOM_HIDMA channel driver and the
+	  hypervisor would run the QCOM_HIDMA_MGMT management driver.
+
diff --git a/drivers/dma/qcom/Makefile b/drivers/dma/qcom/Makefile
index f612ae3..1a5a96d 100644
--- a/drivers/dma/qcom/Makefile
+++ b/drivers/dma/qcom/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o
+obj-$(CONFIG_QCOM_HIDMA_MGMT) += hidma_mgmt.o hidma_mgmt_sys.o
diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
new file mode 100644
index 0000000..94510d6
--- /dev/null
+++ b/drivers/dma/qcom/hidma_mgmt.c
@@ -0,0 +1,315 @@
+/*
+ * Qualcomm Technologies HIDMA DMA engine Management interface
+ *
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/property.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include "hidma_mgmt.h"
+
+#define QOS_N_OFFSET			0x300
+#define CFG_OFFSET			0x400
+#define MAX_BUS_REQ_LEN_OFFSET		0x41C
+#define MAX_XACTIONS_OFFSET		0x420
+#define HW_VERSION_OFFSET		0x424
+#define CHRESET_TIMEOUT_OFFSET		0x418
+
+#define MAX_WR_XACTIONS_MASK		0x1F
+#define MAX_RD_XACTIONS_MASK		0x1F
+#define WEIGHT_MASK			0x7F
+#define MAX_BUS_REQ_LEN_MASK		0xFFFF
+#define CHRESET_TIMEOUUT_MASK		0xFFFFF
+
+#define MAX_WR_XACTIONS_BIT_POS	16
+#define MAX_BUS_WR_REQ_BIT_POS		16
+#define WRR_BIT_POS			8
+#define PRIORITY_BIT_POS		15
+
+#define AUTOSUSPEND_TIMEOUT		2000
+#define MAX_CHANNEL_WEIGHT		15
+
+int hidma_mgmt_setup(struct hidma_mgmt_dev *mgmtdev)
+{
+	u32 val;
+	u32 i;
+
+	if (!is_power_of_2(mgmtdev->max_write_request) ||
+		(mgmtdev->max_write_request < 128) ||
+		(mgmtdev->max_write_request > 1024)) {
+		dev_err(&mgmtdev->pdev->dev, "invalid write request %d\n",
+			mgmtdev->max_write_request);
+		return -EINVAL;
+	}
+
+	if (!is_power_of_2(mgmtdev->max_read_request) ||
+		(mgmtdev->max_read_request < 128) ||
+		(mgmtdev->max_read_request > 1024)) {
+		dev_err(&mgmtdev->pdev->dev, "invalid read request %d\n",
+			mgmtdev->max_read_request);
+		return  -EINVAL;
+	}
+
+	if (mgmtdev->max_wr_xactions > MAX_WR_XACTIONS_MASK) {
+		dev_err(&mgmtdev->pdev->dev,
+			"max_wr_xactions cannot be bigger than %d\n",
+			MAX_WR_XACTIONS_MASK);
+		return -EINVAL;
+	}
+
+	if (mgmtdev->max_rd_xactions > MAX_RD_XACTIONS_MASK) {
+		dev_err(&mgmtdev->pdev->dev,
+			"max_rd_xactions cannot be bigger than %d\n",
+			MAX_RD_XACTIONS_MASK);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < mgmtdev->dma_channels; i++) {
+		if (mgmtdev->priority[i] > 1) {
+			dev_err(&mgmtdev->pdev->dev, "priority can be 0 or 1\n");
+			return -EINVAL;
+		}
+
+		if (mgmtdev->weight[i] > MAX_CHANNEL_WEIGHT) {
+			dev_err(&mgmtdev->pdev->dev,
+				"max value of weight can be %d.\n",
+				MAX_CHANNEL_WEIGHT);
+			return -EINVAL;
+		}
+
+		/* weight needs to be at least one */
+		if (mgmtdev->weight[i] == 0)
+			mgmtdev->weight[i] = 1;
+	}
+
+	pm_runtime_get_sync(&mgmtdev->pdev->dev);
+	val = readl(mgmtdev->dev_virtaddr + MAX_BUS_REQ_LEN_OFFSET);
+	val = val & ~(MAX_BUS_REQ_LEN_MASK << MAX_BUS_WR_REQ_BIT_POS);
+	val = val | (mgmtdev->max_write_request << MAX_BUS_WR_REQ_BIT_POS);
+	val = val & ~(MAX_BUS_REQ_LEN_MASK);
+	val = val | (mgmtdev->max_read_request);
+	writel(val, mgmtdev->dev_virtaddr + MAX_BUS_REQ_LEN_OFFSET);
+
+	val = readl(mgmtdev->dev_virtaddr + MAX_XACTIONS_OFFSET);
+	val = val & ~(MAX_WR_XACTIONS_MASK << MAX_WR_XACTIONS_BIT_POS);
+	val = val | (mgmtdev->max_wr_xactions << MAX_WR_XACTIONS_BIT_POS);
+	val = val & ~(MAX_RD_XACTIONS_MASK);
+	val = val | (mgmtdev->max_rd_xactions);
+	writel(val, mgmtdev->dev_virtaddr + MAX_XACTIONS_OFFSET);
+
+	mgmtdev->hw_version = readl(mgmtdev->dev_virtaddr + HW_VERSION_OFFSET);
+	mgmtdev->hw_version_major = (mgmtdev->hw_version >> 28) & 0xF;
+	mgmtdev->hw_version_minor = (mgmtdev->hw_version >> 16) & 0xF;
+
+	for (i = 0; i < mgmtdev->dma_channels; i++) {
+		val = readl(mgmtdev->dev_virtaddr + QOS_N_OFFSET + (4 * i));
+		val = val & ~(1 << PRIORITY_BIT_POS);
+		val = val |
+			((mgmtdev->priority[i] & 0x1) << PRIORITY_BIT_POS);
+		val = val & ~(WEIGHT_MASK << WRR_BIT_POS);
+		val = val
+			| ((mgmtdev->weight[i] & WEIGHT_MASK) << WRR_BIT_POS);
+		writel(val, mgmtdev->dev_virtaddr + QOS_N_OFFSET + (4 * i));
+	}
+
+	val = readl(mgmtdev->dev_virtaddr + CHRESET_TIMEOUT_OFFSET);
+	val = val & ~CHRESET_TIMEOUUT_MASK;
+	val = val | (mgmtdev->chreset_timeout_cycles & CHRESET_TIMEOUUT_MASK);
+	writel(val, mgmtdev->dev_virtaddr + CHRESET_TIMEOUT_OFFSET);
+
+	pm_runtime_mark_last_busy(&mgmtdev->pdev->dev);
+	pm_runtime_put_autosuspend(&mgmtdev->pdev->dev);
+	return 0;
+}
+
+static int hidma_mgmt_probe(struct platform_device *pdev)
+{
+	struct hidma_mgmt_dev *mgmtdev;
+	struct resource *dma_resource;
+	void *dev_virtaddr;
+	int irq;
+	int rc;
+	u32 val;
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+	dma_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!dma_resource) {
+		dev_err(&pdev->dev, "No memory resources found\n");
+		rc = -ENODEV;
+		goto out;
+	}
+	dev_virtaddr = devm_ioremap_resource(&pdev->dev, dma_resource);
+	if (IS_ERR(dev_virtaddr)) {
+		dev_err(&pdev->dev, "can't map i/o memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "irq resources not found\n");
+		rc = -ENODEV;
+		goto out;
+	}
+
+	mgmtdev = devm_kzalloc(&pdev->dev, sizeof(*mgmtdev), GFP_KERNEL);
+	if (!mgmtdev) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	mgmtdev->pdev = pdev;
+
+	mgmtdev->dev_addrsize = resource_size(dma_resource);
+	mgmtdev->dev_virtaddr = dev_virtaddr;
+
+	if (device_property_read_u32(&pdev->dev, "dma-channels",
+		&mgmtdev->dma_channels)) {
+		dev_err(&pdev->dev, "number of channels missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (device_property_read_u32(&pdev->dev, "channel-reset-timeout-cycles",
+		&mgmtdev->chreset_timeout_cycles)) {
+		dev_err(&pdev->dev, "channel reset timeout missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (device_property_read_u32(&pdev->dev, "max-write-burst-bytes",
+		&mgmtdev->max_write_request)) {
+		dev_err(&pdev->dev, "max-write-burst-bytes missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (device_property_read_u32(&pdev->dev, "max-read-burst-bytes",
+		&mgmtdev->max_read_request)) {
+		dev_err(&pdev->dev, "max-read-burst-bytes missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (device_property_read_u32(&pdev->dev, "max-write-transactions",
+		&mgmtdev->max_wr_xactions)) {
+		dev_err(&pdev->dev, "max-write-transactions missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (device_property_read_u32(&pdev->dev, "max-read-transactions",
+		&mgmtdev->max_rd_xactions)) {
+		dev_err(&pdev->dev, "max-read-transactions missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	mgmtdev->priority = devm_kcalloc(&pdev->dev,
+		mgmtdev->dma_channels, sizeof(*mgmtdev->priority), GFP_KERNEL);
+	if (!mgmtdev->priority) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	mgmtdev->weight = devm_kcalloc(&pdev->dev,
+		mgmtdev->dma_channels, sizeof(*mgmtdev->weight), GFP_KERNEL);
+	if (!mgmtdev->weight) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	if (device_property_read_u32_array(&pdev->dev, "channel-priority",
+				mgmtdev->priority, mgmtdev->dma_channels)) {
+		dev_err(&pdev->dev, "channel-priority missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (device_property_read_u32_array(&pdev->dev, "channel-weight",
+				mgmtdev->weight, mgmtdev->dma_channels)) {
+		dev_err(&pdev->dev, "channel-weight missing\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rc = hidma_mgmt_setup(mgmtdev);
+	if (rc) {
+		dev_err(&pdev->dev, "setup failed\n");
+		goto out;
+	}
+
+	/* start the HW */
+	val = readl(mgmtdev->dev_virtaddr + CFG_OFFSET);
+	val = val | 1;
+	writel(val, mgmtdev->dev_virtaddr + CFG_OFFSET);
+
+
+	rc = hidma_mgmt_init_sys(mgmtdev);
+	if (rc) {
+		dev_err(&pdev->dev, "sysfs setup failed\n");
+		goto out;
+	}
+
+	dev_info(&pdev->dev,
+		 "HW rev: %d.%d @ %pa with %d physical channels\n",
+		 mgmtdev->hw_version_major, mgmtdev->hw_version_minor,
+		 &dma_resource->start, mgmtdev->dma_channels);
+
+	platform_set_drvdata(pdev, mgmtdev);
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_put_autosuspend(&pdev->dev);
+	return 0;
+out:
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put_sync_suspend(&pdev->dev);
+	return rc;
+}
+
+#if IS_ENABLED(CONFIG_ACPI)
+static const struct acpi_device_id hidma_mgmt_acpi_ids[] = {
+	{"QCOM8060"},
+	{},
+};
+#endif
+
+static const struct of_device_id hidma_mgmt_match[] = {
+	{ .compatible = "qcom,hidma-mgmt", },
+	{ .compatible = "qcom,hidma-mgmt-1.0", },
+	{ .compatible = "qcom,hidma-mgmt-1.1", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, hidma_mgmt_match);
+
+static struct platform_driver hidma_mgmt_driver = {
+	.probe = hidma_mgmt_probe,
+	.driver = {
+		.name = "hidma-mgmt",
+		.of_match_table = hidma_mgmt_match,
+		.acpi_match_table = ACPI_PTR(hidma_mgmt_acpi_ids),
+	},
+};
+module_platform_driver(hidma_mgmt_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/qcom/hidma_mgmt.h b/drivers/dma/qcom/hidma_mgmt.h
new file mode 100644
index 0000000..d6f8fa0
--- /dev/null
+++ b/drivers/dma/qcom/hidma_mgmt.h
@@ -0,0 +1,38 @@
+/*
+ * Qualcomm Technologies HIDMA Management common header
+ *
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+struct hidma_mgmt_dev {
+	u8 hw_version_major;
+	u8 hw_version_minor;
+
+	u32 max_wr_xactions;
+	u32 max_rd_xactions;
+	u32 max_write_request;
+	u32 max_read_request;
+	u32 dma_channels;
+	u32 chreset_timeout_cycles;
+	u32 hw_version;
+	u32 *priority;
+	u32 *weight;
+
+	/* Hardware device constants */
+	void __iomem *dev_virtaddr;
+	resource_size_t dev_addrsize;
+
+	struct platform_device *pdev;
+};
+
+int hidma_mgmt_init_sys(struct hidma_mgmt_dev *dev);
+int hidma_mgmt_setup(struct hidma_mgmt_dev *mgmtdev);
diff --git a/drivers/dma/qcom/hidma_mgmt_sys.c b/drivers/dma/qcom/hidma_mgmt_sys.c
new file mode 100644
index 0000000..b1eb9d6
--- /dev/null
+++ b/drivers/dma/qcom/hidma_mgmt_sys.c
@@ -0,0 +1,232 @@
+/*
+ * Qualcomm Technologies HIDMA Management SYS interface
+ *
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+
+#include "hidma_mgmt.h"
+
+struct fileinfo {
+	char *name;
+	int mode;
+	int (*get)(struct hidma_mgmt_dev *mdev);
+	int (*set)(struct hidma_mgmt_dev *mdev, u64 val);
+};
+
+#define IMPLEMENT_GETSET(name)					\
+static int get_##name(struct hidma_mgmt_dev *mdev)		\
+{								\
+	return mdev->name;					\
+}								\
+static int set_##name(struct hidma_mgmt_dev *mdev, u64 val)	\
+{								\
+	u64 tmp;						\
+	int rc;							\
+								\
+	tmp = mdev->name;					\
+	mdev->name = val;					\
+	rc = hidma_mgmt_setup(mdev);				\
+	if (rc)							\
+		mdev->name = tmp;				\
+	return rc;						\
+}
+
+#define DECLARE_ATTRIBUTE(name, mode)				\
+	{#name, mode, get_##name, set_##name}
+
+IMPLEMENT_GETSET(hw_version_major)
+IMPLEMENT_GETSET(hw_version_minor)
+IMPLEMENT_GETSET(max_wr_xactions)
+IMPLEMENT_GETSET(max_rd_xactions)
+IMPLEMENT_GETSET(max_write_request)
+IMPLEMENT_GETSET(max_read_request)
+IMPLEMENT_GETSET(dma_channels)
+IMPLEMENT_GETSET(chreset_timeout_cycles)
+
+static int set_priority(struct hidma_mgmt_dev *mdev, int i, u64 val)
+{
+	u64 tmp;
+	int rc;
+
+	if (i > mdev->dma_channels)
+		return -EINVAL;
+
+	tmp = mdev->priority[i];
+	mdev->priority[i] = val;
+	rc = hidma_mgmt_setup(mdev);
+	if (rc)
+		mdev->priority[i] = tmp;
+	return rc;
+}
+
+static int set_weight(struct hidma_mgmt_dev *mdev, int i, u64 val)
+{
+	u64 tmp;
+	int rc;
+
+	if (i > mdev->dma_channels)
+		return -EINVAL;
+
+	tmp = mdev->weight[i];
+	mdev->weight[i] = val;
+	rc = hidma_mgmt_setup(mdev);
+	if (rc)
+		mdev->weight[i] = tmp;
+	return rc;
+}
+
+static struct fileinfo files[] = {
+	DECLARE_ATTRIBUTE(hw_version_major, S_IRUGO),
+	DECLARE_ATTRIBUTE(hw_version_minor, S_IRUGO),
+	DECLARE_ATTRIBUTE(dma_channels, S_IRUGO),
+	DECLARE_ATTRIBUTE(chreset_timeout_cycles, S_IRUGO),
+	DECLARE_ATTRIBUTE(max_wr_xactions, (S_IRUGO|S_IWUGO)),
+	DECLARE_ATTRIBUTE(max_rd_xactions, (S_IRUGO|S_IWUGO)),
+	DECLARE_ATTRIBUTE(max_write_request, (S_IRUGO|S_IWUGO)),
+	DECLARE_ATTRIBUTE(max_read_request, (S_IRUGO|S_IWUGO)),
+};
+
+static ssize_t show_values(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	int i;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct hidma_mgmt_dev *mdev = platform_get_drvdata(pdev);
+
+	for (i = 0; i < ARRAY_SIZE(files); i++) {
+		if (strcmp(attr->attr.name, files[i].name) == 0) {
+			sprintf(buf, "%d\n", files[i].get(mdev));
+			goto done;
+		}
+	}
+
+	for (i = 0; i < mdev->dma_channels; i++) {
+		char name[30];
+
+		sprintf(name, "channel%d_priority", i);
+		if (strcmp(attr->attr.name, name) == 0) {
+			sprintf(buf, "%d\n", mdev->priority[i]);
+			goto done;
+		}
+
+		sprintf(name, "channel%d_weight", i);
+		if (strcmp(attr->attr.name, name) == 0) {
+			sprintf(buf, "%d\n", mdev->weight[i]);
+			goto done;
+		}
+	}
+
+done:
+	return strlen(buf);
+}
+
+static ssize_t set_values(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct hidma_mgmt_dev *mdev = platform_get_drvdata(pdev);
+	unsigned long tmp;
+	int i, rc;
+
+	rc = kstrtoul(buf, 0, &tmp);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < ARRAY_SIZE(files); i++) {
+		if (strcmp(attr->attr.name, files[i].name) == 0) {
+			rc = files[i].set(mdev, tmp);
+			if (rc)
+				return rc;
+
+			goto done;
+		}
+	}
+
+	for (i = 0; i < mdev->dma_channels; i++) {
+		char name[30];
+
+		sprintf(name, "channel%d_priority", i);
+		if (strcmp(attr->attr.name, name) == 0) {
+			rc = set_priority(mdev, i, tmp);
+			if (rc)
+				return rc;
+			goto done;
+		}
+
+		sprintf(name, "channel%d_weight", i);
+		if (strcmp(attr->attr.name, name) == 0) {
+			rc = set_weight(mdev, i, tmp);
+			if (rc)
+				return rc;
+		}
+	}
+done:
+	return count;
+}
+
+static int create_sysfs_entry(struct hidma_mgmt_dev *dev, char *name, int mode)
+{
+	struct device_attribute *port_attrs;
+	char *name_copy;
+
+	port_attrs = devm_kmalloc(&dev->pdev->dev,
+			sizeof(struct device_attribute), GFP_KERNEL);
+	if (!port_attrs)
+		return -ENOMEM;
+
+	name_copy = devm_kcalloc(&dev->pdev->dev, 1, strlen(name) + 1,
+				GFP_KERNEL);
+	if (!name_copy)
+		return -ENOMEM;
+
+	sprintf(name_copy, "%s", name);
+
+	port_attrs->attr.name = name_copy;
+	port_attrs->attr.mode = mode;
+	port_attrs->show      = show_values;
+	port_attrs->store     = set_values;
+	sysfs_attr_init(&port_attrs->attr);
+
+	return device_create_file(&dev->pdev->dev, port_attrs);
+}
+
+
+int hidma_mgmt_init_sys(struct hidma_mgmt_dev *dev)
+{
+	int rc;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(files); i++) {
+		rc = create_sysfs_entry(dev, files[i].name, files[i].mode);
+		if (rc)
+			return rc;
+	}
+
+	for (i = 0; i < dev->dma_channels; i++) {
+		char name[30];
+
+		sprintf(name, "channel%d_priority", i);
+		rc = create_sysfs_entry(dev, name, (S_IRUGO|S_IWUGO));
+		if (rc)
+			return rc;
+
+		sprintf(name, "channel%d_weight", i);
+		rc = create_sysfs_entry(dev, name, (S_IRUGO|S_IWUGO));
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
