Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/slab.h>
  3#include <linux/io.h>
  4#include <linux/of.h>
  5#include <linux/of_address.h>
  6#include <linux/reset-controller.h>
  7
  8#include "reset.h"
  9
 10#define rcdev_to_unit(rcdev) container_of(rcdev, struct mmp_clk_reset_unit, rcdev)
 11
 12static int mmp_of_reset_xlate(struct reset_controller_dev *rcdev,
 13			  const struct of_phandle_args *reset_spec)
 14{
 15	struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
 16	struct mmp_clk_reset_cell *cell;
 17	int i;
 18
 19	if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
 20		return -EINVAL;
 21
 22	for (i = 0; i < rcdev->nr_resets; i++) {
 23		cell = &unit->cells[i];
 24		if (cell->clk_id == reset_spec->args[0])
 25			break;
 26	}
 27
 28	if (i == rcdev->nr_resets)
 29		return -EINVAL;
 30
 31	return i;
 32}
 33
 34static int mmp_clk_reset_assert(struct reset_controller_dev *rcdev,
 35				unsigned long id)
 36{
 37	struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
 38	struct mmp_clk_reset_cell *cell;
 39	unsigned long flags = 0;
 40	u32 val;
 41
 42	cell = &unit->cells[id];
 43	if (cell->lock)
 44		spin_lock_irqsave(cell->lock, flags);
 45
 46	val = readl(cell->reg);
 47	val |= cell->bits;
 48	writel(val, cell->reg);
 49
 50	if (cell->lock)
 51		spin_unlock_irqrestore(cell->lock, flags);
 52
 53	return 0;
 54}
 55
 56static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev,
 57				unsigned long id)
 58{
 59	struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
 60	struct mmp_clk_reset_cell *cell;
 61	unsigned long flags = 0;
 62	u32 val;
 63
 64	cell = &unit->cells[id];
 65	if (cell->lock)
 66		spin_lock_irqsave(cell->lock, flags);
 67
 68	val = readl(cell->reg);
 69	val &= ~cell->bits;
 70	writel(val, cell->reg);
 71
 72	if (cell->lock)
 73		spin_unlock_irqrestore(cell->lock, flags);
 74
 75	return 0;
 76}
 77
 78static const struct reset_control_ops mmp_clk_reset_ops = {
 79	.assert		= mmp_clk_reset_assert,
 80	.deassert	= mmp_clk_reset_deassert,
 81};
 82
 83void mmp_clk_reset_register(struct device_node *np,
 84			struct mmp_clk_reset_cell *cells, int nr_resets)
 85{
 86	struct mmp_clk_reset_unit *unit;
 87
 88	unit = kzalloc(sizeof(*unit), GFP_KERNEL);
 89	if (!unit)
 90		return;
 91
 92	unit->cells = cells;
 93	unit->rcdev.of_reset_n_cells = 1;
 94	unit->rcdev.nr_resets = nr_resets;
 95	unit->rcdev.ops = &mmp_clk_reset_ops;
 96	unit->rcdev.of_node = np;
 97	unit->rcdev.of_xlate = mmp_of_reset_xlate;
 98
 99	reset_controller_register(&unit->rcdev);
100}