| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /*
- * CZ.NIC's Turris Omnia MCU driver
- *
- * 2024 by Marek Behún <kabel@kernel.org>
- */
- #ifndef __TURRIS_OMNIA_MCU_H
- #define __TURRIS_OMNIA_MCU_H
- #include <linux/bitops.h>
- #include <linux/completion.h>
- #include <linux/gpio/driver.h>
- #include <linux/hw_random.h>
- #include <linux/if_ether.h>
- #include <linux/mutex.h>
- #include <linux/types.h>
- #include <linux/watchdog.h>
- #include <linux/workqueue.h>
- #include <asm/byteorder.h>
- #include <linux/unaligned.h>
- struct i2c_client;
- struct rtc_device;
- struct omnia_mcu {
- struct i2c_client *client;
- const char *type;
- u32 features;
- /* board information */
- u64 board_serial_number;
- u8 board_first_mac[ETH_ALEN];
- u8 board_revision;
- #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
- /* GPIO chip */
- struct gpio_chip gc;
- struct mutex lock;
- unsigned long mask, rising, falling, both, cached, is_cached;
- /* Old MCU firmware handling needs the following */
- struct delayed_work button_release_emul_work;
- unsigned long last_status;
- bool button_pressed_emul;
- #endif
- #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
- /* RTC device for configuring wake-up */
- struct rtc_device *rtcdev;
- u32 rtc_alarm;
- bool front_button_poweron;
- #endif
- #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
- /* MCU watchdog */
- struct watchdog_device wdt;
- #endif
- #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
- /* true random number generator */
- struct hwrng trng;
- struct completion trng_entropy_ready;
- #endif
- };
- int omnia_cmd_write_read(const struct i2c_client *client,
- void *cmd, unsigned int cmd_len,
- void *reply, unsigned int reply_len);
- static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
- unsigned int len)
- {
- return omnia_cmd_write_read(client, cmd, len, NULL, 0);
- }
- static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,
- u8 val)
- {
- u8 buf[2] = { cmd, val };
- return omnia_cmd_write(client, buf, sizeof(buf));
- }
- static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,
- u16 val)
- {
- u8 buf[3];
- buf[0] = cmd;
- put_unaligned_le16(val, &buf[1]);
- return omnia_cmd_write(client, buf, sizeof(buf));
- }
- static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
- u32 val)
- {
- u8 buf[5];
- buf[0] = cmd;
- put_unaligned_le32(val, &buf[1]);
- return omnia_cmd_write(client, buf, sizeof(buf));
- }
- static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
- void *reply, unsigned int len)
- {
- return omnia_cmd_write_read(client, &cmd, 1, reply, len);
- }
- static inline unsigned int
- omnia_compute_reply_length(unsigned long mask, bool interleaved,
- unsigned int offset)
- {
- if (!mask)
- return 0;
- return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
- }
- /* Returns 0 on success */
- static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,
- unsigned long bits, unsigned long *dst)
- {
- __le32 reply;
- int err;
- if (!bits) {
- *dst = 0;
- return 0;
- }
- err = omnia_cmd_read(client, cmd, &reply,
- omnia_compute_reply_length(bits, false, 0));
- if (err)
- return err;
- *dst = le32_to_cpu(reply) & bits;
- return 0;
- }
- static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,
- unsigned long bit)
- {
- unsigned long reply;
- int err;
- err = omnia_cmd_read_bits(client, cmd, bit, &reply);
- if (err)
- return err;
- return !!reply;
- }
- static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
- u32 *dst)
- {
- __le32 reply;
- int err;
- err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
- if (err)
- return err;
- *dst = le32_to_cpu(reply);
- return 0;
- }
- static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,
- u16 *dst)
- {
- __le16 reply;
- int err;
- err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
- if (err)
- return err;
- *dst = le16_to_cpu(reply);
- return 0;
- }
- static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
- u8 *reply)
- {
- return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
- }
- #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
- extern const u8 omnia_int_to_gpio_idx[32];
- extern const struct attribute_group omnia_mcu_gpio_group;
- int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
- #else
- static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
- {
- return 0;
- }
- #endif
- #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
- extern const struct attribute_group omnia_mcu_poweroff_group;
- int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
- #else
- static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)
- {
- return 0;
- }
- #endif
- #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
- int omnia_mcu_register_trng(struct omnia_mcu *mcu);
- #else
- static inline int omnia_mcu_register_trng(struct omnia_mcu *mcu)
- {
- return 0;
- }
- #endif
- #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
- int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
- #else
- static inline int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)
- {
- return 0;
- }
- #endif
- #endif /* __TURRIS_OMNIA_MCU_H */
|