101 lines · c
1// SPDX-License-Identifier: GPL-2.02#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}101