xref: /linux/drivers/reset/spacemit/reset-spacemit-common.c (revision bdbddf72a2ab1cfea699959795d70df3931eefe7)
1*aba86f7bSGuodong Xu // SPDX-License-Identifier: GPL-2.0-only
2*aba86f7bSGuodong Xu 
3*aba86f7bSGuodong Xu /* SpacemiT reset controller driver - common implementation */
4*aba86f7bSGuodong Xu 
5*aba86f7bSGuodong Xu #include <linux/container_of.h>
6*aba86f7bSGuodong Xu #include <linux/device.h>
7*aba86f7bSGuodong Xu #include <linux/module.h>
8*aba86f7bSGuodong Xu 
9*aba86f7bSGuodong Xu #include <soc/spacemit/ccu.h>
10*aba86f7bSGuodong Xu 
11*aba86f7bSGuodong Xu #include "reset-spacemit-common.h"
12*aba86f7bSGuodong Xu 
13*aba86f7bSGuodong Xu static int spacemit_reset_update(struct reset_controller_dev *rcdev,
14*aba86f7bSGuodong Xu 				 unsigned long id, bool assert)
15*aba86f7bSGuodong Xu {
16*aba86f7bSGuodong Xu 	struct ccu_reset_controller *controller;
17*aba86f7bSGuodong Xu 	const struct ccu_reset_data *data;
18*aba86f7bSGuodong Xu 	u32 mask;
19*aba86f7bSGuodong Xu 	u32 val;
20*aba86f7bSGuodong Xu 
21*aba86f7bSGuodong Xu 	controller = container_of(rcdev, struct ccu_reset_controller, rcdev);
22*aba86f7bSGuodong Xu 	data = &controller->data->reset_data[id];
23*aba86f7bSGuodong Xu 	mask = data->assert_mask | data->deassert_mask;
24*aba86f7bSGuodong Xu 	val = assert ? data->assert_mask : data->deassert_mask;
25*aba86f7bSGuodong Xu 
26*aba86f7bSGuodong Xu 	return regmap_update_bits(controller->regmap, data->offset, mask, val);
27*aba86f7bSGuodong Xu }
28*aba86f7bSGuodong Xu 
29*aba86f7bSGuodong Xu static int spacemit_reset_assert(struct reset_controller_dev *rcdev,
30*aba86f7bSGuodong Xu 				 unsigned long id)
31*aba86f7bSGuodong Xu {
32*aba86f7bSGuodong Xu 	return spacemit_reset_update(rcdev, id, true);
33*aba86f7bSGuodong Xu }
34*aba86f7bSGuodong Xu 
35*aba86f7bSGuodong Xu static int spacemit_reset_deassert(struct reset_controller_dev *rcdev,
36*aba86f7bSGuodong Xu 				   unsigned long id)
37*aba86f7bSGuodong Xu {
38*aba86f7bSGuodong Xu 	return spacemit_reset_update(rcdev, id, false);
39*aba86f7bSGuodong Xu }
40*aba86f7bSGuodong Xu 
41*aba86f7bSGuodong Xu static const struct reset_control_ops spacemit_reset_control_ops = {
42*aba86f7bSGuodong Xu 	.assert		= spacemit_reset_assert,
43*aba86f7bSGuodong Xu 	.deassert	= spacemit_reset_deassert,
44*aba86f7bSGuodong Xu };
45*aba86f7bSGuodong Xu 
46*aba86f7bSGuodong Xu static int spacemit_reset_controller_register(struct device *dev,
47*aba86f7bSGuodong Xu 					      struct ccu_reset_controller *controller)
48*aba86f7bSGuodong Xu {
49*aba86f7bSGuodong Xu 	struct reset_controller_dev *rcdev = &controller->rcdev;
50*aba86f7bSGuodong Xu 
51*aba86f7bSGuodong Xu 	rcdev->ops = &spacemit_reset_control_ops;
52*aba86f7bSGuodong Xu 	rcdev->owner = dev->driver->owner;
53*aba86f7bSGuodong Xu 	rcdev->of_node = dev->of_node;
54*aba86f7bSGuodong Xu 	rcdev->nr_resets = controller->data->count;
55*aba86f7bSGuodong Xu 
56*aba86f7bSGuodong Xu 	return devm_reset_controller_register(dev, &controller->rcdev);
57*aba86f7bSGuodong Xu }
58*aba86f7bSGuodong Xu 
59*aba86f7bSGuodong Xu int spacemit_reset_probe(struct auxiliary_device *adev,
60*aba86f7bSGuodong Xu 			 const struct auxiliary_device_id *id)
61*aba86f7bSGuodong Xu {
62*aba86f7bSGuodong Xu 	struct spacemit_ccu_adev *rdev = to_spacemit_ccu_adev(adev);
63*aba86f7bSGuodong Xu 	struct ccu_reset_controller *controller;
64*aba86f7bSGuodong Xu 	struct device *dev = &adev->dev;
65*aba86f7bSGuodong Xu 
66*aba86f7bSGuodong Xu 	controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
67*aba86f7bSGuodong Xu 	if (!controller)
68*aba86f7bSGuodong Xu 		return -ENOMEM;
69*aba86f7bSGuodong Xu 	controller->data = (const struct ccu_reset_controller_data *)id->driver_data;
70*aba86f7bSGuodong Xu 	controller->regmap = rdev->regmap;
71*aba86f7bSGuodong Xu 
72*aba86f7bSGuodong Xu 	return spacemit_reset_controller_register(dev, controller);
73*aba86f7bSGuodong Xu }
74*aba86f7bSGuodong Xu EXPORT_SYMBOL_NS_GPL(spacemit_reset_probe, "RESET_SPACEMIT");
75*aba86f7bSGuodong Xu 
76*aba86f7bSGuodong Xu MODULE_DESCRIPTION("SpacemiT reset controller driver - common code");
77*aba86f7bSGuodong Xu MODULE_LICENSE("GPL");
78