1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * CZ.NIC's Turris Omnia MCU I2C interface commands definitions
4 *
5 * 2024 by Marek Behún <[email protected]>
6 */
7
8 #ifndef __TURRIS_OMNIA_MCU_INTERFACE_H
9 #define __TURRIS_OMNIA_MCU_INTERFACE_H
10
11 #include <linux/bitfield.h>
12 #include <linux/bitops.h>
13 #include <linux/types.h>
14 #include <linux/unaligned.h>
15 #include <asm/byteorder.h>
16
17 enum omnia_commands_e {
18 OMNIA_CMD_GET_STATUS_WORD = 0x01, /* slave sends status word back */
19 OMNIA_CMD_GENERAL_CONTROL = 0x02,
20 OMNIA_CMD_LED_MODE = 0x03, /* default/user */
21 OMNIA_CMD_LED_STATE = 0x04, /* LED on/off */
22 OMNIA_CMD_LED_COLOR = 0x05, /* LED number + RED + GREEN + BLUE */
23 OMNIA_CMD_USER_VOLTAGE = 0x06,
24 OMNIA_CMD_SET_BRIGHTNESS = 0x07,
25 OMNIA_CMD_GET_BRIGHTNESS = 0x08,
26 OMNIA_CMD_GET_RESET = 0x09,
27 OMNIA_CMD_GET_FW_VERSION_APP = 0x0A, /* 20B git hash number */
28 OMNIA_CMD_SET_WATCHDOG_STATE = 0x0B, /* 0 - disable
29 * 1 - enable / ping
30 * after boot watchdog is started
31 * with 2 minutes timeout
32 */
33
34 /* OMNIA_CMD_WATCHDOG_STATUS = 0x0C, not implemented anymore */
35
36 OMNIA_CMD_GET_WATCHDOG_STATE = 0x0D,
37 OMNIA_CMD_GET_FW_VERSION_BOOT = 0x0E, /* 20B Git hash number */
38 OMNIA_CMD_GET_FW_CHECKSUM = 0x0F, /* 4B length, 4B checksum */
39
40 /* available if FEATURES_SUPPORTED bit set in status word */
41 OMNIA_CMD_GET_FEATURES = 0x10,
42
43 /* available if EXT_CMD bit set in features */
44 OMNIA_CMD_GET_EXT_STATUS_DWORD = 0x11,
45 OMNIA_CMD_EXT_CONTROL = 0x12,
46 OMNIA_CMD_GET_EXT_CONTROL_STATUS = 0x13,
47
48 /* available if NEW_INT_API bit set in features */
49 OMNIA_CMD_GET_INT_AND_CLEAR = 0x14,
50 OMNIA_CMD_GET_INT_MASK = 0x15,
51 OMNIA_CMD_SET_INT_MASK = 0x16,
52
53 /* available if FLASHING bit set in features */
54 OMNIA_CMD_FLASH = 0x19,
55
56 /* available if WDT_PING bit set in features */
57 OMNIA_CMD_SET_WDT_TIMEOUT = 0x20,
58 OMNIA_CMD_GET_WDT_TIMELEFT = 0x21,
59
60 /* available if POWEROFF_WAKEUP bit set in features */
61 OMNIA_CMD_SET_WAKEUP = 0x22,
62 OMNIA_CMD_GET_UPTIME_AND_WAKEUP = 0x23,
63 OMNIA_CMD_POWER_OFF = 0x24,
64
65 /* available if USB_OVC_PROT_SETTING bit set in features */
66 OMNIA_CMD_SET_USB_OVC_PROT = 0x25,
67 OMNIA_CMD_GET_USB_OVC_PROT = 0x26,
68
69 /* available if TRNG bit set in features */
70 OMNIA_CMD_TRNG_COLLECT_ENTROPY = 0x28,
71
72 /* available if CRYPTO bit set in features */
73 OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY = 0x29,
74 OMNIA_CMD_CRYPTO_SIGN_MESSAGE = 0x2A,
75 OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE = 0x2B,
76
77 /* available if BOARD_INFO it set in features */
78 OMNIA_CMD_BOARD_INFO_GET = 0x2C,
79 OMNIA_CMD_BOARD_INFO_BURN = 0x2D,
80
81 /* available only at address 0x2b (LED-controller) */
82 /* available only if LED_GAMMA_CORRECTION bit set in features */
83 OMNIA_CMD_SET_GAMMA_CORRECTION = 0x30,
84 OMNIA_CMD_GET_GAMMA_CORRECTION = 0x31,
85
86 /* available only at address 0x2b (LED-controller) */
87 /* available only if PER_LED_CORRECTION bit set in features */
88 /* available only if FROM_BIT_16_INVALID bit NOT set in features */
89 OMNIA_CMD_SET_LED_CORRECTIONS = 0x32,
90 OMNIA_CMD_GET_LED_CORRECTIONS = 0x33,
91 };
92
93 enum omnia_flashing_commands_e {
94 OMNIA_FLASH_CMD_UNLOCK = 0x01,
95 OMNIA_FLASH_CMD_SIZE_AND_CSUM = 0x02,
96 OMNIA_FLASH_CMD_PROGRAM = 0x03,
97 OMNIA_FLASH_CMD_RESET = 0x04,
98 };
99
100 enum omnia_sts_word_e {
101 OMNIA_STS_MCU_TYPE_MASK = GENMASK(1, 0),
102 OMNIA_STS_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 0),
103 OMNIA_STS_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 1),
104 OMNIA_STS_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 2),
105 OMNIA_STS_FEATURES_SUPPORTED = BIT(2),
106 OMNIA_STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3),
107 OMNIA_STS_CARD_DET = BIT(4),
108 OMNIA_STS_MSATA_IND = BIT(5),
109 OMNIA_STS_USB30_OVC = BIT(6),
110 OMNIA_STS_USB31_OVC = BIT(7),
111 OMNIA_STS_USB30_PWRON = BIT(8),
112 OMNIA_STS_USB31_PWRON = BIT(9),
113 OMNIA_STS_ENABLE_4V5 = BIT(10),
114 OMNIA_STS_BUTTON_MODE = BIT(11),
115 OMNIA_STS_BUTTON_PRESSED = BIT(12),
116 OMNIA_STS_BUTTON_COUNTER_MASK = GENMASK(15, 13),
117 };
118
119 enum omnia_ctl_byte_e {
120 OMNIA_CTL_LIGHT_RST = BIT(0),
121 OMNIA_CTL_HARD_RST = BIT(1),
122 /* BIT(2) is currently reserved */
123 OMNIA_CTL_USB30_PWRON = BIT(3),
124 OMNIA_CTL_USB31_PWRON = BIT(4),
125 OMNIA_CTL_ENABLE_4V5 = BIT(5),
126 OMNIA_CTL_BUTTON_MODE = BIT(6),
127 OMNIA_CTL_BOOTLOADER = BIT(7),
128 };
129
130 enum omnia_features_e {
131 OMNIA_FEAT_PERIPH_MCU = BIT(0),
132 OMNIA_FEAT_EXT_CMDS = BIT(1),
133 OMNIA_FEAT_WDT_PING = BIT(2),
134 OMNIA_FEAT_LED_STATE_EXT_MASK = GENMASK(4, 3),
135 OMNIA_FEAT_LED_STATE_EXT = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 1),
136 OMNIA_FEAT_LED_STATE_EXT_V32 = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 2),
137 OMNIA_FEAT_LED_GAMMA_CORRECTION = BIT(5),
138 OMNIA_FEAT_NEW_INT_API = BIT(6),
139 OMNIA_FEAT_BOOTLOADER = BIT(7),
140 OMNIA_FEAT_FLASHING = BIT(8),
141 OMNIA_FEAT_NEW_MESSAGE_API = BIT(9),
142 OMNIA_FEAT_BRIGHTNESS_INT = BIT(10),
143 OMNIA_FEAT_POWEROFF_WAKEUP = BIT(11),
144 OMNIA_FEAT_CAN_OLD_MESSAGE_API = BIT(12),
145 OMNIA_FEAT_TRNG = BIT(13),
146 OMNIA_FEAT_CRYPTO = BIT(14),
147 OMNIA_FEAT_BOARD_INFO = BIT(15),
148
149 /*
150 * Orginally the features command replied only 16 bits. If more were
151 * read, either the I2C transaction failed or 0xff bytes were sent.
152 * Therefore to consider bits 16 - 31 valid, one bit (20) was reserved
153 * to be zero.
154 */
155
156 /* Bits 16 - 19 correspond to bits 0 - 3 of status word */
157 OMNIA_FEAT_MCU_TYPE_MASK = GENMASK(17, 16),
158 OMNIA_FEAT_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 0),
159 OMNIA_FEAT_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 1),
160 OMNIA_FEAT_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 2),
161 OMNIA_FEAT_FEATURES_SUPPORTED = BIT(18),
162 OMNIA_FEAT_USER_REGULATOR_NOT_SUPPORTED = BIT(19),
163
164 /* must not be set */
165 OMNIA_FEAT_FROM_BIT_16_INVALID = BIT(20),
166
167 OMNIA_FEAT_PER_LED_CORRECTION = BIT(21),
168 OMNIA_FEAT_USB_OVC_PROT_SETTING = BIT(22),
169 };
170
171 enum omnia_ext_sts_dword_e {
172 OMNIA_EXT_STS_SFP_nDET = BIT(0),
173 OMNIA_EXT_STS_LED_STATES_MASK = GENMASK(31, 12),
174 OMNIA_EXT_STS_WLAN0_MSATA_LED = BIT(12),
175 OMNIA_EXT_STS_WLAN1_LED = BIT(13),
176 OMNIA_EXT_STS_WLAN2_LED = BIT(14),
177 OMNIA_EXT_STS_WPAN0_LED = BIT(15),
178 OMNIA_EXT_STS_WPAN1_LED = BIT(16),
179 OMNIA_EXT_STS_WPAN2_LED = BIT(17),
180 OMNIA_EXT_STS_WAN_LED0 = BIT(18),
181 OMNIA_EXT_STS_WAN_LED1 = BIT(19),
182 OMNIA_EXT_STS_LAN0_LED0 = BIT(20),
183 OMNIA_EXT_STS_LAN0_LED1 = BIT(21),
184 OMNIA_EXT_STS_LAN1_LED0 = BIT(22),
185 OMNIA_EXT_STS_LAN1_LED1 = BIT(23),
186 OMNIA_EXT_STS_LAN2_LED0 = BIT(24),
187 OMNIA_EXT_STS_LAN2_LED1 = BIT(25),
188 OMNIA_EXT_STS_LAN3_LED0 = BIT(26),
189 OMNIA_EXT_STS_LAN3_LED1 = BIT(27),
190 OMNIA_EXT_STS_LAN4_LED0 = BIT(28),
191 OMNIA_EXT_STS_LAN4_LED1 = BIT(29),
192 OMNIA_EXT_STS_LAN5_LED0 = BIT(30),
193 OMNIA_EXT_STS_LAN5_LED1 = BIT(31),
194 };
195
196 enum omnia_ext_ctl_e {
197 OMNIA_EXT_CTL_nRES_MMC = BIT(0),
198 OMNIA_EXT_CTL_nRES_LAN = BIT(1),
199 OMNIA_EXT_CTL_nRES_PHY = BIT(2),
200 OMNIA_EXT_CTL_nPERST0 = BIT(3),
201 OMNIA_EXT_CTL_nPERST1 = BIT(4),
202 OMNIA_EXT_CTL_nPERST2 = BIT(5),
203 OMNIA_EXT_CTL_PHY_SFP = BIT(6),
204 OMNIA_EXT_CTL_PHY_SFP_AUTO = BIT(7),
205 OMNIA_EXT_CTL_nVHV_CTRL = BIT(8),
206 };
207
208 enum omnia_int_e {
209 OMNIA_INT_CARD_DET = BIT(0),
210 OMNIA_INT_MSATA_IND = BIT(1),
211 OMNIA_INT_USB30_OVC = BIT(2),
212 OMNIA_INT_USB31_OVC = BIT(3),
213 OMNIA_INT_BUTTON_PRESSED = BIT(4),
214 OMNIA_INT_SFP_nDET = BIT(5),
215 OMNIA_INT_BRIGHTNESS_CHANGED = BIT(6),
216 OMNIA_INT_TRNG = BIT(7),
217 OMNIA_INT_MESSAGE_SIGNED = BIT(8),
218
219 OMNIA_INT_LED_STATES_MASK = GENMASK(31, 12),
220 OMNIA_INT_WLAN0_MSATA_LED = BIT(12),
221 OMNIA_INT_WLAN1_LED = BIT(13),
222 OMNIA_INT_WLAN2_LED = BIT(14),
223 OMNIA_INT_WPAN0_LED = BIT(15),
224 OMNIA_INT_WPAN1_LED = BIT(16),
225 OMNIA_INT_WPAN2_LED = BIT(17),
226 OMNIA_INT_WAN_LED0 = BIT(18),
227 OMNIA_INT_WAN_LED1 = BIT(19),
228 OMNIA_INT_LAN0_LED0 = BIT(20),
229 OMNIA_INT_LAN0_LED1 = BIT(21),
230 OMNIA_INT_LAN1_LED0 = BIT(22),
231 OMNIA_INT_LAN1_LED1 = BIT(23),
232 OMNIA_INT_LAN2_LED0 = BIT(24),
233 OMNIA_INT_LAN2_LED1 = BIT(25),
234 OMNIA_INT_LAN3_LED0 = BIT(26),
235 OMNIA_INT_LAN3_LED1 = BIT(27),
236 OMNIA_INT_LAN4_LED0 = BIT(28),
237 OMNIA_INT_LAN4_LED1 = BIT(29),
238 OMNIA_INT_LAN5_LED0 = BIT(30),
239 OMNIA_INT_LAN5_LED1 = BIT(31),
240 };
241
242 enum omnia_cmd_led_mode_e {
243 OMNIA_CMD_LED_MODE_LED_MASK = GENMASK(3, 0),
244 OMNIA_CMD_LED_MODE_USER = BIT(4),
245 };
246
247 #define OMNIA_CMD_LED_MODE_LED(_l) FIELD_PREP(OMNIA_CMD_LED_MODE_LED_MASK, _l)
248
249 enum omnia_cmd_led_state_e {
250 OMNIA_CMD_LED_STATE_LED_MASK = GENMASK(3, 0),
251 OMNIA_CMD_LED_STATE_ON = BIT(4),
252 };
253
254 #define OMNIA_CMD_LED_STATE_LED(_l) FIELD_PREP(OMNIA_CMD_LED_STATE_LED_MASK, _l)
255
256 enum omnia_cmd_poweroff_e {
257 OMNIA_CMD_POWER_OFF_POWERON_BUTTON = BIT(0),
258 OMNIA_CMD_POWER_OFF_MAGIC = 0xdead,
259 };
260
261 enum omnia_cmd_usb_ovc_prot_e {
262 OMNIA_CMD_xET_USB_OVC_PROT_PORT_MASK = GENMASK(3, 0),
263 OMNIA_CMD_xET_USB_OVC_PROT_ENABLE = BIT(4),
264 };
265
266 /* Command execution functions */
267
268 struct i2c_client;
269
270 int omnia_cmd_write_read(const struct i2c_client *client,
271 void *cmd, unsigned int cmd_len,
272 void *reply, unsigned int reply_len);
273
omnia_cmd_write(const struct i2c_client * client,void * cmd,unsigned int len)274 static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
275 unsigned int len)
276 {
277 return omnia_cmd_write_read(client, cmd, len, NULL, 0);
278 }
279
omnia_cmd_write_u8(const struct i2c_client * client,u8 cmd,u8 val)280 static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,
281 u8 val)
282 {
283 u8 buf[2] = { cmd, val };
284
285 return omnia_cmd_write(client, buf, sizeof(buf));
286 }
287
omnia_cmd_write_u16(const struct i2c_client * client,u8 cmd,u16 val)288 static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,
289 u16 val)
290 {
291 u8 buf[3];
292
293 buf[0] = cmd;
294 put_unaligned_le16(val, &buf[1]);
295
296 return omnia_cmd_write(client, buf, sizeof(buf));
297 }
298
omnia_cmd_write_u32(const struct i2c_client * client,u8 cmd,u32 val)299 static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
300 u32 val)
301 {
302 u8 buf[5];
303
304 buf[0] = cmd;
305 put_unaligned_le32(val, &buf[1]);
306
307 return omnia_cmd_write(client, buf, sizeof(buf));
308 }
309
omnia_cmd_read(const struct i2c_client * client,u8 cmd,void * reply,unsigned int len)310 static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
311 void *reply, unsigned int len)
312 {
313 return omnia_cmd_write_read(client, &cmd, 1, reply, len);
314 }
315
316 static inline unsigned int
omnia_compute_reply_length(unsigned long mask,bool interleaved,unsigned int offset)317 omnia_compute_reply_length(unsigned long mask, bool interleaved,
318 unsigned int offset)
319 {
320 if (!mask)
321 return 0;
322
323 return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
324 }
325
326 /* Returns 0 on success */
omnia_cmd_read_bits(const struct i2c_client * client,u8 cmd,unsigned long bits,unsigned long * dst)327 static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,
328 unsigned long bits, unsigned long *dst)
329 {
330 __le32 reply;
331 int err;
332
333 if (!bits) {
334 *dst = 0;
335 return 0;
336 }
337
338 err = omnia_cmd_read(client, cmd, &reply,
339 omnia_compute_reply_length(bits, false, 0));
340 if (err)
341 return err;
342
343 *dst = le32_to_cpu(reply) & bits;
344
345 return 0;
346 }
347
omnia_cmd_read_bit(const struct i2c_client * client,u8 cmd,unsigned long bit)348 static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,
349 unsigned long bit)
350 {
351 unsigned long reply;
352 int err;
353
354 err = omnia_cmd_read_bits(client, cmd, bit, &reply);
355 if (err)
356 return err;
357
358 return !!reply;
359 }
360
omnia_cmd_read_u32(const struct i2c_client * client,u8 cmd,u32 * dst)361 static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
362 u32 *dst)
363 {
364 __le32 reply;
365 int err;
366
367 err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
368 if (err)
369 return err;
370
371 *dst = le32_to_cpu(reply);
372
373 return 0;
374 }
375
omnia_cmd_read_u16(const struct i2c_client * client,u8 cmd,u16 * dst)376 static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,
377 u16 *dst)
378 {
379 __le16 reply;
380 int err;
381
382 err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
383 if (err)
384 return err;
385
386 *dst = le16_to_cpu(reply);
387
388 return 0;
389 }
390
omnia_cmd_read_u8(const struct i2c_client * client,u8 cmd,u8 * reply)391 static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
392 u8 *reply)
393 {
394 return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
395 }
396
397 #endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */
398