a07cbe5797ed4a7b51f62fe3c95fd6e201e59eec
[openwrt/openwrt.git] / target / linux / sunxi / patches-4.4 / 131-reset-add-h3-resets.patch
1 From 5f0bb9d0bc545ef53a83f7bd176fdc0736eed8e5 Mon Sep 17 00:00:00 2001
2 From: Jens Kuske <jenskuske@gmail.com>
3 Date: Tue, 27 Oct 2015 17:50:24 +0100
4 Subject: [PATCH] reset: sunxi: Add Allwinner H3 bus resets
5
6 The H3 bus resets have some holes between the registers, so we add
7 an of_xlate() function to skip them according to the datasheet.
8
9 Signed-off-by: Jens Kuske <jenskuske@gmail.com>
10 ---
11 .../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 +
12 drivers/reset/reset-sunxi.c | 30 +++++++++++++++++++---
13 2 files changed, 28 insertions(+), 3 deletions(-)
14
15 diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
16 index c8f77571..e11f023 100644
17 --- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
18 +++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
19 @@ -8,6 +8,7 @@ Required properties:
20 - compatible: Should be one of the following:
21 "allwinner,sun6i-a31-ahb1-reset"
22 "allwinner,sun6i-a31-clock-reset"
23 + "allwinner,sun8i-h3-bus-reset"
24 - reg: should be register base and length as documented in the
25 datasheet
26 - #reset-cells: 1, see below
27 diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
28 index 3d95c87..c91e146 100644
29 --- a/drivers/reset/reset-sunxi.c
30 +++ b/drivers/reset/reset-sunxi.c
31 @@ -75,7 +75,9 @@ static struct reset_control_ops sunxi_reset_ops = {
32 .deassert = sunxi_reset_deassert,
33 };
34
35 -static int sunxi_reset_init(struct device_node *np)
36 +static int sunxi_reset_init(struct device_node *np,
37 + int (*of_xlate)(struct reset_controller_dev *rcdev,
38 + const struct of_phandle_args *reset_spec))
39 {
40 struct sunxi_reset_data *data;
41 struct resource res;
42 @@ -108,6 +110,7 @@ static int sunxi_reset_init(struct device_node *np)
43 data->rcdev.nr_resets = size * 32;
44 data->rcdev.ops = &sunxi_reset_ops;
45 data->rcdev.of_node = np;
46 + data->rcdev.of_xlate = of_xlate;
47 reset_controller_register(&data->rcdev);
48
49 return 0;
50 @@ -117,6 +120,21 @@ static int sunxi_reset_init(struct device_node *np)
51 return ret;
52 };
53
54 +static int sun8i_h3_bus_reset_xlate(struct reset_controller_dev *rcdev,
55 + const struct of_phandle_args *reset_spec)
56 +{
57 + unsigned int index = reset_spec->args[0];
58 +
59 + if (index < 96)
60 + return index;
61 + else if (index < 128)
62 + return index + 32;
63 + else if (index < 160)
64 + return index + 64;
65 + else
66 + return -EINVAL;
67 +}
68 +
69 /*
70 * These are the reset controller we need to initialize early on in
71 * our system, before we can even think of using a regular device
72 @@ -124,15 +142,21 @@ static int sunxi_reset_init(struct device_node *np)
73 */
74 static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = {
75 { .compatible = "allwinner,sun6i-a31-ahb1-reset", },
76 + { .compatible = "allwinner,sun8i-h3-bus-reset", .data = sun8i_h3_bus_reset_xlate, },
77 { /* sentinel */ },
78 };
79
80 void __init sun6i_reset_init(void)
81 {
82 struct device_node *np;
83 + const struct of_device_id *match;
84 + int (*of_xlate)(struct reset_controller_dev *rcdev,
85 + const struct of_phandle_args *reset_spec);
86
87 - for_each_matching_node(np, sunxi_early_reset_dt_ids)
88 - sunxi_reset_init(np);
89 + for_each_matching_node_and_match(np, sunxi_early_reset_dt_ids, &match) {
90 + of_xlate = match->data;
91 + sunxi_reset_init(np, of_xlate);
92 + }
93 }
94
95 /*