summaryrefslogtreecommitdiff
path: root/include/hwspinlock.h
blob: 99389c13c24e9322c3df915c02127cad3c2d344f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
/*
 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
 */

#ifndef _HWSPINLOCK_H_
#define _HWSPINLOCK_H_

/**
 * Implement a hwspinlock uclass.
 * Hardware spinlocks are used to perform hardware protection of
 * critical sections and synchronisation between multiprocessors.
 */

struct udevice;

/**
 * struct hwspinlock - A handle to (allowing control of) a single hardware
 * spinlock.
 *
 * @dev: The device which implements the hardware spinlock.
 * @id: The hardware spinlock ID within the provider.
 */
struct hwspinlock {
	struct udevice *dev;
	unsigned long id;
};

#if CONFIG_IS_ENABLED(DM_HWSPINLOCK)

/**
 * hwspinlock_get_by_index - Get a hardware spinlock by integer index
 *
 * This looks up and request a hardware spinlock. The index is relative to the
 * client device; each device is assumed to have n hardware spinlock associated
 * with it somehow, and this function finds and requests one of them.
 *
 * @dev:	The client device.
 * @index:	The index of the hardware spinlock to request, within the
 *		client's list of hardware spinlock.
 * @hws:	A pointer to a hardware spinlock struct to initialize.
 * @return 0 if OK, or a negative error code.
 */
int hwspinlock_get_by_index(struct udevice *dev,
			    int index, struct hwspinlock *hws);

/**
 * Lock the hardware spinlock
 *
 * @hws:	A hardware spinlock struct that previously requested by
 *		hwspinlock_get_by_index
 * @timeout:	Timeout value in msecs
 * @return: 0 if OK, -ETIMEDOUT if timeout, -ve on other errors
 */
int hwspinlock_lock_timeout(struct hwspinlock *hws, unsigned int timeout);

/**
 * Unlock the hardware spinlock
 *
 * @hws:	A hardware spinlock struct that previously requested by
 *		hwspinlock_get_by_index
 * @return: 0 if OK, -ve on error
 */
int hwspinlock_unlock(struct hwspinlock *hws);

#else

static inline int hwspinlock_get_by_index(struct udevice *dev,
					  int index,
					  struct hwspinlock *hws)
{
	return -ENOSYS;
}

static inline int hwspinlock_lock_timeout(struct hwspinlock *hws,
					  int timeout)
{
	return -ENOSYS;
}

static inline int hwspinlock_unlock(struct hwspinlock *hws)
{
	return -ENOSYS;
}

#endif /* CONFIG_DM_HWSPINLOCK */

struct ofnode_phandle_args;

/**
 * struct hwspinlock_ops - Driver model hwspinlock operations
 *
 * The uclass interface is implemented by all hwspinlock devices which use
 * driver model.
 */
struct hwspinlock_ops {
	/**
	 * of_xlate - Translate a client's device-tree (OF) hardware specifier.
	 *
	 * The hardware core calls this function as the first step in
	 * implementing a client's hwspinlock_get_by_*() call.
	 *
	 * @hws:	The hardware spinlock struct to hold the translation
	 *			result.
	 * @args:	The hardware spinlock specifier values from device tree.
	 * @return 0 if OK, or a negative error code.
	 */
	int (*of_xlate)(struct hwspinlock *hws,
			struct ofnode_phandle_args *args);

	/**
	 * Lock the hardware spinlock
	 *
	 * @dev:	hwspinlock Device
	 * @index:	index of the lock to be used
	 * @return 0 if OK, -ve on error
	 */
	int (*lock)(struct udevice *dev, int index);

	/**
	 * Unlock the hardware spinlock
	 *
	 * @dev:	hwspinlock Device
	 * @index:	index of the lock to be unlocked
	 * @return 0 if OK, -ve on error
	 */
	int (*unlock)(struct udevice *dev, int index);

	/**
	 * Relax - optional
	 *       Platform-specific relax method, called by hwspinlock core
	 *       while spinning on a lock, between two successive call to
	 *       lock
	 *
	 * @dev:	hwspinlock Device
	 */
	void (*relax)(struct udevice *dev);
};

#endif /* _HWSPINLOCK_H_ */