brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 2e33039 Raw
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