162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2013, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/bitops.h>
762306a36Sopenharmony_ci#include <linux/export.h>
862306a36Sopenharmony_ci#include <linux/regmap.h>
962306a36Sopenharmony_ci#include <linux/reset-controller.h>
1062306a36Sopenharmony_ci#include <linux/delay.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "reset.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic int qcom_reset(struct reset_controller_dev *rcdev, unsigned long id)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	struct qcom_reset_controller *rst = to_qcom_reset_controller(rcdev);
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	rcdev->ops->assert(rcdev, id);
1962306a36Sopenharmony_ci	fsleep(rst->reset_map[id].udelay ?: 1); /* use 1 us as default */
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	rcdev->ops->deassert(rcdev, id);
2262306a36Sopenharmony_ci	return 0;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic int qcom_reset_set_assert(struct reset_controller_dev *rcdev,
2662306a36Sopenharmony_ci				 unsigned long id, bool assert)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	struct qcom_reset_controller *rst;
2962306a36Sopenharmony_ci	const struct qcom_reset_map *map;
3062306a36Sopenharmony_ci	u32 mask;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	rst = to_qcom_reset_controller(rcdev);
3362306a36Sopenharmony_ci	map = &rst->reset_map[id];
3462306a36Sopenharmony_ci	mask = map->bitmask ? map->bitmask : BIT(map->bit);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	regmap_update_bits(rst->regmap, map->reg, mask, assert ? mask : 0);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* Read back the register to ensure write completion, ignore the value */
3962306a36Sopenharmony_ci	regmap_read(rst->regmap, map->reg, &mask);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	return 0;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic int qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	return qcom_reset_set_assert(rcdev, id, true);
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic int qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	return qcom_reset_set_assert(rcdev, id, false);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciconst struct reset_control_ops qcom_reset_ops = {
5562306a36Sopenharmony_ci	.reset = qcom_reset,
5662306a36Sopenharmony_ci	.assert = qcom_reset_assert,
5762306a36Sopenharmony_ci	.deassert = qcom_reset_deassert,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(qcom_reset_ops);
60