1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Amlogic Meson Reset core functions
5 * Copyright (c) 2016-2024 BayLibre, SAS.
6 * Authors: Neil Armstrong <narmstrong@baylibre.com>
7 * Jerome Brunet <jbrunet@baylibre.com>
10 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/regmap.h>
13 #include <linux/reset-controller.h>
15 #include "reset-meson.h"
18 const struct meson_reset_param
*param
;
19 struct reset_controller_dev rcdev
;
23 static void meson_reset_offset_and_bit(struct meson_reset
*data
,
28 unsigned int stride
= regmap_get_reg_stride(data
->map
);
30 *offset
= (id
/ (stride
* BITS_PER_BYTE
)) * stride
;
31 *bit
= id
% (stride
* BITS_PER_BYTE
);
34 static int meson_reset_reset(struct reset_controller_dev
*rcdev
,
37 struct meson_reset
*data
=
38 container_of(rcdev
, struct meson_reset
, rcdev
);
39 unsigned int offset
, bit
;
41 meson_reset_offset_and_bit(data
, id
, &offset
, &bit
);
42 offset
+= data
->param
->reset_offset
;
44 return regmap_write(data
->map
, offset
, BIT(bit
));
47 static int meson_reset_level(struct reset_controller_dev
*rcdev
,
48 unsigned long id
, bool assert)
50 struct meson_reset
*data
=
51 container_of(rcdev
, struct meson_reset
, rcdev
);
52 unsigned int offset
, bit
;
54 meson_reset_offset_and_bit(data
, id
, &offset
, &bit
);
55 offset
+= data
->param
->level_offset
;
56 assert ^= data
->param
->level_low_reset
;
58 return regmap_update_bits(data
->map
, offset
,
59 BIT(bit
), assert ? BIT(bit
) : 0);
62 static int meson_reset_status(struct reset_controller_dev
*rcdev
,
65 struct meson_reset
*data
=
66 container_of(rcdev
, struct meson_reset
, rcdev
);
67 unsigned int val
, offset
, bit
;
69 meson_reset_offset_and_bit(data
, id
, &offset
, &bit
);
70 offset
+= data
->param
->level_offset
;
72 regmap_read(data
->map
, offset
, &val
);
73 val
= !!(BIT(bit
) & val
);
75 return val
^ data
->param
->level_low_reset
;
78 static int meson_reset_assert(struct reset_controller_dev
*rcdev
,
81 return meson_reset_level(rcdev
, id
, true);
84 static int meson_reset_deassert(struct reset_controller_dev
*rcdev
,
87 return meson_reset_level(rcdev
, id
, false);
90 static int meson_reset_level_toggle(struct reset_controller_dev
*rcdev
,
95 ret
= meson_reset_assert(rcdev
, id
);
99 return meson_reset_deassert(rcdev
, id
);
102 const struct reset_control_ops meson_reset_ops
= {
103 .reset
= meson_reset_reset
,
104 .assert = meson_reset_assert
,
105 .deassert
= meson_reset_deassert
,
106 .status
= meson_reset_status
,
108 EXPORT_SYMBOL_NS_GPL(meson_reset_ops
, "MESON_RESET");
110 const struct reset_control_ops meson_reset_toggle_ops
= {
111 .reset
= meson_reset_level_toggle
,
112 .assert = meson_reset_assert
,
113 .deassert
= meson_reset_deassert
,
114 .status
= meson_reset_status
,
116 EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops
, "MESON_RESET");
118 int meson_reset_controller_register(struct device
*dev
, struct regmap
*map
,
119 const struct meson_reset_param
*param
)
121 struct meson_reset
*data
;
123 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
129 data
->rcdev
.owner
= dev
->driver
->owner
;
130 data
->rcdev
.nr_resets
= param
->reset_num
;
131 data
->rcdev
.ops
= data
->param
->reset_ops
;
132 data
->rcdev
.of_node
= dev
->of_node
;
134 return devm_reset_controller_register(dev
, &data
->rcdev
);
136 EXPORT_SYMBOL_NS_GPL(meson_reset_controller_register
, "MESON_RESET");
138 MODULE_DESCRIPTION("Amlogic Meson Reset Core function");
139 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
140 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
141 MODULE_LICENSE("Dual BSD/GPL");
142 MODULE_IMPORT_NS("MESON_RESET");