Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
| 2 | /* |
| 3 | * Based on the linux multiplexer framework |
| 4 | * |
| 5 | * At its core, a multiplexer (or mux), also known as a data selector, is a |
| 6 | * device that selects between several analog or digital input signals and |
| 7 | * forwards it to a single output line. This notion can be extended to work |
| 8 | * with buses, like a I2C bus multiplexer for example. |
| 9 | * |
| 10 | * Copyright (C) 2017 Axentia Technologies AB |
| 11 | * Author: Peter Rosin <peda@axentia.se> |
| 12 | * |
Nishanth Menon | eaa39c6 | 2023-11-01 15:56:03 -0500 | [diff] [blame] | 13 | * Copyright (C) 2017-2018 Texas Instruments Incorporated - https://www.ti.com/ |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 14 | * Jean-Jacques Hiblot <jjhiblot@ti.com> |
| 15 | */ |
| 16 | |
| 17 | #ifndef _MUX_H_ |
| 18 | #define _MUX_H_ |
| 19 | |
| 20 | #include <linux/errno.h> |
| 21 | #include <linux/types.h> |
| 22 | |
| 23 | struct udevice; |
| 24 | struct mux_control; |
| 25 | |
Simon Glass | e287b67 | 2023-02-22 09:33:49 -0700 | [diff] [blame] | 26 | #if IS_ENABLED(CONFIG_MULTIPLEXER) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 27 | /** |
| 28 | * mux_control_states() - Query the number of multiplexer states. |
| 29 | * @mux: The mux-control to query. |
| 30 | * |
| 31 | * Return: The number of multiplexer states. |
| 32 | */ |
| 33 | unsigned int mux_control_states(struct mux_control *mux); |
| 34 | |
| 35 | /** |
| 36 | * mux_control_select() - Select the given multiplexer state. |
| 37 | * @mux: The mux-control to request a change of state from. |
| 38 | * @state: The new requested state. |
| 39 | * |
| 40 | * On successfully selecting the mux-control state, it will be locked until |
| 41 | * there is a call to mux_control_deselect(). If the mux-control is already |
| 42 | * selected when mux_control_select() is called, the function will indicate |
| 43 | * -EBUSY |
| 44 | * |
| 45 | * Therefore, make sure to call mux_control_deselect() when the operation is |
| 46 | * complete and the mux-control is free for others to use, but do not call |
| 47 | * mux_control_deselect() if mux_control_select() fails. |
| 48 | * |
| 49 | * Return: 0 when the mux-control state has the requested state or a negative |
| 50 | * errno on error. |
| 51 | */ |
| 52 | int __must_check mux_control_select(struct mux_control *mux, |
| 53 | unsigned int state); |
Patrick Wildt | 5d073ca | 2021-07-13 23:02:18 +0200 | [diff] [blame] | 54 | #define mux_control_try_select(mux, state) mux_control_select(mux, state) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 55 | |
| 56 | /** |
| 57 | * mux_control_deselect() - Deselect the previously selected multiplexer state. |
| 58 | * @mux: The mux-control to deselect. |
| 59 | * |
| 60 | * It is required that a single call is made to mux_control_deselect() for |
| 61 | * each and every successful call made to either of mux_control_select() or |
| 62 | * mux_control_try_select(). |
| 63 | * |
| 64 | * Return: 0 on success and a negative errno on error. An error can only |
| 65 | * occur if the mux has an idle state. Note that even if an error occurs, the |
| 66 | * mux-control is unlocked and is thus free for the next access. |
| 67 | */ |
| 68 | int mux_control_deselect(struct mux_control *mux); |
| 69 | |
| 70 | /** |
| 71 | * mux_get_by_index() = Get a mux by integer index. |
| 72 | * @dev: The client device. |
| 73 | * @index: The index of the mux to get. |
| 74 | * @mux: A pointer to the 'mux_control' struct to initialize. |
| 75 | * |
| 76 | * This looks up and initializes a mux. The index is relative to the client |
| 77 | * device. |
| 78 | * |
| 79 | * Return: 0 if OK, or a negative error code. |
| 80 | */ |
| 81 | int mux_get_by_index(struct udevice *dev, int index, struct mux_control **mux); |
| 82 | |
| 83 | /** |
| 84 | * mux_control_get() - Get the mux-control for a device. |
| 85 | * @dev: The device that needs a mux-control. |
| 86 | * @mux_name: The name identifying the mux-control. |
| 87 | * @mux: A pointer to the mux-control pointer. |
| 88 | * |
| 89 | * Return: 0 of OK, or a negative error code. |
| 90 | */ |
| 91 | int mux_control_get(struct udevice *dev, const char *name, |
| 92 | struct mux_control **mux); |
| 93 | |
| 94 | /** |
| 95 | * mux_control_put() - Put away the mux-control for good. |
| 96 | * @mux: The mux-control to put away. |
| 97 | * |
| 98 | * mux_control_put() reverses the effects of mux_control_get(). |
| 99 | */ |
| 100 | void mux_control_put(struct mux_control *mux); |
| 101 | |
| 102 | /** |
| 103 | * devm_mux_control_get() - Get the mux-control for a device, with resource |
| 104 | * management. |
| 105 | * @dev: The device that needs a mux-control. |
| 106 | * @mux_name: The name identifying the mux-control. |
| 107 | * |
| 108 | * Return: Pointer to the mux-control, or an ERR_PTR with a negative errno. |
| 109 | */ |
| 110 | struct mux_control *devm_mux_control_get(struct udevice *dev, |
| 111 | const char *mux_name); |
Jean-Jacques Hiblot | 0c1b557 | 2020-10-16 16:16:31 +0530 | [diff] [blame] | 112 | /** |
| 113 | * dm_mux_init() - Initialize the multiplexer controls to their default state. |
| 114 | * |
| 115 | * Return: 0 if OK, -errno otherwise. |
| 116 | */ |
| 117 | int dm_mux_init(void); |
| 118 | |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 119 | #else |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 120 | static inline unsigned int mux_control_states(struct mux_control *mux) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 121 | { |
| 122 | return -ENOSYS; |
| 123 | } |
| 124 | |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 125 | static inline int __must_check mux_control_select(struct mux_control *mux, |
| 126 | unsigned int state) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 127 | { |
| 128 | return -ENOSYS; |
| 129 | } |
| 130 | |
Patrick Wildt | 5d073ca | 2021-07-13 23:02:18 +0200 | [diff] [blame] | 131 | #define mux_control_try_select(mux, state) mux_control_select(mux, state) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 132 | |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 133 | static inline int mux_control_deselect(struct mux_control *mux) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 134 | { |
| 135 | return -ENOSYS; |
| 136 | } |
| 137 | |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 138 | static inline struct mux_control *mux_control_get(struct udevice *dev, const char *mux_name) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 139 | { |
| 140 | return NULL; |
| 141 | } |
| 142 | |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 143 | static inline void mux_control_put(struct mux_control *mux) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 144 | { |
| 145 | } |
| 146 | |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 147 | static inline struct mux_control *devm_mux_control_get(struct udevice *dev, |
| 148 | const char *mux_name) |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 149 | { |
| 150 | return NULL; |
| 151 | } |
Jean-Jacques Hiblot | 0c1b557 | 2020-10-16 16:16:31 +0530 | [diff] [blame] | 152 | |
Andy Shevchenko | f284eb0 | 2024-10-21 17:20:45 +0300 | [diff] [blame] | 153 | static inline int dm_mux_init(void) |
Jean-Jacques Hiblot | 0c1b557 | 2020-10-16 16:16:31 +0530 | [diff] [blame] | 154 | { |
| 155 | return -ENOSYS; |
| 156 | } |
Jean-Jacques Hiblot | f4f9056 | 2020-10-16 16:16:30 +0530 | [diff] [blame] | 157 | #endif |
| 158 | |
| 159 | #endif |