Thomas Gleixner | d2912cb | 2019-06-04 10:11:33 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
Thierry Reding | dc606c5 | 2016-08-18 15:50:09 +0200 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2016 NVIDIA Corporation |
Thierry Reding | dc606c5 | 2016-08-18 15:50:09 +0200 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | #include <linux/reset-controller.h> |
| 7 | |
| 8 | #include <soc/tegra/bpmp.h> |
| 9 | #include <soc/tegra/bpmp-abi.h> |
| 10 | |
| 11 | static struct tegra_bpmp *to_tegra_bpmp(struct reset_controller_dev *rstc) |
| 12 | { |
| 13 | return container_of(rstc, struct tegra_bpmp, rstc); |
| 14 | } |
| 15 | |
| 16 | static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc, |
| 17 | enum mrq_reset_commands command, |
| 18 | unsigned int id) |
| 19 | { |
| 20 | struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc); |
| 21 | struct mrq_reset_request request; |
| 22 | struct tegra_bpmp_message msg; |
Mikko Perttunen | c045ceb | 2021-09-15 11:55:14 +0300 | [diff] [blame] | 23 | int err; |
Thierry Reding | dc606c5 | 2016-08-18 15:50:09 +0200 | [diff] [blame] | 24 | |
| 25 | memset(&request, 0, sizeof(request)); |
| 26 | request.cmd = command; |
| 27 | request.reset_id = id; |
| 28 | |
| 29 | memset(&msg, 0, sizeof(msg)); |
| 30 | msg.mrq = MRQ_RESET; |
| 31 | msg.tx.data = &request; |
| 32 | msg.tx.size = sizeof(request); |
| 33 | |
Mikko Perttunen | c045ceb | 2021-09-15 11:55:14 +0300 | [diff] [blame] | 34 | err = tegra_bpmp_transfer(bpmp, &msg); |
| 35 | if (err) |
| 36 | return err; |
| 37 | if (msg.rx.ret) |
| 38 | return -EINVAL; |
| 39 | |
| 40 | return 0; |
Thierry Reding | dc606c5 | 2016-08-18 15:50:09 +0200 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc, |
| 44 | unsigned long id) |
| 45 | { |
| 46 | return tegra_bpmp_reset_common(rstc, CMD_RESET_MODULE, id); |
| 47 | } |
| 48 | |
| 49 | static int tegra_bpmp_reset_assert(struct reset_controller_dev *rstc, |
| 50 | unsigned long id) |
| 51 | { |
| 52 | return tegra_bpmp_reset_common(rstc, CMD_RESET_ASSERT, id); |
| 53 | } |
| 54 | |
| 55 | static int tegra_bpmp_reset_deassert(struct reset_controller_dev *rstc, |
| 56 | unsigned long id) |
| 57 | { |
| 58 | return tegra_bpmp_reset_common(rstc, CMD_RESET_DEASSERT, id); |
| 59 | } |
| 60 | |
| 61 | static const struct reset_control_ops tegra_bpmp_reset_ops = { |
| 62 | .reset = tegra_bpmp_reset_module, |
| 63 | .assert = tegra_bpmp_reset_assert, |
| 64 | .deassert = tegra_bpmp_reset_deassert, |
| 65 | }; |
| 66 | |
| 67 | int tegra_bpmp_init_resets(struct tegra_bpmp *bpmp) |
| 68 | { |
| 69 | bpmp->rstc.ops = &tegra_bpmp_reset_ops; |
| 70 | bpmp->rstc.owner = THIS_MODULE; |
| 71 | bpmp->rstc.of_node = bpmp->dev->of_node; |
| 72 | bpmp->rstc.nr_resets = bpmp->soc->num_resets; |
| 73 | |
| 74 | return devm_reset_controller_register(bpmp->dev, &bpmp->rstc); |
| 75 | } |