turris-omnia-mcu.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * CZ.NIC's Turris Omnia MCU driver
  4. *
  5. * 2024 by Marek Behún <kabel@kernel.org>
  6. */
  7. #ifndef __TURRIS_OMNIA_MCU_H
  8. #define __TURRIS_OMNIA_MCU_H
  9. #include <linux/bitops.h>
  10. #include <linux/completion.h>
  11. #include <linux/gpio/driver.h>
  12. #include <linux/hw_random.h>
  13. #include <linux/if_ether.h>
  14. #include <linux/mutex.h>
  15. #include <linux/types.h>
  16. #include <linux/watchdog.h>
  17. #include <linux/workqueue.h>
  18. #include <asm/byteorder.h>
  19. #include <linux/unaligned.h>
  20. struct i2c_client;
  21. struct rtc_device;
  22. struct omnia_mcu {
  23. struct i2c_client *client;
  24. const char *type;
  25. u32 features;
  26. /* board information */
  27. u64 board_serial_number;
  28. u8 board_first_mac[ETH_ALEN];
  29. u8 board_revision;
  30. #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
  31. /* GPIO chip */
  32. struct gpio_chip gc;
  33. struct mutex lock;
  34. unsigned long mask, rising, falling, both, cached, is_cached;
  35. /* Old MCU firmware handling needs the following */
  36. struct delayed_work button_release_emul_work;
  37. unsigned long last_status;
  38. bool button_pressed_emul;
  39. #endif
  40. #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
  41. /* RTC device for configuring wake-up */
  42. struct rtc_device *rtcdev;
  43. u32 rtc_alarm;
  44. bool front_button_poweron;
  45. #endif
  46. #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
  47. /* MCU watchdog */
  48. struct watchdog_device wdt;
  49. #endif
  50. #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
  51. /* true random number generator */
  52. struct hwrng trng;
  53. struct completion trng_entropy_ready;
  54. #endif
  55. };
  56. int omnia_cmd_write_read(const struct i2c_client *client,
  57. void *cmd, unsigned int cmd_len,
  58. void *reply, unsigned int reply_len);
  59. static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
  60. unsigned int len)
  61. {
  62. return omnia_cmd_write_read(client, cmd, len, NULL, 0);
  63. }
  64. static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,
  65. u8 val)
  66. {
  67. u8 buf[2] = { cmd, val };
  68. return omnia_cmd_write(client, buf, sizeof(buf));
  69. }
  70. static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,
  71. u16 val)
  72. {
  73. u8 buf[3];
  74. buf[0] = cmd;
  75. put_unaligned_le16(val, &buf[1]);
  76. return omnia_cmd_write(client, buf, sizeof(buf));
  77. }
  78. static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
  79. u32 val)
  80. {
  81. u8 buf[5];
  82. buf[0] = cmd;
  83. put_unaligned_le32(val, &buf[1]);
  84. return omnia_cmd_write(client, buf, sizeof(buf));
  85. }
  86. static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
  87. void *reply, unsigned int len)
  88. {
  89. return omnia_cmd_write_read(client, &cmd, 1, reply, len);
  90. }
  91. static inline unsigned int
  92. omnia_compute_reply_length(unsigned long mask, bool interleaved,
  93. unsigned int offset)
  94. {
  95. if (!mask)
  96. return 0;
  97. return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
  98. }
  99. /* Returns 0 on success */
  100. static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,
  101. unsigned long bits, unsigned long *dst)
  102. {
  103. __le32 reply;
  104. int err;
  105. if (!bits) {
  106. *dst = 0;
  107. return 0;
  108. }
  109. err = omnia_cmd_read(client, cmd, &reply,
  110. omnia_compute_reply_length(bits, false, 0));
  111. if (err)
  112. return err;
  113. *dst = le32_to_cpu(reply) & bits;
  114. return 0;
  115. }
  116. static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,
  117. unsigned long bit)
  118. {
  119. unsigned long reply;
  120. int err;
  121. err = omnia_cmd_read_bits(client, cmd, bit, &reply);
  122. if (err)
  123. return err;
  124. return !!reply;
  125. }
  126. static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
  127. u32 *dst)
  128. {
  129. __le32 reply;
  130. int err;
  131. err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
  132. if (err)
  133. return err;
  134. *dst = le32_to_cpu(reply);
  135. return 0;
  136. }
  137. static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,
  138. u16 *dst)
  139. {
  140. __le16 reply;
  141. int err;
  142. err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
  143. if (err)
  144. return err;
  145. *dst = le16_to_cpu(reply);
  146. return 0;
  147. }
  148. static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
  149. u8 *reply)
  150. {
  151. return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
  152. }
  153. #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
  154. extern const u8 omnia_int_to_gpio_idx[32];
  155. extern const struct attribute_group omnia_mcu_gpio_group;
  156. int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
  157. #else
  158. static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
  159. {
  160. return 0;
  161. }
  162. #endif
  163. #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
  164. extern const struct attribute_group omnia_mcu_poweroff_group;
  165. int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
  166. #else
  167. static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)
  168. {
  169. return 0;
  170. }
  171. #endif
  172. #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
  173. int omnia_mcu_register_trng(struct omnia_mcu *mcu);
  174. #else
  175. static inline int omnia_mcu_register_trng(struct omnia_mcu *mcu)
  176. {
  177. return 0;
  178. }
  179. #endif
  180. #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
  181. int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
  182. #else
  183. static inline int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)
  184. {
  185. return 0;
  186. }
  187. #endif
  188. #endif /* __TURRIS_OMNIA_MCU_H */