brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · fd56aae Raw
127 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2014 MundoReader S.L.4 * Author: Heiko Stuebner <heiko@sntech.de>5 */6 7#include <linux/slab.h>8#include <linux/io.h>9#include <linux/reset-controller.h>10#include <linux/spinlock.h>11#include "clk.h"12 13struct rockchip_softrst {14	struct reset_controller_dev	rcdev;15	const int			*lut;16	void __iomem			*reg_base;17	int				num_regs;18	int				num_per_reg;19	u8				flags;20	spinlock_t			lock;21};22 23static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,24			      unsigned long id)25{26	struct rockchip_softrst *softrst = container_of(rcdev,27						     struct rockchip_softrst,28						     rcdev);29	int bank, offset;30 31	if (softrst->lut)32		id = softrst->lut[id];33 34	bank = id / softrst->num_per_reg;35	offset = id % softrst->num_per_reg;36 37	if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {38		writel(BIT(offset) | (BIT(offset) << 16),39		       softrst->reg_base + (bank * 4));40	} else {41		unsigned long flags;42		u32 reg;43 44		spin_lock_irqsave(&softrst->lock, flags);45 46		reg = readl(softrst->reg_base + (bank * 4));47		writel(reg | BIT(offset), softrst->reg_base + (bank * 4));48 49		spin_unlock_irqrestore(&softrst->lock, flags);50	}51 52	return 0;53}54 55static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,56				unsigned long id)57{58	struct rockchip_softrst *softrst = container_of(rcdev,59						     struct rockchip_softrst,60						     rcdev);61	int bank, offset;62 63	if (softrst->lut)64		id = softrst->lut[id];65 66	bank = id / softrst->num_per_reg;67	offset = id % softrst->num_per_reg;68 69	if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {70		writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));71	} else {72		unsigned long flags;73		u32 reg;74 75		spin_lock_irqsave(&softrst->lock, flags);76 77		reg = readl(softrst->reg_base + (bank * 4));78		writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));79 80		spin_unlock_irqrestore(&softrst->lock, flags);81	}82 83	return 0;84}85 86static const struct reset_control_ops rockchip_softrst_ops = {87	.assert		= rockchip_softrst_assert,88	.deassert	= rockchip_softrst_deassert,89};90 91void rockchip_register_softrst_lut(struct device_node *np,92				   const int *lookup_table,93				   unsigned int num_regs,94				   void __iomem *base, u8 flags)95{96	struct rockchip_softrst *softrst;97	int ret;98 99	softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);100	if (!softrst)101		return;102 103	spin_lock_init(&softrst->lock);104 105	softrst->reg_base = base;106	softrst->lut = lookup_table;107	softrst->flags = flags;108	softrst->num_regs = num_regs;109	softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16110								      : 32;111 112	softrst->rcdev.owner = THIS_MODULE;113	if (lookup_table)114		softrst->rcdev.nr_resets = num_regs;115	else116		softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;117	softrst->rcdev.ops = &rockchip_softrst_ops;118	softrst->rcdev.of_node = np;119	ret = reset_controller_register(&softrst->rcdev);120	if (ret) {121		pr_err("%s: could not register reset controller, %d\n",122		       __func__, ret);123		kfree(softrst);124	}125};126EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut);127