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 (2876B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Hisilicon Reset Controller Driver
      4 *
      5 * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
      6 */
      7
      8#include <linux/io.h>
      9#include <linux/of_address.h>
     10#include <linux/platform_device.h>
     11#include <linux/reset-controller.h>
     12#include <linux/slab.h>
     13#include <linux/spinlock.h>
     14#include "reset.h"
     15
     16#define	HISI_RESET_BIT_MASK	0x1f
     17#define	HISI_RESET_OFFSET_SHIFT	8
     18#define	HISI_RESET_OFFSET_MASK	0xffff00
     19
     20struct hisi_reset_controller {
     21	spinlock_t	lock;
     22	void __iomem	*membase;
     23	struct reset_controller_dev	rcdev;
     24};
     25
     26
     27#define to_hisi_reset_controller(rcdev)  \
     28	container_of(rcdev, struct hisi_reset_controller, rcdev)
     29
     30static int hisi_reset_of_xlate(struct reset_controller_dev *rcdev,
     31			const struct of_phandle_args *reset_spec)
     32{
     33	u32 offset;
     34	u8 bit;
     35
     36	offset = (reset_spec->args[0] << HISI_RESET_OFFSET_SHIFT)
     37		& HISI_RESET_OFFSET_MASK;
     38	bit = reset_spec->args[1] & HISI_RESET_BIT_MASK;
     39
     40	return (offset | bit);
     41}
     42
     43static int hisi_reset_assert(struct reset_controller_dev *rcdev,
     44			      unsigned long id)
     45{
     46	struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev);
     47	unsigned long flags;
     48	u32 offset, reg;
     49	u8 bit;
     50
     51	offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT;
     52	bit = id & HISI_RESET_BIT_MASK;
     53
     54	spin_lock_irqsave(&rstc->lock, flags);
     55
     56	reg = readl(rstc->membase + offset);
     57	writel(reg | BIT(bit), rstc->membase + offset);
     58
     59	spin_unlock_irqrestore(&rstc->lock, flags);
     60
     61	return 0;
     62}
     63
     64static int hisi_reset_deassert(struct reset_controller_dev *rcdev,
     65				unsigned long id)
     66{
     67	struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev);
     68	unsigned long flags;
     69	u32 offset, reg;
     70	u8 bit;
     71
     72	offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT;
     73	bit = id & HISI_RESET_BIT_MASK;
     74
     75	spin_lock_irqsave(&rstc->lock, flags);
     76
     77	reg = readl(rstc->membase + offset);
     78	writel(reg & ~BIT(bit), rstc->membase + offset);
     79
     80	spin_unlock_irqrestore(&rstc->lock, flags);
     81
     82	return 0;
     83}
     84
     85static const struct reset_control_ops hisi_reset_ops = {
     86	.assert		= hisi_reset_assert,
     87	.deassert	= hisi_reset_deassert,
     88};
     89
     90struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev)
     91{
     92	struct hisi_reset_controller *rstc;
     93
     94	rstc = devm_kmalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL);
     95	if (!rstc)
     96		return NULL;
     97
     98	rstc->membase = devm_platform_ioremap_resource(pdev, 0);
     99	if (IS_ERR(rstc->membase))
    100		return NULL;
    101
    102	spin_lock_init(&rstc->lock);
    103	rstc->rcdev.owner = THIS_MODULE;
    104	rstc->rcdev.ops = &hisi_reset_ops;
    105	rstc->rcdev.of_node = pdev->dev.of_node;
    106	rstc->rcdev.of_reset_n_cells = 2;
    107	rstc->rcdev.of_xlate = hisi_reset_of_xlate;
    108	reset_controller_register(&rstc->rcdev);
    109
    110	return rstc;
    111}
    112EXPORT_SYMBOL_GPL(hisi_reset_init);
    113
    114void hisi_reset_exit(struct hisi_reset_controller *rstc)
    115{
    116	reset_controller_unregister(&rstc->rcdev);
    117}
    118EXPORT_SYMBOL_GPL(hisi_reset_exit);