Merge branch 'sunxi/dt-for-7.2' into sunxi/for-next
diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index e7f7cf7..6e6ab21 100644
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -80,6 +80,7 @@
               - const: allwinner,sun4i-a10-sram-c1
               - const: allwinner,sun4i-a10-sram-d
               - const: allwinner,sun50i-a64-sram-c
+              - const: allwinner,sun50i-h616-ve-sram
               - items:
                   - enum:
                       - allwinner,sun5i-a13-sram-a3-a4
@@ -103,7 +104,9 @@
                       - allwinner,sun7i-a20-sram-d
                   - const: allwinner,sun4i-a10-sram-d
               - items:
-                  - const: allwinner,sun50i-h6-sram-c
+                  - enum:
+                      - allwinner,sun50i-h6-sram-c
+                      - allwinner,sun50i-h616-sram-c
                   - const: allwinner,sun50i-a64-sram-c
 
 required:
diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml
index 8985f89..9019c43 100644
--- a/Documentation/devicetree/bindings/sram/sram.yaml
+++ b/Documentation/devicetree/bindings/sram/sram.yaml
@@ -83,6 +83,7 @@
             - allwinner,sun4i-a10-sram-d
             - allwinner,sun9i-a80-smp-sram
             - allwinner,sun50i-a64-sram-c
+            - allwinner,sun50i-h616-ve-sram
             - amlogic,meson8-ao-arc-sram
             - amlogic,meson8b-ao-arc-sram
             - amlogic,meson8-smp-sram
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index b4f2c64..daf0ea5 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -445,6 +445,9 @@ static int regmap_sunxi_rsb_reg_write(void *context, unsigned int reg,
 	struct sunxi_rsb_ctx *ctx = context;
 	struct sunxi_rsb_device *rdev = ctx->rdev;
 
+	if (reg > 0xff)
+		return -EINVAL;
+
 	return sunxi_rsb_write(rdev->rsb, rdev->rtaddr, reg, &val, ctx->size);
 }
 
diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 446b9fc..2ccaeac 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -12,6 +12,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/io.h>
+#include <linux/limits.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -29,16 +30,16 @@ struct sunxi_sram_func {
 };
 
 struct sunxi_sram_data {
-	char			*name;
-	u8			reg;
-	u8			offset;
-	u8			width;
-	struct sunxi_sram_func	*func;
+	char				*name;
+	u8				reg;
+	u8				offset;
+	u8				width;
+	const struct sunxi_sram_func	*func;
 };
 
 struct sunxi_sram_desc {
 	struct sunxi_sram_data	data;
-	bool			claimed;
+	u8			claim_cnt;
 };
 
 #define SUNXI_SRAM_MAP(_reg_val, _val, _func)			\
@@ -54,7 +55,7 @@ struct sunxi_sram_desc {
 		.reg = _reg,					\
 		.offset = _off,					\
 		.width = _width,				\
-		.func = (struct sunxi_sram_func[]){		\
+		.func = (const struct sunxi_sram_func[]){	\
 			__VA_ARGS__, { } },			\
 	}
 
@@ -82,6 +83,12 @@ static struct sunxi_sram_desc sun50i_a64_sram_c = {
 				  SUNXI_SRAM_MAP(0, 1, "de2")),
 };
 
+static struct sunxi_sram_desc sun50i_h616_ve_sram = {
+	.data	= SUNXI_SRAM_DATA("VE", 0x0, 0, 1,
+				  SUNXI_SRAM_MAP(1, 0, "cpu"),
+				  SUNXI_SRAM_MAP(0, 1, "ve")),
+};
+
 static const struct of_device_id sunxi_sram_dt_ids[] = {
 	{
 		.compatible	= "allwinner,sun4i-a10-sram-a3-a4",
@@ -99,6 +106,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
 		.compatible	= "allwinner,sun50i-a64-sram-c",
 		.data		= &sun50i_a64_sram_c.data,
 	},
+	{
+		.compatible	= "allwinner,sun50i-h616-ve-sram",
+		.data		= &sun50i_h616_ve_sram.data,
+	},
 	{}
 };
 
