1 /*
2 * Copyright (c) 2024 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/device.h>
8 #include <zephyr/drivers/i2c.h>
9 #include <zephyr/logging/log_backend.h>
10 #include <zephyr/logging/log_core.h>
11 #include <zephyr/logging/log_ctrl.h>
12 #include <zephyr/logging/log_msg.h>
13 #include <zephyr/logging/log_output.h>
14 #include <zephyr/logging/log_backend_std.h>
15 #include <zephyr/sys/__assert.h>
16 #include <sedi_driver_i2c.h>
17
18 static uint32_t log_format_current = CONFIG_LOG_BACKEND_I2C_OUTPUT_DEFAULT;
19 static uint8_t log_i2c_buf[CONFIG_LOG_I2C_MAX_MSG_LEN];
20 static bool panic_mode;
21 static uint8_t i2c_bus;
22
log_i2c_char_out(uint8_t * data,size_t length,void * ctx)23 static int log_i2c_char_out(uint8_t *data, size_t length, void *ctx)
24 {
25 ARG_UNUSED(ctx);
26
27 __ASSERT_NO_MSG(length > 0 && length <= CONFIG_LOG_I2C_MAX_MSG_LEN);
28
29 sedi_i2c_master_poll_write(i2c_bus, CONFIG_LOG_I2C_DEV_ADDR,
30 data, length, false);
31
32 return length;
33 }
34
35 LOG_OUTPUT_DEFINE(log_output_i2c, log_i2c_char_out,
36 log_i2c_buf, CONFIG_LOG_I2C_MAX_MSG_LEN);
37
log_i2c_panic(struct log_backend const * const backend)38 static void log_i2c_panic(struct log_backend const *const backend)
39 {
40 ARG_UNUSED(backend);
41
42 panic_mode = true;
43 sedi_i2c_control(i2c_bus, SEDI_I2C_ABORT_TRANSFER, 0);
44 log_backend_std_panic(&log_output_i2c);
45 }
46
log_i2c_dropped(const struct log_backend * const backend,uint32_t cnt)47 static void log_i2c_dropped(const struct log_backend *const backend,
48 uint32_t cnt)
49 {
50 ARG_UNUSED(backend);
51
52 log_backend_std_dropped(&log_output_i2c, cnt);
53 }
54
process(const struct log_backend * const backend,union log_msg_generic * msg)55 static void process(const struct log_backend *const backend,
56 union log_msg_generic *msg)
57 {
58 uint32_t flags = log_backend_std_get_flags();
59 log_format_func_t log_output_func = log_format_func_t_get(log_format_current);
60
61 log_output_func(&log_output_i2c, &msg->log, flags);
62 }
63
format_set(const struct log_backend * const backend,uint32_t log_type)64 static int format_set(const struct log_backend *const backend, uint32_t log_type)
65 {
66 log_format_current = log_type;
67 return 0;
68 }
69
log_backend_i2c_init(const struct log_backend * const backend)70 static void log_backend_i2c_init(const struct log_backend *const backend)
71 {
72 #if DT_HAS_CHOSEN(zephyr_log_i2c)
73 uint32_t cfg = I2C_SPEED_SET(I2C_SPEED_FAST) | I2C_MODE_CONTROLLER;
74 int ret = i2c_configure(DEVICE_DT_GET(DT_CHOSEN(zephyr_log_i2c)), cfg);
75
76 if (ret) {
77 goto disable;
78 }
79
80 i2c_bus = DT_PROP(DT_CHOSEN(zephyr_log_i2c), peripheral_id);
81 panic_mode = false;
82
83 return;
84
85 disable:
86 #endif
87 /* No specified log i2c device or device not ready */
88 log_backend_disable(backend);
89 }
90
91 static const struct log_backend_api log_backend_i2c_api = {
92 .process = process,
93 .panic = log_i2c_panic,
94 .init = log_backend_i2c_init,
95 .dropped = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ? NULL : log_i2c_dropped,
96 .format_set = format_set,
97 };
98
99 LOG_BACKEND_DEFINE(log_backend_i2c, log_backend_i2c_api,
100 IS_ENABLED(CONFIG_LOG_BACKEND_I2C_AUTOSTART));
101