diff --git a/Documentation/devicetree/bindings/dma/shdma.txt b/Documentation/devicetree/bindings/dma/shdma.txt
index 2a3f3b8..86d5c50 100644
--- a/Documentation/devicetree/bindings/dma/shdma.txt
+++ b/Documentation/devicetree/bindings/dma/shdma.txt
@@ -14,9 +14,9 @@ still has to be placed under such a multiplexer node.
 Required properties:
 - compatible:	should be "renesas,shdma-mux"
 - #dma-cells:	should be <1>, see "dmas" property below
+- dma-channels:	number of DMA channels
 
 Optional properties (currently unused):
-- dma-channels:	number of DMA channels
 - dma-requests:	number of DMA request signals
 
 * DMA controller
@@ -25,6 +25,7 @@ Required properties:
 - compatible:	should be of the form "renesas,shdma-<soc>", where <soc> should
 		be replaced with the desired SoC model, e.g.
 		"renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
+		"renesas,shdma-r8a7790" for the DMAC on the R8A7790.
 
 Example:
 	dmac: dma-multiplexer@0 {
@@ -70,15 +71,33 @@ Example:
 		};
 	};
 
+For r8a7790 and newer implementations, the information for the channel
+controll register is found in the dma phandle and #dma-cells is set to 2.
+
+	dma0: dma-mux@0 {
+		compatible = "renesas,shdma-mux";
+		#dma-cells = <2>;
+		dma-channels = <20>;
+		dma-requests = <256>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+	}
+
 * DMA client
 
 Required properties:
 - dmas:		a list of <[DMA multiplexer phandle] [MID/RID value]> pairs,
 		where MID/RID values are fixed handles, specified in the SoC
-		manual
+		manual as the value that would be written into the DMASR.
+
+		If the #dma-cells is 2, then the second value is the CHCR
+		register configuration for the channel.
+
 - dma-names:	a list of DMA channel names, one per "dmas" entry
 
 Example:
 	dmas = <&dmac 0xd1
 		&dmac 0xd2>;
 	dma-names = "tx", "rx";
+
diff --git a/drivers/dma/sh/shdma-of.c b/drivers/dma/sh/shdma-of.c
index 06473a0..661ac77 100644
--- a/drivers/dma/sh/shdma-of.c
+++ b/drivers/dma/sh/shdma-of.c
@@ -3,12 +3,15 @@
  *
  * Copyright (C) 2013 Renesas Electronics Inc.
  * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ * Copyright (c) 2014 Codethink Limited
+ *	Ben Dooks <ben.dooks@codethink.co.uk>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
  * published by the Free Software Foundation.
  */
 
+#include <linux/slab.h>
 #include <linux/dmaengine.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -16,17 +19,117 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/shdma-base.h>
+#include <linux/sh_dma.h>
+
+#include <dt-bindings/dma/shdma.h>
 
 #define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
 