@@ -111,7 +122,7 @@ static int sunxi_sram_show(struct seq_file *s, void *data)
 	struct device_node *sram_node, *section_node;
 	const struct sunxi_sram_data *sram_data;
 	const struct of_device_id *match;
-	struct sunxi_sram_func *func;
+	const struct sunxi_sram_func *func;
 	const __be32 *sram_addr_p, *section_addr_p;
 	u32 val;
 
@@ -164,69 +175,97 @@ static inline struct sunxi_sram_desc *to_sram_desc(const struct sunxi_sram_data
 	return container_of(data, struct sunxi_sram_desc, data);
 }
 
-static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *node,
-							 unsigned int *reg_value)
+static const struct sunxi_sram_data *sunxi_sram_get_match(struct device_node *np, u8 val,
+							  unsigned int *reg_value)
 {
 	const struct of_device_id *match;
 	const struct sunxi_sram_data *data;
-	struct sunxi_sram_func *func;
-	struct of_phandle_args args;
-	u8 val;
-	int ret;
+	const struct sunxi_sram_func *func;
 
-	ret = of_parse_phandle_with_fixed_args(node, "allwinner,sram", 1, 0,
-					       &args);
-	if (ret)
-		return ERR_PTR(ret);
+	if (!of_device_is_available(np))
+		return ERR_PTR(-ENODEV);
 
-	if (!of_device_is_available(args.np)) {
-		ret = -EBUSY;
-		goto err;
-	}
-
-	val = args.args[0];
-
-	match = of_match_node(sunxi_sram_dt_ids, args.np);
-	if (!match) {
-		ret = -EINVAL;
-		goto err;
-	}
+	match = of_match_node(sunxi_sram_dt_ids, np);
+	if (!match)
+		return ERR_PTR(-ENODEV);
 
 	data = match->data;
-	if (!data) {
-		ret = -EINVAL;
-		goto err;
-	}
+	if (!data)
+		return ERR_PTR(-EINVAL);
 
-	for (func = data->func; func->func; func++) {
-		if (val == func->val) {
-			if (reg_value)
-				*reg_value = func->reg_val;
-
+	for (func = data->func; func->func; func++)
+		if (val == func->val)
 			break;
-		}
-	}
 
-	if (!func->func) {
-		ret = -EINVAL;
-		goto err;
-	}
+	if (!func->func)
+		return ERR_PTR(-EINVAL);
 
-	of_node_put(args.np);
-	return match->data;
+	if (reg_value)
+		*reg_value = func->reg_val;
 
-err:
-	of_node_put(args.np);
-	return ERR_PTR(ret);
+	return data;
 }
 
