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/slab.h> 12 13 #include "reset.h" 14 15 static inline struct mtk_clk_rst_data *to_mtk_clk_rst_data(struct reset_controller_dev *rcdev) 16 { 17 return container_of(rcdev, struct mtk_clk_rst_data, rcdev); 18 } 19 20 static int mtk_reset_update(struct reset_controller_dev *rcdev, 21 unsigned long id, bool deassert) 22 { 23 struct mtk_clk_rst_data *data = to_mtk_clk_rst_data(rcdev); 24 unsigned int val = deassert ? 0 : ~0; 25 26 return regmap_update_bits(data->regmap, 27 data->desc->rst_bank_ofs[id / RST_NR_PER_BANK], 28 BIT(id % RST_NR_PER_BANK), val); 29 } 30 31 static int mtk_reset_assert(struct reset_controller_dev *rcdev, 32 unsigned long id) 33 { 34 return mtk_reset_update(rcdev, id, false); 35 } 36 37 static int mtk_reset_deassert(struct reset_controller_dev *rcdev, 38 unsigned long id) 39 { 40 return mtk_reset_update(rcdev, id, true); 41 } 42 43 static int mtk_reset(struct reset_controller_dev *rcdev, unsigned long id) 44 { 45 int ret; 46 47 ret = mtk_reset_assert(rcdev, id); 48 if (ret) 49 return ret; 50 51 return mtk_reset_deassert(rcdev, id); 52 } 53 54 static int mtk_reset_update_set_clr(struct reset_controller_dev *rcdev, 55 unsigned long id, bool deassert) 56 { 57 struct mtk_clk_rst_data *data = to_mtk_clk_rst_data(rcdev); 58 unsigned int deassert_ofs = deassert ? 0x4 : 0; 59 60 return regmap_write(data->regmap, 61 data->desc->rst_bank_ofs[id / RST_NR_PER_BANK] + 62 deassert_ofs, 63 BIT(id % RST_NR_PER_BANK)); 64 } 65 66 static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev, 67 unsigned long id) 68 { 69 return mtk_reset_update_set_clr(rcdev, id, false); 70 } 71 72 static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev, 73 unsigned long id) 74 { 75 return mtk_reset_update_set_clr(rcdev, id, true); 76 } 77 78 static int mtk_reset_set_clr(struct reset_controller_dev *rcdev, 79 unsigned long id) 80 { 81 int ret; 82 83 ret = mtk_reset_assert_set_clr(rcdev, id); 84 if (ret) 85 return ret; 86 return mtk_reset_deassert_set_clr(rcdev, id); 87 } 88 89 static const struct reset_control_ops mtk_reset_ops = { 90 .assert = mtk_reset_assert, 91 .deassert = mtk_reset_deassert, 92 .reset = mtk_reset, 93 }; 94 95 static const struct reset_control_ops mtk_reset_ops_set_clr = { 96 .assert = mtk_reset_assert_set_clr, 97 .deassert = mtk_reset_deassert_set_clr, 98 .reset = mtk_reset_set_clr, 99 }; 100 101 static int reset_xlate(struct reset_controller_dev *rcdev, 102 const struct of_phandle_args *reset_spec) 103 { 104 struct mtk_clk_rst_data *data = to_mtk_clk_rst_data(rcdev); 105 106 if (reset_spec->args[0] >= rcdev->nr_resets || 107 reset_spec->args[0] >= data->desc->rst_idx_map_nr) 108 return -EINVAL; 109 110 return data->desc->rst_idx_map[reset_spec->args[0]]; 111 } 112 113 int mtk_register_reset_controller_with_dev(struct device *dev, 114 const struct mtk_clk_rst_desc *desc) 115 { 116 struct device_node *np = dev->of_node; 117 struct regmap *regmap; 118 const struct reset_control_ops *rcops = NULL; 119 struct mtk_clk_rst_data *data; 120 int ret; 121 122 if (!desc) { 123 dev_err(dev, "mtk clock reset desc is NULL\n"); 124 return -EINVAL; 125 } 126 127 switch (desc->version) { 128 case MTK_RST_SIMPLE: 129 rcops = &mtk_reset_ops; 130 break; 131 case MTK_RST_SET_CLR: 132 rcops = &mtk_reset_ops_set_clr; 133 break; 134 default: 135 dev_err(dev, "Unknown reset version %d\n", desc->version); 136 return -EINVAL; 137 } 138 139 regmap = device_node_to_regmap(np); 140 if (IS_ERR(regmap)) { 141 dev_err(dev, "Cannot find regmap %pe\n", regmap); 142 return PTR_ERR(regmap); 143 } 144 145 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 146 if (!data) 147 return -ENOMEM; 148 149 data->desc = desc; 150 data->regmap = regmap; 151 data->rcdev.owner = THIS_MODULE; 152 data->rcdev.ops = rcops; 153 data->rcdev.of_node = np; 154 data->rcdev.dev = dev; 155 156 if (data->desc->rst_idx_map_nr > 0) { 157 data->rcdev.of_reset_n_cells = 1; 158 data->rcdev.nr_resets = desc->rst_idx_map_nr; 159 data->rcdev.of_xlate = reset_xlate; 160 } else { 161 data->rcdev.nr_resets = desc->rst_bank_nr * RST_NR_PER_BANK; 162 } 163 164 ret = devm_reset_controller_register(dev, &data->rcdev); 165 if (ret) { 166 dev_err(dev, "could not register reset controller: %d\n", ret); 167 return ret; 168 } 169 170 return 0; 171 } 172 EXPORT_SYMBOL_GPL(mtk_register_reset_controller_with_dev); 173 174 MODULE_LICENSE("GPL"); 175