serial: Add missing Kconfig dependencies for debug consoles
[oweals/u-boot.git] / drivers / hwspinlock / hwspinlock-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <hwspinlock.h>
10 #include <log.h>
11 #include <dm/device-internal.h>
12 #include <dm/device_compat.h>
13 #include <linux/compat.h>
14
15 static inline const struct hwspinlock_ops *
16 hwspinlock_dev_ops(struct udevice *dev)
17 {
18         return (const struct hwspinlock_ops *)dev->driver->ops;
19 }
20
21 static int hwspinlock_of_xlate_default(struct hwspinlock *hws,
22                                        struct ofnode_phandle_args *args)
23 {
24         if (args->args_count > 1) {
25                 debug("Invaild args_count: %d\n", args->args_count);
26                 return -EINVAL;
27         }
28
29         if (args->args_count)
30                 hws->id = args->args[0];
31         else
32                 hws->id = 0;
33
34         return 0;
35 }
36
37 int hwspinlock_get_by_index(struct udevice *dev, int index,
38                             struct hwspinlock *hws)
39 {
40         int ret;
41         struct ofnode_phandle_args args;
42         struct udevice *dev_hws;
43         const struct hwspinlock_ops *ops;
44
45         assert(hws);
46         hws->dev = NULL;
47
48         ret = dev_read_phandle_with_args(dev, "hwlocks", "#hwlock-cells", 1,
49                                          index, &args);
50         if (ret) {
51                 dev_dbg(dev, "%s: dev_read_phandle_with_args: err=%d\n",
52                         __func__, ret);
53                 return ret;
54         }
55
56         ret = uclass_get_device_by_ofnode(UCLASS_HWSPINLOCK,
57                                           args.node, &dev_hws);
58         if (ret) {
59                 dev_dbg(dev,
60                         "%s: uclass_get_device_by_of_offset failed: err=%d\n",
61                         __func__, ret);
62                 return ret;
63         }
64
65         hws->dev = dev_hws;
66
67         ops = hwspinlock_dev_ops(dev_hws);
68
69         if (ops->of_xlate)
70                 ret = ops->of_xlate(hws, &args);
71         else
72                 ret = hwspinlock_of_xlate_default(hws, &args);
73         if (ret)
74                 dev_dbg(dev, "of_xlate() failed: %d\n", ret);
75
76         return ret;
77 }
78
79 int hwspinlock_lock_timeout(struct hwspinlock *hws, unsigned int timeout)
80 {
81         const struct hwspinlock_ops *ops;
82         ulong start;
83         int ret;
84
85         assert(hws);
86
87         if (!hws->dev)
88                 return -EINVAL;
89
90         ops = hwspinlock_dev_ops(hws->dev);
91         if (!ops->lock)
92                 return -ENOSYS;
93
94         start = get_timer(0);
95         do {
96                 ret = ops->lock(hws->dev, hws->id);
97                 if (!ret)
98                         return ret;
99
100                 if (ops->relax)
101                         ops->relax(hws->dev);
102         } while (get_timer(start) < timeout);
103
104         return -ETIMEDOUT;
105 }
106
107 int hwspinlock_unlock(struct hwspinlock *hws)
108 {
109         const struct hwspinlock_ops *ops;
110
111         assert(hws);
112
113         if (!hws->dev)
114                 return -EINVAL;
115
116         ops = hwspinlock_dev_ops(hws->dev);
117         if (!ops->unlock)
118                 return -ENOSYS;
119
120         return ops->unlock(hws->dev, hws->id);
121 }
122
123 static int hwspinlock_post_bind(struct udevice *dev)
124 {
125 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
126         struct hwspinlock_ops *ops = device_get_ops(dev);
127         static int reloc_done;
128
129         if (!reloc_done) {
130                 if (ops->lock)
131                         ops->lock += gd->reloc_off;
132                 if (ops->unlock)
133                         ops->unlock += gd->reloc_off;
134                 if (ops->relax)
135                         ops->relax += gd->reloc_off;
136
137                 reloc_done++;
138         }
139 #endif
140         return 0;
141 }
142
143 UCLASS_DRIVER(hwspinlock) = {
144         .id             = UCLASS_HWSPINLOCK,
145         .name           = "hwspinlock",
146         .post_bind      = hwspinlock_post_bind,
147 };