175 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 15static 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 20static 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 31static int mtk_reset_assert(struct reset_controller_dev *rcdev,32 unsigned long id)33{34 return mtk_reset_update(rcdev, id, false);35}36 37static int mtk_reset_deassert(struct reset_controller_dev *rcdev,38 unsigned long id)39{40 return mtk_reset_update(rcdev, id, true);41}42 43static 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 54static 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 66static 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 72static 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 78static 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 89static const struct reset_control_ops mtk_reset_ops = {90 .assert = mtk_reset_assert,91 .deassert = mtk_reset_deassert,92 .reset = mtk_reset,93};94 95static 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 101static 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 113int 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}172EXPORT_SYMBOL_GPL(mtk_register_reset_controller_with_dev);173 174MODULE_LICENSE("GPL");175