1b844655cSEtienne Carriere // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2b844655cSEtienne Carriere /*
3bdde1c99SEtienne Carriere * Copyright (c) 2017-2024, STMicroelectronics
4b844655cSEtienne Carriere *
5b844655cSEtienne Carriere * The driver API is defined in header file stm32_i2c.h.
6b844655cSEtienne Carriere *
7b844655cSEtienne Carriere * I2C bus driver does not register to the PM framework. It is the
8b844655cSEtienne Carriere * responsibility of the bus owner to call the related STM32 I2C driver
9b844655cSEtienne Carriere * API functions when bus suspends or resumes.
10b844655cSEtienne Carriere */
11b844655cSEtienne Carriere
12b844655cSEtienne Carriere #include <arm.h>
13*1e3057c6SEtienne Carriere #include <atomic.h>
14929ec061SEtienne Carriere #include <drivers/clk.h>
15929ec061SEtienne Carriere #include <drivers/clk_dt.h>
1673ba32ebSEtienne Carriere #include <drivers/pinctrl.h>
1773ba32ebSEtienne Carriere #include <drivers/stm32_gpio.h>
18b844655cSEtienne Carriere #include <drivers/stm32_i2c.h>
19b844655cSEtienne Carriere #include <io.h>
2037fbce01SEtienne Carriere #include <kernel/boot.h>
21b844655cSEtienne Carriere #include <kernel/delay.h>
22b844655cSEtienne Carriere #include <kernel/dt.h>
235bc9f8e5SEtienne Carriere #include <kernel/dt_driver.h>
24*1e3057c6SEtienne Carriere #include <kernel/interrupt.h>
25bdde1c99SEtienne Carriere #include <kernel/mutex_pm_aware.h>
26*1e3057c6SEtienne Carriere #include <kernel/notif.h>
27b844655cSEtienne Carriere #include <kernel/panic.h>
28*1e3057c6SEtienne Carriere #include <kernel/thread.h>
29b844655cSEtienne Carriere #include <libfdt.h>
30b844655cSEtienne Carriere #include <stdbool.h>
31b844655cSEtienne Carriere #include <stdlib.h>
32b844655cSEtienne Carriere #include <stm32_util.h>
33b844655cSEtienne Carriere #include <trace.h>
34b844655cSEtienne Carriere
35b844655cSEtienne Carriere /* STM32 I2C registers offsets */
36b844655cSEtienne Carriere #define I2C_CR1 0x00U
37b844655cSEtienne Carriere #define I2C_CR2 0x04U
38b844655cSEtienne Carriere #define I2C_OAR1 0x08U
39b844655cSEtienne Carriere #define I2C_OAR2 0x0CU
40b844655cSEtienne Carriere #define I2C_TIMINGR 0x10U
41b844655cSEtienne Carriere #define I2C_TIMEOUTR 0x14U
42b844655cSEtienne Carriere #define I2C_ISR 0x18U
43b844655cSEtienne Carriere #define I2C_ICR 0x1CU
44b844655cSEtienne Carriere #define I2C_PECR 0x20U
45b844655cSEtienne Carriere #define I2C_RXDR 0x24U
46b844655cSEtienne Carriere #define I2C_TXDR 0x28U
47c2e4eb43SAnton Rybakov #define I2C_SIZE 0x2CU
48b844655cSEtienne Carriere
49b844655cSEtienne Carriere /* Bit definition for I2C_CR1 register */
50b844655cSEtienne Carriere #define I2C_CR1_PE BIT(0)
51b844655cSEtienne Carriere #define I2C_CR1_TXIE BIT(1)
52b844655cSEtienne Carriere #define I2C_CR1_RXIE BIT(2)
53b844655cSEtienne Carriere #define I2C_CR1_ADDRIE BIT(3)
54b844655cSEtienne Carriere #define I2C_CR1_NACKIE BIT(4)
55b844655cSEtienne Carriere #define I2C_CR1_STOPIE BIT(5)
56b844655cSEtienne Carriere #define I2C_CR1_TCIE BIT(6)
57b844655cSEtienne Carriere #define I2C_CR1_ERRIE BIT(7)
58b844655cSEtienne Carriere #define I2C_CR1_DNF GENMASK_32(11, 8)
59b844655cSEtienne Carriere #define I2C_CR1_ANFOFF BIT(12)
60b844655cSEtienne Carriere #define I2C_CR1_SWRST BIT(13)
61b844655cSEtienne Carriere #define I2C_CR1_TXDMAEN BIT(14)
62b844655cSEtienne Carriere #define I2C_CR1_RXDMAEN BIT(15)
63b844655cSEtienne Carriere #define I2C_CR1_SBC BIT(16)
64b844655cSEtienne Carriere #define I2C_CR1_NOSTRETCH BIT(17)
65b844655cSEtienne Carriere #define I2C_CR1_WUPEN BIT(18)
66b844655cSEtienne Carriere #define I2C_CR1_GCEN BIT(19)
67b844655cSEtienne Carriere #define I2C_CR1_SMBHEN BIT(22)
68b844655cSEtienne Carriere #define I2C_CR1_SMBDEN BIT(21)
69b844655cSEtienne Carriere #define I2C_CR1_ALERTEN BIT(22)
70b844655cSEtienne Carriere #define I2C_CR1_PECEN BIT(23)
71b844655cSEtienne Carriere
72b844655cSEtienne Carriere /* Bit definition for I2C_CR2 register */
73b844655cSEtienne Carriere #define I2C_CR2_SADD GENMASK_32(9, 0)
74b844655cSEtienne Carriere #define I2C_CR2_RD_WRN BIT(10)
75b844655cSEtienne Carriere #define I2C_CR2_RD_WRN_OFFSET 10U
76b844655cSEtienne Carriere #define I2C_CR2_ADD10 BIT(11)
77b844655cSEtienne Carriere #define I2C_CR2_HEAD10R BIT(12)
78b844655cSEtienne Carriere #define I2C_CR2_START BIT(13)
79b844655cSEtienne Carriere #define I2C_CR2_STOP BIT(14)
80b844655cSEtienne Carriere #define I2C_CR2_NACK BIT(15)
81b844655cSEtienne Carriere #define I2C_CR2_NBYTES GENMASK_32(23, 16)
82b844655cSEtienne Carriere #define I2C_CR2_NBYTES_OFFSET 16U
83b844655cSEtienne Carriere #define I2C_CR2_RELOAD BIT(24)
84b844655cSEtienne Carriere #define I2C_CR2_AUTOEND BIT(25)
85b844655cSEtienne Carriere #define I2C_CR2_PECBYTE BIT(26)
86b844655cSEtienne Carriere
87b844655cSEtienne Carriere /* Bit definition for I2C_OAR1 register */
88b844655cSEtienne Carriere #define I2C_OAR1_OA1 GENMASK_32(9, 0)
89b844655cSEtienne Carriere #define I2C_OAR1_OA1MODE BIT(10)
90b844655cSEtienne Carriere #define I2C_OAR1_OA1EN BIT(15)
91b844655cSEtienne Carriere
92b844655cSEtienne Carriere /* Bit definition for I2C_OAR2 register */
93b844655cSEtienne Carriere #define I2C_OAR2_OA2 GENMASK_32(7, 1)
94b844655cSEtienne Carriere #define I2C_OAR2_OA2MSK GENMASK_32(10, 8)
95b844655cSEtienne Carriere #define I2C_OAR2_OA2NOMASK 0
96b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK01 BIT(8)
97b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK02 BIT(9)
98b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK03 GENMASK_32(9, 8)
99b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK04 BIT(10)
100b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10))
101b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10))
102b844655cSEtienne Carriere #define I2C_OAR2_OA2MASK07 GENMASK_32(10, 8)
103b844655cSEtienne Carriere #define I2C_OAR2_OA2EN BIT(15)
104b844655cSEtienne Carriere
105b844655cSEtienne Carriere /* Bit definition for I2C_TIMINGR register */
106b844655cSEtienne Carriere #define I2C_TIMINGR_SCLL GENMASK_32(7, 0)
107b844655cSEtienne Carriere #define I2C_TIMINGR_SCLH GENMASK_32(15, 8)
108b844655cSEtienne Carriere #define I2C_TIMINGR_SDADEL GENMASK_32(19, 16)
109b844655cSEtienne Carriere #define I2C_TIMINGR_SCLDEL GENMASK_32(23, 20)
110b844655cSEtienne Carriere #define I2C_TIMINGR_PRESC GENMASK_32(31, 28)
111b844655cSEtienne Carriere #define I2C_TIMINGR_SCLL_MAX (I2C_TIMINGR_SCLL + 1)
112b844655cSEtienne Carriere #define I2C_TIMINGR_SCLH_MAX ((I2C_TIMINGR_SCLH >> 8) + 1)
113b844655cSEtienne Carriere #define I2C_TIMINGR_SDADEL_MAX ((I2C_TIMINGR_SDADEL >> 16) + 1)
114b844655cSEtienne Carriere #define I2C_TIMINGR_SCLDEL_MAX ((I2C_TIMINGR_SCLDEL >> 20) + 1)
115b844655cSEtienne Carriere #define I2C_TIMINGR_PRESC_MAX ((I2C_TIMINGR_PRESC >> 28) + 1)
116b844655cSEtienne Carriere #define I2C_SET_TIMINGR_SCLL(n) ((n) & \
117b844655cSEtienne Carriere (I2C_TIMINGR_SCLL_MAX - 1))
118b844655cSEtienne Carriere #define I2C_SET_TIMINGR_SCLH(n) (((n) & \
119b844655cSEtienne Carriere (I2C_TIMINGR_SCLH_MAX - 1)) << 8)
120b844655cSEtienne Carriere #define I2C_SET_TIMINGR_SDADEL(n) (((n) & \
121b844655cSEtienne Carriere (I2C_TIMINGR_SDADEL_MAX - 1)) << 16)
122b844655cSEtienne Carriere #define I2C_SET_TIMINGR_SCLDEL(n) (((n) & \
123b844655cSEtienne Carriere (I2C_TIMINGR_SCLDEL_MAX - 1)) << 20)
124b844655cSEtienne Carriere #define I2C_SET_TIMINGR_PRESC(n) (((n) & \
125b844655cSEtienne Carriere (I2C_TIMINGR_PRESC_MAX - 1)) << 28)
126b844655cSEtienne Carriere
127b844655cSEtienne Carriere /* Bit definition for I2C_TIMEOUTR register */
128b844655cSEtienne Carriere #define I2C_TIMEOUTR_TIMEOUTA GENMASK_32(11, 0)
129b844655cSEtienne Carriere #define I2C_TIMEOUTR_TIDLE BIT(12)
130b844655cSEtienne Carriere #define I2C_TIMEOUTR_TIMOUTEN BIT(15)
131b844655cSEtienne Carriere #define I2C_TIMEOUTR_TIMEOUTB GENMASK_32(27, 16)
132b844655cSEtienne Carriere #define I2C_TIMEOUTR_TEXTEN BIT(31)
133b844655cSEtienne Carriere
134b844655cSEtienne Carriere /* Bit definition for I2C_ISR register */
135b844655cSEtienne Carriere #define I2C_ISR_TXE BIT(0)
136b844655cSEtienne Carriere #define I2C_ISR_TXIS BIT(1)
137b844655cSEtienne Carriere #define I2C_ISR_RXNE BIT(2)
138b844655cSEtienne Carriere #define I2C_ISR_ADDR BIT(3)
139b844655cSEtienne Carriere #define I2C_ISR_NACKF BIT(4)
140b844655cSEtienne Carriere #define I2C_ISR_STOPF BIT(5)
141b844655cSEtienne Carriere #define I2C_ISR_TC BIT(6)
142b844655cSEtienne Carriere #define I2C_ISR_TCR BIT(7)
143b844655cSEtienne Carriere #define I2C_ISR_BERR BIT(8)
144b844655cSEtienne Carriere #define I2C_ISR_ARLO BIT(9)
145b844655cSEtienne Carriere #define I2C_ISR_OVR BIT(10)
146b844655cSEtienne Carriere #define I2C_ISR_PECERR BIT(11)
147b844655cSEtienne Carriere #define I2C_ISR_TIMEOUT BIT(12)
148b844655cSEtienne Carriere #define I2C_ISR_ALERT BIT(13)
149b844655cSEtienne Carriere #define I2C_ISR_BUSY BIT(15)
150b844655cSEtienne Carriere #define I2C_ISR_DIR BIT(16)
151b844655cSEtienne Carriere #define I2C_ISR_ADDCODE GENMASK_32(23, 17)
152b844655cSEtienne Carriere
153b844655cSEtienne Carriere /* Bit definition for I2C_ICR register */
154b844655cSEtienne Carriere #define I2C_ICR_ADDRCF BIT(3)
155b844655cSEtienne Carriere #define I2C_ICR_NACKCF BIT(4)
156b844655cSEtienne Carriere #define I2C_ICR_STOPCF BIT(5)
157b844655cSEtienne Carriere #define I2C_ICR_BERRCF BIT(8)
158b844655cSEtienne Carriere #define I2C_ICR_ARLOCF BIT(9)
159b844655cSEtienne Carriere #define I2C_ICR_OVRCF BIT(10)
160b844655cSEtienne Carriere #define I2C_ICR_PECCF BIT(11)
161b844655cSEtienne Carriere #define I2C_ICR_TIMOUTCF BIT(12)
162b844655cSEtienne Carriere #define I2C_ICR_ALERTCF BIT(13)
163b844655cSEtienne Carriere
164b844655cSEtienne Carriere /* Max data size for a single I2C transfer */
165b844655cSEtienne Carriere #define MAX_NBYTE_SIZE 255U
166b844655cSEtienne Carriere
1673ebb1380SEtienne Carriere #define I2C_NSEC_PER_SEC 1000000000UL
168834ce4c6SEtienne Carriere #define I2C_TIMEOUT_BUSY_MS 25
169834ce4c6SEtienne Carriere #define I2C_TIMEOUT_BUSY_US (I2C_TIMEOUT_BUSY_MS * 1000)
17098fca444SJorge Ramirez-Ortiz #define I2C_TIMEOUT_RXNE_MS 5
171*1e3057c6SEtienne Carriere #define I2C_TIMEOUT_ITR_LOCKED_MS 100
172b844655cSEtienne Carriere
1735bc9f8e5SEtienne Carriere #define I2C_TIMEOUT_DEFAULT_MS 100
1745bc9f8e5SEtienne Carriere
175b844655cSEtienne Carriere #define CR2_RESET_MASK (I2C_CR2_SADD | I2C_CR2_HEAD10R | \
176b844655cSEtienne Carriere I2C_CR2_NBYTES | I2C_CR2_RELOAD | \
177b844655cSEtienne Carriere I2C_CR2_RD_WRN)
178b844655cSEtienne Carriere
179b844655cSEtienne Carriere #define TIMINGR_CLEAR_MASK (I2C_TIMINGR_SCLL | I2C_TIMINGR_SCLH | \
180b844655cSEtienne Carriere I2C_TIMINGR_SDADEL | \
181b844655cSEtienne Carriere I2C_TIMINGR_SCLDEL | I2C_TIMINGR_PRESC)
182b844655cSEtienne Carriere
183b844655cSEtienne Carriere /*
184b844655cSEtienne Carriere * I2C transfer modes
185b844655cSEtienne Carriere * I2C_RELOAD: Enable Reload mode
186b844655cSEtienne Carriere * I2C_AUTOEND_MODE: Enable automatic end mode
187b844655cSEtienne Carriere * I2C_SOFTEND_MODE: Enable software end mode
188b844655cSEtienne Carriere */
189b844655cSEtienne Carriere #define I2C_RELOAD_MODE I2C_CR2_RELOAD
190b844655cSEtienne Carriere #define I2C_AUTOEND_MODE I2C_CR2_AUTOEND
191b844655cSEtienne Carriere #define I2C_SOFTEND_MODE 0x0
192b844655cSEtienne Carriere
193b844655cSEtienne Carriere /*
194b844655cSEtienne Carriere * Start/restart/stop I2C transfer requests.
195b844655cSEtienne Carriere *
196b844655cSEtienne Carriere * I2C_NO_STARTSTOP: Don't Generate stop and start condition
197b844655cSEtienne Carriere * I2C_GENERATE_STOP: Generate stop condition (size should be set to 0)
198b844655cSEtienne Carriere * I2C_GENERATE_START_READ: Generate Restart for read request.
199b844655cSEtienne Carriere * I2C_GENERATE_START_WRITE: Generate Restart for write request
200b844655cSEtienne Carriere */
201b844655cSEtienne Carriere #define I2C_NO_STARTSTOP 0x0
202b844655cSEtienne Carriere #define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP)
203b844655cSEtienne Carriere #define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \
204b844655cSEtienne Carriere I2C_CR2_RD_WRN)
205b844655cSEtienne Carriere #define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START)
206b844655cSEtienne Carriere
207b844655cSEtienne Carriere /* Memory address byte sizes */
208b844655cSEtienne Carriere #define I2C_MEMADD_SIZE_8BIT 1
209b844655cSEtienne Carriere #define I2C_MEMADD_SIZE_16BIT 2
210b844655cSEtienne Carriere
2113ebb1380SEtienne Carriere /* Effective rate cannot be lower than 80% target rate */
2123ebb1380SEtienne Carriere #define RATE_MIN(rate) (((rate) * 80U) / 100U)
2133ebb1380SEtienne Carriere
214b844655cSEtienne Carriere /*
215b844655cSEtienne Carriere * struct i2c_spec_s - Private I2C timing specifications.
216b844655cSEtienne Carriere * @rate: I2C bus speed (Hz)
217b844655cSEtienne Carriere * @fall_max: Max fall time of both SDA and SCL signals (ns)
218b844655cSEtienne Carriere * @rise_max: Max rise time of both SDA and SCL signals (ns)
219b844655cSEtienne Carriere * @hddat_min: Min data hold time (ns)
220b844655cSEtienne Carriere * @vddat_max: Max data valid time (ns)
221b844655cSEtienne Carriere * @sudat_min: Min data setup time (ns)
222b844655cSEtienne Carriere * @l_min: Min low period of the SCL clock (ns)
223b844655cSEtienne Carriere * @h_min: Min high period of the SCL clock (ns)
224b844655cSEtienne Carriere */
225b844655cSEtienne Carriere struct i2c_spec_s {
226b844655cSEtienne Carriere uint32_t rate;
227b844655cSEtienne Carriere uint32_t fall_max;
228b844655cSEtienne Carriere uint32_t rise_max;
229b844655cSEtienne Carriere uint32_t hddat_min;
230b844655cSEtienne Carriere uint32_t vddat_max;
231b844655cSEtienne Carriere uint32_t sudat_min;
232b844655cSEtienne Carriere uint32_t l_min;
233b844655cSEtienne Carriere uint32_t h_min;
234b844655cSEtienne Carriere };
235b844655cSEtienne Carriere
236b844655cSEtienne Carriere /*
237b844655cSEtienne Carriere * struct i2c_timing_s - Private I2C output parameters.
238b844655cSEtienne Carriere * @scldel: Data setup time
239b844655cSEtienne Carriere * @sdadel: Data hold time
240b844655cSEtienne Carriere * @sclh: SCL high period (master mode)
241b844655cSEtienne Carriere * @sclh: SCL low period (master mode)
242b844655cSEtienne Carriere * @is_saved: True if relating to a configuration candidate
243b844655cSEtienne Carriere */
244b844655cSEtienne Carriere struct i2c_timing_s {
245b844655cSEtienne Carriere uint8_t scldel;
246b844655cSEtienne Carriere uint8_t sdadel;
247b844655cSEtienne Carriere uint8_t sclh;
248b844655cSEtienne Carriere uint8_t scll;
249b844655cSEtienne Carriere bool is_saved;
250b844655cSEtienne Carriere };
251b844655cSEtienne Carriere
2523ebb1380SEtienne Carriere /* This table must be sorted in increasing value for field @rate */
253b844655cSEtienne Carriere static const struct i2c_spec_s i2c_specs[] = {
2543ebb1380SEtienne Carriere /* Standard - 100KHz */
2553ebb1380SEtienne Carriere {
25661e7d84cSEtienne Carriere .rate = I2C_STANDARD_RATE,
257b844655cSEtienne Carriere .fall_max = 300,
258b844655cSEtienne Carriere .rise_max = 1000,
259b844655cSEtienne Carriere .hddat_min = 0,
260b844655cSEtienne Carriere .vddat_max = 3450,
261b844655cSEtienne Carriere .sudat_min = 250,
262b844655cSEtienne Carriere .l_min = 4700,
263b844655cSEtienne Carriere .h_min = 4000,
264b844655cSEtienne Carriere },
2653ebb1380SEtienne Carriere /* Fast - 400KHz */
2663ebb1380SEtienne Carriere {
26761e7d84cSEtienne Carriere .rate = I2C_FAST_RATE,
268b844655cSEtienne Carriere .fall_max = 300,
269b844655cSEtienne Carriere .rise_max = 300,
270b844655cSEtienne Carriere .hddat_min = 0,
271b844655cSEtienne Carriere .vddat_max = 900,
272b844655cSEtienne Carriere .sudat_min = 100,
273b844655cSEtienne Carriere .l_min = 1300,
274b844655cSEtienne Carriere .h_min = 600,
275b844655cSEtienne Carriere },
2763ebb1380SEtienne Carriere /* FastPlus - 1MHz */
2773ebb1380SEtienne Carriere {
27861e7d84cSEtienne Carriere .rate = I2C_FAST_PLUS_RATE,
279b844655cSEtienne Carriere .fall_max = 100,
280b844655cSEtienne Carriere .rise_max = 120,
281b844655cSEtienne Carriere .hddat_min = 0,
282b844655cSEtienne Carriere .vddat_max = 450,
283b844655cSEtienne Carriere .sudat_min = 50,
284b844655cSEtienne Carriere .l_min = 500,
285b844655cSEtienne Carriere .h_min = 260,
286b844655cSEtienne Carriere },
287b844655cSEtienne Carriere };
288b844655cSEtienne Carriere
289b844655cSEtienne Carriere /*
290b844655cSEtienne Carriere * I2C request parameters
291b844655cSEtienne Carriere * @dev_addr: I2C address of the target device
292b844655cSEtienne Carriere * @mode: Communication mode, one of I2C_MODE_(MASTER|MEM)
293b844655cSEtienne Carriere * @mem_addr: Target memory cell accessed in device (memory mode)
294b844655cSEtienne Carriere * @mem_addr_size: Byte size of the memory cell address (memory mode)
295b844655cSEtienne Carriere * @timeout_ms: Timeout in millisenconds for the request
296b844655cSEtienne Carriere */
297b844655cSEtienne Carriere struct i2c_request {
298b844655cSEtienne Carriere uint32_t dev_addr;
299b844655cSEtienne Carriere enum i2c_mode_e mode;
300b844655cSEtienne Carriere uint32_t mem_addr;
301b844655cSEtienne Carriere uint32_t mem_addr_size;
302b844655cSEtienne Carriere unsigned int timeout_ms;
303b844655cSEtienne Carriere };
304b844655cSEtienne Carriere
305ded20780SEtienne Carriere /* Place holder for STM32MP15 non-secure I2C bus compat data */
306ded20780SEtienne Carriere static const int non_secure_bus;
307ded20780SEtienne Carriere
get_base(struct i2c_handle_s * hi2c)308b844655cSEtienne Carriere static vaddr_t get_base(struct i2c_handle_s *hi2c)
309b844655cSEtienne Carriere {
310717f942aSLionel Debieve return io_pa_or_va_secure(&hi2c->base, hi2c->reg_size);
311b844655cSEtienne Carriere }
312b844655cSEtienne Carriere
notif_i2c_timeout(struct i2c_handle_s * hi2c)313b844655cSEtienne Carriere static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
314b844655cSEtienne Carriere {
315b844655cSEtienne Carriere hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
316b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
317b844655cSEtienne Carriere }
318b844655cSEtienne Carriere
get_specs(uint32_t rate)3193ebb1380SEtienne Carriere static const struct i2c_spec_s *get_specs(uint32_t rate)
3203ebb1380SEtienne Carriere {
3213ebb1380SEtienne Carriere size_t i = 0;
3223ebb1380SEtienne Carriere
3233ebb1380SEtienne Carriere for (i = 0; i < ARRAY_SIZE(i2c_specs); i++)
3243ebb1380SEtienne Carriere if (rate <= i2c_specs[i].rate)
3253ebb1380SEtienne Carriere return i2c_specs + i;
3263ebb1380SEtienne Carriere
3273ebb1380SEtienne Carriere return NULL;
3283ebb1380SEtienne Carriere }
3293ebb1380SEtienne Carriere
save_cfg(struct i2c_handle_s * hi2c,struct i2c_cfg * cfg)330b844655cSEtienne Carriere static void save_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg)
331b844655cSEtienne Carriere {
332b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
333b844655cSEtienne Carriere
334929ec061SEtienne Carriere clk_enable(hi2c->clock);
335b844655cSEtienne Carriere
336b844655cSEtienne Carriere cfg->cr1 = io_read32(base + I2C_CR1);
337b844655cSEtienne Carriere cfg->cr2 = io_read32(base + I2C_CR2);
338b844655cSEtienne Carriere cfg->oar1 = io_read32(base + I2C_OAR1);
339b844655cSEtienne Carriere cfg->oar2 = io_read32(base + I2C_OAR2);
340b844655cSEtienne Carriere cfg->timingr = io_read32(base + I2C_TIMINGR);
341b844655cSEtienne Carriere
342929ec061SEtienne Carriere clk_disable(hi2c->clock);
343b844655cSEtienne Carriere }
344b844655cSEtienne Carriere
restore_cfg(struct i2c_handle_s * hi2c,struct i2c_cfg * cfg)345b844655cSEtienne Carriere static void restore_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg)
346b844655cSEtienne Carriere {
347b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
348b844655cSEtienne Carriere
349929ec061SEtienne Carriere clk_enable(hi2c->clock);
350b844655cSEtienne Carriere
351b844655cSEtienne Carriere io_clrbits32(base + I2C_CR1, I2C_CR1_PE);
352b844655cSEtienne Carriere io_write32(base + I2C_TIMINGR, cfg->timingr & TIMINGR_CLEAR_MASK);
353b844655cSEtienne Carriere io_write32(base + I2C_OAR1, cfg->oar1);
354b844655cSEtienne Carriere io_write32(base + I2C_CR2, cfg->cr2);
355b844655cSEtienne Carriere io_write32(base + I2C_OAR2, cfg->oar2);
356b844655cSEtienne Carriere io_write32(base + I2C_CR1, cfg->cr1 & ~I2C_CR1_PE);
357b844655cSEtienne Carriere io_setbits32(base + I2C_CR1, cfg->cr1 & I2C_CR1_PE);
358b844655cSEtienne Carriere
359929ec061SEtienne Carriere clk_disable(hi2c->clock);
360b844655cSEtienne Carriere }
361b844655cSEtienne Carriere
dump_cfg(struct i2c_cfg * cfg __maybe_unused)362b844655cSEtienne Carriere static void __maybe_unused dump_cfg(struct i2c_cfg *cfg __maybe_unused)
363b844655cSEtienne Carriere {
364c50e170eSEtienne Carriere DMSG("CR1: %#"PRIx32, cfg->cr1);
365c50e170eSEtienne Carriere DMSG("CR2: %#"PRIx32, cfg->cr2);
366c50e170eSEtienne Carriere DMSG("OAR1: %#"PRIx32, cfg->oar1);
367c50e170eSEtienne Carriere DMSG("OAR2: %#"PRIx32, cfg->oar2);
368c50e170eSEtienne Carriere DMSG("TIM: %#"PRIx32, cfg->timingr);
369b844655cSEtienne Carriere }
370b844655cSEtienne Carriere
dump_i2c(struct i2c_handle_s * hi2c)371b844655cSEtienne Carriere static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c)
372b844655cSEtienne Carriere {
373b844655cSEtienne Carriere vaddr_t __maybe_unused base = get_base(hi2c);
374b844655cSEtienne Carriere
375929ec061SEtienne Carriere clk_enable(hi2c->clock);
376b844655cSEtienne Carriere
377c50e170eSEtienne Carriere DMSG("CR1: %#"PRIx32, io_read32(base + I2C_CR1));
378c50e170eSEtienne Carriere DMSG("CR2: %#"PRIx32, io_read32(base + I2C_CR2));
379c50e170eSEtienne Carriere DMSG("OAR1: %#"PRIx32, io_read32(base + I2C_OAR1));
380c50e170eSEtienne Carriere DMSG("OAR2: %#"PRIx32, io_read32(base + I2C_OAR2));
381c50e170eSEtienne Carriere DMSG("TIM: %#"PRIx32, io_read32(base + I2C_TIMINGR));
382b844655cSEtienne Carriere
383929ec061SEtienne Carriere clk_disable(hi2c->clock);
384b844655cSEtienne Carriere }
385b844655cSEtienne Carriere
386b844655cSEtienne Carriere /*
387b844655cSEtienne Carriere * Compute the I2C device timings
388b844655cSEtienne Carriere *
389b844655cSEtienne Carriere * @init: Ref to the initialization configuration structure
390b844655cSEtienne Carriere * @clock_src: I2C clock source frequency (Hz)
391b844655cSEtienne Carriere * @timing: Pointer to the final computed timing result
392b844655cSEtienne Carriere * Return 0 on success or a negative value
393b844655cSEtienne Carriere */
i2c_compute_timing(struct stm32_i2c_init_s * init,unsigned long clock_src,uint32_t * timing)394b844655cSEtienne Carriere static int i2c_compute_timing(struct stm32_i2c_init_s *init,
3953ebb1380SEtienne Carriere unsigned long clock_src, uint32_t *timing)
396b844655cSEtienne Carriere {
3973ebb1380SEtienne Carriere const struct i2c_spec_s *specs = NULL;
3983ebb1380SEtienne Carriere uint32_t speed_freq = 0;
399b844655cSEtienne Carriere uint32_t i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq);
400b844655cSEtienne Carriere uint32_t i2cclk = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, clock_src);
401b844655cSEtienne Carriere uint32_t p_prev = I2C_TIMINGR_PRESC_MAX;
402b844655cSEtienne Carriere uint32_t af_delay_min = 0;
403b844655cSEtienne Carriere uint32_t af_delay_max = 0;
404b844655cSEtienne Carriere uint32_t dnf_delay = 0;
405b844655cSEtienne Carriere uint32_t tsync = 0;
406b844655cSEtienne Carriere uint32_t clk_min = 0;
407b844655cSEtienne Carriere uint32_t clk_max = 0;
408b844655cSEtienne Carriere int clk_error_prev = 0;
409b844655cSEtienne Carriere uint16_t p = 0;
410b844655cSEtienne Carriere uint16_t l = 0;
411b844655cSEtienne Carriere uint16_t a = 0;
412b844655cSEtienne Carriere uint16_t h = 0;
413b844655cSEtienne Carriere unsigned int sdadel_min = 0;
414b844655cSEtienne Carriere unsigned int sdadel_max = 0;
415b844655cSEtienne Carriere unsigned int scldel_min = 0;
416b844655cSEtienne Carriere unsigned int delay = 0;
417b844655cSEtienne Carriere int s = -1;
418b844655cSEtienne Carriere struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX] = { 0 };
419b844655cSEtienne Carriere
4203ebb1380SEtienne Carriere specs = get_specs(init->bus_rate);
4213ebb1380SEtienne Carriere if (!specs) {
422c50e170eSEtienne Carriere DMSG("I2C speed out of bound: %"PRId32"Hz", init->bus_rate);
423b844655cSEtienne Carriere return -1;
424b844655cSEtienne Carriere }
425b844655cSEtienne Carriere
4263ebb1380SEtienne Carriere speed_freq = specs->rate;
427b844655cSEtienne Carriere i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq);
428b844655cSEtienne Carriere clk_error_prev = INT_MAX;
429b844655cSEtienne Carriere
4303ebb1380SEtienne Carriere if (init->rise_time > specs->rise_max ||
4313ebb1380SEtienne Carriere init->fall_time > specs->fall_max) {
432c50e170eSEtienne Carriere DMSG("I2C rise{%"PRId32">%"PRId32"}/fall{%"PRId32">%"PRId32"}",
4333ebb1380SEtienne Carriere init->rise_time, specs->rise_max,
4343ebb1380SEtienne Carriere init->fall_time, specs->fall_max);
435b844655cSEtienne Carriere return -1;
436b844655cSEtienne Carriere }
437b844655cSEtienne Carriere
438b844655cSEtienne Carriere if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) {
439c50e170eSEtienne Carriere DMSG("DNF out of bound %"PRId8"/%d",
440b844655cSEtienne Carriere init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX);
441b844655cSEtienne Carriere return -1;
442b844655cSEtienne Carriere }
443b844655cSEtienne Carriere
444b844655cSEtienne Carriere /* Analog and Digital Filters */
445b844655cSEtienne Carriere if (init->analog_filter) {
446b844655cSEtienne Carriere af_delay_min = STM32_I2C_ANALOG_FILTER_DELAY_MIN;
447b844655cSEtienne Carriere af_delay_max = STM32_I2C_ANALOG_FILTER_DELAY_MAX;
448b844655cSEtienne Carriere }
449b844655cSEtienne Carriere dnf_delay = init->digital_filter_coef * i2cclk;
450b844655cSEtienne Carriere
4513ebb1380SEtienne Carriere sdadel_min = specs->hddat_min + init->fall_time;
452b844655cSEtienne Carriere delay = af_delay_min - ((init->digital_filter_coef + 3) * i2cclk);
453b844655cSEtienne Carriere if (SUB_OVERFLOW(sdadel_min, delay, &sdadel_min))
454b844655cSEtienne Carriere sdadel_min = 0;
455b844655cSEtienne Carriere
4563ebb1380SEtienne Carriere sdadel_max = specs->vddat_max - init->rise_time;
457b844655cSEtienne Carriere delay = af_delay_max - ((init->digital_filter_coef + 4) * i2cclk);
458b844655cSEtienne Carriere if (SUB_OVERFLOW(sdadel_max, delay, &sdadel_max))
459b844655cSEtienne Carriere sdadel_max = 0;
460b844655cSEtienne Carriere
4613ebb1380SEtienne Carriere scldel_min = init->rise_time + specs->sudat_min;
462b844655cSEtienne Carriere
463b844655cSEtienne Carriere DMSG("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u",
464b844655cSEtienne Carriere sdadel_min, sdadel_max, scldel_min);
465b844655cSEtienne Carriere
466b844655cSEtienne Carriere /* Compute possible values for PRESC, SCLDEL and SDADEL */
467b844655cSEtienne Carriere for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) {
468b844655cSEtienne Carriere for (l = 0; l < I2C_TIMINGR_SCLDEL_MAX; l++) {
469b844655cSEtienne Carriere uint32_t scldel = (l + 1) * (p + 1) * i2cclk;
470b844655cSEtienne Carriere
471b844655cSEtienne Carriere if (scldel < scldel_min)
472b844655cSEtienne Carriere continue;
473b844655cSEtienne Carriere
474b844655cSEtienne Carriere for (a = 0; a < I2C_TIMINGR_SDADEL_MAX; a++) {
475b844655cSEtienne Carriere uint32_t sdadel = (a * (p + 1) + 1) * i2cclk;
476b844655cSEtienne Carriere
477b844655cSEtienne Carriere if ((sdadel >= sdadel_min) &&
478b844655cSEtienne Carriere (sdadel <= sdadel_max) &&
479b844655cSEtienne Carriere (p != p_prev)) {
480b844655cSEtienne Carriere solutions[p].scldel = l;
481b844655cSEtienne Carriere solutions[p].sdadel = a;
482b844655cSEtienne Carriere solutions[p].is_saved = true;
483b844655cSEtienne Carriere p_prev = p;
484b844655cSEtienne Carriere break;
485b844655cSEtienne Carriere }
486b844655cSEtienne Carriere }
487b844655cSEtienne Carriere
488b844655cSEtienne Carriere if (p_prev == p)
489b844655cSEtienne Carriere break;
490b844655cSEtienne Carriere }
491b844655cSEtienne Carriere }
492b844655cSEtienne Carriere
493b844655cSEtienne Carriere if (p_prev == I2C_TIMINGR_PRESC_MAX) {
494c50e170eSEtienne Carriere DMSG("I2C no Prescaler solution");
495b844655cSEtienne Carriere return -1;
496b844655cSEtienne Carriere }
497b844655cSEtienne Carriere
498b844655cSEtienne Carriere tsync = af_delay_min + dnf_delay + (2 * i2cclk);
4993ebb1380SEtienne Carriere clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate);
5003ebb1380SEtienne Carriere clk_min = I2C_NSEC_PER_SEC / specs->rate;
501b844655cSEtienne Carriere
502b844655cSEtienne Carriere /*
503b844655cSEtienne Carriere * Among prescaler possibilities discovered above figures out SCL Low
504b844655cSEtienne Carriere * and High Period. Provided:
505b844655cSEtienne Carriere * - SCL Low Period has to be higher than Low Period of the SCL Clock
506b844655cSEtienne Carriere * defined by I2C Specification. I2C Clock has to be lower than
507b844655cSEtienne Carriere * (SCL Low Period - Analog/Digital filters) / 4.
508b844655cSEtienne Carriere * - SCL High Period has to be lower than High Period of the SCL Clock
509b844655cSEtienne Carriere * defined by I2C Specification.
510b844655cSEtienne Carriere * - I2C Clock has to be lower than SCL High Period.
511b844655cSEtienne Carriere */
512b844655cSEtienne Carriere for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) {
513b844655cSEtienne Carriere uint32_t prescaler = (p + 1) * i2cclk;
514b844655cSEtienne Carriere
515b844655cSEtienne Carriere if (!solutions[p].is_saved)
516b844655cSEtienne Carriere continue;
517b844655cSEtienne Carriere
518b844655cSEtienne Carriere for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) {
519b844655cSEtienne Carriere uint32_t tscl_l = ((l + 1) * prescaler) + tsync;
520b844655cSEtienne Carriere
5213ebb1380SEtienne Carriere if (tscl_l < specs->l_min ||
5223ebb1380SEtienne Carriere i2cclk >= ((tscl_l - af_delay_min - dnf_delay) / 4))
523b844655cSEtienne Carriere continue;
524b844655cSEtienne Carriere
525b844655cSEtienne Carriere for (h = 0; h < I2C_TIMINGR_SCLH_MAX; h++) {
526b844655cSEtienne Carriere uint32_t tscl_h = ((h + 1) * prescaler) + tsync;
527b844655cSEtienne Carriere uint32_t tscl = tscl_l + tscl_h +
528b844655cSEtienne Carriere init->rise_time +
529b844655cSEtienne Carriere init->fall_time;
530b844655cSEtienne Carriere
5313ebb1380SEtienne Carriere if (tscl >= clk_min && tscl <= clk_max &&
5323ebb1380SEtienne Carriere tscl_h >= specs->h_min && i2cclk < tscl_h) {
533b844655cSEtienne Carriere int clk_error = tscl - i2cbus;
534b844655cSEtienne Carriere
535b844655cSEtienne Carriere if (clk_error < 0)
536b844655cSEtienne Carriere clk_error = -clk_error;
537b844655cSEtienne Carriere
538b844655cSEtienne Carriere if (clk_error < clk_error_prev) {
539b844655cSEtienne Carriere clk_error_prev = clk_error;
540b844655cSEtienne Carriere solutions[p].scll = l;
541b844655cSEtienne Carriere solutions[p].sclh = h;
542b844655cSEtienne Carriere s = p;
543b844655cSEtienne Carriere }
544b844655cSEtienne Carriere }
545b844655cSEtienne Carriere }
546b844655cSEtienne Carriere }
547b844655cSEtienne Carriere }
548b844655cSEtienne Carriere
549b844655cSEtienne Carriere if (s < 0) {
550c50e170eSEtienne Carriere DMSG("I2C no solution at all");
551b844655cSEtienne Carriere return -1;
552b844655cSEtienne Carriere }
553b844655cSEtienne Carriere
554b844655cSEtienne Carriere /* Finalize timing settings */
555b844655cSEtienne Carriere *timing = I2C_SET_TIMINGR_PRESC(s) |
556b844655cSEtienne Carriere I2C_SET_TIMINGR_SCLDEL(solutions[s].scldel) |
557b844655cSEtienne Carriere I2C_SET_TIMINGR_SDADEL(solutions[s].sdadel) |
558b844655cSEtienne Carriere I2C_SET_TIMINGR_SCLH(solutions[s].sclh) |
559b844655cSEtienne Carriere I2C_SET_TIMINGR_SCLL(solutions[s].scll);
560b844655cSEtienne Carriere
561c50e170eSEtienne Carriere DMSG("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%"PRIu8"/%"PRIu8,
562b844655cSEtienne Carriere s, solutions[s].scldel, solutions[s].sdadel);
563c50e170eSEtienne Carriere DMSG("I2C TIMINGR (SCLH/SCLL): %"PRIu8"/%"PRIu8,
564b844655cSEtienne Carriere solutions[s].sclh, solutions[s].scll);
565c50e170eSEtienne Carriere DMSG("I2C TIMINGR: 0x%"PRIx32, *timing);
566b844655cSEtienne Carriere
567b844655cSEtienne Carriere return 0;
568b844655cSEtienne Carriere }
569b844655cSEtienne Carriere
5703ebb1380SEtienne Carriere /* i2c_specs[] must be sorted by increasing rate */
i2c_specs_is_consistent(void)5713ebb1380SEtienne Carriere static bool __maybe_unused i2c_specs_is_consistent(void)
5723ebb1380SEtienne Carriere {
5733ebb1380SEtienne Carriere size_t i = 0;
5743ebb1380SEtienne Carriere
5753ebb1380SEtienne Carriere COMPILE_TIME_ASSERT(ARRAY_SIZE(i2c_specs));
5763ebb1380SEtienne Carriere
5773ebb1380SEtienne Carriere for (i = 1; i < ARRAY_SIZE(i2c_specs); i++)
5783ebb1380SEtienne Carriere if (i2c_specs[i - 1].rate >= i2c_specs[i].rate)
5793ebb1380SEtienne Carriere return false;
5803ebb1380SEtienne Carriere
5813ebb1380SEtienne Carriere return true;
5823ebb1380SEtienne Carriere }
5833ebb1380SEtienne Carriere
5843ebb1380SEtienne Carriere /*
5853ebb1380SEtienne Carriere * @brief From requested rate, get the closest I2C rate without exceeding it,
5863ebb1380SEtienne Carriere * within I2C specification values defined in @i2c_specs.
5873ebb1380SEtienne Carriere * @param rate: The requested rate.
5883ebb1380SEtienne Carriere * @retval Found rate, else the lowest value supported by platform.
5893ebb1380SEtienne Carriere */
get_lower_rate(uint32_t rate)5903ebb1380SEtienne Carriere static uint32_t get_lower_rate(uint32_t rate)
5913ebb1380SEtienne Carriere {
5923ebb1380SEtienne Carriere size_t i = 0;
5933ebb1380SEtienne Carriere
5943ebb1380SEtienne Carriere for (i = ARRAY_SIZE(i2c_specs); i > 0; i--)
5953ebb1380SEtienne Carriere if (rate > i2c_specs[i - 1].rate)
5963ebb1380SEtienne Carriere return i2c_specs[i - 1].rate;
5973ebb1380SEtienne Carriere
5983ebb1380SEtienne Carriere return i2c_specs[0].rate;
5993ebb1380SEtienne Carriere }
6003ebb1380SEtienne Carriere
601b844655cSEtienne Carriere /*
602b844655cSEtienne Carriere * Setup the I2C device timings
603b844655cSEtienne Carriere *
604b844655cSEtienne Carriere * @hi2c: I2C handle structure
605b844655cSEtienne Carriere * @init: Ref to the initialization configuration structure
606b844655cSEtienne Carriere * @timing: Output TIMINGR register configuration value
607b844655cSEtienne Carriere * @retval 0 if OK, negative value else
608b844655cSEtienne Carriere */
i2c_setup_timing(struct i2c_handle_s * hi2c,struct stm32_i2c_init_s * init,uint32_t * timing)609b844655cSEtienne Carriere static int i2c_setup_timing(struct i2c_handle_s *hi2c,
610b844655cSEtienne Carriere struct stm32_i2c_init_s *init,
611b844655cSEtienne Carriere uint32_t *timing)
612b844655cSEtienne Carriere {
613b844655cSEtienne Carriere int rc = 0;
6143ebb1380SEtienne Carriere unsigned long clock_src = 0;
615b844655cSEtienne Carriere
6163ebb1380SEtienne Carriere assert(i2c_specs_is_consistent());
6173ebb1380SEtienne Carriere
618929ec061SEtienne Carriere clock_src = clk_get_rate(hi2c->clock);
619b844655cSEtienne Carriere if (!clock_src) {
620c50e170eSEtienne Carriere DMSG("Null I2C clock rate");
621b844655cSEtienne Carriere return -1;
622b844655cSEtienne Carriere }
623b844655cSEtienne Carriere
62431c3d89fSEtienne Carriere /*
62531c3d89fSEtienne Carriere * If the timing has already been computed, and the frequency is the
62631c3d89fSEtienne Carriere * same as when it was computed, then use the saved timing.
62731c3d89fSEtienne Carriere */
62831c3d89fSEtienne Carriere if (clock_src == hi2c->saved_frequency) {
62931c3d89fSEtienne Carriere *timing = hi2c->saved_timing;
63031c3d89fSEtienne Carriere return 0;
63131c3d89fSEtienne Carriere }
63231c3d89fSEtienne Carriere
633b844655cSEtienne Carriere do {
634b844655cSEtienne Carriere rc = i2c_compute_timing(init, clock_src, timing);
635b844655cSEtienne Carriere if (rc) {
636c50e170eSEtienne Carriere DMSG("Failed to compute I2C timings");
6373ebb1380SEtienne Carriere if (init->bus_rate > I2C_STANDARD_RATE) {
6383ebb1380SEtienne Carriere init->bus_rate = get_lower_rate(init->bus_rate);
6393ebb1380SEtienne Carriere IMSG("Downgrade I2C speed to %"PRIu32"Hz)",
6403ebb1380SEtienne Carriere init->bus_rate);
641b844655cSEtienne Carriere } else {
642b844655cSEtienne Carriere break;
643b844655cSEtienne Carriere }
644b844655cSEtienne Carriere }
645b844655cSEtienne Carriere } while (rc);
646b844655cSEtienne Carriere
647b844655cSEtienne Carriere if (rc) {
648c50e170eSEtienne Carriere DMSG("Impossible to compute I2C timings");
649b844655cSEtienne Carriere return rc;
650b844655cSEtienne Carriere }
651b844655cSEtienne Carriere
6523ebb1380SEtienne Carriere DMSG("I2C Freq(%"PRIu32"Hz), Clk Source(%lu)",
6533ebb1380SEtienne Carriere init->bus_rate, clock_src);
654c50e170eSEtienne Carriere DMSG("I2C Rise(%"PRId32") and Fall(%"PRId32") Time",
655b844655cSEtienne Carriere init->rise_time, init->fall_time);
656c50e170eSEtienne Carriere DMSG("I2C Analog Filter(%s), DNF(%"PRIu8")",
657b844655cSEtienne Carriere init->analog_filter ? "On" : "Off", init->digital_filter_coef);
658b844655cSEtienne Carriere
65931c3d89fSEtienne Carriere hi2c->saved_timing = *timing;
66031c3d89fSEtienne Carriere hi2c->saved_frequency = clock_src;
66131c3d89fSEtienne Carriere
662b844655cSEtienne Carriere return 0;
663b844655cSEtienne Carriere }
664b844655cSEtienne Carriere
665b844655cSEtienne Carriere /*
666b844655cSEtienne Carriere * Configure I2C Analog noise filter.
667b844655cSEtienne Carriere * @hi2c: I2C handle structure
668b844655cSEtienne Carriere * @analog_filter_on: True if enabling analog filter, false otherwise
669b844655cSEtienne Carriere */
i2c_config_analog_filter(struct i2c_handle_s * hi2c,bool analog_filter_on)67087aead6fSEtienne Carriere static void i2c_config_analog_filter(struct i2c_handle_s *hi2c,
671b844655cSEtienne Carriere bool analog_filter_on)
672b844655cSEtienne Carriere {
673b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
674b844655cSEtienne Carriere
675b844655cSEtienne Carriere /* Disable the selected I2C peripheral */
676b844655cSEtienne Carriere io_clrbits32(base + I2C_CR1, I2C_CR1_PE);
677b844655cSEtienne Carriere
678b844655cSEtienne Carriere /* Reset I2Cx ANOFF bit */
679b844655cSEtienne Carriere io_clrbits32(base + I2C_CR1, I2C_CR1_ANFOFF);
680b844655cSEtienne Carriere
681b844655cSEtienne Carriere /* Set analog filter bit if filter is disabled */
682b844655cSEtienne Carriere if (!analog_filter_on)
683b844655cSEtienne Carriere io_setbits32(base + I2C_CR1, I2C_CR1_ANFOFF);
684b844655cSEtienne Carriere
685b844655cSEtienne Carriere /* Enable the selected I2C peripheral */
686b844655cSEtienne Carriere io_setbits32(base + I2C_CR1, I2C_CR1_PE);
687b844655cSEtienne Carriere }
688b844655cSEtienne Carriere
stm32_i2c_get_setup_from_fdt(void * fdt,int node,struct stm32_i2c_init_s * init,struct pinctrl_state ** pinctrl,struct pinctrl_state ** pinctrl_sleep)6892b81d819SEtienne Carriere TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node,
690c75303f7SEtienne Carriere struct stm32_i2c_init_s *init,
69173ba32ebSEtienne Carriere struct pinctrl_state **pinctrl,
6929ef7a09cSEtienne Carriere struct pinctrl_state **pinctrl_sleep)
693b844655cSEtienne Carriere {
694929ec061SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
695b844655cSEtienne Carriere const fdt32_t *cuint = NULL;
696b844655cSEtienne Carriere struct dt_node_info info = { .status = 0 };
69773ba32ebSEtienne Carriere int __maybe_unused count = 0;
698b844655cSEtienne Carriere
699b844655cSEtienne Carriere /* Default STM32 specific configs caller may need to overwrite */
700b844655cSEtienne Carriere memset(init, 0, sizeof(*init));
701b844655cSEtienne Carriere
702f354a5d8SGatien Chevallier fdt_fill_device_info(fdt, &info, node);
703717f942aSLionel Debieve assert(info.reg != DT_INFO_INVALID_REG &&
704929ec061SEtienne Carriere info.reg_size != DT_INFO_INVALID_REG_SIZE);
705717f942aSLionel Debieve
706b844655cSEtienne Carriere init->pbase = info.reg;
707717f942aSLionel Debieve init->reg_size = info.reg_size;
708929ec061SEtienne Carriere
709929ec061SEtienne Carriere res = clk_dt_get_by_index(fdt, node, 0, &init->clock);
710929ec061SEtienne Carriere if (res)
711929ec061SEtienne Carriere return res;
712b844655cSEtienne Carriere
713b844655cSEtienne Carriere cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
714b844655cSEtienne Carriere if (cuint)
715b844655cSEtienne Carriere init->rise_time = fdt32_to_cpu(*cuint);
716b844655cSEtienne Carriere else
717b844655cSEtienne Carriere init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
718b844655cSEtienne Carriere
719b844655cSEtienne Carriere cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
720b844655cSEtienne Carriere if (cuint)
721b844655cSEtienne Carriere init->fall_time = fdt32_to_cpu(*cuint);
722b844655cSEtienne Carriere else
723b844655cSEtienne Carriere init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
724b844655cSEtienne Carriere
725b844655cSEtienne Carriere cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
726b844655cSEtienne Carriere if (cuint) {
7273ebb1380SEtienne Carriere init->bus_rate = fdt32_to_cpu(*cuint);
7283ebb1380SEtienne Carriere
7293ebb1380SEtienne Carriere if (init->bus_rate > I2C_FAST_PLUS_RATE) {
7303ebb1380SEtienne Carriere DMSG("Invalid bus speed (%"PRIu32" > %i)",
7313ebb1380SEtienne Carriere init->bus_rate, I2C_FAST_PLUS_RATE);
7322b81d819SEtienne Carriere return TEE_ERROR_GENERIC;
733b844655cSEtienne Carriere }
734b844655cSEtienne Carriere } else {
7353ebb1380SEtienne Carriere init->bus_rate = I2C_STANDARD_RATE;
736b844655cSEtienne Carriere }
737b844655cSEtienne Carriere
73873ba32ebSEtienne Carriere if (pinctrl) {
73973ba32ebSEtienne Carriere res = pinctrl_get_state_by_name(fdt, node, "default", pinctrl);
74073ba32ebSEtienne Carriere if (res)
74173ba32ebSEtienne Carriere return res;
74273ba32ebSEtienne Carriere }
74373ba32ebSEtienne Carriere
74473ba32ebSEtienne Carriere if (pinctrl_sleep) {
74573ba32ebSEtienne Carriere res = pinctrl_get_state_by_name(fdt, node, "sleep",
74673ba32ebSEtienne Carriere pinctrl_sleep);
74773ba32ebSEtienne Carriere if (res == TEE_ERROR_ITEM_NOT_FOUND)
74873ba32ebSEtienne Carriere res = TEE_SUCCESS;
74973ba32ebSEtienne Carriere if (res)
75073ba32ebSEtienne Carriere return res;
75173ba32ebSEtienne Carriere }
752c75303f7SEtienne Carriere
7532b81d819SEtienne Carriere return TEE_SUCCESS;
754b844655cSEtienne Carriere }
755b844655cSEtienne Carriere
init_i2c_bus_access_lock(struct i2c_handle_s * hi2c)756*1e3057c6SEtienne Carriere static void init_i2c_bus_access_lock(struct i2c_handle_s *hi2c)
757*1e3057c6SEtienne Carriere {
758*1e3057c6SEtienne Carriere mutex_pm_aware_init(&hi2c->mu);
759*1e3057c6SEtienne Carriere hi2c->consumer_itr_lock = 0;
760*1e3057c6SEtienne Carriere }
761*1e3057c6SEtienne Carriere
is_thread_context(void)762*1e3057c6SEtienne Carriere static bool is_thread_context(void)
763*1e3057c6SEtienne Carriere {
764*1e3057c6SEtienne Carriere return thread_is_in_normal_mode() && thread_get_id_may_fail() >= 0;
765*1e3057c6SEtienne Carriere }
766*1e3057c6SEtienne Carriere
lock_i2c_bus_access(struct i2c_handle_s * hi2c)767*1e3057c6SEtienne Carriere static void lock_i2c_bus_access(struct i2c_handle_s *hi2c)
768*1e3057c6SEtienne Carriere {
769*1e3057c6SEtienne Carriere /*
770*1e3057c6SEtienne Carriere * In order to support cases when a PMIC interrupt triggers
771*1e3057c6SEtienne Carriere * before async notif is supported, we allow I2C access under
772*1e3057c6SEtienne Carriere * interrupt context. To do so, thread context ensures PMIC
773*1e3057c6SEtienne Carriere * interrupt (actually the related PWR interrupt) is masked
774*1e3057c6SEtienne Carriere * while we're accessing the I2C from a thread context. We
775*1e3057c6SEtienne Carriere * must also make sure any pending interrupts under execution
776*1e3057c6SEtienne Carriere * complete before accessing the bus on async notif enable
777*1e3057c6SEtienne Carriere * transition.
778*1e3057c6SEtienne Carriere */
779*1e3057c6SEtienne Carriere if (is_thread_context()) {
780*1e3057c6SEtienne Carriere struct stm32_itr_dep *itr_dep = NULL;
781*1e3057c6SEtienne Carriere uint32_t exceptions = 0;
782*1e3057c6SEtienne Carriere uint64_t timeout = 0;
783*1e3057c6SEtienne Carriere
784*1e3057c6SEtienne Carriere /* Lock thread access */
785*1e3057c6SEtienne Carriere mutex_pm_aware_lock(&hi2c->mu);
786*1e3057c6SEtienne Carriere FMSG("Thread access");
787*1e3057c6SEtienne Carriere
788*1e3057c6SEtienne Carriere /*
789*1e3057c6SEtienne Carriere * When async notif is not started, mask registered consumer
790*1e3057c6SEtienne Carriere * interrupt during the thread context I2C access so we don't
791*1e3057c6SEtienne Carriere * conflict with a interrupt access to the I2C bus. When async
792*1e3057c6SEtienne Carriere * notif is started, all PMIC interrupts are routed to a thread
793*1e3057c6SEtienne Carriere * execution context so we don't need to mask them.
794*1e3057c6SEtienne Carriere */
795*1e3057c6SEtienne Carriere if (!notif_async_is_started(0)) {
796*1e3057c6SEtienne Carriere exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
797*1e3057c6SEtienne Carriere
798*1e3057c6SEtienne Carriere hi2c->consumer_itr_masked = true;
799*1e3057c6SEtienne Carriere
800*1e3057c6SEtienne Carriere /* Ensure next pending interrupts are masked */
801*1e3057c6SEtienne Carriere SLIST_FOREACH(itr_dep, &hi2c->consumer_itr_head, link)
802*1e3057c6SEtienne Carriere interrupt_mask(itr_dep->chip, itr_dep->num);
803*1e3057c6SEtienne Carriere
804*1e3057c6SEtienne Carriere thread_unmask_exceptions(exceptions);
805*1e3057c6SEtienne Carriere }
806*1e3057c6SEtienne Carriere
807*1e3057c6SEtienne Carriere /* Wait possibly executing interrupt transfer completion */
808*1e3057c6SEtienne Carriere timeout = timeout_init_us(I2C_TIMEOUT_ITR_LOCKED_MS * 1000);
809*1e3057c6SEtienne Carriere while (!timeout_elapsed(timeout))
810*1e3057c6SEtienne Carriere if (!atomic_load_int(&hi2c->consumer_itr_lock))
811*1e3057c6SEtienne Carriere break;
812*1e3057c6SEtienne Carriere
813*1e3057c6SEtienne Carriere if (atomic_load_int(&hi2c->consumer_itr_lock)) {
814*1e3057c6SEtienne Carriere EMSG("Unexpected lengthy I2C xfer, base PA %"PRIxPA,
815*1e3057c6SEtienne Carriere hi2c->base.pa);
816*1e3057c6SEtienne Carriere panic();
817*1e3057c6SEtienne Carriere }
818*1e3057c6SEtienne Carriere } else {
819*1e3057c6SEtienne Carriere FMSG("Interrupt access");
820*1e3057c6SEtienne Carriere atomic_store_int(&hi2c->consumer_itr_lock, 1);
821*1e3057c6SEtienne Carriere }
822*1e3057c6SEtienne Carriere }
823*1e3057c6SEtienne Carriere
unlock_i2c_bus_access(struct i2c_handle_s * hi2c)824*1e3057c6SEtienne Carriere static void unlock_i2c_bus_access(struct i2c_handle_s *hi2c)
825*1e3057c6SEtienne Carriere {
826*1e3057c6SEtienne Carriere if (is_thread_context()) {
827*1e3057c6SEtienne Carriere FMSG("Thread access completed");
828*1e3057c6SEtienne Carriere
829*1e3057c6SEtienne Carriere if (hi2c->consumer_itr_masked) {
830*1e3057c6SEtienne Carriere struct stm32_itr_dep *itr_dep = NULL;
831*1e3057c6SEtienne Carriere
832*1e3057c6SEtienne Carriere /* Unmask possibly pending interrupts */
833*1e3057c6SEtienne Carriere SLIST_FOREACH(itr_dep, &hi2c->consumer_itr_head, link)
834*1e3057c6SEtienne Carriere interrupt_unmask(itr_dep->chip, itr_dep->num);
835*1e3057c6SEtienne Carriere
836*1e3057c6SEtienne Carriere hi2c->consumer_itr_masked = false;
837*1e3057c6SEtienne Carriere }
838*1e3057c6SEtienne Carriere
839*1e3057c6SEtienne Carriere /* Unlock thread access */
840*1e3057c6SEtienne Carriere mutex_pm_aware_unlock(&hi2c->mu);
841*1e3057c6SEtienne Carriere } else {
842*1e3057c6SEtienne Carriere FMSG("Interrupt access completed");
843*1e3057c6SEtienne Carriere atomic_store_int(&hi2c->consumer_itr_lock, 0);
844*1e3057c6SEtienne Carriere }
845*1e3057c6SEtienne Carriere }
846*1e3057c6SEtienne Carriere
stm32_i2c_init(struct i2c_handle_s * hi2c,struct stm32_i2c_init_s * init_data)847b844655cSEtienne Carriere int stm32_i2c_init(struct i2c_handle_s *hi2c,
848b844655cSEtienne Carriere struct stm32_i2c_init_s *init_data)
849b844655cSEtienne Carriere {
850b844655cSEtienne Carriere int rc = 0;
851b844655cSEtienne Carriere uint32_t timing = 0;
852b844655cSEtienne Carriere vaddr_t base = 0;
853b844655cSEtienne Carriere uint32_t val = 0;
854b844655cSEtienne Carriere
855*1e3057c6SEtienne Carriere init_i2c_bus_access_lock(hi2c);
856bdde1c99SEtienne Carriere
857b844655cSEtienne Carriere rc = i2c_setup_timing(hi2c, init_data, &timing);
858b844655cSEtienne Carriere if (rc)
859b844655cSEtienne Carriere return rc;
860b844655cSEtienne Carriere
861929ec061SEtienne Carriere clk_enable(hi2c->clock);
862929ec061SEtienne Carriere
863b844655cSEtienne Carriere base = get_base(hi2c);
864b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_BUSY;
865b844655cSEtienne Carriere
866b844655cSEtienne Carriere /* Disable the selected I2C peripheral */
867b844655cSEtienne Carriere io_clrbits32(base + I2C_CR1, I2C_CR1_PE);
868b844655cSEtienne Carriere
869b844655cSEtienne Carriere /* Configure I2Cx: Frequency range */
870b844655cSEtienne Carriere io_write32(base + I2C_TIMINGR, timing & TIMINGR_CLEAR_MASK);
871b844655cSEtienne Carriere
872b844655cSEtienne Carriere /* Disable Own Address1 before set the Own Address1 configuration */
873b844655cSEtienne Carriere io_write32(base + I2C_OAR1, 0);
874b844655cSEtienne Carriere
875b844655cSEtienne Carriere /* Configure I2Cx: Own Address1 and ack own address1 mode */
876b844655cSEtienne Carriere if (init_data->addr_mode_10b_not_7b)
877b844655cSEtienne Carriere io_write32(base + I2C_OAR1,
878b844655cSEtienne Carriere I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
879b844655cSEtienne Carriere init_data->own_address1);
880b844655cSEtienne Carriere else
881b844655cSEtienne Carriere io_write32(base + I2C_OAR1,
882b844655cSEtienne Carriere I2C_OAR1_OA1EN | init_data->own_address1);
883b844655cSEtienne Carriere
884b844655cSEtienne Carriere /* Configure I2Cx: Addressing Master mode */
885b844655cSEtienne Carriere io_write32(base + I2C_CR2, 0);
886b844655cSEtienne Carriere if (init_data->addr_mode_10b_not_7b)
887b844655cSEtienne Carriere io_setbits32(base + I2C_CR2, I2C_CR2_ADD10);
888b844655cSEtienne Carriere
889b844655cSEtienne Carriere /*
890b844655cSEtienne Carriere * Enable the AUTOEND by default, and enable NACK
891b844655cSEtienne Carriere * (should be disabled only during Slave process).
892b844655cSEtienne Carriere */
893b844655cSEtienne Carriere io_setbits32(base + I2C_CR2, I2C_CR2_AUTOEND | I2C_CR2_NACK);
894b844655cSEtienne Carriere
895b844655cSEtienne Carriere /* Disable Own Address2 before set the Own Address2 configuration */
896b844655cSEtienne Carriere io_write32(base + I2C_OAR2, 0);
897b844655cSEtienne Carriere
898b844655cSEtienne Carriere /* Configure I2Cx: Dual mode and Own Address2 */
899b844655cSEtienne Carriere if (init_data->dual_address_mode)
900b844655cSEtienne Carriere io_write32(base + I2C_OAR2,
901b844655cSEtienne Carriere I2C_OAR2_OA2EN | init_data->own_address2 |
902b844655cSEtienne Carriere (init_data->own_address2_masks << 8));
903b844655cSEtienne Carriere
904b844655cSEtienne Carriere /* Configure I2Cx: Generalcall and NoStretch mode */
905b844655cSEtienne Carriere val = 0;
906b844655cSEtienne Carriere if (init_data->general_call_mode)
907b844655cSEtienne Carriere val |= I2C_CR1_GCEN;
908b844655cSEtienne Carriere if (init_data->no_stretch_mode)
909b844655cSEtienne Carriere val |= I2C_CR1_NOSTRETCH;
910b844655cSEtienne Carriere io_write32(base + I2C_CR1, val);
911b844655cSEtienne Carriere
912b844655cSEtienne Carriere /* Enable the selected I2C peripheral */
913b844655cSEtienne Carriere io_setbits32(base + I2C_CR1, I2C_CR1_PE);
914b844655cSEtienne Carriere
915b844655cSEtienne Carriere hi2c->i2c_err = I2C_ERROR_NONE;
916b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
917b844655cSEtienne Carriere
91887aead6fSEtienne Carriere i2c_config_analog_filter(hi2c, init_data->analog_filter);
919b844655cSEtienne Carriere
920929ec061SEtienne Carriere clk_disable(hi2c->clock);
921b844655cSEtienne Carriere
9222b9d7661SEtienne Carriere if (hi2c->pinctrl && pinctrl_apply_state(hi2c->pinctrl))
9232b9d7661SEtienne Carriere return -1;
9242b9d7661SEtienne Carriere
92587aead6fSEtienne Carriere return 0;
926b844655cSEtienne Carriere }
927b844655cSEtienne Carriere
928b844655cSEtienne Carriere /* I2C transmit (TX) data register flush sequence */
i2c_flush_txdr(struct i2c_handle_s * hi2c)929b844655cSEtienne Carriere static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
930b844655cSEtienne Carriere {
931b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
932b844655cSEtienne Carriere
933b844655cSEtienne Carriere /*
934b844655cSEtienne Carriere * If a pending TXIS flag is set,
935b844655cSEtienne Carriere * write a dummy data in TXDR to clear it.
936b844655cSEtienne Carriere */
937b844655cSEtienne Carriere if (io_read32(base + I2C_ISR) & I2C_ISR_TXIS)
938b844655cSEtienne Carriere io_write32(base + I2C_TXDR, 0);
939b844655cSEtienne Carriere
940b844655cSEtienne Carriere /* Flush TX register if not empty */
941b844655cSEtienne Carriere if ((io_read32(base + I2C_ISR) & I2C_ISR_TXE) == 0)
942b844655cSEtienne Carriere io_setbits32(base + I2C_ISR, I2C_ISR_TXE);
943b844655cSEtienne Carriere }
944b844655cSEtienne Carriere
945b844655cSEtienne Carriere /*
946b844655cSEtienne Carriere * Wait for a single target I2C_ISR bit to reach an awaited value (0 or 1)
947b844655cSEtienne Carriere *
948b844655cSEtienne Carriere * @hi2c: I2C handle structure
949b844655cSEtienne Carriere * @bit_mask: Bit mask for the target single bit position to consider
950b844655cSEtienne Carriere * @awaited_value: Awaited value of the target bit in I2C_ISR, 0 or 1
951b844655cSEtienne Carriere * @timeout_ref: Expriation timeout reference
952b844655cSEtienne Carriere * Return 0 on success and a non-zero value on timeout
953b844655cSEtienne Carriere */
wait_isr_event(struct i2c_handle_s * hi2c,uint32_t bit_mask,unsigned int awaited_value,uint64_t timeout_ref)954b844655cSEtienne Carriere static int wait_isr_event(struct i2c_handle_s *hi2c, uint32_t bit_mask,
955b844655cSEtienne Carriere unsigned int awaited_value, uint64_t timeout_ref)
956b844655cSEtienne Carriere {
957b844655cSEtienne Carriere vaddr_t isr = get_base(hi2c) + I2C_ISR;
958b844655cSEtienne Carriere
959b844655cSEtienne Carriere assert(IS_POWER_OF_TWO(bit_mask) && !(awaited_value & ~1U));
960b844655cSEtienne Carriere
961b844655cSEtienne Carriere /* May timeout while TEE thread is suspended */
962b844655cSEtienne Carriere while (!timeout_elapsed(timeout_ref))
963b844655cSEtienne Carriere if (!!(io_read32(isr) & bit_mask) == awaited_value)
964b844655cSEtienne Carriere break;
965b844655cSEtienne Carriere
966b844655cSEtienne Carriere if (!!(io_read32(isr) & bit_mask) == awaited_value)
967b844655cSEtienne Carriere return 0;
968b844655cSEtienne Carriere
969b844655cSEtienne Carriere notif_i2c_timeout(hi2c);
970b844655cSEtienne Carriere return -1;
971b844655cSEtienne Carriere }
972b844655cSEtienne Carriere
973b844655cSEtienne Carriere /* Handle Acknowledge-Failed sequence detection during an I2C Communication */
i2c_ack_failed(struct i2c_handle_s * hi2c,uint64_t timeout_ref)974b844655cSEtienne Carriere static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
975b844655cSEtienne Carriere {
976b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
977b844655cSEtienne Carriere
978b844655cSEtienne Carriere if ((io_read32(base + I2C_ISR) & I2C_ISR_NACKF) == 0U)
979b844655cSEtienne Carriere return 0;
980b844655cSEtienne Carriere
981b844655cSEtienne Carriere /*
982b844655cSEtienne Carriere * Wait until STOP Flag is reset. Use polling method.
983b844655cSEtienne Carriere * AutoEnd should be initiate after AF.
984b844655cSEtienne Carriere * Timeout may elpased while TEE thread is suspended.
985b844655cSEtienne Carriere */
986b844655cSEtienne Carriere while (!timeout_elapsed(timeout_ref))
987b844655cSEtienne Carriere if (io_read32(base + I2C_ISR) & I2C_ISR_STOPF)
988b844655cSEtienne Carriere break;
989b844655cSEtienne Carriere
990b844655cSEtienne Carriere if ((io_read32(base + I2C_ISR) & I2C_ISR_STOPF) == 0) {
991b844655cSEtienne Carriere notif_i2c_timeout(hi2c);
992b844655cSEtienne Carriere return -1;
993b844655cSEtienne Carriere }
994b844655cSEtienne Carriere
995b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_NACKF);
996b844655cSEtienne Carriere
997b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
998b844655cSEtienne Carriere
999b844655cSEtienne Carriere i2c_flush_txdr(hi2c);
1000b844655cSEtienne Carriere
1001b844655cSEtienne Carriere io_clrbits32(base + I2C_CR2, CR2_RESET_MASK);
1002b844655cSEtienne Carriere
1003b844655cSEtienne Carriere hi2c->i2c_err |= I2C_ERROR_ACKF;
1004b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
1005b844655cSEtienne Carriere
1006b844655cSEtienne Carriere return -1;
1007b844655cSEtienne Carriere }
1008b844655cSEtienne Carriere
1009b844655cSEtienne Carriere /* Wait TXIS bit is 1 in I2C_ISR register */
i2c_wait_txis(struct i2c_handle_s * hi2c,uint64_t timeout_ref)1010b844655cSEtienne Carriere static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
1011b844655cSEtienne Carriere {
1012b844655cSEtienne Carriere while (!timeout_elapsed(timeout_ref)) {
1013b844655cSEtienne Carriere if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_TXIS)
1014b844655cSEtienne Carriere break;
1015b844655cSEtienne Carriere if (i2c_ack_failed(hi2c, timeout_ref))
1016b844655cSEtienne Carriere return -1;
1017b844655cSEtienne Carriere }
1018b844655cSEtienne Carriere
1019b844655cSEtienne Carriere if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_TXIS)
1020b844655cSEtienne Carriere return 0;
1021b844655cSEtienne Carriere
1022b844655cSEtienne Carriere if (i2c_ack_failed(hi2c, timeout_ref))
1023b844655cSEtienne Carriere return -1;
1024b844655cSEtienne Carriere
1025b844655cSEtienne Carriere notif_i2c_timeout(hi2c);
1026b844655cSEtienne Carriere return -1;
1027b844655cSEtienne Carriere }
1028b844655cSEtienne Carriere
1029b844655cSEtienne Carriere /* Wait STOPF bit is 1 in I2C_ISR register */
i2c_wait_stop(struct i2c_handle_s * hi2c,uint64_t timeout_ref)1030b844655cSEtienne Carriere static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
1031b844655cSEtienne Carriere {
1032ae49405bSEtienne Carriere while (!timeout_elapsed(timeout_ref)) {
1033b844655cSEtienne Carriere if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_STOPF)
1034b844655cSEtienne Carriere break;
1035b844655cSEtienne Carriere
1036b844655cSEtienne Carriere if (i2c_ack_failed(hi2c, timeout_ref))
1037b844655cSEtienne Carriere return -1;
1038b844655cSEtienne Carriere }
1039b844655cSEtienne Carriere
1040b844655cSEtienne Carriere if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_STOPF)
1041b844655cSEtienne Carriere return 0;
1042b844655cSEtienne Carriere
1043b844655cSEtienne Carriere if (i2c_ack_failed(hi2c, timeout_ref))
1044b844655cSEtienne Carriere return -1;
1045b844655cSEtienne Carriere
1046b844655cSEtienne Carriere notif_i2c_timeout(hi2c);
1047b844655cSEtienne Carriere return -1;
1048b844655cSEtienne Carriere }
1049b844655cSEtienne Carriere
1050b844655cSEtienne Carriere /*
1051b844655cSEtienne Carriere * Load I2C_CR2 register for a I2C transfer
1052b844655cSEtienne Carriere *
1053b844655cSEtienne Carriere * @hi2c: I2C handle structure
1054b844655cSEtienne Carriere * @dev_addr: Slave address to be transferred
1055b844655cSEtienne Carriere * @size: Number of bytes to be transferred
1056b844655cSEtienne Carriere * @i2c_mode: One of I2C_{RELOAD|AUTOEND|SOFTEND}_MODE: Enable Reload mode.
1057b844655cSEtienne Carriere * @startstop: One of I2C_NO_STARTSTOP, I2C_GENERATE_STOP,
1058b844655cSEtienne Carriere * I2C_GENERATE_START_{READ|WRITE}
1059b844655cSEtienne Carriere */
i2c_transfer_config(struct i2c_handle_s * hi2c,uint32_t dev_addr,uint32_t size,uint32_t i2c_mode,uint32_t startstop)1060b844655cSEtienne Carriere static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint32_t dev_addr,
1061b844655cSEtienne Carriere uint32_t size, uint32_t i2c_mode,
1062b844655cSEtienne Carriere uint32_t startstop)
1063b844655cSEtienne Carriere {
1064b844655cSEtienne Carriere uint32_t clr_value = I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
1065b844655cSEtienne Carriere I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP |
1066b844655cSEtienne Carriere (I2C_CR2_RD_WRN &
1067b844655cSEtienne Carriere (startstop >> (31U - I2C_CR2_RD_WRN_OFFSET)));
1068b844655cSEtienne Carriere uint32_t set_value = (dev_addr & I2C_CR2_SADD) |
1069b844655cSEtienne Carriere ((size << I2C_CR2_NBYTES_OFFSET) &
1070b844655cSEtienne Carriere I2C_CR2_NBYTES) |
1071b844655cSEtienne Carriere i2c_mode | startstop;
1072b844655cSEtienne Carriere
1073b844655cSEtienne Carriere io_clrsetbits32(get_base(hi2c) + I2C_CR2, clr_value, set_value);
1074b844655cSEtienne Carriere }
1075b844655cSEtienne Carriere
1076b844655cSEtienne Carriere /*
1077b844655cSEtienne Carriere * Master sends target device address followed by internal memory
1078b844655cSEtienne Carriere * address for a memory write request.
1079b844655cSEtienne Carriere * Function returns 0 on success or a negative value.
1080b844655cSEtienne Carriere */
i2c_request_mem_write(struct i2c_handle_s * hi2c,struct i2c_request * request,uint64_t timeout_ref)1081b844655cSEtienne Carriere static int i2c_request_mem_write(struct i2c_handle_s *hi2c,
1082b844655cSEtienne Carriere struct i2c_request *request,
1083b844655cSEtienne Carriere uint64_t timeout_ref)
1084b844655cSEtienne Carriere {
1085b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
1086b844655cSEtienne Carriere
1087b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, request->mem_addr_size,
1088b844655cSEtienne Carriere I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
1089b844655cSEtienne Carriere
1090b844655cSEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1091b844655cSEtienne Carriere return -1;
1092b844655cSEtienne Carriere
1093b844655cSEtienne Carriere if (request->mem_addr_size == I2C_MEMADD_SIZE_8BIT) {
1094b844655cSEtienne Carriere /* Send memory address */
1095b844655cSEtienne Carriere io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU);
1096b844655cSEtienne Carriere } else {
1097b844655cSEtienne Carriere /* Send MSB of memory address */
1098b844655cSEtienne Carriere io_write8(base + I2C_TXDR, (request->mem_addr & 0xFF00U) >> 8);
1099b844655cSEtienne Carriere
1100b844655cSEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1101b844655cSEtienne Carriere return -1;
1102b844655cSEtienne Carriere
1103b844655cSEtienne Carriere /* Send LSB of memory address */
1104b844655cSEtienne Carriere io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU);
1105b844655cSEtienne Carriere }
1106b844655cSEtienne Carriere
1107b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref))
1108b844655cSEtienne Carriere return -1;
1109b844655cSEtienne Carriere
1110b844655cSEtienne Carriere return 0;
1111b844655cSEtienne Carriere }
1112b844655cSEtienne Carriere
1113b844655cSEtienne Carriere /*
1114b844655cSEtienne Carriere * Master sends target device address followed by internal memory
1115b844655cSEtienne Carriere * address to prepare a memory read request.
1116b844655cSEtienne Carriere * Function returns 0 on success or a negative value.
1117b844655cSEtienne Carriere */
i2c_request_mem_read(struct i2c_handle_s * hi2c,struct i2c_request * request,uint64_t timeout_ref)1118b844655cSEtienne Carriere static int i2c_request_mem_read(struct i2c_handle_s *hi2c,
1119b844655cSEtienne Carriere struct i2c_request *request,
1120b844655cSEtienne Carriere uint64_t timeout_ref)
1121b844655cSEtienne Carriere {
1122b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
1123b844655cSEtienne Carriere
1124b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, request->mem_addr_size,
1125b844655cSEtienne Carriere I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
1126b844655cSEtienne Carriere
1127b844655cSEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1128b844655cSEtienne Carriere return -1;
1129b844655cSEtienne Carriere
1130b844655cSEtienne Carriere if (request->mem_addr_size == I2C_MEMADD_SIZE_8BIT) {
1131b844655cSEtienne Carriere /* Send memory address */
1132b844655cSEtienne Carriere io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU);
1133b844655cSEtienne Carriere } else {
1134b844655cSEtienne Carriere /* Send MSB of memory address */
1135b844655cSEtienne Carriere io_write8(base + I2C_TXDR, (request->mem_addr & 0xFF00U) >> 8);
1136b844655cSEtienne Carriere
1137b844655cSEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1138b844655cSEtienne Carriere return -1;
1139b844655cSEtienne Carriere
1140b844655cSEtienne Carriere /* Send LSB of memory address */
1141b844655cSEtienne Carriere io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU);
1142b844655cSEtienne Carriere }
1143b844655cSEtienne Carriere
1144b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_TC, 1, timeout_ref))
1145b844655cSEtienne Carriere return -1;
1146b844655cSEtienne Carriere
1147b844655cSEtienne Carriere return 0;
1148b844655cSEtienne Carriere }
1149b844655cSEtienne Carriere
1150b844655cSEtienne Carriere /*
1151b844655cSEtienne Carriere * Write an amount of data in blocking mode
1152b844655cSEtienne Carriere *
1153b844655cSEtienne Carriere * @hi2c: Reference to struct i2c_handle_s
1154b844655cSEtienne Carriere * @request: I2C request parameters
1155b844655cSEtienne Carriere * @p_data: Pointer to data buffer
1156b844655cSEtienne Carriere * @size: Amount of data to be sent
1157b844655cSEtienne Carriere * Return 0 on success or a negative value
1158b844655cSEtienne Carriere */
do_write(struct i2c_handle_s * hi2c,struct i2c_request * request,uint8_t * p_data,uint16_t size)11595bc9f8e5SEtienne Carriere static int do_write(struct i2c_handle_s *hi2c, struct i2c_request *request,
1160b844655cSEtienne Carriere uint8_t *p_data, uint16_t size)
1161b844655cSEtienne Carriere {
1162b844655cSEtienne Carriere uint64_t timeout_ref = 0;
1163b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
1164b844655cSEtienne Carriere int rc = -1;
1165b844655cSEtienne Carriere uint8_t *p_buff = p_data;
1166b844655cSEtienne Carriere size_t xfer_size = 0;
1167b844655cSEtienne Carriere size_t xfer_count = size;
1168b844655cSEtienne Carriere
1169b844655cSEtienne Carriere if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM)
1170b844655cSEtienne Carriere return -1;
1171b844655cSEtienne Carriere
1172b844655cSEtienne Carriere if (!p_data || !size)
1173b844655cSEtienne Carriere return -1;
1174b844655cSEtienne Carriere
1175*1e3057c6SEtienne Carriere lock_i2c_bus_access(hi2c);
1176bdde1c99SEtienne Carriere
1177bdde1c99SEtienne Carriere if (hi2c->i2c_state != I2C_STATE_READY) {
1178*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1179bdde1c99SEtienne Carriere return -1;
1180bdde1c99SEtienne Carriere }
1181bdde1c99SEtienne Carriere
1182929ec061SEtienne Carriere clk_enable(hi2c->clock);
1183b844655cSEtienne Carriere
1184b844655cSEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
1185b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref))
1186b844655cSEtienne Carriere goto bail;
1187b844655cSEtienne Carriere
1188b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_BUSY_TX;
1189b844655cSEtienne Carriere hi2c->i2c_err = I2C_ERROR_NONE;
1190b844655cSEtienne Carriere timeout_ref = timeout_init_us(request->timeout_ms * 1000);
1191b844655cSEtienne Carriere
1192b844655cSEtienne Carriere if (request->mode == I2C_MODE_MEM) {
1193b844655cSEtienne Carriere /* In memory mode, send slave address and memory address */
1194b844655cSEtienne Carriere if (i2c_request_mem_write(hi2c, request, timeout_ref))
1195b844655cSEtienne Carriere goto bail;
1196b844655cSEtienne Carriere
1197b844655cSEtienne Carriere if (xfer_count > MAX_NBYTE_SIZE) {
1198b844655cSEtienne Carriere xfer_size = MAX_NBYTE_SIZE;
1199b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, xfer_size,
1200b844655cSEtienne Carriere I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
1201b844655cSEtienne Carriere } else {
1202b844655cSEtienne Carriere xfer_size = xfer_count;
1203b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, xfer_size,
1204b844655cSEtienne Carriere I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
1205b844655cSEtienne Carriere }
1206b844655cSEtienne Carriere } else {
1207b844655cSEtienne Carriere /* In master mode, send slave address */
1208b844655cSEtienne Carriere if (xfer_count > MAX_NBYTE_SIZE) {
1209b844655cSEtienne Carriere xfer_size = MAX_NBYTE_SIZE;
1210b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, xfer_size,
1211b844655cSEtienne Carriere I2C_RELOAD_MODE,
1212b844655cSEtienne Carriere I2C_GENERATE_START_WRITE);
1213b844655cSEtienne Carriere } else {
1214b844655cSEtienne Carriere xfer_size = xfer_count;
1215b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, xfer_size,
1216b844655cSEtienne Carriere I2C_AUTOEND_MODE,
1217b844655cSEtienne Carriere I2C_GENERATE_START_WRITE);
1218b844655cSEtienne Carriere }
1219b844655cSEtienne Carriere }
1220b844655cSEtienne Carriere
1221b844655cSEtienne Carriere do {
1222b844655cSEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1223b844655cSEtienne Carriere goto bail;
1224b844655cSEtienne Carriere
1225b844655cSEtienne Carriere io_write8(base + I2C_TXDR, *p_buff);
1226b844655cSEtienne Carriere p_buff++;
1227b844655cSEtienne Carriere xfer_count--;
1228b844655cSEtienne Carriere xfer_size--;
1229b844655cSEtienne Carriere
1230b844655cSEtienne Carriere if (xfer_count && !xfer_size) {
1231b844655cSEtienne Carriere /* Wait until TCR flag is set */
1232b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref))
1233b844655cSEtienne Carriere goto bail;
1234b844655cSEtienne Carriere
1235b844655cSEtienne Carriere if (xfer_count > MAX_NBYTE_SIZE) {
1236b844655cSEtienne Carriere xfer_size = MAX_NBYTE_SIZE;
1237b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr,
1238b844655cSEtienne Carriere xfer_size,
1239b844655cSEtienne Carriere I2C_RELOAD_MODE,
1240b844655cSEtienne Carriere I2C_NO_STARTSTOP);
1241b844655cSEtienne Carriere } else {
1242b844655cSEtienne Carriere xfer_size = xfer_count;
1243b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr,
1244b844655cSEtienne Carriere xfer_size,
1245b844655cSEtienne Carriere I2C_AUTOEND_MODE,
1246b844655cSEtienne Carriere I2C_NO_STARTSTOP);
1247b844655cSEtienne Carriere }
1248b844655cSEtienne Carriere }
1249b844655cSEtienne Carriere
1250b844655cSEtienne Carriere } while (xfer_count > 0U);
1251b844655cSEtienne Carriere
1252b844655cSEtienne Carriere /*
1253b844655cSEtienne Carriere * No need to Check TC flag, with AUTOEND mode the stop
1254b844655cSEtienne Carriere * is automatically generated.
1255b844655cSEtienne Carriere * Wait until STOPF flag is reset.
1256b844655cSEtienne Carriere */
1257b844655cSEtienne Carriere if (i2c_wait_stop(hi2c, timeout_ref))
1258b844655cSEtienne Carriere goto bail;
1259b844655cSEtienne Carriere
1260b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
1261b844655cSEtienne Carriere
1262b844655cSEtienne Carriere io_clrbits32(base + I2C_CR2, CR2_RESET_MASK);
1263b844655cSEtienne Carriere
1264b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
1265b844655cSEtienne Carriere
1266b844655cSEtienne Carriere rc = 0;
1267b844655cSEtienne Carriere
1268b844655cSEtienne Carriere bail:
1269929ec061SEtienne Carriere clk_disable(hi2c->clock);
1270*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1271b844655cSEtienne Carriere
1272b844655cSEtienne Carriere return rc;
1273b844655cSEtienne Carriere }
1274b844655cSEtienne Carriere
stm32_i2c_mem_write(struct i2c_handle_s * hi2c,uint32_t dev_addr,uint32_t mem_addr,uint32_t mem_addr_size,uint8_t * p_data,size_t size,unsigned int timeout_ms)1275b844655cSEtienne Carriere int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint32_t dev_addr,
1276b844655cSEtienne Carriere uint32_t mem_addr, uint32_t mem_addr_size,
1277b844655cSEtienne Carriere uint8_t *p_data, size_t size, unsigned int timeout_ms)
1278b844655cSEtienne Carriere {
1279b844655cSEtienne Carriere struct i2c_request request = {
1280b844655cSEtienne Carriere .dev_addr = dev_addr,
1281b844655cSEtienne Carriere .mode = I2C_MODE_MEM,
1282b844655cSEtienne Carriere .mem_addr = mem_addr,
1283b844655cSEtienne Carriere .mem_addr_size = mem_addr_size,
1284b844655cSEtienne Carriere .timeout_ms = timeout_ms,
1285b844655cSEtienne Carriere };
1286b844655cSEtienne Carriere
12875bc9f8e5SEtienne Carriere return do_write(hi2c, &request, p_data, size);
1288b844655cSEtienne Carriere }
1289b844655cSEtienne Carriere
stm32_i2c_master_transmit(struct i2c_handle_s * hi2c,uint32_t dev_addr,uint8_t * p_data,size_t size,unsigned int timeout_ms)1290b844655cSEtienne Carriere int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint32_t dev_addr,
1291b844655cSEtienne Carriere uint8_t *p_data, size_t size,
1292b844655cSEtienne Carriere unsigned int timeout_ms)
1293b844655cSEtienne Carriere {
1294b844655cSEtienne Carriere struct i2c_request request = {
1295b844655cSEtienne Carriere .dev_addr = dev_addr,
1296b844655cSEtienne Carriere .mode = I2C_MODE_MASTER,
1297b844655cSEtienne Carriere .timeout_ms = timeout_ms,
1298b844655cSEtienne Carriere };
1299b844655cSEtienne Carriere
13005bc9f8e5SEtienne Carriere return do_write(hi2c, &request, p_data, size);
1301b844655cSEtienne Carriere }
1302b844655cSEtienne Carriere
stm32_i2c_read_write_membyte(struct i2c_handle_s * hi2c,uint16_t dev_addr,unsigned int mem_addr,uint8_t * p_data,bool write)1303834ce4c6SEtienne Carriere int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr,
1304834ce4c6SEtienne Carriere unsigned int mem_addr, uint8_t *p_data,
1305834ce4c6SEtienne Carriere bool write)
1306834ce4c6SEtienne Carriere {
1307834ce4c6SEtienne Carriere uint64_t timeout_ref = 0;
1308834ce4c6SEtienne Carriere uintptr_t base = get_base(hi2c);
1309834ce4c6SEtienne Carriere int rc = -1;
1310834ce4c6SEtienne Carriere uint8_t *p_buff = p_data;
1311834ce4c6SEtienne Carriere uint32_t event_mask = 0;
1312834ce4c6SEtienne Carriere
1313*1e3057c6SEtienne Carriere lock_i2c_bus_access(hi2c);
1314bdde1c99SEtienne Carriere
1315bdde1c99SEtienne Carriere if (hi2c->i2c_state != I2C_STATE_READY || !p_data) {
1316*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1317834ce4c6SEtienne Carriere return -1;
1318bdde1c99SEtienne Carriere }
1319834ce4c6SEtienne Carriere
1320929ec061SEtienne Carriere clk_enable(hi2c->clock);
1321834ce4c6SEtienne Carriere
1322834ce4c6SEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US);
1323834ce4c6SEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref))
1324834ce4c6SEtienne Carriere goto bail;
1325834ce4c6SEtienne Carriere
1326834ce4c6SEtienne Carriere hi2c->i2c_state = write ? I2C_STATE_BUSY_TX : I2C_STATE_BUSY_RX;
1327834ce4c6SEtienne Carriere hi2c->i2c_err = I2C_ERROR_NONE;
1328834ce4c6SEtienne Carriere
1329834ce4c6SEtienne Carriere i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT,
1330834ce4c6SEtienne Carriere write ? I2C_RELOAD_MODE : I2C_SOFTEND_MODE,
1331834ce4c6SEtienne Carriere I2C_GENERATE_START_WRITE);
1332834ce4c6SEtienne Carriere
1333834ce4c6SEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US);
1334834ce4c6SEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1335834ce4c6SEtienne Carriere goto bail;
1336834ce4c6SEtienne Carriere
1337834ce4c6SEtienne Carriere io_write8(base + I2C_TXDR, mem_addr);
1338834ce4c6SEtienne Carriere
1339834ce4c6SEtienne Carriere if (write)
1340834ce4c6SEtienne Carriere event_mask = I2C_ISR_TCR;
1341834ce4c6SEtienne Carriere else
1342834ce4c6SEtienne Carriere event_mask = I2C_ISR_TC;
1343834ce4c6SEtienne Carriere
1344834ce4c6SEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US);
1345834ce4c6SEtienne Carriere if (wait_isr_event(hi2c, event_mask, 1, timeout_ref))
1346834ce4c6SEtienne Carriere goto bail;
1347834ce4c6SEtienne Carriere
1348834ce4c6SEtienne Carriere i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT,
1349834ce4c6SEtienne Carriere I2C_AUTOEND_MODE,
1350834ce4c6SEtienne Carriere write ? I2C_NO_STARTSTOP : I2C_GENERATE_START_READ);
1351834ce4c6SEtienne Carriere
1352834ce4c6SEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US);
1353834ce4c6SEtienne Carriere if (write) {
1354834ce4c6SEtienne Carriere if (i2c_wait_txis(hi2c, timeout_ref))
1355834ce4c6SEtienne Carriere goto bail;
1356834ce4c6SEtienne Carriere
1357834ce4c6SEtienne Carriere io_write8(base + I2C_TXDR, *p_buff);
1358834ce4c6SEtienne Carriere } else {
1359834ce4c6SEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1, timeout_ref))
1360834ce4c6SEtienne Carriere goto bail;
1361834ce4c6SEtienne Carriere
1362834ce4c6SEtienne Carriere *p_buff = io_read8(base + I2C_RXDR);
1363834ce4c6SEtienne Carriere }
1364834ce4c6SEtienne Carriere
1365834ce4c6SEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US);
1366834ce4c6SEtienne Carriere if (i2c_wait_stop(hi2c, timeout_ref))
1367834ce4c6SEtienne Carriere goto bail;
1368834ce4c6SEtienne Carriere
1369834ce4c6SEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
1370834ce4c6SEtienne Carriere io_clrbits32(base + I2C_CR2, CR2_RESET_MASK);
1371834ce4c6SEtienne Carriere
1372834ce4c6SEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
1373834ce4c6SEtienne Carriere
1374834ce4c6SEtienne Carriere rc = 0;
1375834ce4c6SEtienne Carriere
1376834ce4c6SEtienne Carriere bail:
1377929ec061SEtienne Carriere clk_disable(hi2c->clock);
1378*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1379834ce4c6SEtienne Carriere
1380834ce4c6SEtienne Carriere return rc;
1381834ce4c6SEtienne Carriere }
1382834ce4c6SEtienne Carriere
1383b844655cSEtienne Carriere /*
1384b844655cSEtienne Carriere * Read an amount of data in blocking mode
1385b844655cSEtienne Carriere *
1386b844655cSEtienne Carriere * @hi2c: Reference to struct i2c_handle_s
1387b844655cSEtienne Carriere * @request: I2C request parameters
1388b844655cSEtienne Carriere * @p_data: Pointer to data buffer
1389b844655cSEtienne Carriere * @size: Amount of data to be sent
1390b844655cSEtienne Carriere * Return 0 on success or a negative value
1391b844655cSEtienne Carriere */
do_read(struct i2c_handle_s * hi2c,struct i2c_request * request,uint8_t * p_data,uint32_t size)13925bc9f8e5SEtienne Carriere static int do_read(struct i2c_handle_s *hi2c, struct i2c_request *request,
1393b844655cSEtienne Carriere uint8_t *p_data, uint32_t size)
1394b844655cSEtienne Carriere {
1395b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
1396b844655cSEtienne Carriere uint64_t timeout_ref = 0;
1397b844655cSEtienne Carriere int rc = -1;
1398b844655cSEtienne Carriere uint8_t *p_buff = p_data;
1399b844655cSEtienne Carriere size_t xfer_count = size;
1400b844655cSEtienne Carriere size_t xfer_size = 0;
1401b844655cSEtienne Carriere
1402b844655cSEtienne Carriere if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM)
1403b844655cSEtienne Carriere return -1;
1404b844655cSEtienne Carriere
1405b844655cSEtienne Carriere if (!p_data || !size)
1406b844655cSEtienne Carriere return -1;
1407b844655cSEtienne Carriere
1408*1e3057c6SEtienne Carriere lock_i2c_bus_access(hi2c);
1409bdde1c99SEtienne Carriere
1410bdde1c99SEtienne Carriere if (hi2c->i2c_state != I2C_STATE_READY) {
1411*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1412bdde1c99SEtienne Carriere return -1;
1413bdde1c99SEtienne Carriere }
1414bdde1c99SEtienne Carriere
1415929ec061SEtienne Carriere clk_enable(hi2c->clock);
1416b844655cSEtienne Carriere
1417b844655cSEtienne Carriere timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
1418b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref))
1419b844655cSEtienne Carriere goto bail;
1420b844655cSEtienne Carriere
1421b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_BUSY_RX;
1422b844655cSEtienne Carriere hi2c->i2c_err = I2C_ERROR_NONE;
1423b844655cSEtienne Carriere timeout_ref = timeout_init_us(request->timeout_ms * 1000);
1424b844655cSEtienne Carriere
1425b844655cSEtienne Carriere if (request->mode == I2C_MODE_MEM) {
1426b844655cSEtienne Carriere /* Send memory address */
1427b844655cSEtienne Carriere if (i2c_request_mem_read(hi2c, request, timeout_ref))
1428b844655cSEtienne Carriere goto bail;
1429b844655cSEtienne Carriere }
1430b844655cSEtienne Carriere
1431b844655cSEtienne Carriere /*
1432b844655cSEtienne Carriere * Send slave address.
1433b844655cSEtienne Carriere * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE
1434b844655cSEtienne Carriere * and generate RESTART.
1435b844655cSEtienne Carriere */
1436b844655cSEtienne Carriere if (xfer_count > MAX_NBYTE_SIZE) {
1437b844655cSEtienne Carriere xfer_size = MAX_NBYTE_SIZE;
1438b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, xfer_size,
1439b844655cSEtienne Carriere I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
1440b844655cSEtienne Carriere } else {
1441b844655cSEtienne Carriere xfer_size = xfer_count;
1442b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr, xfer_size,
1443b844655cSEtienne Carriere I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
1444b844655cSEtienne Carriere }
1445b844655cSEtienne Carriere
1446b844655cSEtienne Carriere do {
144798fca444SJorge Ramirez-Ortiz if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1,
144898fca444SJorge Ramirez-Ortiz timeout_init_us(I2C_TIMEOUT_RXNE_MS * 1000)))
1449b844655cSEtienne Carriere goto bail;
1450b844655cSEtienne Carriere
1451b844655cSEtienne Carriere *p_buff = io_read8(base + I2C_RXDR);
1452b844655cSEtienne Carriere p_buff++;
1453b844655cSEtienne Carriere xfer_size--;
1454b844655cSEtienne Carriere xfer_count--;
1455b844655cSEtienne Carriere
1456b844655cSEtienne Carriere if (xfer_count && !xfer_size) {
1457b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref))
1458b844655cSEtienne Carriere goto bail;
1459b844655cSEtienne Carriere
1460b844655cSEtienne Carriere if (xfer_count > MAX_NBYTE_SIZE) {
1461b844655cSEtienne Carriere xfer_size = MAX_NBYTE_SIZE;
1462b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr,
1463b844655cSEtienne Carriere xfer_size,
1464b844655cSEtienne Carriere I2C_RELOAD_MODE,
1465b844655cSEtienne Carriere I2C_NO_STARTSTOP);
1466b844655cSEtienne Carriere } else {
1467b844655cSEtienne Carriere xfer_size = xfer_count;
1468b844655cSEtienne Carriere i2c_transfer_config(hi2c, request->dev_addr,
1469b844655cSEtienne Carriere xfer_size,
1470b844655cSEtienne Carriere I2C_AUTOEND_MODE,
1471b844655cSEtienne Carriere I2C_NO_STARTSTOP);
1472b844655cSEtienne Carriere }
1473b844655cSEtienne Carriere }
1474b844655cSEtienne Carriere } while (xfer_count > 0U);
1475b844655cSEtienne Carriere
1476b844655cSEtienne Carriere /*
1477b844655cSEtienne Carriere * No need to Check TC flag, with AUTOEND mode the stop
1478b844655cSEtienne Carriere * is automatically generated.
1479b844655cSEtienne Carriere * Wait until STOPF flag is reset.
1480b844655cSEtienne Carriere */
1481b844655cSEtienne Carriere if (i2c_wait_stop(hi2c, timeout_ref))
1482b844655cSEtienne Carriere goto bail;
1483b844655cSEtienne Carriere
1484646c0a2bSJorge Ramirez-Ortiz /* Clear the NACK generated at the end of the transfer */
1485646c0a2bSJorge Ramirez-Ortiz if ((io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_NACKF))
1486646c0a2bSJorge Ramirez-Ortiz io_write32(get_base(hi2c) + I2C_ICR, I2C_ICR_NACKCF);
1487646c0a2bSJorge Ramirez-Ortiz
1488b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
1489b844655cSEtienne Carriere
1490b844655cSEtienne Carriere io_clrbits32(base + I2C_CR2, CR2_RESET_MASK);
1491b844655cSEtienne Carriere
1492b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
1493b844655cSEtienne Carriere
1494b844655cSEtienne Carriere rc = 0;
1495b844655cSEtienne Carriere
1496b844655cSEtienne Carriere bail:
1497929ec061SEtienne Carriere clk_disable(hi2c->clock);
1498*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1499b844655cSEtienne Carriere
1500b844655cSEtienne Carriere return rc;
1501b844655cSEtienne Carriere }
1502b844655cSEtienne Carriere
stm32_i2c_mem_read(struct i2c_handle_s * hi2c,uint32_t dev_addr,uint32_t mem_addr,uint32_t mem_addr_size,uint8_t * p_data,size_t size,unsigned int timeout_ms)1503b844655cSEtienne Carriere int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint32_t dev_addr,
1504b844655cSEtienne Carriere uint32_t mem_addr, uint32_t mem_addr_size,
1505b844655cSEtienne Carriere uint8_t *p_data, size_t size, unsigned int timeout_ms)
1506b844655cSEtienne Carriere {
1507b844655cSEtienne Carriere struct i2c_request request = {
1508b844655cSEtienne Carriere .dev_addr = dev_addr,
1509b844655cSEtienne Carriere .mode = I2C_MODE_MEM,
1510b844655cSEtienne Carriere .mem_addr = mem_addr,
1511b844655cSEtienne Carriere .mem_addr_size = mem_addr_size,
1512b844655cSEtienne Carriere .timeout_ms = timeout_ms,
1513b844655cSEtienne Carriere };
1514b844655cSEtienne Carriere
15155bc9f8e5SEtienne Carriere return do_read(hi2c, &request, p_data, size);
1516b844655cSEtienne Carriere }
1517b844655cSEtienne Carriere
stm32_i2c_master_receive(struct i2c_handle_s * hi2c,uint32_t dev_addr,uint8_t * p_data,size_t size,unsigned int timeout_ms)1518b844655cSEtienne Carriere int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint32_t dev_addr,
1519b844655cSEtienne Carriere uint8_t *p_data, size_t size,
1520b844655cSEtienne Carriere unsigned int timeout_ms)
1521b844655cSEtienne Carriere {
1522b844655cSEtienne Carriere struct i2c_request request = {
1523b844655cSEtienne Carriere .dev_addr = dev_addr,
1524b844655cSEtienne Carriere .mode = I2C_MODE_MASTER,
1525b844655cSEtienne Carriere .timeout_ms = timeout_ms,
1526b844655cSEtienne Carriere };
1527b844655cSEtienne Carriere
15285bc9f8e5SEtienne Carriere return do_read(hi2c, &request, p_data, size);
1529b844655cSEtienne Carriere }
1530b844655cSEtienne Carriere
stm32_i2c_dev_to_handle(struct i2c_dev * i2c_dev)15315bc9f8e5SEtienne Carriere static struct i2c_handle_s *stm32_i2c_dev_to_handle(struct i2c_dev *i2c_dev)
15325bc9f8e5SEtienne Carriere {
15335bc9f8e5SEtienne Carriere struct stm32_i2c_dev *dev = container_of(i2c_dev, struct stm32_i2c_dev,
15345bc9f8e5SEtienne Carriere i2c_dev);
15355bc9f8e5SEtienne Carriere
15365bc9f8e5SEtienne Carriere return dev->handle;
15375bc9f8e5SEtienne Carriere }
15385bc9f8e5SEtienne Carriere
stm32_i2c_read_data(struct i2c_dev * i2c_dev,uint8_t * buf,size_t len)15395bc9f8e5SEtienne Carriere static TEE_Result stm32_i2c_read_data(struct i2c_dev *i2c_dev, uint8_t *buf,
15405bc9f8e5SEtienne Carriere size_t len)
15415bc9f8e5SEtienne Carriere {
15425bc9f8e5SEtienne Carriere struct i2c_handle_s *i2c_handle = stm32_i2c_dev_to_handle(i2c_dev);
15435bc9f8e5SEtienne Carriere int rc = 0;
15445bc9f8e5SEtienne Carriere
15455bc9f8e5SEtienne Carriere rc = stm32_i2c_master_receive(i2c_handle, i2c_dev->addr, buf, len,
15465bc9f8e5SEtienne Carriere I2C_TIMEOUT_DEFAULT_MS);
15475bc9f8e5SEtienne Carriere if (!rc)
15485bc9f8e5SEtienne Carriere return TEE_SUCCESS;
15495bc9f8e5SEtienne Carriere else
15505bc9f8e5SEtienne Carriere return TEE_ERROR_GENERIC;
15515bc9f8e5SEtienne Carriere }
15525bc9f8e5SEtienne Carriere
stm32_i2c_write_data(struct i2c_dev * i2c_dev,const uint8_t * buf,size_t len)15535bc9f8e5SEtienne Carriere static TEE_Result stm32_i2c_write_data(struct i2c_dev *i2c_dev,
15545bc9f8e5SEtienne Carriere const uint8_t *buf, size_t len)
15555bc9f8e5SEtienne Carriere {
15565bc9f8e5SEtienne Carriere struct i2c_handle_s *i2c_handle = stm32_i2c_dev_to_handle(i2c_dev);
15575bc9f8e5SEtienne Carriere uint8_t *buf2 = (uint8_t *)buf;
15585bc9f8e5SEtienne Carriere int rc = 0;
15595bc9f8e5SEtienne Carriere
15605bc9f8e5SEtienne Carriere rc = stm32_i2c_master_transmit(i2c_handle, i2c_dev->addr, buf2, len,
15615bc9f8e5SEtienne Carriere I2C_TIMEOUT_DEFAULT_MS);
15625bc9f8e5SEtienne Carriere if (!rc)
15635bc9f8e5SEtienne Carriere return TEE_SUCCESS;
15645bc9f8e5SEtienne Carriere else
15655bc9f8e5SEtienne Carriere return TEE_ERROR_GENERIC;
15665bc9f8e5SEtienne Carriere }
15675bc9f8e5SEtienne Carriere
15685bc9f8e5SEtienne Carriere static const struct i2c_ctrl_ops stm32_i2c_ops = {
15695bc9f8e5SEtienne Carriere .read = stm32_i2c_read_data,
15705bc9f8e5SEtienne Carriere .write = stm32_i2c_write_data,
15715bc9f8e5SEtienne Carriere };
15725bc9f8e5SEtienne Carriere
stm32_i2c_is_device_ready(struct i2c_handle_s * hi2c,uint32_t dev_addr,unsigned int trials,unsigned int timeout_ms)1573b844655cSEtienne Carriere bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr,
1574b844655cSEtienne Carriere unsigned int trials, unsigned int timeout_ms)
1575b844655cSEtienne Carriere {
1576b844655cSEtienne Carriere vaddr_t base = get_base(hi2c);
1577b844655cSEtienne Carriere unsigned int i2c_trials = 0U;
1578b844655cSEtienne Carriere bool rc = false;
1579b844655cSEtienne Carriere
1580*1e3057c6SEtienne Carriere lock_i2c_bus_access(hi2c);
1581bdde1c99SEtienne Carriere
1582bdde1c99SEtienne Carriere if (hi2c->i2c_state != I2C_STATE_READY) {
1583*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1584b844655cSEtienne Carriere return rc;
1585bdde1c99SEtienne Carriere }
1586b844655cSEtienne Carriere
1587929ec061SEtienne Carriere clk_enable(hi2c->clock);
1588b844655cSEtienne Carriere
1589b844655cSEtienne Carriere if (io_read32(base + I2C_ISR) & I2C_ISR_BUSY)
1590b844655cSEtienne Carriere goto bail;
1591b844655cSEtienne Carriere
1592b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_BUSY;
1593b844655cSEtienne Carriere hi2c->i2c_err = I2C_ERROR_NONE;
1594b844655cSEtienne Carriere
1595b844655cSEtienne Carriere do {
1596b844655cSEtienne Carriere uint64_t timeout_ref = 0;
1597b844655cSEtienne Carriere vaddr_t isr = base + I2C_ISR;
1598b844655cSEtienne Carriere
1599b844655cSEtienne Carriere /* Generate Start */
1600b844655cSEtienne Carriere if ((io_read32(base + I2C_OAR1) & I2C_OAR1_OA1MODE) == 0)
1601b844655cSEtienne Carriere io_write32(base + I2C_CR2,
1602b844655cSEtienne Carriere ((dev_addr & I2C_CR2_SADD) |
1603b844655cSEtienne Carriere I2C_CR2_START | I2C_CR2_AUTOEND) &
1604b844655cSEtienne Carriere ~I2C_CR2_RD_WRN);
1605b844655cSEtienne Carriere else
1606b844655cSEtienne Carriere io_write32(base + I2C_CR2,
1607b844655cSEtienne Carriere ((dev_addr & I2C_CR2_SADD) |
1608b844655cSEtienne Carriere I2C_CR2_START | I2C_CR2_ADD10) &
1609b844655cSEtienne Carriere ~I2C_CR2_RD_WRN);
1610b844655cSEtienne Carriere
1611b844655cSEtienne Carriere /*
1612b844655cSEtienne Carriere * No need to Check TC flag, with AUTOEND mode the stop
1613b844655cSEtienne Carriere * is automatically generated.
1614b844655cSEtienne Carriere * Wait until STOPF flag is set or a NACK flag is set.
1615b844655cSEtienne Carriere */
1616b844655cSEtienne Carriere timeout_ref = timeout_init_us(timeout_ms * 1000);
1617b844655cSEtienne Carriere while (!timeout_elapsed(timeout_ref))
1618b844655cSEtienne Carriere if (io_read32(isr) & (I2C_ISR_STOPF | I2C_ISR_NACKF))
1619b844655cSEtienne Carriere break;
1620b844655cSEtienne Carriere
1621b844655cSEtienne Carriere if ((io_read32(isr) & (I2C_ISR_STOPF | I2C_ISR_NACKF)) == 0) {
1622b844655cSEtienne Carriere notif_i2c_timeout(hi2c);
1623b844655cSEtienne Carriere goto bail;
1624b844655cSEtienne Carriere }
1625b844655cSEtienne Carriere
1626b844655cSEtienne Carriere if ((io_read32(base + I2C_ISR) & I2C_ISR_NACKF) == 0U) {
1627b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref))
1628b844655cSEtienne Carriere goto bail;
1629b844655cSEtienne Carriere
1630b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
1631b844655cSEtienne Carriere
1632b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
1633b844655cSEtienne Carriere
1634b844655cSEtienne Carriere rc = true;
1635b844655cSEtienne Carriere goto bail;
1636b844655cSEtienne Carriere }
1637b844655cSEtienne Carriere
1638b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref))
1639b844655cSEtienne Carriere goto bail;
1640b844655cSEtienne Carriere
1641b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_NACKF);
1642b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
1643b844655cSEtienne Carriere
1644b844655cSEtienne Carriere if (i2c_trials == trials) {
1645b844655cSEtienne Carriere io_setbits32(base + I2C_CR2, I2C_CR2_STOP);
1646b844655cSEtienne Carriere
1647b844655cSEtienne Carriere if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref))
1648b844655cSEtienne Carriere goto bail;
1649b844655cSEtienne Carriere
1650b844655cSEtienne Carriere io_write32(base + I2C_ICR, I2C_ISR_STOPF);
1651b844655cSEtienne Carriere }
1652b844655cSEtienne Carriere
1653b844655cSEtienne Carriere i2c_trials++;
1654b844655cSEtienne Carriere } while (i2c_trials < trials);
1655b844655cSEtienne Carriere
1656b844655cSEtienne Carriere notif_i2c_timeout(hi2c);
1657b844655cSEtienne Carriere
1658b844655cSEtienne Carriere bail:
1659929ec061SEtienne Carriere clk_disable(hi2c->clock);
1660*1e3057c6SEtienne Carriere unlock_i2c_bus_access(hi2c);
1661b844655cSEtienne Carriere
1662b844655cSEtienne Carriere return rc;
1663b844655cSEtienne Carriere }
1664b844655cSEtienne Carriere
stm32_i2c_interrupt_access_lockdeps(struct i2c_handle_s * hi2c,struct itr_chip * itr_chip,size_t itr_num)1665*1e3057c6SEtienne Carriere void stm32_i2c_interrupt_access_lockdeps(struct i2c_handle_s *hi2c,
1666*1e3057c6SEtienne Carriere struct itr_chip *itr_chip,
1667*1e3057c6SEtienne Carriere size_t itr_num)
1668*1e3057c6SEtienne Carriere {
1669*1e3057c6SEtienne Carriere struct stm32_itr_dep *itr_dep = NULL;
1670*1e3057c6SEtienne Carriere
1671*1e3057c6SEtienne Carriere itr_dep = calloc(1, sizeof(*itr_dep));
1672*1e3057c6SEtienne Carriere if (!itr_dep)
1673*1e3057c6SEtienne Carriere panic();
1674*1e3057c6SEtienne Carriere
1675*1e3057c6SEtienne Carriere itr_dep->chip = itr_chip;
1676*1e3057c6SEtienne Carriere itr_dep->num = itr_num;
1677*1e3057c6SEtienne Carriere SLIST_INSERT_HEAD(&hi2c->consumer_itr_head, itr_dep, link);
1678*1e3057c6SEtienne Carriere }
1679*1e3057c6SEtienne Carriere
stm32_i2c_resume(struct i2c_handle_s * hi2c)1680b844655cSEtienne Carriere void stm32_i2c_resume(struct i2c_handle_s *hi2c)
1681b844655cSEtienne Carriere {
1682b844655cSEtienne Carriere if (hi2c->i2c_state == I2C_STATE_READY)
1683b844655cSEtienne Carriere return;
1684b844655cSEtienne Carriere
1685b844655cSEtienne Carriere if ((hi2c->i2c_state != I2C_STATE_RESET) &&
1686b844655cSEtienne Carriere (hi2c->i2c_state != I2C_STATE_SUSPENDED))
1687b844655cSEtienne Carriere panic();
1688b844655cSEtienne Carriere
168973ba32ebSEtienne Carriere if (pinctrl_apply_state(hi2c->pinctrl))
169073ba32ebSEtienne Carriere panic();
1691c75303f7SEtienne Carriere
1692b844655cSEtienne Carriere if (hi2c->i2c_state == I2C_STATE_RESET) {
1693c75303f7SEtienne Carriere /* There is no valid I2C configuration to be loaded yet */
1694b844655cSEtienne Carriere return;
1695b844655cSEtienne Carriere }
1696b844655cSEtienne Carriere
1697b844655cSEtienne Carriere restore_cfg(hi2c, &hi2c->sec_cfg);
1698b844655cSEtienne Carriere
1699b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_READY;
1700b844655cSEtienne Carriere }
1701b844655cSEtienne Carriere
stm32_i2c_suspend(struct i2c_handle_s * hi2c)1702b844655cSEtienne Carriere void stm32_i2c_suspend(struct i2c_handle_s *hi2c)
1703b844655cSEtienne Carriere {
1704b844655cSEtienne Carriere if (hi2c->i2c_state == I2C_STATE_SUSPENDED)
1705b844655cSEtienne Carriere return;
1706b844655cSEtienne Carriere
1707b844655cSEtienne Carriere if (hi2c->i2c_state != I2C_STATE_READY)
1708b844655cSEtienne Carriere panic();
1709b844655cSEtienne Carriere
1710b844655cSEtienne Carriere save_cfg(hi2c, &hi2c->sec_cfg);
171173ba32ebSEtienne Carriere
171273ba32ebSEtienne Carriere if (hi2c->pinctrl_sleep && pinctrl_apply_state(hi2c->pinctrl_sleep))
171373ba32ebSEtienne Carriere panic();
1714b844655cSEtienne Carriere
1715b844655cSEtienne Carriere hi2c->i2c_state = I2C_STATE_SUSPENDED;
1716b844655cSEtienne Carriere }
17175bc9f8e5SEtienne Carriere
stm32_get_i2c_dev(struct dt_pargs * args,void * data,struct i2c_dev ** out_device)17185bc9f8e5SEtienne Carriere static TEE_Result stm32_get_i2c_dev(struct dt_pargs *args, void *data,
17195bc9f8e5SEtienne Carriere struct i2c_dev **out_device)
17205bc9f8e5SEtienne Carriere {
17215bc9f8e5SEtienne Carriere struct stm32_i2c_dev *stm32_i2c_dev = NULL;
17225bc9f8e5SEtienne Carriere paddr_t addr = 0;
17235bc9f8e5SEtienne Carriere
1724f4cc581bSEtienne Carriere addr = fdt_reg_base_address(args->fdt, args->consumer_node);
17255bc9f8e5SEtienne Carriere if (addr == DT_INFO_INVALID_REG) {
17265bc9f8e5SEtienne Carriere DMSG("Can't get device I2C address");
17275bc9f8e5SEtienne Carriere return TEE_ERROR_GENERIC;
17285bc9f8e5SEtienne Carriere }
17295bc9f8e5SEtienne Carriere
17305bc9f8e5SEtienne Carriere stm32_i2c_dev = calloc(1, sizeof(*stm32_i2c_dev));
17315bc9f8e5SEtienne Carriere if (!stm32_i2c_dev)
17325bc9f8e5SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY;
17335bc9f8e5SEtienne Carriere
17345bc9f8e5SEtienne Carriere stm32_i2c_dev->handle = data;
17355bc9f8e5SEtienne Carriere stm32_i2c_dev->i2c_dev.addr = addr;
17365bc9f8e5SEtienne Carriere stm32_i2c_dev->i2c_ctrl.ops = &stm32_i2c_ops;
17375bc9f8e5SEtienne Carriere stm32_i2c_dev->i2c_dev.ctrl = &stm32_i2c_dev->i2c_ctrl;
17385bc9f8e5SEtienne Carriere
17395bc9f8e5SEtienne Carriere *out_device = &stm32_i2c_dev->i2c_dev;
17405bc9f8e5SEtienne Carriere
17415bc9f8e5SEtienne Carriere return TEE_SUCCESS;
17425bc9f8e5SEtienne Carriere }
17435bc9f8e5SEtienne Carriere
stm32_i2c_probe(const void * fdt,int node,const void * compat_data)17445bc9f8e5SEtienne Carriere static TEE_Result stm32_i2c_probe(const void *fdt, int node,
1745ded20780SEtienne Carriere const void *compat_data)
17465bc9f8e5SEtienne Carriere {
17475bc9f8e5SEtienne Carriere TEE_Result res = TEE_SUCCESS;
17485bc9f8e5SEtienne Carriere int subnode = 0;
17495bc9f8e5SEtienne Carriere struct i2c_handle_s *i2c_handle_p = NULL;
17505bc9f8e5SEtienne Carriere struct stm32_i2c_init_s init_data = { };
17515bc9f8e5SEtienne Carriere struct pinctrl_state *pinctrl_active = NULL;
17525bc9f8e5SEtienne Carriere struct pinctrl_state *pinctrl_idle = NULL;
17535bc9f8e5SEtienne Carriere
17545bc9f8e5SEtienne Carriere res = stm32_i2c_get_setup_from_fdt((void *)fdt, node, &init_data,
17555bc9f8e5SEtienne Carriere &pinctrl_active, &pinctrl_idle);
17565bc9f8e5SEtienne Carriere if (res)
17575bc9f8e5SEtienne Carriere return res;
17585bc9f8e5SEtienne Carriere
17595bc9f8e5SEtienne Carriere i2c_handle_p = calloc(1, sizeof(struct i2c_handle_s));
17605bc9f8e5SEtienne Carriere if (!i2c_handle_p)
17615bc9f8e5SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY;
17625bc9f8e5SEtienne Carriere
17635bc9f8e5SEtienne Carriere i2c_handle_p->reg_size = init_data.reg_size;
17645bc9f8e5SEtienne Carriere i2c_handle_p->clock = init_data.clock;
17655bc9f8e5SEtienne Carriere i2c_handle_p->base.pa = init_data.pbase;
17665bc9f8e5SEtienne Carriere i2c_handle_p->base.va = io_pa_or_va(&i2c_handle_p->base,
17675bc9f8e5SEtienne Carriere init_data.reg_size);
17685bc9f8e5SEtienne Carriere assert(i2c_handle_p->base.va);
17695bc9f8e5SEtienne Carriere i2c_handle_p->clock = init_data.clock;
17705bc9f8e5SEtienne Carriere i2c_handle_p->i2c_state = I2C_STATE_RESET;
17715bc9f8e5SEtienne Carriere i2c_handle_p->pinctrl = pinctrl_active;
17725bc9f8e5SEtienne Carriere i2c_handle_p->pinctrl_sleep = pinctrl_idle;
17735bc9f8e5SEtienne Carriere
1774ded20780SEtienne Carriere if (compat_data != &non_secure_bus)
1775ded20780SEtienne Carriere i2c_handle_p->i2c_secure = true;
1776ded20780SEtienne Carriere
17775bc9f8e5SEtienne Carriere init_data.analog_filter = true;
17785bc9f8e5SEtienne Carriere init_data.digital_filter_coef = 0;
17795bc9f8e5SEtienne Carriere
1780c425380fSEtienne Carriere if (stm32_i2c_init(i2c_handle_p, &init_data))
17815bc9f8e5SEtienne Carriere panic("Couldn't initialise I2C");
17825bc9f8e5SEtienne Carriere
17835bc9f8e5SEtienne Carriere res = i2c_register_provider(fdt, node, stm32_get_i2c_dev, i2c_handle_p);
17845bc9f8e5SEtienne Carriere if (res)
17855bc9f8e5SEtienne Carriere panic("Couldn't register I2C provider");
17865bc9f8e5SEtienne Carriere
17875bc9f8e5SEtienne Carriere fdt_for_each_subnode(subnode, fdt, node) {
17885bc9f8e5SEtienne Carriere res = dt_driver_maybe_add_probe_node(fdt, subnode);
17895bc9f8e5SEtienne Carriere if (res) {
17905bc9f8e5SEtienne Carriere EMSG("Failed on node %s with %#"PRIx32,
17915bc9f8e5SEtienne Carriere fdt_get_name(fdt, subnode, NULL), res);
17925bc9f8e5SEtienne Carriere panic();
17935bc9f8e5SEtienne Carriere }
17945bc9f8e5SEtienne Carriere }
17955bc9f8e5SEtienne Carriere
17965bc9f8e5SEtienne Carriere return res;
17975bc9f8e5SEtienne Carriere }
17985bc9f8e5SEtienne Carriere
17995bc9f8e5SEtienne Carriere static const struct dt_device_match stm32_i2c_match_table[] = {
18005bc9f8e5SEtienne Carriere { .compatible = "st,stm32mp15-i2c" },
18015bc9f8e5SEtienne Carriere { .compatible = "st,stm32mp13-i2c" },
1802ded20780SEtienne Carriere {
1803ded20780SEtienne Carriere .compatible = "st,stm32mp15-i2c-non-secure",
1804ded20780SEtienne Carriere .compat_data = &non_secure_bus,
1805ded20780SEtienne Carriere },
18060f92c2adSThomas Bourgoin { .compatible = "st,stm32mp25-i2c" },
18075bc9f8e5SEtienne Carriere { }
18085bc9f8e5SEtienne Carriere };
18095bc9f8e5SEtienne Carriere
18105bc9f8e5SEtienne Carriere DEFINE_DT_DRIVER(stm32_i2c_dt_driver) = {
18115bc9f8e5SEtienne Carriere .name = "stm32_i2c",
18125bc9f8e5SEtienne Carriere .match_table = stm32_i2c_match_table,
18135bc9f8e5SEtienne Carriere .probe = stm32_i2c_probe,
18145bc9f8e5SEtienne Carriere .type = DT_DRIVER_I2C
18155bc9f8e5SEtienne Carriere };
1816