Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2014 MediaTek Inc.
  4 */
  5
  6#include <linux/mfd/syscon.h>
  7#include <linux/module.h>
  8#include <linux/of.h>
  9#include <linux/platform_device.h>
 10#include <linux/regmap.h>
 11#include <linux/reset-controller.h>
 12#include <linux/slab.h>
 13
 14#include "clk-mtk.h"
 15
 16struct mtk_reset {
 17	struct regmap *regmap;
 18	int regofs;
 19	struct reset_controller_dev rcdev;
 20};
 21
 22static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev,
 23	unsigned long id)
 24{
 25	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
 26	unsigned int reg = data->regofs + ((id / 32) << 4);
 27
 28	return regmap_write(data->regmap, reg, 1);
 29}
 30
 31static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev,
 32	unsigned long id)
 33{
 34	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
 35	unsigned int reg = data->regofs + ((id / 32) << 4) + 0x4;
 36
 37	return regmap_write(data->regmap, reg, 1);
 38}
 39
 40static int mtk_reset_assert(struct reset_controller_dev *rcdev,
 41			      unsigned long id)
 42{
 43	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
 44
 45	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
 46			BIT(id % 32), ~0);
 47}
 48
 49static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
 50				unsigned long id)
 51{
 52	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
 53
 54	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
 55			BIT(id % 32), 0);
 56}
 57
 58static int mtk_reset(struct reset_controller_dev *rcdev,
 59			      unsigned long id)
 60{
 61	int ret;
 62
 63	ret = mtk_reset_assert(rcdev, id);
 64	if (ret)
 65		return ret;
 66
 67	return mtk_reset_deassert(rcdev, id);
 68}
 69
 70static int mtk_reset_set_clr(struct reset_controller_dev *rcdev,
 71	unsigned long id)
 72{
 73	int ret;
 74
 75	ret = mtk_reset_assert_set_clr(rcdev, id);
 76	if (ret)
 77		return ret;
 78	return mtk_reset_deassert_set_clr(rcdev, id);
 79}
 80
 81static const struct reset_control_ops mtk_reset_ops = {
 82	.assert = mtk_reset_assert,
 83	.deassert = mtk_reset_deassert,
 84	.reset = mtk_reset,
 85};
 86
 87static const struct reset_control_ops mtk_reset_ops_set_clr = {
 88	.assert = mtk_reset_assert_set_clr,
 89	.deassert = mtk_reset_deassert_set_clr,
 90	.reset = mtk_reset_set_clr,
 91};
 92
 93static void mtk_register_reset_controller_common(struct device_node *np,
 94			unsigned int num_regs, int regofs,
 95			const struct reset_control_ops *reset_ops)
 96{
 97	struct mtk_reset *data;
 98	int ret;
 99	struct regmap *regmap;
100
101	regmap = syscon_node_to_regmap(np);
102	if (IS_ERR(regmap)) {
103		pr_err("Cannot find regmap for %pOF: %ld\n", np,
104				PTR_ERR(regmap));
105		return;
106	}
107
108	data = kzalloc(sizeof(*data), GFP_KERNEL);
109	if (!data)
110		return;
111
112	data->regmap = regmap;
113	data->regofs = regofs;
114	data->rcdev.owner = THIS_MODULE;
115	data->rcdev.nr_resets = num_regs * 32;
116	data->rcdev.ops = reset_ops;
117	data->rcdev.of_node = np;
118
119	ret = reset_controller_register(&data->rcdev);
120	if (ret) {
121		pr_err("could not register reset controller: %d\n", ret);
122		kfree(data);
123		return;
124	}
125}
126
127void mtk_register_reset_controller(struct device_node *np,
128	unsigned int num_regs, int regofs)
129{
130	mtk_register_reset_controller_common(np, num_regs, regofs,
131		&mtk_reset_ops);
132}
133
134void mtk_register_reset_controller_set_clr(struct device_node *np,
135	unsigned int num_regs, int regofs)
136{
137	mtk_register_reset_controller_common(np, num_regs, regofs,
138		&mtk_reset_ops_set_clr);
139}