1 /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
2 /*
3  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4  */
5 
6 #ifndef _HWSPINLOCK_H_
7 #define _HWSPINLOCK_H_
8 
9 #include <linux/errno.h>
10 
11 /**
12  * Implement a hwspinlock uclass.
13  * Hardware spinlocks are used to perform hardware protection of
14  * critical sections and synchronisation between multiprocessors.
15  */
16 
17 struct udevice;
18 
19 /**
20  * struct hwspinlock - A handle to (allowing control of) a single hardware
21  * spinlock.
22  *
23  * @dev: The device which implements the hardware spinlock.
24  * @id: The hardware spinlock ID within the provider.
25  */
26 struct hwspinlock {
27 	struct udevice *dev;
28 	unsigned long id;
29 };
30 
31 #if CONFIG_IS_ENABLED(DM_HWSPINLOCK)
32 
33 /**
34  * hwspinlock_get_by_index - Get a hardware spinlock by integer index
35  *
36  * This looks up and request a hardware spinlock. The index is relative to the
37  * client device; each device is assumed to have n hardware spinlock associated
38  * with it somehow, and this function finds and requests one of them.
39  *
40  * @dev:	The client device.
41  * @index:	The index of the hardware spinlock to request, within the
42  *		client's list of hardware spinlock.
43  * @hws:	A pointer to a hardware spinlock struct to initialize.
44  * Return: 0 if OK, or a negative error code.
45  */
46 int hwspinlock_get_by_index(struct udevice *dev,
47 			    int index, struct hwspinlock *hws);
48 
49 /**
50  * Lock the hardware spinlock
51  *
52  * @hws:	A hardware spinlock struct that previously requested by
53  *		hwspinlock_get_by_index
54  * @timeout:	Timeout value in msecs
55  * @return: 0 if OK, -ETIMEDOUT if timeout, -ve on other errors
56  */
57 int hwspinlock_lock_timeout(struct hwspinlock *hws, unsigned int timeout);
58 
59 /**
60  * Unlock the hardware spinlock
61  *
62  * @hws:	A hardware spinlock struct that previously requested by
63  *		hwspinlock_get_by_index
64  * @return: 0 if OK, -ve on error
65  */
66 int hwspinlock_unlock(struct hwspinlock *hws);
67 
68 #else
69 
hwspinlock_get_by_index(struct udevice * dev,int index,struct hwspinlock * hws)70 static inline int hwspinlock_get_by_index(struct udevice *dev,
71 					  int index,
72 					  struct hwspinlock *hws)
73 {
74 	return -ENOSYS;
75 }
76 
hwspinlock_lock_timeout(struct hwspinlock * hws,int timeout)77 static inline int hwspinlock_lock_timeout(struct hwspinlock *hws,
78 					  int timeout)
79 {
80 	return -ENOSYS;
81 }
82 
hwspinlock_unlock(struct hwspinlock * hws)83 static inline int hwspinlock_unlock(struct hwspinlock *hws)
84 {
85 	return -ENOSYS;
86 }
87 
88 #endif /* CONFIG_DM_HWSPINLOCK */
89 
90 struct ofnode_phandle_args;
91 
92 /**
93  * struct hwspinlock_ops - Driver model hwspinlock operations
94  *
95  * The uclass interface is implemented by all hwspinlock devices which use
96  * driver model.
97  */
98 struct hwspinlock_ops {
99 	/**
100 	 * of_xlate - Translate a client's device-tree (OF) hardware specifier.
101 	 *
102 	 * The hardware core calls this function as the first step in
103 	 * implementing a client's hwspinlock_get_by_*() call.
104 	 *
105 	 * @hws:	The hardware spinlock struct to hold the translation
106 	 *			result.
107 	 * @args:	The hardware spinlock specifier values from device tree.
108 	 * @return 0 if OK, or a negative error code.
109 	 */
110 	int (*of_xlate)(struct hwspinlock *hws,
111 			struct ofnode_phandle_args *args);
112 
113 	/**
114 	 * Lock the hardware spinlock
115 	 *
116 	 * @dev:	hwspinlock Device
117 	 * @index:	index of the lock to be used
118 	 * @return 0 if OK, -ve on error
119 	 */
120 	int (*lock)(struct udevice *dev, int index);
121 
122 	/**
123 	 * Unlock the hardware spinlock
124 	 *
125 	 * @dev:	hwspinlock Device
126 	 * @index:	index of the lock to be unlocked
127 	 * @return 0 if OK, -ve on error
128 	 */
129 	int (*unlock)(struct udevice *dev, int index);
130 
131 	/**
132 	 * Relax - optional
133 	 *       Platform-specific relax method, called by hwspinlock core
134 	 *       while spinning on a lock, between two successive call to
135 	 *       lock
136 	 *
137 	 * @dev:	hwspinlock Device
138 	 */
139 	void (*relax)(struct udevice *dev);
140 };
141 
142 #endif /* _HWSPINLOCK_H_ */
143