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