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