1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * CZ.NIC's Turris Omnia MCU driver
4  *
5  * 2024 by Marek Behún <[email protected]>
6  */
7 
8 #ifndef __TURRIS_OMNIA_MCU_H
9 #define __TURRIS_OMNIA_MCU_H
10 
11 #include <linux/completion.h>
12 #include <linux/gpio/driver.h>
13 #include <linux/hw_random.h>
14 #include <linux/if_ether.h>
15 #include <linux/mutex.h>
16 #include <linux/types.h>
17 #include <linux/watchdog.h>
18 #include <linux/workqueue.h>
19 
20 struct i2c_client;
21 struct rtc_device;
22 
23 /**
24  * struct omnia_mcu - driver private data structure
25  * @client:			I2C client
26  * @type:			MCU type (STM32, GD32, MKL, or unknown)
27  * @features:			bitmap of features supported by the MCU firmware
28  * @board_serial_number:	board serial number, if stored in MCU
29  * @board_first_mac:		board first MAC address, if stored in MCU
30  * @board_revision:		board revision, if stored in MCU
31  * @gc:				GPIO chip
32  * @lock:			mutex to protect internal GPIO chip state
33  * @mask:			bitmap of masked IRQs
34  * @rising:			bitmap of rising edge IRQs
35  * @falling:			bitmap of falling edge IRQs
36  * @both:			bitmap of both edges IRQs
37  * @cached:			bitmap of cached IRQ line values (when an IRQ line is configured for
38  *				both edges, we cache the corresponding GPIO values in the IRQ
39  *				handler)
40  * @is_cached:			bitmap of which IRQ line values are cached
41  * @button_release_emul_work:	front button release emulation work, used with old MCU firmware
42  *				versions which did not send button release events, only button press
43  *				events
44  * @last_status:		cached value of the status word, to be compared with new value to
45  *				determine which interrupt events occurred, used with old MCU
46  *				firmware versions which only informed that the status word changed,
47  *				but not which bits of the status word changed
48  * @button_pressed_emul:	the front button is still emulated to be pressed
49  * @rtcdev:			RTC device, does not actually count real-time, the device is only
50  *				used for the RTC alarm mechanism, so that the board can be
51  *				configured to wake up from poweroff state at a specific time
52  * @rtc_alarm:			RTC alarm that was set for the board to wake up on, in MCU time
53  *				(seconds since last MCU reset)
54  * @front_button_poweron:	the front button should power on the device after it is powered off
55  * @wdt:			watchdog driver structure
56  * @trng:			RNG driver structure
57  * @trng_entropy_ready:		RNG entropy ready completion
58  */
59 struct omnia_mcu {
60 	struct i2c_client *client;
61 	const char *type;
62 	u32 features;
63 
64 	u64 board_serial_number;
65 	u8 board_first_mac[ETH_ALEN];
66 	u8 board_revision;
67 
68 #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
69 	struct gpio_chip gc;
70 	struct mutex lock;
71 	unsigned long mask, rising, falling, both, cached, is_cached;
72 	struct delayed_work button_release_emul_work;
73 	unsigned long last_status;
74 	bool button_pressed_emul;
75 #endif
76 
77 #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
78 	struct rtc_device *rtcdev;
79 	u32 rtc_alarm;
80 	bool front_button_poweron;
81 #endif
82 
83 #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
84 	struct watchdog_device wdt;
85 #endif
86 
87 #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
88 	struct hwrng trng;
89 	struct completion trng_entropy_ready;
90 #endif
91 };
92 
93 #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
94 extern const u8 omnia_int_to_gpio_idx[32];
95 extern const struct attribute_group omnia_mcu_gpio_group;
96 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
97 #else
omnia_mcu_register_gpiochip(struct omnia_mcu * mcu)98 static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
99 {
100 	return 0;
101 }
102 #endif
103 
104 #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
105 extern const struct attribute_group omnia_mcu_poweroff_group;
106 int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
107 #else
omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu * mcu)108 static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)
109 {
110 	return 0;
111 }
112 #endif
113 
114 #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
115 int omnia_mcu_register_trng(struct omnia_mcu *mcu);
116 #else
omnia_mcu_register_trng(struct omnia_mcu * mcu)117 static inline int omnia_mcu_register_trng(struct omnia_mcu *mcu)
118 {
119 	return 0;
120 }
121 #endif
122 
123 #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
124 int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
125 #else
omnia_mcu_register_watchdog(struct omnia_mcu * mcu)126 static inline int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)
127 {
128 	return 0;
129 }
130 #endif
131 
132 #endif /* __TURRIS_OMNIA_MCU_H */
133