+#include "shdma-arm.h"
+
+static const unsigned int arm_dma_ts_shift[] = SH_DMAE_TS_SHIFT;
+
+static struct sh_dmae_pdata arm_dmae_info = {
+	.ts_low_shift	= SHDMA_ARM_TS_LOW_SHIFT,
+	.ts_low_mask	= SHDMA_ARM_TS_LOW_BIT << SHDMA_ARM_TS_LOW_SHIFT,
+	.ts_high_shift	= SHDMA_ARM_TS_HI_SHIFT,
+	.ts_high_mask	= SHDMA_ARM_TS_HI_BIT << SHDMA_ARM_TS_HI_SHIFT,
+	.ts_shift	= arm_dma_ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(arm_dma_ts_shift),
+	.dmaor_init	= DMAOR_DME,
+	.chclr_present	= 1,
+	.chclr_bitwise	= 1,
+};
+
+struct sh_dmae_of_info shdma_arm_info = {
+	.pdata_template	= &arm_dmae_info,
+	.channel_offset	= 0x8000-0x20,
+	.channel_stride	= 0x80,
+	.offset		= 0x0,
+	.dmars		= 0x40,
+	.chclr_offset	= 0x80,
+};
+
+/* Need global index due to shdma_slave_used being global */
+static atomic_t of_slave_index = ATOMIC_INIT(0);
+
+struct shdma_of_client {
+	int				index;
+	struct list_head		node;
+	struct sh_dmae_slave_config	cfg;
+};
+
+struct shdma_of_pdata {
+	struct sh_dmae_pdata	pdata;
+	struct shdma_of_state	*state;
+};
+
+struct shdma_of_state {
+	struct list_head	of_slaves;
+};
+
+#define to_of_pdata(_pd) container_of(_pd, struct shdma_of_pdata, pdata)
+
+struct shdma_of_client *shdma_of_find_client(struct shdma_of_state *state, int id)
+{
+	struct shdma_of_client *client;
+
+	list_for_each_entry(client, &state->of_slaves, node) {
+		if (client->cfg.slave_id == id)
+			return client;
+	}
+
+	return NULL;
+}
+
+struct sh_dmae_slave_config *
+shdma_find_slave_of(struct sh_dmae_device *shdev, int match, int *index)
+{
+	struct shdma_of_pdata *pdata = to_of_pdata(shdev->pdata);
+	struct sh_dmae_slave_config *cfg = NULL;
+	struct shdma_of_client *client;
+
+	pr_info("looking for %02x\n", match);
+
+	client = shdma_of_find_client(pdata->state, match);
+	if (client) {
+		*index = client->index;
+		cfg = &client->cfg;
+	}
+
+	return cfg;
+}
+
 static struct dma_chan *shdma_of_xlate(struct of_phandle_args *dma_spec,
 				       struct of_dma *ofdma)
 {
+	struct platform_device *pdev = ofdma->of_dma_data;
 	u32 id = dma_spec->args[0];
 	dma_cap_mask_t mask;
 	struct dma_chan *chan;
 
-	if (dma_spec->args_count != 1)
+	if (dma_spec->args_count == 2) {
+		struct shdma_of_state *state = platform_get_drvdata(pdev);
+		struct shdma_of_client *client;
+
+		client = shdma_of_find_client(state, id);
+		if (!client) {
+			client = devm_kzalloc(&pdev->dev, sizeof(*client),
+					      GFP_KERNEL);
+			if (!client)
+				return NULL;
+
+			client->index = atomic_inc_return(&of_slave_index);
+			client->cfg.slave_id = id;
+			client->cfg.mid_rid = id;
+			client->cfg.chcr = dma_spec->args[1];
+
+			dev_dbg(&pdev->dev, "new client %d, %02x\n",
+				client->index, id);
+
+			list_add_tail(&client->node, &state->of_slaves);
+		}
+	} else if (dma_spec->args_count != 1)
 		return NULL;
 
 	dma_cap_zero(mask);
@@ -40,11 +143,80 @@ static struct dma_chan *shdma_of_xlate(struct of_phandle_args *dma_spec,
 	return chan;
 }
 
+const struct sh_dmae_pdata *
+sh_dma_probe_of(struct platform_device *pdev, const struct of_device_id *ofmatch)
+{
+	const struct device_node *np = pdev->dev.of_node;
+	const struct sh_dmae_of_info *ofinf;
+	struct device *dev = &pdev->dev;
+	struct sh_dmae_pdata *pdata;
+	struct shdma_of_pdata *ofdata;
+	struct sh_dmae_channel *chan;
+	u32 nr_chan;
+	unsigned ch;
+	int ret;
+
+	if (!ofmatch)
+		return NULL;
+
+	ofdata = devm_kzalloc(dev, sizeof(struct shdma_of_pdata), GFP_KERNEL);
+	if (!ofdata)
+		return NULL;
+
+	ofinf = ofmatch->data;
+	pdata = &ofdata->pdata;
+	*pdata = *ofinf->pdata_template;	/* copy in template first */
+	ofdata->state = dev_get_drvdata(dev->parent);
+
+	ret = of_property_read_u32(np, "dma-channels", &nr_chan);
+	if (ret < 0) {
+		dev_err(dev, "failed to get number of channels\n");
+		return NULL;
+	}
+
+	chan = devm_kcalloc(dev, nr_chan, sizeof(struct sh_dmae_channel),
+			    GFP_KERNEL);
+	if (!chan) {
+		dev_err(dev, "cannot allocate %d channels\n", nr_chan);
+		return NULL;
+	}
+
+	pdata->channel = chan;
+	pdata->channel_num = nr_chan;
+
+	dev_dbg(dev, "%d dma channels allocated\n", nr_chan);
+
+	for (ch = 0; ch < nr_chan; ch++) {
+		struct sh_dmae_channel *cp = chan + ch;
+		u32 base = ofinf->channel_offset + ofinf->channel_stride * ch;
+
+		cp->offset = base + ofinf->offset;
+		cp->dmars = base + ofinf->dmars;
+		cp->chclr_bit = ch;
+		cp->chclr_offset = ofinf->chclr_offset;
+
+		dev_dbg(dev, "ch %d: off %08x, dmars %08x, bit %d, off %d\n",
+			ch, cp->offset, cp->dmars,
+			cp->chclr_bit, cp->chclr_offset);
+	}
+
+	pdev->dev.platform_data = pdata;
+	return pdata;
+};
+
 static int shdma_of_probe(struct platform_device *pdev)
 {
 	const struct of_dev_auxdata *lookup = dev_get_platdata(&pdev->dev);
+	struct shdma_of_state *state;
 	int ret;
 
+	state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&state->of_slaves);
+	platform_set_drvdata(pdev, state);
+
 	ret = of_dma_controller_register(pdev->dev.of_node,
 					 shdma_of_xlate, pdev);
 	if (ret < 0)
diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
index 758a57b..05b84b9 100644
--- a/drivers/dma/sh/shdma.h
+++ b/drivers/dma/sh/shdma.h
@@ -56,6 +56,26 @@ struct sh_dmae_desc {
 	struct shdma_desc shdma_desc;
 };
 
+/*
+ * Template information for building shdma data, provided as part of the
+ * data field in the of_device_id structure. This is then used to build
+ * the platform data for the dma code.
+ */
+struct sh_dmae_of_info {
+	struct sh_dmae_pdata	*pdata_template;
+	unsigned int		channel_offset;
+	unsigned int		channel_stride;
+	int			offset;
+	int			dmars;
+	int			chclr_offset;
+	int			chclr_bit;
+};
+
+extern struct sh_dmae_of_info shdma_arm_info;
+
+extern const struct sh_dmae_pdata *sh_dma_probe_of(struct platform_device *pdev,
+						   const struct of_device_id *match);
+
 #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, shdma_chan)
 #define to_sh_desc(lh) container_of(lh, struct sh_desc, node)
 #define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)
@@ -69,4 +89,13 @@ extern const struct sh_dmae_pdata r8a73a4_dma_pdata;
 #define r8a73a4_shdma_devid NULL
 #endif
 
+#ifdef CONFIG_OF
+extern struct sh_dmae_slave_config *shdma_find_slave_of(struct sh_dmae_device *shdev, int match, int *index);
+#else
+static inline struct sh_dmae_slave_config *shdma_find_slave_of(struct sh_dmae_device *shdev, int match, int *index)
+{
+	return NULL;
+}
+#endif
+
 #endif	/* __DMA_SHDMA_H */
diff --git a/include/dt-bindings/dma/shdma.h b/include/dt-bindings/dma/shdma.h
new file mode 100644
index 0000000..0c8fc9e
--- /dev/null
+++ b/include/dt-bindings/dma/shdma.h
@@ -0,0 +1,45 @@
+/* DMA binding definitions for SH-DMAC engines.
+ *
+ * Moved from sh_dma.h to share with device tree by Ben Dooks.
+ * Orignal code from:
+ *   shdma.h: Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *   shdma-arm.h: Copyright (C) 2013 Renesas Electronics, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define SHDMA_DM_INC	0x00004000
+#define SHDMA_DM_DEC	0x00008000
+#define SHDMA_DM_FIX	0x0000c000
+#define SHDMA_SM_INC	0x00001000
+#define SHDMA_SM_DEC	0x00002000
+#define SHDMA_SM_FIX	0x00003000
+#define SHDMA_CHCR_DE	0x00000001
+#define SHDMA_CHCR_TE	0x00000002
+#define SHDMA_CHCR_IE	0x00000004
+
+/* ARM specific definitions */
+
+#define SHDMA_ARM_SZ_8BIT	(0)
+#define SHDMA_ARM_SZ_16BIT	(1)
+#define SHDMA_ARM_SZ_32BIT	(2)
+#define SHDMA_ARM_SZ_64BIT	(7)
+#define SHDMA_ARM_SZ_128BIT	(3)
+#define SHDMA_ARM_SZ_256BIT	(4)
+#define SHDMA_ARM_SZ_512BIT	(5)
+
+#define SHDMA_ARM_TS_LOW_BIT	(0x3)
+#define SHDMA_ARM_TS_HI_BIT	(0xc)
+
+#define SHDMA_ARM_TS_LOW_SHIFT	(3)
+#define SHDMA_ARM_TS_HI_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
+
+#define SHDMA_ARM_TS_INDEX2VAL(i) \
+	((((i) & SHDMA_ARM_TS_LOW_BIT) << SHDMA_ARM_TS_LOW_SHIFT) |\
+	 (((i) & SHDMA_ARM_TS_HI_BIT)  << SHDMA_ARM_TS_HI_SHIFT))
+
+#define SHDMA_ARM_CHCR_RX(size) (SHDMA_DM_INC | SHDMA_SM_FIX | 0x800 | SHDMA_ARM_TS_INDEX2VAL(size))
+#define SHDMA_ARM_CHCR_TX(size) (SHDMA_DM_FIX | SHDMA_SM_INC | 0x800 | SHDMA_ARM_TS_INDEX2VAL(size))
+
