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 16 struct mtk_reset { 17 struct regmap *regmap; 18 int regofs; 19 struct reset_controller_dev rcdev; 20 }; 21 22 static 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 31 static 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 40 static 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 49 static 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 58 static 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 70 static 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 81 static const struct reset_control_ops mtk_reset_ops = { 82 .assert = mtk_reset_assert, 83 .deassert = mtk_reset_deassert, 84 .reset = mtk_reset, 85 }; 86 87 static 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 93 static 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 127 void 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 134 void 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