1 /* SPDX-License-Identifier: GPL-2.0 */
3 * CZ.NIC's Turris Omnia MCU driver
5 * 2024 by Marek BehĂșn <kabel@kernel.org>
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>
27 * struct omnia_mcu - driver private data structure
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
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
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
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
63 struct i2c_client
*client
;
67 u64 board_serial_number
;
68 u8 board_first_mac
[ETH_ALEN
];
71 #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
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
;
80 #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
81 struct rtc_device
*rtcdev
;
83 bool front_button_poweron
;
86 #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
87 struct watchdog_device wdt
;
90 #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
92 struct completion trng_entropy_ready
;
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
,
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
,
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
,
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
,
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
,
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
)
164 err
= omnia_cmd_read(client
, cmd
, &reply
,
165 omnia_compute_reply_length(bits
, false, 0));
169 *dst
= le32_to_cpu(reply
) & bits
;
174 static inline int omnia_cmd_read_bit(const struct i2c_client
*client
, u8 cmd
,
180 err
= omnia_cmd_read_bits(client
, cmd
, bit
, &reply
);
187 static inline int omnia_cmd_read_u32(const struct i2c_client
*client
, u8 cmd
,
193 err
= omnia_cmd_read(client
, cmd
, &reply
, sizeof(reply
));
197 *dst
= le32_to_cpu(reply
);
202 static inline int omnia_cmd_read_u16(const struct i2c_client
*client
, u8 cmd
,
208 err
= omnia_cmd_read(client
, cmd
, &reply
, sizeof(reply
));
212 *dst
= le16_to_cpu(reply
);
217 static inline int omnia_cmd_read_u8(const struct i2c_client
*client
, u8 cmd
,
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
);
228 static inline int omnia_mcu_register_gpiochip(struct omnia_mcu
*mcu
)
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
);
238 static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu
*mcu
)
244 #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
245 int omnia_mcu_register_trng(struct omnia_mcu
*mcu
);
247 static inline int omnia_mcu_register_trng(struct omnia_mcu
*mcu
)
253 #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
254 int omnia_mcu_register_watchdog(struct omnia_mcu
*mcu
);
256 static inline int omnia_mcu_register_watchdog(struct omnia_mcu
*mcu
)
262 #endif /* __TURRIS_OMNIA_MCU_H */