10
10
#include <zephyr/drivers/pinctrl.h>
11
11
#include <zephyr/kernel.h>
12
12
#include <zephyr/logging/log.h>
13
- #if defined(CONFIG_I2C_SILABS_DMA )
14
13
#include <zephyr/drivers/dma.h>
15
- #endif
16
14
#include <zephyr/drivers/clock_control.h>
17
15
#include <zephyr/drivers/clock_control/clock_control_silabs.h>
18
16
#include <zephyr/pm/device.h>
19
17
#include <zephyr/pm/device_runtime.h>
20
18
#include <zephyr/pm/policy.h>
21
- #include <sl_hal_i2c.h>
22
19
#include <sl_i2c.h>
23
- #include <sl_status.h>
24
20
#include <sli_i2c.h>
25
21
26
22
#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
@@ -36,7 +32,7 @@ struct i2c_silabs_dma_config {
36
32
/* Structure for I2C device configuration */
37
33
struct i2c_silabs_dev_config {
38
34
const struct pinctrl_dev_config * pcfg ; /* Pin configuration for the I2C instance */
39
- I2C_TypeDef * base ; /* I2C peripheral base address */
35
+ sl_peripheral_t peripheral ; /* I2C peripheral structure */
40
36
uint32_t bitrate ; /* I2C bitrate (clock frequency) */
41
37
void (* irq_config_func )(void ); /* IRQ configuration function */
42
38
const struct device * clock ; /* Clock device */
@@ -47,11 +43,12 @@ struct i2c_silabs_dev_config {
47
43
struct i2c_silabs_dev_data {
48
44
struct k_sem bus_lock ; /* Semaphore to lock the I2C bus */
49
45
struct k_sem transfer_sem ; /* Semaphore to manage transfer */
50
- sli_i2c_instance_t i2c_instance ; /* I2C instance structure */
46
+ sl_i2c_handle_t i2c_handle ; /* I2C handle structure */
51
47
struct i2c_silabs_dma_config dma_rx ; /* DMA configuration for RX */
52
48
struct i2c_silabs_dma_config dma_tx ; /* DMA configuration for TX */
53
49
bool asynchronous ; /* Indicates if transfer is asynchronous */
54
50
bool last_transfer ; /* Transfer is the last in the sequence */
51
+ bool is_10bit_addr ; /* Indicates if addr is 7-bit or 10-bit */
55
52
#if defined CONFIG_I2C_CALLBACK
56
53
i2c_callback_t callback ; /* I2C callback function pointer */
57
54
void * callback_context ; /* Context for I2C callback */
@@ -64,15 +61,15 @@ static int i2c_silabs_pm_action(const struct device *dev, enum pm_device_action
64
61
65
62
static bool i2c_silabs_is_dma_enabled_instance (const struct device * dev )
66
63
{
67
- #ifdef CONFIG_I2C_SILABS_DMA
68
64
struct i2c_silabs_dev_data * data = dev -> data ;
65
+
66
+ if (!IS_ENABLED (CONFIG_I2C_SILABS_DMA )) {
67
+ return false;
68
+ }
69
69
70
70
__ASSERT_NO_MSG (!!data -> dma_tx .dma_dev == !!data -> dma_rx .dma_dev );
71
71
72
72
return data -> dma_rx .dma_dev != NULL ;
73
- #else
74
- return false;
75
- #endif
76
73
}
77
74
78
75
static void i2c_silabs_pm_policy_state_lock_get (const struct device * dev )
@@ -92,18 +89,17 @@ static int i2c_silabs_dev_configure(const struct device *dev, uint32_t dev_confi
92
89
{
93
90
const struct i2c_silabs_dev_config * config = dev -> config ;
94
91
struct i2c_silabs_dev_data * data = dev -> data ;
95
- sl_i2c_init_params_t init_params ;
96
92
97
93
/* Determine the I2C speed and corresponding baudrate */
98
94
switch (I2C_SPEED_GET (dev_config )) {
99
95
case I2C_SPEED_STANDARD :
100
- init_params . freq_mode = SL_I2C_FREQ_STANDARD_MODE ;
96
+ data -> i2c_handle . frequency_mode = SL_I2C_FREQ_STANDARD_MODE ;
101
97
break ;
102
98
case I2C_SPEED_FAST :
103
- init_params . freq_mode = SL_I2C_FREQ_FAST_MODE ;
99
+ data -> i2c_handle . frequency_mode = SL_I2C_FREQ_FAST_MODE ;
104
100
break ;
105
101
case I2C_SPEED_FAST_PLUS :
106
- init_params . freq_mode = SL_I2C_FREQ_FASTPLUS_MODE ;
102
+ data -> i2c_handle . frequency_mode = SL_I2C_FREQ_FASTPLUS_MODE ;
107
103
break ;
108
104
default :
109
105
return - EINVAL ;
@@ -112,19 +108,17 @@ static int i2c_silabs_dev_configure(const struct device *dev, uint32_t dev_confi
112
108
/* Take the bus lock semaphore to ensure exclusive access */
113
109
k_sem_take (& data -> bus_lock , K_FOREVER );
114
110
/* Initialize I2C parameters */
115
- init_params .i2c_base_addr = config -> base ;
116
- data -> i2c_instance .i2c_base_addr = init_params .i2c_base_addr ;
111
+ data -> i2c_handle .i2c_peripheral = config -> peripheral ;
117
112
118
113
/* Set the operating mode (leader or follower) */
119
114
#if defined(CONFIG_I2C_TARGET )
120
- init_params .operating_mode = SL_I2C_FOLLOWER_MODE ;
115
+ data -> i2c_handle .operating_mode = SL_I2C_FOLLOWER_MODE ;
121
116
#else
122
- init_params .operating_mode = SL_I2C_LEADER_MODE ;
117
+ data -> i2c_handle .operating_mode = SL_I2C_LEADER_MODE ;
123
118
#endif /* CONFIG_I2C_TARGET */
124
- data -> i2c_instance .operating_mode = init_params .operating_mode ;
125
119
126
120
/* Configure the I2C instance */
127
- sli_i2c_instance_configuration ( & init_params );
121
+ sli_i2c_init_core ( & data -> i2c_handle );
128
122
129
123
/* Release the bus lock semaphore */
130
124
k_sem_give (& data -> bus_lock );
@@ -137,25 +131,22 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
137
131
uint16_t addr , i2c_callback_t cb , void * userdata ,
138
132
bool asynchronous )
139
133
{
140
- #if defined(CONFIG_I2C_SILABS_DMA )
141
134
struct i2c_silabs_dev_data * data = dev -> data ;
142
135
__maybe_unused const struct i2c_silabs_dev_config * config = dev -> config ;
143
- sl_i2c_handle_t * i2c_handle = (sl_i2c_handle_t * )& data -> i2c_instance ;
144
136
#if defined(CONFIG_I2C_CALLBACK )
145
137
data -> callback_invoked = false;
146
138
#endif
147
139
data -> pm_lock_done = false;
148
140
uint8_t i = 0 ;
149
141
int err = 0 ;
150
142
143
+ if (!IS_ENABLED (CONFIG_I2C_SILABS_DMA )) {
144
+ return - ENOTSUP ;
145
+ }
146
+
151
147
/* Get the power management policy state lock */
152
148
i2c_silabs_pm_policy_state_lock_get (dev );
153
149
154
- #if defined(CONFIG_I2C_TARGET )
155
- /* Set follower address in target mode */
156
- sli_i2c_set_follower_address (config -> base , addr , data -> i2c_instance .is_10bit_addr );
157
- #endif /* CONFIG_I2C_TARGET */
158
-
159
150
while (i < num_msgs ) {
160
151
uint8_t msgs_in_transfer = 1 ;
161
152
@@ -167,33 +158,49 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
167
158
data -> last_transfer = (i + msgs_in_transfer ) == num_msgs ;
168
159
169
160
if (msgs_in_transfer == 2 ) {
170
- if (sl_i2c_transfer_non_blocking ( i2c_handle , msgs [ i ]. buf , msgs [ i ]. len ,
171
- msgs [i + 1 ].buf , msgs [i + 1 ].len , NULL ,
172
- NULL ) != 0 ) {
161
+ if (sl_i2c_leader_transfer_non_blocking (
162
+ & data -> i2c_handle , addr , msgs [i ].buf , msgs [i ].len ,
163
+ msgs [ i + 1 ]. buf , msgs [ i + 1 ]. len , NULL ) != 0 ) {
173
164
k_sem_give (& data -> bus_lock );
174
165
return - EIO ;
175
166
}
176
167
} else if (msgs [i ].flags & I2C_MSG_READ ) {
177
168
/* Start DMA receive */
178
- if (sl_i2c_receive_non_blocking (i2c_handle , msgs [i ].buf , msgs [i ].len , NULL ,
179
- NULL ) != 0 ) {
169
+ #if defined(CONFIG_I2C_TARGET )
170
+ if (sl_i2c_follower_receive_non_blocking (& data -> i2c_handle , msgs [i ].buf ,
171
+ msgs [i ].len , NULL ) != 0 ) {
172
+ k_sem_give (& data -> bus_lock );
173
+ return - EIO ;
174
+ }
175
+ #else
176
+ if (sl_i2c_leader_receive_non_blocking (& data -> i2c_handle , addr , msgs [i ].buf ,
177
+ msgs [i ].len , NULL ) != 0 ) {
180
178
k_sem_give (& data -> bus_lock );
181
179
return - EIO ;
182
180
}
181
+ #endif
183
182
} else {
184
183
/* Start DMA send */
185
- if (sl_i2c_send_non_blocking (i2c_handle , msgs [i ].buf , msgs [i ].len , NULL ,
186
- NULL ) != 0 ) {
184
+ #if defined(CONFIG_I2C_TARGET )
185
+ if (sl_i2c_follower_send_non_blocking (& data -> i2c_handle , msgs [i ].buf ,
186
+ msgs [i ].len , NULL ) != 0 ) {
187
+ k_sem_give (& data -> bus_lock );
188
+ return - EIO ;
189
+ }
190
+ #else
191
+ if (sl_i2c_leader_send_non_blocking (& data -> i2c_handle , addr , msgs [i ].buf ,
192
+ msgs [i ].len , NULL ) != 0 ) {
187
193
k_sem_give (& data -> bus_lock );
188
194
return - EIO ;
189
195
}
196
+ #endif
190
197
}
191
198
if (!asynchronous ) {
192
199
/* Wait for DMA transfer to complete */
193
200
if (k_sem_take (& data -> transfer_sem , K_MSEC (CONFIG_I2C_SILABS_TIMEOUT ))) {
194
201
err = - ETIMEDOUT ;
195
202
}
196
- if (data -> i2c_instance .state == SLI_I2C_STATE_ERROR ) {
203
+ if (data -> i2c_handle .state == SL_I2C_STATE_ERROR ) {
197
204
err = - EIO ;
198
205
}
199
206
k_sem_reset (& data -> transfer_sem );
@@ -205,17 +212,13 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
205
212
}
206
213
207
214
return err ;
208
- #else
209
- return - ENOTSUP ;
210
- #endif /* CONFIG_I2C_SILABS_DMA */
211
215
}
212
216
213
217
/* Function to handle synchronous transfer */
214
218
static int i2c_silabs_transfer_sync (const struct device * dev , struct i2c_msg * msgs ,
215
219
uint8_t num_msgs , uint16_t addr )
216
220
{
217
221
struct i2c_silabs_dev_data * data = dev -> data ;
218
- sl_i2c_handle_t * i2c_handle = (sl_i2c_handle_t * )& data -> i2c_instance ;
219
222
uint8_t i = 0 ;
220
223
221
224
/* Get the power management policy state lock */
@@ -227,24 +230,46 @@ static int i2c_silabs_transfer_sync(const struct device *dev, struct i2c_msg *ms
227
230
if ((msgs [i ].flags & I2C_MSG_WRITE ) == 0 && (i + 1 < num_msgs ) &&
228
231
(msgs [i + 1 ].flags & I2C_MSG_READ )) {
229
232
msgs_in_transfer = 2 ;
230
- if (sl_i2c_transfer (i2c_handle , msgs [i ].buf , msgs [i ].len , msgs [i + 1 ].buf ,
231
- msgs [i + 1 ].len ) != 0 ) {
233
+ if (sl_i2c_leader_transfer_blocking (& data -> i2c_handle , addr , msgs [i ].buf ,
234
+ msgs [i ].len , msgs [i + 1 ].buf ,
235
+ msgs [i + 1 ].len ,
236
+ CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
232
237
k_sem_give (& data -> bus_lock );
233
238
return - EIO ;
234
239
}
235
240
i ++ ;
236
241
} else if (msgs [i ].flags & I2C_MSG_READ ) {
237
- if (sl_i2c_receive_blocking (i2c_handle , msgs [i ].buf , msgs [i ].len ,
238
- CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
242
+ #if defined(CONFIG_I2C_TARGET )
243
+ if (sl_i2c_follower_receive_blocking (& data -> i2c_handle , msgs [i ].buf ,
244
+ msgs [i ].len ,
245
+ CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
239
246
k_sem_give (& data -> bus_lock );
240
247
return - ETIMEDOUT ;
241
248
}
249
+ #else
250
+ if (sl_i2c_leader_receive_blocking (& data -> i2c_handle , addr , msgs [i ].buf ,
251
+ msgs [i ].len ,
252
+ CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
253
+ k_sem_give (& data -> bus_lock );
254
+ return - ETIMEDOUT ;
255
+ }
256
+ #endif
242
257
} else {
243
- if (sl_i2c_send_blocking (i2c_handle , msgs [i ].buf , msgs [i ].len ,
244
- CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
258
+ #if defined(CONFIG_I2C_TARGET )
259
+ if (sl_i2c_follower_send_blocking (& data -> i2c_handle , msgs [i ].buf ,
260
+ msgs [i ].len ,
261
+ CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
262
+ k_sem_give (& data -> bus_lock );
263
+ return - ETIMEDOUT ;
264
+ }
265
+ #else
266
+ if (sl_i2c_leader_send_blocking (& data -> i2c_handle , addr , msgs [i ].buf ,
267
+ msgs [i ].len ,
268
+ CONFIG_I2C_SILABS_TIMEOUT ) != 0 ) {
245
269
k_sem_give (& data -> bus_lock );
246
270
return - ETIMEDOUT ;
247
271
}
272
+ #endif
248
273
}
249
274
i += msgs_in_transfer ;
250
275
}
@@ -265,7 +290,6 @@ static int i2c_silabs_transfer_impl(const struct device *dev, struct i2c_msg *ms
265
290
{
266
291
struct i2c_silabs_dev_data * data = dev -> data ;
267
292
__maybe_unused const struct i2c_silabs_dev_config * config = dev -> config ;
268
- sl_i2c_handle_t * i2c_handle = (sl_i2c_handle_t * )& data -> i2c_instance ;
269
293
int ret = - EINVAL ; /* Initialize ret to a default error value */
270
294
271
295
/* Check for invalid number of messages */
@@ -276,9 +300,9 @@ static int i2c_silabs_transfer_impl(const struct device *dev, struct i2c_msg *ms
276
300
/* Check and set the address mode (7-bit or 10-bit) based on */
277
301
/* the provided address */
278
302
if (addr <= 0x7F ) {
279
- data -> i2c_instance . is_10bit_addr = false; /* 7-bit address */
303
+ data -> is_10bit_addr = false; /* 7-bit address */
280
304
} else if (addr <= 0x3FF ) {
281
- data -> i2c_instance . is_10bit_addr = true; /* 10-bit address */
305
+ data -> is_10bit_addr = true; /* 10-bit address */
282
306
} else {
283
307
return - EINVAL ;
284
308
}
@@ -292,11 +316,13 @@ static int i2c_silabs_transfer_impl(const struct device *dev, struct i2c_msg *ms
292
316
return ret ;
293
317
}
294
318
319
+ #if defined(CONFIG_I2C_TARGET )
295
320
/* Set the follower address */
296
- if (sl_i2c_set_follower_address (i2c_handle , addr ) != 0 ) {
321
+ if (sl_i2c_set_follower_address (& data -> i2c_handle , addr , data -> is_10bit_addr ) != 0 ) {
297
322
k_sem_give (& data -> bus_lock );
298
323
return - EINVAL ;
299
324
}
325
+ #endif
300
326
301
327
if (i2c_silabs_is_dma_enabled_instance (dev )) {
302
328
/* DMA transfer handle a/synchronous transfers */
@@ -373,25 +399,23 @@ static int i2c_silabs_dev_init(const struct device *dev)
373
399
return - EINVAL ;
374
400
}
375
401
376
- #if defined(CONFIG_I2C_SILABS_DMA )
377
- if (i2c_silabs_is_dma_enabled_instance (dev )) {
402
+ if (IS_ENABLED (CONFIG_I2C_SILABS_DMA ) && i2c_silabs_is_dma_enabled_instance (dev )) {
378
403
if (!device_is_ready (data -> dma_rx .dma_dev ) ||
379
404
!device_is_ready (data -> dma_tx .dma_dev )) {
380
405
return - ENODEV ;
381
406
}
382
407
data -> dma_rx .dma_channel = dma_request_channel (data -> dma_rx .dma_dev , NULL );
383
- data -> i2c_instance .dma_channel .dma_rx_channel = data -> dma_rx .dma_channel ;
408
+ data -> i2c_handle .dma_channel .dma_rx_channel = data -> dma_rx .dma_channel ;
384
409
385
410
data -> dma_tx .dma_channel = dma_request_channel (data -> dma_tx .dma_dev , NULL );
386
- data -> i2c_instance .dma_channel .dma_tx_channel = data -> dma_tx .dma_channel ;
411
+ data -> i2c_handle .dma_channel .dma_tx_channel = data -> dma_tx .dma_channel ;
387
412
388
413
if (data -> dma_rx .dma_channel < 0 || data -> dma_tx .dma_channel < 0 ) {
389
414
dma_release_channel (data -> dma_rx .dma_dev , data -> dma_rx .dma_channel );
390
415
dma_release_channel (data -> dma_tx .dma_dev , data -> dma_tx .dma_channel );
391
416
return - EAGAIN ;
392
417
}
393
418
}
394
- #endif /* CONFIG_I2C_SILABS_DMA */
395
419
396
420
/* Configure IRQ */
397
421
config -> irq_config_func ();
@@ -445,15 +469,14 @@ static int i2c_silabs_pm_action(const struct device *dev, enum pm_device_action
445
469
void i2c_silabs_isr_handler (const struct device * dev )
446
470
{
447
471
struct i2c_silabs_dev_data * data = dev -> data ;
448
- sli_i2c_instance_t * sl_i2c_instance = & data -> i2c_instance ;
472
+ sl_i2c_handle_t * sl_i2c_handle = & data -> i2c_handle ;
449
473
450
474
#if defined(CONFIG_I2C_TARGET )
451
- sli_i2c_follower_dispatch_interrupt (sl_i2c_instance );
475
+ sli_i2c_follower_dispatch_interrupt (sl_i2c_handle );
452
476
#else
453
- sli_i2c_leader_dispatch_interrupt (sl_i2c_instance );
477
+ sli_i2c_leader_dispatch_interrupt (sl_i2c_handle );
454
478
#endif
455
- if (sl_i2c_instance -> transfer_event != SL_I2C_EVENT_IN_PROGRESS &&
456
- sl_i2c_instance -> rstart == 0 ) {
479
+ if (sl_i2c_handle -> event != SL_I2C_EVENT_IN_PROGRESS ) {
457
480
if (!data -> asynchronous ) {
458
481
k_sem_give (& data -> transfer_sem );
459
482
}
@@ -462,9 +485,9 @@ void i2c_silabs_isr_handler(const struct device *dev)
462
485
int err = 0 ;
463
486
464
487
data -> callback_invoked = true;
465
- if (sl_i2c_instance -> transfer_event == SL_I2C_EVENT_ARBITRATION_LOST ||
466
- sl_i2c_instance -> transfer_event == SL_I2C_EVENT_BUS_ERROR ||
467
- sl_i2c_instance -> transfer_event == SL_I2C_EVENT_INVALID_ADDR ) {
488
+ if (sl_i2c_handle -> event == SL_I2C_EVENT_ARBITRATION_LOST ||
489
+ sl_i2c_handle -> event == SL_I2C_EVENT_BUS_ERROR ||
490
+ sl_i2c_handle -> event == SL_I2C_EVENT_INVALID_ADDR ) {
468
491
err = - EIO ;
469
492
}
470
493
data -> callback (dev , err , data -> callback_context );
@@ -506,7 +529,7 @@ static DEVICE_API(i2c, i2c_silabs_dev_driver_api) = {
506
529
\
507
530
static const struct i2c_silabs_dev_config i2c_silabs_dev_config_##idx = { \
508
531
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
509
- .base = (I2C_TypeDef *)DT_INST_REG_ADDR( idx), \
532
+ .peripheral = SL_PERIPHERAL_I2C## idx, \
510
533
.bitrate = DT_INST_PROP(idx, clock_frequency), \
511
534
.irq_config_func = i2c_silabs_irq_config_##idx, \
512
535
.clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \
0 commit comments