1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Toshiba Visconti ARM SoC reset controller 4 * 5 * Copyright (c) 2021 TOSHIBA CORPORATION 6 * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation 7 * 8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 9 */ 10 #include <linux/delay.h> 11 #include <linux/device.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/regmap.h> 14 #include <linux/slab.h> 15 16 #include "reset.h" 17 18 static inline struct visconti_reset *to_visconti_reset(struct reset_controller_dev *rcdev) 19 { 20 return container_of(rcdev, struct visconti_reset, rcdev); 21 } 22 23 static int visconti_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) 24 { 25 struct visconti_reset *reset = to_visconti_reset(rcdev); 26 const struct visconti_reset_data *data = &reset->resets[id]; 27 u32 rst = BIT(data->rs_idx); 28 unsigned long flags; 29 int ret; 30 31 spin_lock_irqsave(reset->lock, flags); 32 ret = regmap_update_bits(reset->regmap, data->rson_offset, rst, rst); 33 spin_unlock_irqrestore(reset->lock, flags); 34 35 return ret; 36 } 37 38 static int visconti_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) 39 { 40 struct visconti_reset *reset = to_visconti_reset(rcdev); 41 const struct visconti_reset_data *data = &reset->resets[id]; 42 u32 rst = BIT(data->rs_idx); 43 unsigned long flags; 44 int ret; 45 46 spin_lock_irqsave(reset->lock, flags); 47 ret = regmap_update_bits(reset->regmap, data->rsoff_offset, rst, rst); 48 spin_unlock_irqrestore(reset->lock, flags); 49 50 return ret; 51 } 52 53 static int visconti_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) 54 { 55 visconti_reset_assert(rcdev, id); 56 udelay(1); 57 visconti_reset_deassert(rcdev, id); 58 59 return 0; 60 } 61 62 static int visconti_reset_status(struct reset_controller_dev *rcdev, unsigned long id) 63 { 64 struct visconti_reset *reset = to_visconti_reset(rcdev); 65 const struct visconti_reset_data *data = &reset->resets[id]; 66 unsigned long flags; 67 u32 reg; 68 int ret; 69 70 spin_lock_irqsave(reset->lock, flags); 71 ret = regmap_read(reset->regmap, data->rson_offset, ®); 72 spin_unlock_irqrestore(reset->lock, flags); 73 if (ret) 74 return ret; 75 76 return !(reg & data->rs_idx); 77 } 78 79 const struct reset_control_ops visconti_reset_ops = { 80 .assert = visconti_reset_assert, 81 .deassert = visconti_reset_deassert, 82 .reset = visconti_reset_reset, 83 .status = visconti_reset_status, 84 }; 85 86 int visconti_register_reset_controller(struct device *dev, 87 struct regmap *regmap, 88 const struct visconti_reset_data *resets, 89 unsigned int num_resets, 90 const struct reset_control_ops *reset_ops, 91 spinlock_t *lock) 92 { 93 struct visconti_reset *reset; 94 95 reset = devm_kzalloc(dev, sizeof(*reset), GFP_KERNEL); 96 if (!reset) 97 return -ENOMEM; 98 99 reset->regmap = regmap; 100 reset->resets = resets; 101 reset->rcdev.ops = reset_ops; 102 reset->rcdev.nr_resets = num_resets; 103 reset->rcdev.of_node = dev->of_node; 104 reset->lock = lock; 105 106 return devm_reset_controller_register(dev, &reset->rcdev); 107 } 108