1 /*
2 * Copyright (c) 2021 Telink Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT telink_b91_i2c
8
9 #include "i2c.h"
10 #include "clock.h"
11
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(i2c_telink);
14
15 #include <drivers/i2c.h>
16 #include "i2c-priv.h"
17 #include <drivers/pinmux.h>
18 #include <dt-bindings/pinctrl/b91-pinctrl.h>
19
20 /* I2C configuration structure */
21 struct i2c_b91_cfg {
22 uint32_t bitrate;
23 const uint32_t *pinctrl_list;
24 size_t pinctrl_list_size;
25 };
26
27 /* I2C data structure */
28 struct i2c_b91_data {
29 struct k_sem mutex;
30 };
31
32 /* API implementation: configure */
i2c_b91_configure(const struct device * dev,uint32_t dev_config)33 static int i2c_b91_configure(const struct device *dev, uint32_t dev_config)
34 {
35 ARG_UNUSED(dev);
36
37 uint32_t i2c_speed = 0u;
38
39 /* check address size */
40 if (dev_config & I2C_ADDR_10_BITS) {
41 LOG_ERR("10-bits address is not supported");
42 return -ENOTSUP;
43 }
44
45 /* check I2C Master/Slave configuration */
46 if (!(dev_config & I2C_MODE_MASTER)) {
47 LOG_ERR("I2C slave is not implemented");
48 return -ENOTSUP;
49 }
50
51 /* check i2c speed */
52 switch (I2C_SPEED_GET(dev_config)) {
53 case I2C_SPEED_STANDARD:
54 i2c_speed = 100000u;
55 break;
56
57 case I2C_SPEED_FAST:
58 i2c_speed = 400000U;
59 break;
60
61 case I2C_SPEED_FAST_PLUS:
62 case I2C_SPEED_HIGH:
63 case I2C_SPEED_ULTRA:
64 default:
65 LOG_ERR("Unsupported I2C speed requested");
66 return -ENOTSUP;
67 }
68
69 /* init i2c */
70 i2c_master_init();
71 i2c_set_master_clk((unsigned char)(sys_clk.pclk * 1000 * 1000 / (4 * i2c_speed)));
72
73 return 0;
74 }
75
76 /* API implementation: transfer */
i2c_b91_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)77 static int i2c_b91_transfer(const struct device *dev,
78 struct i2c_msg *msgs,
79 uint8_t num_msgs,
80 uint16_t addr)
81 {
82 int status = 0;
83 uint8_t send_stop = 0;
84 struct i2c_b91_data *data = dev->data;
85
86 /* get the mutex */
87 k_sem_take(&data->mutex, K_FOREVER);
88
89 /* loop through all messages */
90 for (int i = 0; i < num_msgs; i++) {
91 /* check addr size */
92 if (msgs[i].flags & I2C_MSG_ADDR_10_BITS) {
93 LOG_ERR("10-bits address is not supported");
94 k_sem_give(&data->mutex);
95 return -ENOTSUP;
96 }
97
98 /* config stop bit */
99 send_stop = msgs[i].flags & I2C_MSG_STOP ? 1 : 0;
100 i2c_master_send_stop(send_stop);
101
102 /* transfer data */
103 if (msgs[i].flags & I2C_MSG_READ) {
104 status = i2c_master_read(addr, msgs[i].buf, msgs[i].len);
105 } else {
106 status = i2c_master_write(addr, msgs[i].buf, msgs[i].len);
107 }
108
109 /* check status */
110 if (!status) {
111 LOG_ERR("Failed to transfer I2C messages\n");
112 k_sem_give(&data->mutex);
113 return -EIO;
114 }
115 }
116
117 /* release the mutex */
118 k_sem_give(&data->mutex);
119
120 return 0;
121 };
122
123 /* API implementation: init */
i2c_b91_init(const struct device * dev)124 static int i2c_b91_init(const struct device *dev)
125 {
126 int status = 0;
127 const struct device *pinmux;
128 const struct i2c_b91_cfg *cfg = dev->config;
129 struct i2c_b91_data *data = dev->data;
130 uint32_t dev_config = (I2C_MODE_MASTER | i2c_map_dt_bitrate(cfg->bitrate));
131
132 /* init mutex */
133 k_sem_init(&data->mutex, 1, 1);
134
135 /* config i2c on startup */
136 status = i2c_b91_configure(dev, dev_config);
137 if (status != 0) {
138 LOG_ERR("Failed to configure I2C on init");
139 return status;
140 }
141
142 /* get pinmux driver */
143 pinmux = DEVICE_DT_GET(DT_NODELABEL(pinmux));
144 if (!device_is_ready(pinmux)) {
145 return -ENODEV;
146 }
147
148 /* config pins */
149 for (int i = 0; i < cfg->pinctrl_list_size; i++) {
150 pinmux_pin_set(pinmux, B91_PINMUX_GET_PIN(cfg->pinctrl_list[i]),
151 B91_PINMUX_GET_FUNC(cfg->pinctrl_list[i]));
152 }
153
154 return 0;
155 }
156
157 /* I2C driver APIs structure */
158 static const struct i2c_driver_api i2c_b91_api = {
159 .configure = i2c_b91_configure,
160 .transfer = i2c_b91_transfer,
161 };
162
163 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1,
164 "unsupported I2C instance");
165
166 /* I2C driver registration */
167 #define I2C_B91_INIT(inst) \
168 \
169 static const uint32_t i2c_pins_##inst[] = \
170 B91_PINMUX_DT_INST_GET_ARRAY(inst, 0); \
171 \
172 static struct i2c_b91_data i2c_b91_data_##inst; \
173 \
174 static struct i2c_b91_cfg i2c_b91_cfg_##inst = { \
175 .bitrate = DT_INST_PROP(inst, clock_frequency), \
176 .pinctrl_list_size = ARRAY_SIZE(i2c_pins_##inst), \
177 .pinctrl_list = i2c_pins_##inst \
178 }; \
179 \
180 DEVICE_DT_INST_DEFINE(inst, i2c_b91_init, \
181 NULL, \
182 &i2c_b91_data_##inst, \
183 &i2c_b91_cfg_##inst, \
184 POST_KERNEL, \
185 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
186 &i2c_b91_api);
187
188 DT_INST_FOREACH_STATUS_OKAY(I2C_B91_INIT)
189