1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2010 John Crispin <blogic@phrozen.org>
5 * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
6 * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
7 * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
10 #include <linux/mfd/syscon.h>
11 #include <linux/module.h>
12 #include <linux/regmap.h>
13 #include <linux/reset-controller.h>
14 #include <linux/of_address.h>
15 #include <linux/of_platform.h>
16 #include <linux/platform_device.h>
17 #include <linux/property.h>
19 #define LANTIQ_RCU_RESET_TIMEOUT 10000
21 struct lantiq_rcu_reset_priv
{
22 struct reset_controller_dev rcdev
;
24 struct regmap
*regmap
;
29 static struct lantiq_rcu_reset_priv
*to_lantiq_rcu_reset_priv(
30 struct reset_controller_dev
*rcdev
)
32 return container_of(rcdev
, struct lantiq_rcu_reset_priv
, rcdev
);
35 static int lantiq_rcu_reset_status(struct reset_controller_dev
*rcdev
,
38 struct lantiq_rcu_reset_priv
*priv
= to_lantiq_rcu_reset_priv(rcdev
);
39 unsigned int status
= (id
>> 8) & 0x1f;
43 ret
= regmap_read(priv
->regmap
, priv
->status_offset
, &val
);
47 return !!(val
& BIT(status
));
50 static int lantiq_rcu_reset_status_timeout(struct reset_controller_dev
*rcdev
,
51 unsigned long id
, bool assert)
54 int retry
= LANTIQ_RCU_RESET_TIMEOUT
;
57 ret
= lantiq_rcu_reset_status(rcdev
, id
);
68 static int lantiq_rcu_reset_update(struct reset_controller_dev
*rcdev
,
69 unsigned long id
, bool assert)
71 struct lantiq_rcu_reset_priv
*priv
= to_lantiq_rcu_reset_priv(rcdev
);
72 unsigned int set
= id
& 0x1f;
73 u32 val
= assert ? BIT(set
) : 0;
76 ret
= regmap_update_bits(priv
->regmap
, priv
->reset_offset
, BIT(set
),
79 dev_err(priv
->dev
, "Failed to set reset bit %u\n", set
);
84 ret
= lantiq_rcu_reset_status_timeout(rcdev
, id
, assert);
86 dev_err(priv
->dev
, "Failed to %s bit %u\n",
87 assert ? "assert" : "deassert", set
);
92 static int lantiq_rcu_reset_assert(struct reset_controller_dev
*rcdev
,
95 return lantiq_rcu_reset_update(rcdev
, id
, true);
98 static int lantiq_rcu_reset_deassert(struct reset_controller_dev
*rcdev
,
101 return lantiq_rcu_reset_update(rcdev
, id
, false);
104 static int lantiq_rcu_reset_reset(struct reset_controller_dev
*rcdev
,
109 ret
= lantiq_rcu_reset_assert(rcdev
, id
);
113 return lantiq_rcu_reset_deassert(rcdev
, id
);
116 static const struct reset_control_ops lantiq_rcu_reset_ops
= {
117 .assert = lantiq_rcu_reset_assert
,
118 .deassert
= lantiq_rcu_reset_deassert
,
119 .status
= lantiq_rcu_reset_status
,
120 .reset
= lantiq_rcu_reset_reset
,
123 static int lantiq_rcu_reset_of_parse(struct platform_device
*pdev
,
124 struct lantiq_rcu_reset_priv
*priv
)
126 struct device
*dev
= &pdev
->dev
;
127 const __be32
*offset
;
129 priv
->regmap
= syscon_node_to_regmap(dev
->of_node
->parent
);
130 if (IS_ERR(priv
->regmap
)) {
131 dev_err(&pdev
->dev
, "Failed to lookup RCU regmap\n");
132 return PTR_ERR(priv
->regmap
);
135 offset
= of_get_address(dev
->of_node
, 0, NULL
, NULL
);
137 dev_err(&pdev
->dev
, "Failed to get RCU reset offset\n");
140 priv
->reset_offset
= __be32_to_cpu(*offset
);
142 offset
= of_get_address(dev
->of_node
, 1, NULL
, NULL
);
144 dev_err(&pdev
->dev
, "Failed to get RCU status offset\n");
147 priv
->status_offset
= __be32_to_cpu(*offset
);
152 static int lantiq_rcu_reset_xlate(struct reset_controller_dev
*rcdev
,
153 const struct of_phandle_args
*reset_spec
)
155 unsigned int status
, set
;
157 set
= reset_spec
->args
[0];
158 status
= reset_spec
->args
[1];
160 if (set
>= rcdev
->nr_resets
|| status
>= rcdev
->nr_resets
)
163 return (status
<< 8) | set
;
166 static int lantiq_rcu_reset_probe(struct platform_device
*pdev
)
168 struct lantiq_rcu_reset_priv
*priv
;
171 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
175 priv
->dev
= &pdev
->dev
;
176 platform_set_drvdata(pdev
, priv
);
178 err
= lantiq_rcu_reset_of_parse(pdev
, priv
);
182 priv
->rcdev
.ops
= &lantiq_rcu_reset_ops
;
183 priv
->rcdev
.owner
= THIS_MODULE
;
184 priv
->rcdev
.of_node
= pdev
->dev
.of_node
;
185 priv
->rcdev
.nr_resets
= 32;
186 priv
->rcdev
.of_xlate
= lantiq_rcu_reset_xlate
;
187 priv
->rcdev
.of_reset_n_cells
= 2;
189 return reset_controller_register(&priv
->rcdev
);
192 static const struct of_device_id lantiq_rcu_reset_dt_ids
[] = {
193 { .compatible
= "lantiq,danube-reset", },
194 { .compatible
= "lantiq,xrx200-reset", },
197 MODULE_DEVICE_TABLE(of
, lantiq_rcu_reset_dt_ids
);
199 static struct platform_driver lantiq_rcu_reset_driver
= {
200 .probe
= lantiq_rcu_reset_probe
,
202 .name
= "lantiq-reset",
203 .of_match_table
= lantiq_rcu_reset_dt_ids
,
206 module_platform_driver(lantiq_rcu_reset_driver
);
208 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
209 MODULE_DESCRIPTION("Lantiq XWAY RCU Reset Controller Driver");
210 MODULE_LICENSE("GPL");