linux/drivers/clk/mediatek/reset.c
<<
>>
Prefs
   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 = device_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}
 140