reset.c (3350B)
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: %pe\n", np, regmap); 104 return; 105 } 106 107 data = kzalloc(sizeof(*data), GFP_KERNEL); 108 if (!data) 109 return; 110 111 data->regmap = regmap; 112 data->regofs = regofs; 113 data->rcdev.owner = THIS_MODULE; 114 data->rcdev.nr_resets = num_regs * 32; 115 data->rcdev.ops = reset_ops; 116 data->rcdev.of_node = np; 117 118 ret = reset_controller_register(&data->rcdev); 119 if (ret) { 120 pr_err("could not register reset controller: %d\n", ret); 121 kfree(data); 122 return; 123 } 124} 125 126void mtk_register_reset_controller(struct device_node *np, 127 unsigned int num_regs, int regofs) 128{ 129 mtk_register_reset_controller_common(np, num_regs, regofs, 130 &mtk_reset_ops); 131} 132 133void mtk_register_reset_controller_set_clr(struct device_node *np, 134 unsigned int num_regs, int regofs) 135{ 136 mtk_register_reset_controller_common(np, num_regs, regofs, 137 &mtk_reset_ops_set_clr); 138} 139 140MODULE_LICENSE("GPL");