-int sunxi_sram_claim(struct device *dev)
+#define SUNXI_SRAM_PROP "allwinner,sram"
+#define SUNXI_SRAM_CELLS 1
+
+static int sunxi_sram_claim_one(struct device_node *np, u8 arg)
 {
 	const struct sunxi_sram_data *sram_data;
 	struct sunxi_sram_desc *sram_desc;
 	unsigned int device;
 	u32 val, mask;
 
+	sram_data = sunxi_sram_get_match(np, arg, &device);
+	if (IS_ERR(sram_data))
+		return PTR_ERR(sram_data);
+
+	sram_desc = to_sram_desc(sram_data);
+
+	spin_lock(&sram_lock);
+
+	if (sram_desc->claim_cnt) {
+		if (!WARN_ON(sram_desc->claim_cnt == U8_MAX))
+			sram_desc->claim_cnt++;
+	} else {
+		mask = GENMASK(sram_data->offset + sram_data->width - 1,
+			       sram_data->offset);
+		val = readl(base + sram_data->reg);
+		val &= ~mask;
+		writel(val | ((device << sram_data->offset) & mask),
+		       base + sram_data->reg);
+
+		sram_desc->claim_cnt++;
+	}
+
+	spin_unlock(&sram_lock);
+
+	return 0;
+}
+
+static void sunxi_sram_release_one(struct device_node *np, u8 arg)
+{
+	const struct sunxi_sram_data *sram_data;
+	struct sunxi_sram_desc *sram_desc;
+
+	sram_data = sunxi_sram_get_match(np, arg, NULL);
+	if (IS_ERR(sram_data))
+		return;
+
+	sram_desc = to_sram_desc(sram_data);
+
+	spin_lock(&sram_lock);
+	if (!WARN_ON(sram_desc->claim_cnt == 0))
+		sram_desc->claim_cnt--;
+	spin_unlock(&sram_lock);
+}
+
+int sunxi_sram_claim(struct device *dev)
+{
+	struct of_phandle_iterator it;
+	int err;
+	int count = 0;
+
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
@@ -236,50 +275,53 @@ int sunxi_sram_claim(struct device *dev)
 	if (!dev || !dev->of_node)
 		return -EINVAL;
 
-	sram_data = sunxi_sram_of_parse(dev->of_node, &device);
-	if (IS_ERR(sram_data))
-		return PTR_ERR(sram_data);
+	of_for_each_phandle(&it, err, dev->of_node, SUNXI_SRAM_PROP,
+			    NULL, SUNXI_SRAM_CELLS) {
+		u32 args[SUNXI_SRAM_CELLS];
 
-	sram_desc = to_sram_desc(sram_data);
+		of_phandle_iterator_args(&it, args, SUNXI_SRAM_CELLS);
 
-	spin_lock(&sram_lock);
+		err = sunxi_sram_claim_one(it.node, args[0]);
+		if (err)
+			goto err;
 
-	if (sram_desc->claimed) {
-		spin_unlock(&sram_lock);
-		return -EBUSY;
+		count++;
 	}
 
-	mask = GENMASK(sram_data->offset + sram_data->width - 1,
-		       sram_data->offset);
-	val = readl(base + sram_data->reg);
-	val &= ~mask;
-	writel(val | ((device << sram_data->offset) & mask),
-	       base + sram_data->reg);
-
-	sram_desc->claimed = true;
-	spin_unlock(&sram_lock);
+	if (count == 0)
+		return -ENOENT;
 
 	return 0;
+
+err:
+	while (count--) {
+		struct of_phandle_args args;
+
+		of_parse_phandle_with_fixed_args(dev->of_node, SUNXI_SRAM_PROP,
+						 SUNXI_SRAM_CELLS, count, &args);
+		sunxi_sram_release_one(args.np, args.args[0]);
+	}
+
+	return err;
 }
 EXPORT_SYMBOL(sunxi_sram_claim);
 
 void sunxi_sram_release(struct device *dev)
 {
-	const struct sunxi_sram_data *sram_data;
-	struct sunxi_sram_desc *sram_desc;
+	struct of_phandle_iterator it;
+	int err;
 
 	if (!dev || !dev->of_node)
 		return;
 
-	sram_data = sunxi_sram_of_parse(dev->of_node, NULL);
-	if (IS_ERR(sram_data))
-		return;
+	of_for_each_phandle(&it, err, dev->of_node, SUNXI_SRAM_PROP,
+			    NULL, SUNXI_SRAM_CELLS) {
+		u32 args[SUNXI_SRAM_CELLS];
 
-	sram_desc = to_sram_desc(sram_data);
+		of_phandle_iterator_args(&it, args, SUNXI_SRAM_CELLS);
 
-	spin_lock(&sram_lock);
-	sram_desc->claimed = false;
-	spin_unlock(&sram_lock);
+		sunxi_sram_release_one(it.node, args[0]);
+	}
 }
 EXPORT_SYMBOL(sunxi_sram_release);