108 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Toshiba Visconti ARM SoC reset controller4 *5 * Copyright (c) 2021 TOSHIBA CORPORATION6 * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation7 *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 18static inline struct visconti_reset *to_visconti_reset(struct reset_controller_dev *rcdev)19{20 return container_of(rcdev, struct visconti_reset, rcdev);21}22 23static 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 38static 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 53static 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 62static 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 79const 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 86int 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