cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

reset.c (2938B)


      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
     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, &reg);
     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}