1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Reset driver for the StarFive JH71X0 SoCs
5 * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
8 #include <linux/bitmap.h>
9 #include <linux/device.h>
11 #include <linux/iopoll.h>
12 #include <linux/reset-controller.h>
13 #include <linux/spinlock.h>
15 #include "reset-starfive-jh71x0.h"
18 struct reset_controller_dev rcdev
;
19 /* protect registers against concurrent read-modify-write */
26 static inline struct jh71x0_reset
*
27 jh71x0_reset_from(struct reset_controller_dev
*rcdev
)
29 return container_of(rcdev
, struct jh71x0_reset
, rcdev
);
32 static int jh71x0_reset_update(struct reset_controller_dev
*rcdev
,
33 unsigned long id
, bool assert)
35 struct jh71x0_reset
*data
= jh71x0_reset_from(rcdev
);
36 unsigned long offset
= id
/ 32;
37 u32 mask
= BIT(id
% 32);
38 void __iomem
*reg_assert
= data
->assert + offset
* sizeof(u32
);
39 void __iomem
*reg_status
= data
->status
+ offset
* sizeof(u32
);
40 u32 done
= data
->asserted
? data
->asserted
[offset
] & mask
: 0;
48 spin_lock_irqsave(&data
->lock
, flags
);
50 value
= readl(reg_assert
);
55 writel(value
, reg_assert
);
57 /* if the associated clock is gated, deasserting might otherwise hang forever */
58 ret
= readl_poll_timeout_atomic(reg_status
, value
, (value
& mask
) == done
, 0, 1000);
60 spin_unlock_irqrestore(&data
->lock
, flags
);
64 static int jh71x0_reset_assert(struct reset_controller_dev
*rcdev
,
67 return jh71x0_reset_update(rcdev
, id
, true);
70 static int jh71x0_reset_deassert(struct reset_controller_dev
*rcdev
,
73 return jh71x0_reset_update(rcdev
, id
, false);
76 static int jh71x0_reset_reset(struct reset_controller_dev
*rcdev
,
81 ret
= jh71x0_reset_assert(rcdev
, id
);
85 return jh71x0_reset_deassert(rcdev
, id
);
88 static int jh71x0_reset_status(struct reset_controller_dev
*rcdev
,
91 struct jh71x0_reset
*data
= jh71x0_reset_from(rcdev
);
92 unsigned long offset
= id
/ 32;
93 u32 mask
= BIT(id
% 32);
94 void __iomem
*reg_status
= data
->status
+ offset
* sizeof(u32
);
95 u32 value
= readl(reg_status
);
98 return !(value
& mask
);
100 return !((value
^ data
->asserted
[offset
]) & mask
);
103 static const struct reset_control_ops jh71x0_reset_ops
= {
104 .assert = jh71x0_reset_assert
,
105 .deassert
= jh71x0_reset_deassert
,
106 .reset
= jh71x0_reset_reset
,
107 .status
= jh71x0_reset_status
,
110 int reset_starfive_jh71x0_register(struct device
*dev
, struct device_node
*of_node
,
111 void __iomem
*assert, void __iomem
*status
,
112 const u32
*asserted
, unsigned int nr_resets
,
113 struct module
*owner
)
115 struct jh71x0_reset
*data
;
117 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
121 data
->rcdev
.ops
= &jh71x0_reset_ops
;
122 data
->rcdev
.owner
= owner
;
123 data
->rcdev
.nr_resets
= nr_resets
;
124 data
->rcdev
.dev
= dev
;
125 data
->rcdev
.of_node
= of_node
;
127 spin_lock_init(&data
->lock
);
128 data
->assert = assert;
129 data
->status
= status
;
130 data
->asserted
= asserted
;
132 return devm_reset_controller_register(dev
, &data
->rcdev
);
134 EXPORT_SYMBOL_GPL(reset_starfive_jh71x0_register
);