]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1d80c142 MR |
2 | /* |
3 | * Copyright (C) 2016 Maxime Ripard | |
4 | * Maxime Ripard <maxime.ripard@free-electrons.com> | |
1d80c142 MR |
5 | */ |
6 | ||
734d21cc | 7 | #include <linux/delay.h> |
1d80c142 MR |
8 | #include <linux/io.h> |
9 | #include <linux/reset-controller.h> | |
10 | ||
11 | #include "ccu_reset.h" | |
12 | ||
13 | static int ccu_reset_assert(struct reset_controller_dev *rcdev, | |
14 | unsigned long id) | |
15 | { | |
16 | struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); | |
17 | const struct ccu_reset_map *map = &ccu->reset_map[id]; | |
18 | unsigned long flags; | |
19 | u32 reg; | |
20 | ||
21 | spin_lock_irqsave(ccu->lock, flags); | |
22 | ||
23 | reg = readl(ccu->base + map->reg); | |
24 | writel(reg & ~map->bit, ccu->base + map->reg); | |
25 | ||
26 | spin_unlock_irqrestore(ccu->lock, flags); | |
27 | ||
28 | return 0; | |
29 | } | |
30 | ||
31 | static int ccu_reset_deassert(struct reset_controller_dev *rcdev, | |
32 | unsigned long id) | |
33 | { | |
34 | struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); | |
35 | const struct ccu_reset_map *map = &ccu->reset_map[id]; | |
36 | unsigned long flags; | |
37 | u32 reg; | |
38 | ||
39 | spin_lock_irqsave(ccu->lock, flags); | |
40 | ||
41 | reg = readl(ccu->base + map->reg); | |
42 | writel(reg | map->bit, ccu->base + map->reg); | |
43 | ||
44 | spin_unlock_irqrestore(ccu->lock, flags); | |
45 | ||
46 | return 0; | |
47 | } | |
48 | ||
734d21cc MR |
49 | static int ccu_reset_reset(struct reset_controller_dev *rcdev, |
50 | unsigned long id) | |
51 | { | |
52 | ccu_reset_assert(rcdev, id); | |
53 | udelay(10); | |
54 | ccu_reset_deassert(rcdev, id); | |
55 | ||
56 | return 0; | |
57 | } | |
58 | ||
5da672cf CYT |
59 | static int ccu_reset_status(struct reset_controller_dev *rcdev, |
60 | unsigned long id) | |
61 | { | |
62 | struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); | |
63 | const struct ccu_reset_map *map = &ccu->reset_map[id]; | |
64 | ||
65 | /* | |
66 | * The reset control API expects 0 if reset is not asserted, | |
67 | * which is the opposite of what our hardware uses. | |
68 | */ | |
69 | return !(map->bit & readl(ccu->base + map->reg)); | |
70 | } | |
71 | ||
1d80c142 MR |
72 | const struct reset_control_ops ccu_reset_ops = { |
73 | .assert = ccu_reset_assert, | |
74 | .deassert = ccu_reset_deassert, | |
734d21cc | 75 | .reset = ccu_reset_reset, |
5da672cf | 76 | .status = ccu_reset_status, |
1d80c142 | 77 | }; |