1 | // SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause |
2 | /* |
3 | * UCSI driver for STMicroelectronics STM32G0 Type-C PD controller |
4 | * |
5 | * Copyright (C) 2022, STMicroelectronics - All Rights Reserved |
6 | * Author: Fabrice Gasnier <fabrice.gasnier@foss.st.com>. |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/firmware.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> |
15 | #include <asm/unaligned.h> |
16 | |
17 | #include "ucsi.h" |
18 | |
19 | /* STM32G0 I2C bootloader addr: 0b1010001x (See AN2606) */ |
20 | #define STM32G0_I2C_BL_ADDR (0xa2 >> 1) |
21 | |
22 | /* STM32G0 I2C bootloader max data size */ |
23 | #define STM32G0_I2C_BL_SZ 256 |
24 | |
25 | /* STM32 I2C bootloader commands (See AN4221) */ |
26 | #define STM32_CMD_GVR 0x01 /* Gets the bootloader version */ |
27 | #define STM32_CMD_GVR_LEN 1 |
28 | #define STM32_CMD_RM 0x11 /* Reag memory */ |
29 | #define STM32_CMD_WM 0x31 /* Write memory */ |
30 | #define STM32_CMD_ADDR_LEN 5 /* Address len for go, mem write... */ |
31 | #define STM32_CMD_ERASE 0x44 /* Erase page, bank or all */ |
32 | #define STM32_CMD_ERASE_SPECIAL_LEN 3 |
33 | #define STM32_CMD_GLOBAL_MASS_ERASE 0xffff /* All-bank erase */ |
34 | |
35 | /* STM32 I2C bootloader answer status */ |
36 | #define STM32G0_I2C_BL_ACK 0x79 |
37 | #define STM32G0_I2C_BL_NACK 0x1f |
38 | #define STM32G0_I2C_BL_BUSY 0x76 |
39 | |
40 | /* STM32G0 flash definitions */ |
41 | #define STM32G0_USER_OPTION_BYTES 0x1fff7800 |
42 | #define STM32G0_USER_OB_NBOOT0 BIT(26) |
43 | #define STM32G0_USER_OB_NBOOT_SEL BIT(24) |
44 | #define STM32G0_USER_OB_BOOT_MAIN (STM32G0_USER_OB_NBOOT0 | STM32G0_USER_OB_NBOOT_SEL) |
45 | #define STM32G0_MAIN_MEM_ADDR 0x08000000 |
46 | |
47 | /* STM32 Firmware definitions: additional commands */ |
48 | #define STM32G0_FW_GETVER 0x00 /* Gets the firmware version */ |
49 | #define STM32G0_FW_GETVER_LEN 4 |
50 | #define STM32G0_FW_RSTGOBL 0x21 /* Reset and go to bootloader */ |
51 | #define STM32G0_FW_KEYWORD 0xa56959a6 |
52 | |
53 | /* ucsi_stm32g0_fw_info located at the end of the firmware */ |
54 | struct ucsi_stm32g0_fw_info { |
55 | u32 version; |
56 | u32 keyword; |
57 | }; |
58 | |
59 | struct ucsi_stm32g0 { |
60 | struct i2c_client *client; |
61 | struct i2c_client *i2c_bl; |
62 | bool in_bootloader; |
63 | u8 bl_version; |
64 | struct completion complete; |
65 | struct device *dev; |
66 | unsigned long flags; |
67 | const char *fw_name; |
68 | struct ucsi *ucsi; |
69 | bool suspended; |
70 | bool wakeup_event; |
71 | }; |
72 | |
73 | /* |
74 | * Bootloader commands helpers: |
75 | * - send command (2 bytes) |
76 | * - check ack |
77 | * Then either: |
78 | * - receive data |
79 | * - receive data + check ack |
80 | * - send data + check ack |
81 | * These operations depends on the command and have various length. |
82 | */ |
83 | static int ucsi_stm32g0_bl_check_ack(struct ucsi *ucsi) |
84 | { |
85 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
86 | struct i2c_client *client = g0->i2c_bl; |
87 | unsigned char ack; |
88 | struct i2c_msg msg[] = { |
89 | { |
90 | .addr = client->addr, |
91 | .flags = I2C_M_RD, |
92 | .len = 1, |
93 | .buf = &ack, |
94 | }, |
95 | }; |
96 | int ret; |
97 | |
98 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
99 | if (ret != ARRAY_SIZE(msg)) { |
100 | dev_err(g0->dev, "i2c bl ack (%02x), error: %d\n" , client->addr, ret); |
101 | |
102 | return ret < 0 ? ret : -EIO; |
103 | } |
104 | |
105 | /* The 'ack' byte should contain bootloader answer: ack/nack/busy */ |
106 | switch (ack) { |
107 | case STM32G0_I2C_BL_ACK: |
108 | return 0; |
109 | case STM32G0_I2C_BL_NACK: |
110 | return -ENOENT; |
111 | case STM32G0_I2C_BL_BUSY: |
112 | return -EBUSY; |
113 | default: |
114 | dev_err(g0->dev, "i2c bl ack (%02x), invalid byte: %02x\n" , |
115 | client->addr, ack); |
116 | return -EINVAL; |
117 | } |
118 | } |
119 | |
120 | static int ucsi_stm32g0_bl_cmd_check_ack(struct ucsi *ucsi, unsigned int cmd, bool check_ack) |
121 | { |
122 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
123 | struct i2c_client *client = g0->i2c_bl; |
124 | unsigned char buf[2]; |
125 | struct i2c_msg msg[] = { |
126 | { |
127 | .addr = client->addr, |
128 | .flags = 0, |
129 | .len = sizeof(buf), |
130 | .buf = buf, |
131 | }, |
132 | }; |
133 | int ret; |
134 | |
135 | /* |
136 | * Send STM32 bootloader command format is two bytes: |
137 | * - command code |
138 | * - XOR'ed command code |
139 | */ |
140 | buf[0] = cmd; |
141 | buf[1] = cmd ^ 0xff; |
142 | |
143 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
144 | if (ret != ARRAY_SIZE(msg)) { |
145 | dev_dbg(g0->dev, "i2c bl cmd %d (%02x), error: %d\n" , cmd, client->addr, ret); |
146 | |
147 | return ret < 0 ? ret : -EIO; |
148 | } |
149 | |
150 | if (check_ack) |
151 | return ucsi_stm32g0_bl_check_ack(ucsi); |
152 | |
153 | return 0; |
154 | } |
155 | |
156 | static int ucsi_stm32g0_bl_cmd(struct ucsi *ucsi, unsigned int cmd) |
157 | { |
158 | return ucsi_stm32g0_bl_cmd_check_ack(ucsi, cmd, check_ack: true); |
159 | } |
160 | |
161 | static int ucsi_stm32g0_bl_rcv_check_ack(struct ucsi *ucsi, void *data, size_t len, bool check_ack) |
162 | { |
163 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
164 | struct i2c_client *client = g0->i2c_bl; |
165 | struct i2c_msg msg[] = { |
166 | { |
167 | .addr = client->addr, |
168 | .flags = I2C_M_RD, |
169 | .len = len, |
170 | .buf = data, |
171 | }, |
172 | }; |
173 | int ret; |
174 | |
175 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
176 | if (ret != ARRAY_SIZE(msg)) { |
177 | dev_err(g0->dev, "i2c bl rcv %02x, error: %d\n" , client->addr, ret); |
178 | |
179 | return ret < 0 ? ret : -EIO; |
180 | } |
181 | |
182 | if (check_ack) |
183 | return ucsi_stm32g0_bl_check_ack(ucsi); |
184 | |
185 | return 0; |
186 | } |
187 | |
188 | static int ucsi_stm32g0_bl_rcv(struct ucsi *ucsi, void *data, size_t len) |
189 | { |
190 | return ucsi_stm32g0_bl_rcv_check_ack(ucsi, data, len, check_ack: true); |
191 | } |
192 | |
193 | static int ucsi_stm32g0_bl_rcv_woack(struct ucsi *ucsi, void *data, size_t len) |
194 | { |
195 | return ucsi_stm32g0_bl_rcv_check_ack(ucsi, data, len, check_ack: false); |
196 | } |
197 | |
198 | static int ucsi_stm32g0_bl_send(struct ucsi *ucsi, void *data, size_t len) |
199 | { |
200 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
201 | struct i2c_client *client = g0->i2c_bl; |
202 | struct i2c_msg msg[] = { |
203 | { |
204 | .addr = client->addr, |
205 | .flags = 0, |
206 | .len = len, |
207 | .buf = data, |
208 | }, |
209 | }; |
210 | int ret; |
211 | |
212 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
213 | if (ret != ARRAY_SIZE(msg)) { |
214 | dev_err(g0->dev, "i2c bl send %02x, error: %d\n" , client->addr, ret); |
215 | |
216 | return ret < 0 ? ret : -EIO; |
217 | } |
218 | |
219 | return ucsi_stm32g0_bl_check_ack(ucsi); |
220 | } |
221 | |
222 | /* Bootloader commands */ |
223 | static int ucsi_stm32g0_bl_get_version(struct ucsi *ucsi, u8 *bl_version) |
224 | { |
225 | int ret; |
226 | |
227 | ret = ucsi_stm32g0_bl_cmd(ucsi, STM32_CMD_GVR); |
228 | if (ret) |
229 | return ret; |
230 | |
231 | return ucsi_stm32g0_bl_rcv(ucsi, data: bl_version, STM32_CMD_GVR_LEN); |
232 | } |
233 | |
234 | static int ucsi_stm32g0_bl_send_addr(struct ucsi *ucsi, u32 addr) |
235 | { |
236 | u8 data8[STM32_CMD_ADDR_LEN]; |
237 | |
238 | /* Address format: 4 bytes addr (MSB first) + XOR'ed addr bytes */ |
239 | put_unaligned_be32(val: addr, p: data8); |
240 | data8[4] = data8[0] ^ data8[1] ^ data8[2] ^ data8[3]; |
241 | |
242 | return ucsi_stm32g0_bl_send(ucsi, data: data8, STM32_CMD_ADDR_LEN); |
243 | } |
244 | |
245 | static int ucsi_stm32g0_bl_global_mass_erase(struct ucsi *ucsi) |
246 | { |
247 | u8 data8[4]; |
248 | u16 *data16 = (u16 *)&data8[0]; |
249 | int ret; |
250 | |
251 | data16[0] = STM32_CMD_GLOBAL_MASS_ERASE; |
252 | data8[2] = data8[0] ^ data8[1]; |
253 | |
254 | ret = ucsi_stm32g0_bl_cmd(ucsi, STM32_CMD_ERASE); |
255 | if (ret) |
256 | return ret; |
257 | |
258 | return ucsi_stm32g0_bl_send(ucsi, data: data8, STM32_CMD_ERASE_SPECIAL_LEN); |
259 | } |
260 | |
261 | static int ucsi_stm32g0_bl_write(struct ucsi *ucsi, u32 addr, const void *data, size_t len) |
262 | { |
263 | u8 *data8; |
264 | int i, ret; |
265 | |
266 | if (!len || len > STM32G0_I2C_BL_SZ) |
267 | return -EINVAL; |
268 | |
269 | /* Write memory: len bytes -1, data up to 256 bytes + XOR'ed bytes */ |
270 | data8 = kmalloc(STM32G0_I2C_BL_SZ + 2, GFP_KERNEL); |
271 | if (!data8) |
272 | return -ENOMEM; |
273 | |
274 | ret = ucsi_stm32g0_bl_cmd(ucsi, STM32_CMD_WM); |
275 | if (ret) |
276 | goto free; |
277 | |
278 | ret = ucsi_stm32g0_bl_send_addr(ucsi, addr); |
279 | if (ret) |
280 | goto free; |
281 | |
282 | data8[0] = len - 1; |
283 | memcpy(data8 + 1, data, len); |
284 | data8[len + 1] = data8[0]; |
285 | for (i = 1; i <= len; i++) |
286 | data8[len + 1] ^= data8[i]; |
287 | |
288 | ret = ucsi_stm32g0_bl_send(ucsi, data: data8, len: len + 2); |
289 | free: |
290 | kfree(objp: data8); |
291 | |
292 | return ret; |
293 | } |
294 | |
295 | static int ucsi_stm32g0_bl_read(struct ucsi *ucsi, u32 addr, void *data, size_t len) |
296 | { |
297 | int ret; |
298 | |
299 | if (!len || len > STM32G0_I2C_BL_SZ) |
300 | return -EINVAL; |
301 | |
302 | ret = ucsi_stm32g0_bl_cmd(ucsi, STM32_CMD_RM); |
303 | if (ret) |
304 | return ret; |
305 | |
306 | ret = ucsi_stm32g0_bl_send_addr(ucsi, addr); |
307 | if (ret) |
308 | return ret; |
309 | |
310 | ret = ucsi_stm32g0_bl_cmd(ucsi, cmd: len - 1); |
311 | if (ret) |
312 | return ret; |
313 | |
314 | return ucsi_stm32g0_bl_rcv_woack(ucsi, data, len); |
315 | } |
316 | |
317 | /* Firmware commands (the same address as the bootloader) */ |
318 | static int ucsi_stm32g0_fw_cmd(struct ucsi *ucsi, unsigned int cmd) |
319 | { |
320 | return ucsi_stm32g0_bl_cmd_check_ack(ucsi, cmd, check_ack: false); |
321 | } |
322 | |
323 | static int ucsi_stm32g0_fw_rcv(struct ucsi *ucsi, void *data, size_t len) |
324 | { |
325 | return ucsi_stm32g0_bl_rcv_woack(ucsi, data, len); |
326 | } |
327 | |
328 | /* UCSI ops */ |
329 | static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t len) |
330 | { |
331 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
332 | struct i2c_client *client = g0->client; |
333 | u8 reg = offset; |
334 | struct i2c_msg msg[] = { |
335 | { |
336 | .addr = client->addr, |
337 | .flags = 0, |
338 | .len = 1, |
339 | .buf = ®, |
340 | }, |
341 | { |
342 | .addr = client->addr, |
343 | .flags = I2C_M_RD, |
344 | .len = len, |
345 | .buf = val, |
346 | }, |
347 | }; |
348 | int ret; |
349 | |
350 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
351 | if (ret != ARRAY_SIZE(msg)) { |
352 | dev_err(g0->dev, "i2c read %02x, %02x error: %d\n" , client->addr, reg, ret); |
353 | |
354 | return ret < 0 ? ret : -EIO; |
355 | } |
356 | |
357 | return 0; |
358 | } |
359 | |
360 | static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, const void *val, |
361 | size_t len) |
362 | { |
363 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
364 | struct i2c_client *client = g0->client; |
365 | struct i2c_msg msg[] = { |
366 | { |
367 | .addr = client->addr, |
368 | .flags = 0, |
369 | } |
370 | }; |
371 | unsigned char *buf; |
372 | int ret; |
373 | |
374 | buf = kmalloc(size: len + 1, GFP_KERNEL); |
375 | if (!buf) |
376 | return -ENOMEM; |
377 | |
378 | buf[0] = offset; |
379 | memcpy(&buf[1], val, len); |
380 | msg[0].len = len + 1; |
381 | msg[0].buf = buf; |
382 | |
383 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
384 | kfree(objp: buf); |
385 | if (ret != ARRAY_SIZE(msg)) { |
386 | dev_err(g0->dev, "i2c write %02x, %02x error: %d\n" , client->addr, offset, ret); |
387 | |
388 | return ret < 0 ? ret : -EIO; |
389 | } |
390 | |
391 | return 0; |
392 | } |
393 | |
394 | static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const void *val, |
395 | size_t len) |
396 | { |
397 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
398 | int ret; |
399 | |
400 | set_bit(COMMAND_PENDING, addr: &g0->flags); |
401 | |
402 | ret = ucsi_stm32g0_async_write(ucsi, offset, val, len); |
403 | if (ret) |
404 | goto out_clear_bit; |
405 | |
406 | if (!wait_for_completion_timeout(x: &g0->complete, timeout: msecs_to_jiffies(m: 5000))) |
407 | ret = -ETIMEDOUT; |
408 | |
409 | out_clear_bit: |
410 | clear_bit(COMMAND_PENDING, addr: &g0->flags); |
411 | |
412 | return ret; |
413 | } |
414 | |
415 | static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) |
416 | { |
417 | struct ucsi_stm32g0 *g0 = data; |
418 | u32 cci; |
419 | int ret; |
420 | |
421 | if (g0->suspended) |
422 | g0->wakeup_event = true; |
423 | |
424 | ret = ucsi_stm32g0_read(ucsi: g0->ucsi, UCSI_CCI, val: &cci, len: sizeof(cci)); |
425 | if (ret) |
426 | return IRQ_NONE; |
427 | |
428 | if (UCSI_CCI_CONNECTOR(cci)) |
429 | ucsi_connector_change(ucsi: g0->ucsi, UCSI_CCI_CONNECTOR(cci)); |
430 | |
431 | if (test_bit(COMMAND_PENDING, &g0->flags) && |
432 | cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE)) |
433 | complete(&g0->complete); |
434 | |
435 | return IRQ_HANDLED; |
436 | } |
437 | |
438 | static const struct ucsi_operations ucsi_stm32g0_ops = { |
439 | .read = ucsi_stm32g0_read, |
440 | .sync_write = ucsi_stm32g0_sync_write, |
441 | .async_write = ucsi_stm32g0_async_write, |
442 | }; |
443 | |
444 | static int ucsi_stm32g0_register(struct ucsi *ucsi) |
445 | { |
446 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
447 | struct i2c_client *client = g0->client; |
448 | int ret; |
449 | |
450 | /* Request alert interrupt */ |
451 | ret = request_threaded_irq(irq: client->irq, NULL, thread_fn: ucsi_stm32g0_irq_handler, IRQF_ONESHOT, |
452 | name: dev_name(dev: g0->dev), dev: g0); |
453 | if (ret) { |
454 | dev_err(g0->dev, "request IRQ failed: %d\n" , ret); |
455 | return ret; |
456 | } |
457 | |
458 | ret = ucsi_register(ucsi); |
459 | if (ret) { |
460 | dev_err_probe(dev: g0->dev, err: ret, fmt: "ucsi_register failed\n" ); |
461 | free_irq(client->irq, g0); |
462 | return ret; |
463 | } |
464 | |
465 | return 0; |
466 | } |
467 | |
468 | static void ucsi_stm32g0_unregister(struct ucsi *ucsi) |
469 | { |
470 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
471 | struct i2c_client *client = g0->client; |
472 | |
473 | ucsi_unregister(ucsi); |
474 | free_irq(client->irq, g0); |
475 | } |
476 | |
477 | static void ucsi_stm32g0_fw_cb(const struct firmware *fw, void *context) |
478 | { |
479 | struct ucsi_stm32g0 *g0; |
480 | const u8 *data, *end; |
481 | const struct ucsi_stm32g0_fw_info *fw_info; |
482 | u32 addr = STM32G0_MAIN_MEM_ADDR, ob, fw_version; |
483 | int ret, size; |
484 | |
485 | if (!context) |
486 | return; |
487 | |
488 | g0 = ucsi_get_drvdata(ucsi: context); |
489 | |
490 | if (!fw) |
491 | goto fw_release; |
492 | |
493 | fw_info = (struct ucsi_stm32g0_fw_info *)(fw->data + fw->size - sizeof(*fw_info)); |
494 | |
495 | if (!g0->in_bootloader) { |
496 | /* Read running firmware version */ |
497 | ret = ucsi_stm32g0_fw_cmd(ucsi: g0->ucsi, STM32G0_FW_GETVER); |
498 | if (ret) { |
499 | dev_err(g0->dev, "Get version cmd failed %d\n" , ret); |
500 | goto fw_release; |
501 | } |
502 | ret = ucsi_stm32g0_fw_rcv(ucsi: g0->ucsi, data: &fw_version, |
503 | STM32G0_FW_GETVER_LEN); |
504 | if (ret) { |
505 | dev_err(g0->dev, "Get version failed %d\n" , ret); |
506 | goto fw_release; |
507 | } |
508 | |
509 | /* Sanity check on keyword and firmware version */ |
510 | if (fw_info->keyword != STM32G0_FW_KEYWORD || fw_info->version == fw_version) |
511 | goto fw_release; |
512 | |
513 | dev_info(g0->dev, "Flashing FW: %08x (%08x cur)\n" , fw_info->version, fw_version); |
514 | |
515 | /* Switch to bootloader mode */ |
516 | ucsi_stm32g0_unregister(ucsi: g0->ucsi); |
517 | ret = ucsi_stm32g0_fw_cmd(ucsi: g0->ucsi, STM32G0_FW_RSTGOBL); |
518 | if (ret) { |
519 | dev_err(g0->dev, "bootloader cmd failed %d\n" , ret); |
520 | goto fw_release; |
521 | } |
522 | g0->in_bootloader = true; |
523 | |
524 | /* STM32G0 reboot delay */ |
525 | msleep(msecs: 100); |
526 | } |
527 | |
528 | ret = ucsi_stm32g0_bl_global_mass_erase(ucsi: g0->ucsi); |
529 | if (ret) { |
530 | dev_err(g0->dev, "Erase failed %d\n" , ret); |
531 | goto fw_release; |
532 | } |
533 | |
534 | data = fw->data; |
535 | end = fw->data + fw->size; |
536 | while (data < end) { |
537 | if ((end - data) < STM32G0_I2C_BL_SZ) |
538 | size = end - data; |
539 | else |
540 | size = STM32G0_I2C_BL_SZ; |
541 | |
542 | ret = ucsi_stm32g0_bl_write(ucsi: g0->ucsi, addr, data, len: size); |
543 | if (ret) { |
544 | dev_err(g0->dev, "Write failed %d\n" , ret); |
545 | goto fw_release; |
546 | } |
547 | addr += size; |
548 | data += size; |
549 | } |
550 | |
551 | dev_dbg(g0->dev, "Configure to boot from main flash\n" ); |
552 | |
553 | ret = ucsi_stm32g0_bl_read(ucsi: g0->ucsi, STM32G0_USER_OPTION_BYTES, data: &ob, len: sizeof(ob)); |
554 | if (ret) { |
555 | dev_err(g0->dev, "read user option bytes failed %d\n" , ret); |
556 | goto fw_release; |
557 | } |
558 | |
559 | dev_dbg(g0->dev, "STM32G0_USER_OPTION_BYTES 0x%08x\n" , ob); |
560 | |
561 | /* Configure user option bytes to boot from main flash next time */ |
562 | ob |= STM32G0_USER_OB_BOOT_MAIN; |
563 | |
564 | /* Writing option bytes will also reset G0 for updates to be loaded */ |
565 | ret = ucsi_stm32g0_bl_write(ucsi: g0->ucsi, STM32G0_USER_OPTION_BYTES, data: &ob, len: sizeof(ob)); |
566 | if (ret) { |
567 | dev_err(g0->dev, "write user option bytes failed %d\n" , ret); |
568 | goto fw_release; |
569 | } |
570 | |
571 | dev_info(g0->dev, "Starting, option bytes:0x%08x\n" , ob); |
572 | |
573 | /* STM32G0 FW boot delay */ |
574 | msleep(msecs: 500); |
575 | |
576 | /* Register UCSI interface */ |
577 | if (!ucsi_stm32g0_register(ucsi: g0->ucsi)) |
578 | g0->in_bootloader = false; |
579 | |
580 | fw_release: |
581 | release_firmware(fw); |
582 | } |
583 | |
584 | static int ucsi_stm32g0_probe_bootloader(struct ucsi *ucsi) |
585 | { |
586 | struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); |
587 | int ret; |
588 | u16 ucsi_version; |
589 | |
590 | /* firmware-name is optional */ |
591 | if (device_property_present(dev: g0->dev, propname: "firmware-name" )) { |
592 | ret = device_property_read_string(dev: g0->dev, propname: "firmware-name" , val: &g0->fw_name); |
593 | if (ret < 0) |
594 | return dev_err_probe(dev: g0->dev, err: ret, fmt: "Error reading firmware-name\n" ); |
595 | } |
596 | |
597 | if (g0->fw_name) { |
598 | /* STM32G0 in bootloader mode communicates at reserved address 0x51 */ |
599 | g0->i2c_bl = i2c_new_dummy_device(adapter: g0->client->adapter, STM32G0_I2C_BL_ADDR); |
600 | if (IS_ERR(ptr: g0->i2c_bl)) { |
601 | ret = dev_err_probe(dev: g0->dev, err: PTR_ERR(ptr: g0->i2c_bl), |
602 | fmt: "Failed to register bootloader I2C address\n" ); |
603 | return ret; |
604 | } |
605 | } |
606 | |
607 | /* |
608 | * Try to guess if the STM32G0 is running a UCSI firmware. First probe the UCSI FW at its |
609 | * i2c address. Fallback to bootloader i2c address only if firmware-name is specified. |
610 | */ |
611 | ret = ucsi_stm32g0_read(ucsi, UCSI_VERSION, val: &ucsi_version, len: sizeof(ucsi_version)); |
612 | if (!ret || !g0->fw_name) |
613 | return ret; |
614 | |
615 | /* Speculatively read the bootloader version that has a known length. */ |
616 | ret = ucsi_stm32g0_bl_get_version(ucsi, bl_version: &g0->bl_version); |
617 | if (ret < 0) { |
618 | i2c_unregister_device(client: g0->i2c_bl); |
619 | return ret; |
620 | } |
621 | |
622 | /* Device in bootloader mode */ |
623 | g0->in_bootloader = true; |
624 | dev_info(g0->dev, "Bootloader Version 0x%02x\n" , g0->bl_version); |
625 | |
626 | return 0; |
627 | } |
628 | |
629 | static int ucsi_stm32g0_probe(struct i2c_client *client) |
630 | { |
631 | struct device *dev = &client->dev; |
632 | struct ucsi_stm32g0 *g0; |
633 | int ret; |
634 | |
635 | g0 = devm_kzalloc(dev, size: sizeof(*g0), GFP_KERNEL); |
636 | if (!g0) |
637 | return -ENOMEM; |
638 | |
639 | g0->dev = dev; |
640 | g0->client = client; |
641 | init_completion(x: &g0->complete); |
642 | i2c_set_clientdata(client, data: g0); |
643 | |
644 | g0->ucsi = ucsi_create(dev, ops: &ucsi_stm32g0_ops); |
645 | if (IS_ERR(ptr: g0->ucsi)) |
646 | return PTR_ERR(ptr: g0->ucsi); |
647 | |
648 | ucsi_set_drvdata(ucsi: g0->ucsi, data: g0); |
649 | |
650 | ret = ucsi_stm32g0_probe_bootloader(ucsi: g0->ucsi); |
651 | if (ret < 0) |
652 | goto destroy; |
653 | |
654 | /* |
655 | * Don't register in bootloader mode: wait for the firmware to be loaded and started before |
656 | * registering UCSI device. |
657 | */ |
658 | if (!g0->in_bootloader) { |
659 | ret = ucsi_stm32g0_register(ucsi: g0->ucsi); |
660 | if (ret < 0) |
661 | goto freei2c; |
662 | } |
663 | |
664 | if (g0->fw_name) { |
665 | /* |
666 | * Asynchronously flash (e.g. bootloader mode) or update the running firmware, |
667 | * not to hang the boot process |
668 | */ |
669 | ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, name: g0->fw_name, device: g0->dev, |
670 | GFP_KERNEL, context: g0->ucsi, cont: ucsi_stm32g0_fw_cb); |
671 | if (ret < 0) { |
672 | dev_err_probe(dev, err: ret, fmt: "firmware request failed\n" ); |
673 | goto unregister; |
674 | } |
675 | } |
676 | |
677 | return 0; |
678 | |
679 | unregister: |
680 | if (!g0->in_bootloader) |
681 | ucsi_stm32g0_unregister(ucsi: g0->ucsi); |
682 | freei2c: |
683 | if (g0->fw_name) |
684 | i2c_unregister_device(client: g0->i2c_bl); |
685 | destroy: |
686 | ucsi_destroy(ucsi: g0->ucsi); |
687 | |
688 | return ret; |
689 | } |
690 | |
691 | static void ucsi_stm32g0_remove(struct i2c_client *client) |
692 | { |
693 | struct ucsi_stm32g0 *g0 = i2c_get_clientdata(client); |
694 | |
695 | if (!g0->in_bootloader) |
696 | ucsi_stm32g0_unregister(ucsi: g0->ucsi); |
697 | if (g0->fw_name) |
698 | i2c_unregister_device(client: g0->i2c_bl); |
699 | ucsi_destroy(ucsi: g0->ucsi); |
700 | } |
701 | |
702 | static int ucsi_stm32g0_suspend(struct device *dev) |
703 | { |
704 | struct ucsi_stm32g0 *g0 = dev_get_drvdata(dev); |
705 | struct i2c_client *client = g0->client; |
706 | |
707 | if (g0->in_bootloader) |
708 | return 0; |
709 | |
710 | /* Keep the interrupt disabled until the i2c bus has been resumed */ |
711 | disable_irq(irq: client->irq); |
712 | |
713 | g0->suspended = true; |
714 | g0->wakeup_event = false; |
715 | |
716 | if (device_may_wakeup(dev) || device_wakeup_path(dev)) |
717 | enable_irq_wake(irq: client->irq); |
718 | |
719 | return 0; |
720 | } |
721 | |
722 | static int ucsi_stm32g0_resume(struct device *dev) |
723 | { |
724 | struct ucsi_stm32g0 *g0 = dev_get_drvdata(dev); |
725 | struct i2c_client *client = g0->client; |
726 | |
727 | if (g0->in_bootloader) |
728 | return 0; |
729 | |
730 | if (device_may_wakeup(dev) || device_wakeup_path(dev)) |
731 | disable_irq_wake(irq: client->irq); |
732 | |
733 | enable_irq(irq: client->irq); |
734 | |
735 | /* Enforce any pending handler gets called to signal a wakeup_event */ |
736 | synchronize_irq(irq: client->irq); |
737 | |
738 | if (g0->wakeup_event) |
739 | pm_wakeup_event(dev: g0->dev, msec: 0); |
740 | |
741 | g0->suspended = false; |
742 | |
743 | return 0; |
744 | } |
745 | |
746 | static DEFINE_SIMPLE_DEV_PM_OPS(ucsi_stm32g0_pm_ops, ucsi_stm32g0_suspend, ucsi_stm32g0_resume); |
747 | |
748 | static const struct of_device_id __maybe_unused ucsi_stm32g0_typec_of_match[] = { |
749 | { .compatible = "st,stm32g0-typec" }, |
750 | {}, |
751 | }; |
752 | MODULE_DEVICE_TABLE(of, ucsi_stm32g0_typec_of_match); |
753 | |
754 | static const struct i2c_device_id ucsi_stm32g0_typec_i2c_devid[] = { |
755 | {"stm32g0-typec" , 0}, |
756 | {}, |
757 | }; |
758 | MODULE_DEVICE_TABLE(i2c, ucsi_stm32g0_typec_i2c_devid); |
759 | |
760 | static struct i2c_driver ucsi_stm32g0_i2c_driver = { |
761 | .driver = { |
762 | .name = "ucsi-stm32g0-i2c" , |
763 | .of_match_table = of_match_ptr(ucsi_stm32g0_typec_of_match), |
764 | .pm = pm_sleep_ptr(&ucsi_stm32g0_pm_ops), |
765 | }, |
766 | .probe = ucsi_stm32g0_probe, |
767 | .remove = ucsi_stm32g0_remove, |
768 | .id_table = ucsi_stm32g0_typec_i2c_devid |
769 | }; |
770 | module_i2c_driver(ucsi_stm32g0_i2c_driver); |
771 | |
772 | MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@foss.st.com>" ); |
773 | MODULE_DESCRIPTION("STMicroelectronics STM32G0 Type-C controller" ); |
774 | MODULE_LICENSE("Dual BSD/GPL" ); |
775 | MODULE_ALIAS("platform:ucsi-stm32g0" ); |
776 | |