1 /*
2 * Copyright (c) 2023 Microchip Technology Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <string.h>
9 #include <zephyr/drivers/i2c.h>
10 #include <zephyr/irq.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/irq.h>
15 #include <zephyr/logging/log.h>
16 #include <zephyr/sys/sys_io.h>
17 #include <zephyr/sys/atomic.h>
18 #include <zephyr/sys/barrier.h>
19 LOG_MODULE_REGISTER(i2c_mchp, CONFIG_I2C_LOG_LEVEL);
20
21 #define DT_DRV_COMPAT microchip_mpfs_i2c
22
23 #define CORE_I2C_CTRL (0x00)
24 #define CORE_I2C_STATUS (0x04)
25 #define CORE_I2C_DATA (0x08)
26 #define CORE_I2C_ADDR_0 (0x0C)
27 #define CORE_I2C_FREQ (0x14)
28 #define CORE_I2C_GLITCHREG (0x18)
29 #define CORE_I2C_ADDR_1 (0x1C)
30
31 #define CTRL_CR0 BIT(0)
32 #define CTRL_CR1 BIT(1)
33 #define CTRL_AA BIT(2)
34 #define CTRL_SI BIT(3)
35 #define CTRL_STO BIT(4)
36 #define CTRL_STA BIT(5)
37 #define CTRL_ENS1 BIT(6)
38 #define CTRL_CR2 BIT(7)
39
40 #define STATUS_M_START_SENT (0x08)
41 #define STATUS_M_REPEATED_START_SENT (0x10)
42 #define STATUS_M_SLAW_ACK (0x18)
43 #define STATUS_M_SLAW_NACK (0x20)
44 #define STATUS_M_TX_DATA_ACK (0x28)
45 #define STATUS_M_TX_DATA_NACK (0x30)
46 #define STATUS_M_ARB_LOST (0x38)
47 #define STATUS_M_SLAR_ACK (0x40)
48 #define STATUS_M_SLAR_NACK (0x48)
49 #define STATUS_M_RX_DATA_ACKED (0x50)
50 #define STATUS_M_RX_DATA_NACKED (0x58)
51 #define STATUS_S_SLAW_ACKED (0x60)
52 #define STATUS_S_ARB_LOST_SLAW_ACKED (0x68)
53 #define STATUS_S_GENERAL_CALL_ACKED (0x70)
54 #define STATUS_S_ARB_LOST_GENERAL_CALL_ACKED (0x78)
55 #define STATUS_S_RX_DATA_ACKED (0x80)
56 #define STATUS_S_RX_DATA_NACKED (0x88)
57 #define STATUS_S_GENERAL_CALL_RX_DATA_ACKED (0x90)
58 #define STATUS_S_GENERAL_CALL_RX_DATA_NACKED (0x98)
59 #define STATUS_S_RX_STOP (0xA0)
60 #define STATUS_S_SLAR_ACKED (0xA8)
61 #define STATUS_S_ARB_LOST_SLAR_ACKED (0xB0)
62 #define STATUS_S_TX_DATA_ACK (0xB8)
63 #define STATUS_S_TX_DATA_NACK (0xC0)
64 #define STATUS_LAST_DATA_ACK (0xC8)
65
66 #define PCLK_DIV_960 (CTRL_CR2)
67 #define PCLK_DIV_256 (0)
68 #define PCLK_DIV_224 (CTRL_CR0)
69 #define PCLK_DIV_192 (CTRL_CR1)
70 #define PCLK_DIV_160 (CTRL_CR0 | CTRL_CR1)
71 #define PCLK_DIV_120 (CTRL_CR0 | CTRL_CR2)
72 #define PCLK_DIV_60 (CTRL_CR1 | CTRL_CR2)
73 #define BCLK_DIV_8 (CTRL_CR0 | CTRL_CR1 | CTRL_CR2)
74 #define CLK_MASK (CTRL_CR0 | CTRL_CR1 | CTRL_CR2)
75
76 /* -- Transactions types -- */
77 #define NO_TRANSACTION (0x00)
78 #define CONTROLLER_WRITE_TRANSACTION (0x01)
79 #define CONTROLLER_READ_TRANSACTION (0x02)
80 #define CONTROLLER_RANDOM_READ_TRANSACTION (0x03)
81 #define WRITE_TARGET_TRANSACTION (0x04)
82 #define READ_TARGET_TRANSACTION (0x05)
83
84 #define MSS_I2C_RELEASE_BUS (0x00)
85 #define MSS_I2C_HOLD_BUS (0x01)
86 #define TARGET_ADDR_SHIFT (0x01)
87
88 #define MSS_I2C_SUCCESS (0x00)
89 #define MSS_I2C_IN_PROGRESS (0x01)
90 #define MSS_I2C_FAILED (0x02)
91 #define MSS_I2C_TIMED_OUT (0x03)
92
93 struct mss_i2c_config {
94 uint32_t clock_freq;
95 uintptr_t i2c_base_addr;
96 uint32_t i2c_irq_base;
97 };
98
99 struct mss_i2c_data {
100 uint8_t ser_address;
101 uint8_t target_addr;
102 uint8_t options;
103 uint8_t transaction;
104 const uint8_t *controller_tx_buffer;
105 uint16_t controller_tx_size;
106 uint16_t controller_tx_idx;
107 uint8_t dir;
108 uint8_t *controller_rx_buffer;
109 uint16_t controller_rx_size;
110 uint16_t controller_rx_idx;
111 atomic_t controller_status;
112 uint32_t controller_timeout_ms;
113 const uint8_t *target_tx_buffer;
114 uint16_t target_tx_size;
115 uint16_t target_tx_idx;
116 uint8_t *target_rx_buffer;
117 uint16_t target_rx_size;
118 uint16_t target_rx_idx;
119 atomic_t target_status;
120 uint8_t target_mem_offset_length;
121 uint8_t is_target_enabled;
122 uint8_t bus_status;
123 uint8_t is_transaction_pending;
124 uint8_t pending_transaction;
125
126 sys_slist_t cb;
127 };
128
129
mss_i2c_configure(const struct device * dev,uint32_t dev_config_raw)130 static int mss_i2c_configure(const struct device *dev, uint32_t dev_config_raw)
131 {
132 const struct mss_i2c_config *cfg = dev->config;
133
134 uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
135
136 switch (I2C_SPEED_GET(dev_config_raw)) {
137 case I2C_SPEED_STANDARD:
138 sys_write8((ctrl | PCLK_DIV_960), cfg->i2c_base_addr + CORE_I2C_CTRL);
139 break;
140 case I2C_SPEED_FAST:
141 sys_write8((ctrl | PCLK_DIV_256), cfg->i2c_base_addr + CORE_I2C_CTRL);
142 break;
143 default:
144 return -EINVAL;
145 }
146
147 return 0;
148 }
149
mss_wait_complete(const struct device * dev)150 static int mss_wait_complete(const struct device *dev)
151 {
152 struct mss_i2c_data *const data = dev->data;
153 atomic_t i2c_status = 0;
154
155 do {
156 i2c_status = atomic_get(&data->controller_status);
157 } while (i2c_status == MSS_I2C_IN_PROGRESS);
158
159 return i2c_status;
160 }
161
mss_i2c_read(const struct device * dev,uint8_t serial_addr,uint8_t * read_buffer,uint32_t read_size)162 static int mss_i2c_read(const struct device *dev, uint8_t serial_addr, uint8_t *read_buffer,
163 uint32_t read_size)
164 {
165 struct mss_i2c_data *const data = dev->data;
166 const struct mss_i2c_config *cfg = dev->config;
167
168 uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
169
170 data->target_addr = serial_addr << TARGET_ADDR_SHIFT;
171 data->pending_transaction = CONTROLLER_READ_TRANSACTION;
172 data->dir = I2C_MSG_READ;
173 data->controller_rx_buffer = read_buffer;
174 data->controller_rx_size = read_size;
175 data->controller_rx_idx = 0u;
176
177 sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL);
178
179 return 0;
180 }
181
mss_i2c_write(const struct device * dev,uint8_t serial_addr,uint8_t * tx_buffer,uint32_t tx_num_write)182 static int mss_i2c_write(const struct device *dev, uint8_t serial_addr, uint8_t *tx_buffer,
183 uint32_t tx_num_write)
184 {
185 struct mss_i2c_data *const data = dev->data;
186 const struct mss_i2c_config *cfg = dev->config;
187 uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
188
189 atomic_t target_status = data->target_status;
190
191 if (data->transaction == NO_TRANSACTION) {
192 data->transaction = CONTROLLER_WRITE_TRANSACTION;
193 }
194
195 data->pending_transaction = CONTROLLER_WRITE_TRANSACTION;
196 data->target_addr = serial_addr << TARGET_ADDR_SHIFT;
197 data->dir = I2C_MSG_WRITE;
198 data->controller_tx_buffer = tx_buffer;
199 data->controller_tx_size = tx_num_write;
200 data->controller_tx_idx = 0u;
201 atomic_set(&data->controller_status, MSS_I2C_IN_PROGRESS);
202
203 if (target_status == MSS_I2C_IN_PROGRESS) {
204 data->is_transaction_pending = CONTROLLER_WRITE_TRANSACTION;
205 } else {
206 sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL);
207 }
208
209 if (data->bus_status == MSS_I2C_HOLD_BUS) {
210 sys_write8((ctrl & ~CTRL_SI), cfg->i2c_base_addr + CORE_I2C_CTRL);
211 }
212
213 return 0;
214 }
215
216
mss_i2c_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)217 static int mss_i2c_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs,
218 uint16_t addr)
219 {
220 for (int i = 0; i < num_msgs; i++) {
221 struct i2c_msg *current = &msgs[i];
222
223 if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
224 mss_i2c_read(dev, addr, current->buf, current->len);
225 mss_wait_complete(dev);
226 } else {
227 mss_i2c_write(dev, addr, current->buf, current->len);
228 mss_wait_complete(dev);
229 }
230 }
231
232 return 0;
233 }
234
235 static DEVICE_API(i2c, mss_i2c_driver_api) = {
236 .configure = mss_i2c_configure,
237 .transfer = mss_i2c_transfer,
238 #ifdef CONFIG_I2C_RTIO
239 .iodev_submit = i2c_iodev_submit_fallback,
240 #endif
241 };
242
mss_i2c_reset(const struct device * dev)243 static void mss_i2c_reset(const struct device *dev)
244 {
245 const struct mss_i2c_config *cfg = dev->config;
246 uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
247
248 sys_write8((ctrl & ~CTRL_ENS1), cfg->i2c_base_addr + CORE_I2C_CTRL);
249
250 ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
251
252 sys_write8((ctrl | CTRL_ENS1), cfg->i2c_base_addr + CORE_I2C_CTRL);
253 }
254
255
mss_i2c_irq_handler(const struct device * dev)256 static void mss_i2c_irq_handler(const struct device *dev)
257 {
258 struct mss_i2c_data *const data = dev->data;
259 const struct mss_i2c_config *cfg = dev->config;
260
261 uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
262
263 uint8_t status = sys_read8(cfg->i2c_base_addr + CORE_I2C_STATUS);
264
265 uint8_t hold_bus = 0;
266
267 switch (status) {
268 case STATUS_M_START_SENT:
269 case STATUS_M_REPEATED_START_SENT:
270 sys_write8((ctrl & ~CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL);
271
272 sys_write8(data->target_addr | data->dir, cfg->i2c_base_addr + CORE_I2C_DATA);
273
274 data->controller_tx_idx = 0;
275 data->controller_rx_idx = 0;
276
277 data->is_transaction_pending = false;
278 data->transaction = data->pending_transaction;
279 break;
280 case STATUS_M_ARB_LOST:
281 sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL);
282 LOG_WRN("lost arbitration: %x\n", status);
283 break;
284 case STATUS_M_SLAW_ACK:
285 case STATUS_M_TX_DATA_ACK:
286 if (data->controller_tx_idx < data->controller_tx_size) {
287 sys_write8(data->controller_tx_buffer[data->controller_tx_idx],
288 cfg->i2c_base_addr + CORE_I2C_DATA);
289
290 data->controller_tx_idx++;
291
292 } else if (data->transaction == CONTROLLER_RANDOM_READ_TRANSACTION) {
293 data->dir = I2C_MSG_READ;
294 sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL);
295
296 } else {
297 data->transaction = NO_TRANSACTION;
298 hold_bus = data->options & MSS_I2C_HOLD_BUS;
299 data->bus_status = hold_bus;
300
301 if (hold_bus == MSS_I2C_RELEASE_BUS) {
302 sys_write8((ctrl | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL);
303 }
304 }
305 atomic_set(&data->controller_status, MSS_I2C_SUCCESS);
306 break;
307 case STATUS_M_TX_DATA_NACK:
308 case STATUS_M_SLAR_NACK:
309 case STATUS_M_SLAW_NACK:
310 sys_write8((ctrl | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL);
311 atomic_set(&data->controller_status, MSS_I2C_FAILED);
312 data->transaction = NO_TRANSACTION;
313 break;
314 case STATUS_M_SLAR_ACK:
315 if (data->controller_rx_size > 1u) {
316 sys_write8((ctrl | CTRL_AA), cfg->i2c_base_addr + CORE_I2C_CTRL);
317
318 } else if (data->controller_rx_size == 1u) {
319 sys_write8((ctrl & ~CTRL_AA), cfg->i2c_base_addr + CORE_I2C_CTRL);
320
321 } else {
322 sys_write8((ctrl | CTRL_AA | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL);
323 atomic_set(&data->controller_status, MSS_I2C_SUCCESS);
324 data->transaction = NO_TRANSACTION;
325 }
326 break;
327 case STATUS_M_RX_DATA_ACKED:
328 data->controller_rx_buffer[data->controller_rx_idx] =
329 sys_read8(cfg->i2c_base_addr + CORE_I2C_DATA);
330
331 data->controller_rx_idx++;
332
333 /* Second Last byte */
334 if (data->controller_rx_idx >= (data->controller_rx_size - 1u)) {
335 sys_write8((ctrl & ~CTRL_AA), cfg->i2c_base_addr + CORE_I2C_CTRL);
336 } else {
337 atomic_set(&data->controller_status, MSS_I2C_IN_PROGRESS);
338 }
339 break;
340 case STATUS_M_RX_DATA_NACKED:
341
342 data->controller_rx_buffer[data->controller_rx_idx] =
343 sys_read8(cfg->i2c_base_addr + CORE_I2C_DATA);
344
345 hold_bus = data->options & MSS_I2C_HOLD_BUS;
346 data->bus_status = hold_bus;
347
348 if (hold_bus == 0u) {
349 sys_write8((ctrl | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL);
350 }
351
352 data->transaction = NO_TRANSACTION;
353 atomic_set(&data->controller_status, MSS_I2C_SUCCESS);
354 break;
355 default:
356 break;
357 }
358
359 ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL);
360
361 sys_write8((ctrl & ~CTRL_SI), cfg->i2c_base_addr + CORE_I2C_CTRL);
362 }
363
364 #define MSS_I2C_INIT(n) \
365 static int mss_i2c_init_##n(const struct device *dev) \
366 { \
367 mss_i2c_reset(dev); \
368 \
369 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), mss_i2c_irq_handler, \
370 DEVICE_DT_INST_GET(n), 0); \
371 \
372 irq_enable(DT_INST_IRQN(n)); \
373 \
374 return 0; \
375 } \
376 \
377 static struct mss_i2c_data mss_i2c_data_##n; \
378 \
379 static const struct mss_i2c_config mss_i2c_config_##n = { \
380 .i2c_base_addr = DT_INST_REG_ADDR(n), \
381 .i2c_irq_base = DT_INST_IRQN(n), \
382 .clock_freq = DT_INST_PROP(n, clock_frequency), \
383 }; \
384 \
385 I2C_DEVICE_DT_INST_DEFINE(n, mss_i2c_init_##n, NULL, &mss_i2c_data_##n, \
386 &mss_i2c_config_##n, PRE_KERNEL_1, CONFIG_I2C_INIT_PRIORITY, \
387 &mss_i2c_driver_api);
388
389 DT_INST_FOREACH_STATUS_OKAY(MSS_I2C_INIT)
390