Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / platform / cznic / turris-omnia-mcu.h
blob2b13e28ee323b3058d9f2b603e3f6084a4413333
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * CZ.NIC's Turris Omnia MCU driver
5 * 2024 by Marek BehĂșn <kabel@kernel.org>
6 */
8 #ifndef __TURRIS_OMNIA_MCU_H
9 #define __TURRIS_OMNIA_MCU_H
11 #include <linux/bitops.h>
12 #include <linux/completion.h>
13 #include <linux/gpio/driver.h>
14 #include <linux/hw_random.h>
15 #include <linux/if_ether.h>
16 #include <linux/mutex.h>
17 #include <linux/types.h>
18 #include <linux/watchdog.h>
19 #include <linux/workqueue.h>
20 #include <asm/byteorder.h>
21 #include <linux/unaligned.h>
23 struct i2c_client;
24 struct rtc_device;
26 /**
27 * struct omnia_mcu - driver private data structure
28 * @client: I2C client
29 * @type: MCU type (STM32, GD32, MKL, or unknown)
30 * @features: bitmap of features supported by the MCU firmware
31 * @board_serial_number: board serial number, if stored in MCU
32 * @board_first_mac: board first MAC address, if stored in MCU
33 * @board_revision: board revision, if stored in MCU
34 * @gc: GPIO chip
35 * @lock: mutex to protect internal GPIO chip state
36 * @mask: bitmap of masked IRQs
37 * @rising: bitmap of rising edge IRQs
38 * @falling: bitmap of falling edge IRQs
39 * @both: bitmap of both edges IRQs
40 * @cached: bitmap of cached IRQ line values (when an IRQ line is configured for
41 * both edges, we cache the corresponding GPIO values in the IRQ
42 * handler)
43 * @is_cached: bitmap of which IRQ line values are cached
44 * @button_release_emul_work: front button release emulation work, used with old MCU firmware
45 * versions which did not send button release events, only button press
46 * events
47 * @last_status: cached value of the status word, to be compared with new value to
48 * determine which interrupt events occurred, used with old MCU
49 * firmware versions which only informed that the status word changed,
50 * but not which bits of the status word changed
51 * @button_pressed_emul: the front button is still emulated to be pressed
52 * @rtcdev: RTC device, does not actually count real-time, the device is only
53 * used for the RTC alarm mechanism, so that the board can be
54 * configured to wake up from poweroff state at a specific time
55 * @rtc_alarm: RTC alarm that was set for the board to wake up on, in MCU time
56 * (seconds since last MCU reset)
57 * @front_button_poweron: the front button should power on the device after it is powered off
58 * @wdt: watchdog driver structure
59 * @trng: RNG driver structure
60 * @trng_entropy_ready: RNG entropy ready completion
62 struct omnia_mcu {
63 struct i2c_client *client;
64 const char *type;
65 u32 features;
67 u64 board_serial_number;
68 u8 board_first_mac[ETH_ALEN];
69 u8 board_revision;
71 #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
72 struct gpio_chip gc;
73 struct mutex lock;
74 unsigned long mask, rising, falling, both, cached, is_cached;
75 struct delayed_work button_release_emul_work;
76 unsigned long last_status;
77 bool button_pressed_emul;
78 #endif
80 #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
81 struct rtc_device *rtcdev;
82 u32 rtc_alarm;
83 bool front_button_poweron;
84 #endif
86 #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
87 struct watchdog_device wdt;
88 #endif
90 #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
91 struct hwrng trng;
92 struct completion trng_entropy_ready;
93 #endif
96 int omnia_cmd_write_read(const struct i2c_client *client,
97 void *cmd, unsigned int cmd_len,
98 void *reply, unsigned int reply_len);
100 static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
101 unsigned int len)
103 return omnia_cmd_write_read(client, cmd, len, NULL, 0);
106 static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,
107 u8 val)
109 u8 buf[2] = { cmd, val };
111 return omnia_cmd_write(client, buf, sizeof(buf));
114 static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,
115 u16 val)
117 u8 buf[3];
119 buf[0] = cmd;
120 put_unaligned_le16(val, &buf[1]);
122 return omnia_cmd_write(client, buf, sizeof(buf));
125 static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
126 u32 val)
128 u8 buf[5];
130 buf[0] = cmd;
131 put_unaligned_le32(val, &buf[1]);
133 return omnia_cmd_write(client, buf, sizeof(buf));
136 static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
137 void *reply, unsigned int len)
139 return omnia_cmd_write_read(client, &cmd, 1, reply, len);
142 static inline unsigned int
143 omnia_compute_reply_length(unsigned long mask, bool interleaved,
144 unsigned int offset)
146 if (!mask)
147 return 0;
149 return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
152 /* Returns 0 on success */
153 static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,
154 unsigned long bits, unsigned long *dst)
156 __le32 reply;
157 int err;
159 if (!bits) {
160 *dst = 0;
161 return 0;
164 err = omnia_cmd_read(client, cmd, &reply,
165 omnia_compute_reply_length(bits, false, 0));
166 if (err)
167 return err;
169 *dst = le32_to_cpu(reply) & bits;
171 return 0;
174 static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,
175 unsigned long bit)
177 unsigned long reply;
178 int err;
180 err = omnia_cmd_read_bits(client, cmd, bit, &reply);
181 if (err)
182 return err;
184 return !!reply;
187 static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
188 u32 *dst)
190 __le32 reply;
191 int err;
193 err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
194 if (err)
195 return err;
197 *dst = le32_to_cpu(reply);
199 return 0;
202 static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,
203 u16 *dst)
205 __le16 reply;
206 int err;
208 err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
209 if (err)
210 return err;
212 *dst = le16_to_cpu(reply);
214 return 0;
217 static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
218 u8 *reply)
220 return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
223 #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
224 extern const u8 omnia_int_to_gpio_idx[32];
225 extern const struct attribute_group omnia_mcu_gpio_group;
226 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
227 #else
228 static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
230 return 0;
232 #endif
234 #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
235 extern const struct attribute_group omnia_mcu_poweroff_group;
236 int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
237 #else
238 static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)
240 return 0;
242 #endif
244 #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
245 int omnia_mcu_register_trng(struct omnia_mcu *mcu);
246 #else
247 static inline int omnia_mcu_register_trng(struct omnia_mcu *mcu)
249 return 0;
251 #endif
253 #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
254 int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
255 #else
256 static inline int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)
258 return 0;
260 #endif
262 #endif /* __TURRIS_OMNIA_MCU_H */