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
17struct 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 */
26struct 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 */
46int 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 */
57int 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 */
66int hwspinlock_unlock(struct hwspinlock *hws);
67
68#else
69
70static inline int hwspinlock_get_by_index(struct udevice *dev,
71					  int index,
72					  struct hwspinlock *hws)
73{
74	return -ENOSYS;
75}
76
77static inline int hwspinlock_lock_timeout(struct hwspinlock *hws,
78					  int timeout)
79{
80	return -ENOSYS;
81}
82
83static inline int hwspinlock_unlock(struct hwspinlock *hws)
84{
85	return -ENOSYS;
86}
87
88#endif /* CONFIG_DM_HWSPINLOCK */
89
90struct 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 */
98struct 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