xref: /openbmc/linux/drivers/i2c/busses/i2c-stm32f7.c (revision 419be8e1)
19c41e452SBenjamin Gaignard // SPDX-License-Identifier: GPL-2.0
2aeb068c5SPierre-Yves MORDRET /*
3aeb068c5SPierre-Yves MORDRET  * Driver for STMicroelectronics STM32F7 I2C controller
4aeb068c5SPierre-Yves MORDRET  *
5aeb068c5SPierre-Yves MORDRET  * This I2C controller is described in the STM32F75xxx and STM32F74xxx Soc
6aeb068c5SPierre-Yves MORDRET  * reference manual.
7aeb068c5SPierre-Yves MORDRET  * Please see below a link to the documentation:
8aeb068c5SPierre-Yves MORDRET  * http://www.st.com/resource/en/reference_manual/dm00124865.pdf
9aeb068c5SPierre-Yves MORDRET  *
10aeb068c5SPierre-Yves MORDRET  * Copyright (C) M'boumba Cedric Madianga 2017
119c41e452SBenjamin Gaignard  * Copyright (C) STMicroelectronics 2017
12aeb068c5SPierre-Yves MORDRET  * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
13aeb068c5SPierre-Yves MORDRET  *
14aeb068c5SPierre-Yves MORDRET  * This driver is based on i2c-stm32f4.c
15aeb068c5SPierre-Yves MORDRET  *
16aeb068c5SPierre-Yves MORDRET  */
17aeb068c5SPierre-Yves MORDRET #include <linux/clk.h>
18aeb068c5SPierre-Yves MORDRET #include <linux/delay.h>
19aeb068c5SPierre-Yves MORDRET #include <linux/err.h>
20aeb068c5SPierre-Yves MORDRET #include <linux/i2c.h>
21aeb068c5SPierre-Yves MORDRET #include <linux/interrupt.h>
22aeb068c5SPierre-Yves MORDRET #include <linux/io.h>
23aeb068c5SPierre-Yves MORDRET #include <linux/iopoll.h>
24cb944fb9SPierre-Yves MORDRET #include <linux/mfd/syscon.h>
25aeb068c5SPierre-Yves MORDRET #include <linux/module.h>
26aeb068c5SPierre-Yves MORDRET #include <linux/of.h>
27aeb068c5SPierre-Yves MORDRET #include <linux/of_address.h>
28aeb068c5SPierre-Yves MORDRET #include <linux/of_platform.h>
29aeb068c5SPierre-Yves MORDRET #include <linux/platform_device.h>
304e7bca6fSPierre-Yves MORDRET #include <linux/pinctrl/consumer.h>
314e7bca6fSPierre-Yves MORDRET #include <linux/pm_runtime.h>
32*419be8e1SAlain Volmat #include <linux/pm_wakeirq.h>
33cb944fb9SPierre-Yves MORDRET #include <linux/regmap.h>
34aeb068c5SPierre-Yves MORDRET #include <linux/reset.h>
35aeb068c5SPierre-Yves MORDRET #include <linux/slab.h>
36aeb068c5SPierre-Yves MORDRET 
37aeb068c5SPierre-Yves MORDRET #include "i2c-stm32.h"
38aeb068c5SPierre-Yves MORDRET 
39aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C registers */
40aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1				0x00
41aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2				0x04
4260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1			0x08
4360d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2			0x0C
449e48155fSPierre-Yves MORDRET #define STM32F7_I2C_PECR			0x20
45aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR			0x10
46aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR				0x18
47aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR				0x1C
48aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_RXDR			0x24
49aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TXDR			0x28
50aeb068c5SPierre-Yves MORDRET 
51aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C control 1 */
529e48155fSPierre-Yves MORDRET #define STM32F7_I2C_CR1_PECEN			BIT(23)
53*419be8e1SAlain Volmat #define STM32F7_I2C_CR1_WUPEN			BIT(18)
5460d609f3SPierre-Yves MORDRET #define STM32F7_I2C_CR1_SBC			BIT(16)
557ecc8cfdSPierre-Yves MORDRET #define STM32F7_I2C_CR1_RXDMAEN			BIT(15)
567ecc8cfdSPierre-Yves MORDRET #define STM32F7_I2C_CR1_TXDMAEN			BIT(14)
57aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_ANFOFF			BIT(12)
58aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_ERRIE			BIT(7)
59aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_TCIE			BIT(6)
60aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_STOPIE			BIT(5)
61aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_NACKIE			BIT(4)
62aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_ADDRIE			BIT(3)
63aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_RXIE			BIT(2)
64aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_TXIE			BIT(1)
65aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_PE			BIT(0)
66aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ALL_IRQ_MASK		(STM32F7_I2C_CR1_ERRIE \
67aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_TCIE \
68aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_STOPIE \
69aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_NACKIE \
70aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_RXIE \
71aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_TXIE)
7260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_XFER_IRQ_MASK		(STM32F7_I2C_CR1_TCIE \
7360d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_STOPIE \
7460d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_NACKIE \
7560d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_RXIE \
7660d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_TXIE)
77aeb068c5SPierre-Yves MORDRET 
78aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C control 2 */
799e48155fSPierre-Yves MORDRET #define STM32F7_I2C_CR2_PECBYTE			BIT(26)
80aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_RELOAD			BIT(24)
81aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_NBYTES_MASK		GENMASK(23, 16)
82aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_NBYTES(n)		(((n) & 0xff) << 16)
83aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_NACK			BIT(15)
84aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_STOP			BIT(14)
85aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_START			BIT(13)
868c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_HEAD10R			BIT(12)
878c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_ADD10			BIT(11)
88aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_RD_WRN			BIT(10)
898c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD10_MASK		GENMASK(9, 0)
908c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD10(n)		(((n) & \
918c7ecc99SPierre-Yves MORDRET 						STM32F7_I2C_CR2_SADD10_MASK))
92aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD7_MASK		GENMASK(7, 1)
93aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD7(n)		(((n) & 0x7f) << 1)
94aeb068c5SPierre-Yves MORDRET 
9560d609f3SPierre-Yves MORDRET /* STM32F7 I2C Own Address 1 */
9660d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1EN			BIT(15)
9760d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1MODE		BIT(10)
9860d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_10_MASK		GENMASK(9, 0)
9960d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_10(n)		(((n) & \
10060d609f3SPierre-Yves MORDRET 						STM32F7_I2C_OAR1_OA1_10_MASK))
10160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_7_MASK		GENMASK(7, 1)
10260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_7(n)		(((n) & 0x7f) << 1)
10360d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_MASK			(STM32F7_I2C_OAR1_OA1_7_MASK \
10460d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR1_OA1_10_MASK \
10560d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR1_OA1EN \
10660d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR1_OA1MODE)
10760d609f3SPierre-Yves MORDRET 
10860d609f3SPierre-Yves MORDRET /* STM32F7 I2C Own Address 2 */
10960d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2EN			BIT(15)
11060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2MSK_MASK		GENMASK(10, 8)
11160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2MSK(n)		(((n) & 0x7) << 8)
11260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2_7_MASK		GENMASK(7, 1)
11360d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2_7(n)		(((n) & 0x7f) << 1)
11460d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_MASK			(STM32F7_I2C_OAR2_OA2MSK_MASK \
11560d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR2_OA2_7_MASK \
11660d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR2_OA2EN)
11760d609f3SPierre-Yves MORDRET 
118aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C Interrupt Status */
11960d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ADDCODE_MASK		GENMASK(23, 17)
12060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ADDCODE_GET(n) \
12160d609f3SPierre-Yves MORDRET 				(((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17)
12260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_DIR			BIT(16)
123aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_BUSY			BIT(15)
1249e48155fSPierre-Yves MORDRET #define STM32F7_I2C_ISR_PECERR			BIT(11)
125aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ARLO			BIT(9)
126aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_BERR			BIT(8)
127aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TCR			BIT(7)
128aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TC			BIT(6)
129aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_STOPF			BIT(5)
130aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_NACKF			BIT(4)
13160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ADDR			BIT(3)
132aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_RXNE			BIT(2)
133aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TXIS			BIT(1)
13460d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TXE			BIT(0)
135aeb068c5SPierre-Yves MORDRET 
136aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C Interrupt Clear */
1379e48155fSPierre-Yves MORDRET #define STM32F7_I2C_ICR_PECCF			BIT(11)
138aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_ARLOCF			BIT(9)
139aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_BERRCF			BIT(8)
140aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_STOPCF			BIT(5)
141aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_NACKCF			BIT(4)
14260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ICR_ADDRCF			BIT(3)
143aeb068c5SPierre-Yves MORDRET 
144aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C Timing */
145aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_PRESC(n)		(((n) & 0xf) << 28)
146aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SCLDEL(n)		(((n) & 0xf) << 20)
147aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SDADEL(n)		(((n) & 0xf) << 16)
148aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SCLH(n)		(((n) & 0xff) << 8)
149aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SCLL(n)		((n) & 0xff)
150aeb068c5SPierre-Yves MORDRET 
151aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_MAX_LEN			0xff
1527ecc8cfdSPierre-Yves MORDRET #define STM32F7_I2C_DMA_LEN_MIN			0x16
15360d609f3SPierre-Yves MORDRET #define STM32F7_I2C_MAX_SLAVE			0x2
154aeb068c5SPierre-Yves MORDRET 
155aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_DNF_DEFAULT			0
156aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_DNF_MAX			16
157aeb068c5SPierre-Yves MORDRET 
158aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ANALOG_FILTER_ENABLE	1
159aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ANALOG_FILTER_DELAY_MIN	50	/* ns */
160aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ANALOG_FILTER_DELAY_MAX	260	/* ns */
161aeb068c5SPierre-Yves MORDRET 
162aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_RISE_TIME_DEFAULT		25	/* ns */
163aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_FALL_TIME_DEFAULT		10	/* ns */
164aeb068c5SPierre-Yves MORDRET 
165aeb068c5SPierre-Yves MORDRET #define STM32F7_PRESC_MAX			BIT(4)
166aeb068c5SPierre-Yves MORDRET #define STM32F7_SCLDEL_MAX			BIT(4)
167aeb068c5SPierre-Yves MORDRET #define STM32F7_SDADEL_MAX			BIT(4)
168aeb068c5SPierre-Yves MORDRET #define STM32F7_SCLH_MAX			BIT(8)
169aeb068c5SPierre-Yves MORDRET #define STM32F7_SCLL_MAX			BIT(8)
170aeb068c5SPierre-Yves MORDRET 
1714e7bca6fSPierre-Yves MORDRET #define STM32F7_AUTOSUSPEND_DELAY		(HZ / 100)
1724e7bca6fSPierre-Yves MORDRET 
173aeb068c5SPierre-Yves MORDRET /**
174ea6dd25dSAlain Volmat  * struct stm32f7_i2c_regs - i2c f7 registers backup
175ea6dd25dSAlain Volmat  * @cr1: Control register 1
176ea6dd25dSAlain Volmat  * @cr2: Control register 2
177ea6dd25dSAlain Volmat  * @oar1: Own address 1 register
178ea6dd25dSAlain Volmat  * @oar2: Own address 2 register
179ea6dd25dSAlain Volmat  * @pecr: PEC register
180ea6dd25dSAlain Volmat  * @tmgr: Timing register
181ea6dd25dSAlain Volmat  */
182ea6dd25dSAlain Volmat struct stm32f7_i2c_regs {
183ea6dd25dSAlain Volmat 	u32 cr1;
184ea6dd25dSAlain Volmat 	u32 cr2;
185ea6dd25dSAlain Volmat 	u32 oar1;
186ea6dd25dSAlain Volmat 	u32 oar2;
187ea6dd25dSAlain Volmat 	u32 pecr;
188ea6dd25dSAlain Volmat 	u32 tmgr;
189ea6dd25dSAlain Volmat };
190ea6dd25dSAlain Volmat 
191ea6dd25dSAlain Volmat /**
192aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_spec - private i2c specification timing
193aeb068c5SPierre-Yves MORDRET  * @rate: I2C bus speed (Hz)
194aeb068c5SPierre-Yves MORDRET  * @rate_min: 80% of I2C bus speed (Hz)
195aeb068c5SPierre-Yves MORDRET  * @rate_max: 100% of I2C bus speed (Hz)
196aeb068c5SPierre-Yves MORDRET  * @fall_max: Max fall time of both SDA and SCL signals (ns)
197aeb068c5SPierre-Yves MORDRET  * @rise_max: Max rise time of both SDA and SCL signals (ns)
198aeb068c5SPierre-Yves MORDRET  * @hddat_min: Min data hold time (ns)
199aeb068c5SPierre-Yves MORDRET  * @vddat_max: Max data valid time (ns)
200aeb068c5SPierre-Yves MORDRET  * @sudat_min: Min data setup time (ns)
201aeb068c5SPierre-Yves MORDRET  * @l_min: Min low period of the SCL clock (ns)
202aeb068c5SPierre-Yves MORDRET  * @h_min: Min high period of the SCL clock (ns)
203aeb068c5SPierre-Yves MORDRET  */
204aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_spec {
205aeb068c5SPierre-Yves MORDRET 	u32 rate;
206aeb068c5SPierre-Yves MORDRET 	u32 rate_min;
207aeb068c5SPierre-Yves MORDRET 	u32 rate_max;
208aeb068c5SPierre-Yves MORDRET 	u32 fall_max;
209aeb068c5SPierre-Yves MORDRET 	u32 rise_max;
210aeb068c5SPierre-Yves MORDRET 	u32 hddat_min;
211aeb068c5SPierre-Yves MORDRET 	u32 vddat_max;
212aeb068c5SPierre-Yves MORDRET 	u32 sudat_min;
213aeb068c5SPierre-Yves MORDRET 	u32 l_min;
214aeb068c5SPierre-Yves MORDRET 	u32 h_min;
215aeb068c5SPierre-Yves MORDRET };
216aeb068c5SPierre-Yves MORDRET 
217aeb068c5SPierre-Yves MORDRET /**
218aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_setup - private I2C timing setup parameters
219aeb068c5SPierre-Yves MORDRET  * @speed: I2C speed mode (standard, Fast Plus)
220aeb068c5SPierre-Yves MORDRET  * @speed_freq: I2C speed frequency  (Hz)
221aeb068c5SPierre-Yves MORDRET  * @clock_src: I2C clock source frequency (Hz)
222aeb068c5SPierre-Yves MORDRET  * @rise_time: Rise time (ns)
223aeb068c5SPierre-Yves MORDRET  * @fall_time: Fall time (ns)
224aeb068c5SPierre-Yves MORDRET  * @dnf: Digital filter coefficient (0-16)
225aeb068c5SPierre-Yves MORDRET  * @analog_filter: Analog filter delay (On/Off)
226aeb068c5SPierre-Yves MORDRET  */
227aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_setup {
228aeb068c5SPierre-Yves MORDRET 	enum stm32_i2c_speed speed;
229aeb068c5SPierre-Yves MORDRET 	u32 speed_freq;
230aeb068c5SPierre-Yves MORDRET 	u32 clock_src;
231aeb068c5SPierre-Yves MORDRET 	u32 rise_time;
232aeb068c5SPierre-Yves MORDRET 	u32 fall_time;
233aeb068c5SPierre-Yves MORDRET 	u8 dnf;
234aeb068c5SPierre-Yves MORDRET 	bool analog_filter;
235aeb068c5SPierre-Yves MORDRET };
236aeb068c5SPierre-Yves MORDRET 
237aeb068c5SPierre-Yves MORDRET /**
238aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_timings - private I2C output parameters
239c599eb4fSPierre-Yves MORDRET  * @node: List entry
240c599eb4fSPierre-Yves MORDRET  * @presc: Prescaler value
241aeb068c5SPierre-Yves MORDRET  * @scldel: Data setup time
242aeb068c5SPierre-Yves MORDRET  * @sdadel: Data hold time
243aeb068c5SPierre-Yves MORDRET  * @sclh: SCL high period (master mode)
244c599eb4fSPierre-Yves MORDRET  * @scll: SCL low period (master mode)
245aeb068c5SPierre-Yves MORDRET  */
246aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_timings {
247aeb068c5SPierre-Yves MORDRET 	struct list_head node;
248aeb068c5SPierre-Yves MORDRET 	u8 presc;
249aeb068c5SPierre-Yves MORDRET 	u8 scldel;
250aeb068c5SPierre-Yves MORDRET 	u8 sdadel;
251aeb068c5SPierre-Yves MORDRET 	u8 sclh;
252aeb068c5SPierre-Yves MORDRET 	u8 scll;
253aeb068c5SPierre-Yves MORDRET };
254aeb068c5SPierre-Yves MORDRET 
255aeb068c5SPierre-Yves MORDRET /**
256aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_msg - client specific data
2578c7ecc99SPierre-Yves MORDRET  * @addr: 8-bit or 10-bit slave addr, including r/w bit
258aeb068c5SPierre-Yves MORDRET  * @count: number of bytes to be transferred
259aeb068c5SPierre-Yves MORDRET  * @buf: data buffer
260aeb068c5SPierre-Yves MORDRET  * @result: result of the transfer
261aeb068c5SPierre-Yves MORDRET  * @stop: last I2C msg to be sent, i.e. STOP to be generated
2629e48155fSPierre-Yves MORDRET  * @smbus: boolean to know if the I2C IP is used in SMBus mode
2639e48155fSPierre-Yves MORDRET  * @size: type of SMBus protocol
2649e48155fSPierre-Yves MORDRET  * @read_write: direction of SMBus protocol
2659e48155fSPierre-Yves MORDRET  * SMBus block read and SMBus block write - block read process call protocols
266c599eb4fSPierre-Yves MORDRET  * @smbus_buf: buffer to be used for SMBus protocol transfer. It will
2679e48155fSPierre-Yves MORDRET  * contain a maximum of 32 bytes of data + byte command + byte count + PEC
2689e48155fSPierre-Yves MORDRET  * This buffer has to be 32-bit aligned to be compliant with memory address
2699e48155fSPierre-Yves MORDRET  * register in DMA mode.
270aeb068c5SPierre-Yves MORDRET  */
271aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_msg {
2728c7ecc99SPierre-Yves MORDRET 	u16 addr;
273aeb068c5SPierre-Yves MORDRET 	u32 count;
274aeb068c5SPierre-Yves MORDRET 	u8 *buf;
275aeb068c5SPierre-Yves MORDRET 	int result;
276aeb068c5SPierre-Yves MORDRET 	bool stop;
2779e48155fSPierre-Yves MORDRET 	bool smbus;
2789e48155fSPierre-Yves MORDRET 	int size;
2799e48155fSPierre-Yves MORDRET 	char read_write;
2809e48155fSPierre-Yves MORDRET 	u8 smbus_buf[I2C_SMBUS_BLOCK_MAX + 3] __aligned(4);
281aeb068c5SPierre-Yves MORDRET };
282aeb068c5SPierre-Yves MORDRET 
283aeb068c5SPierre-Yves MORDRET /**
284aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_dev - private data of the controller
285aeb068c5SPierre-Yves MORDRET  * @adap: I2C adapter for this controller
286aeb068c5SPierre-Yves MORDRET  * @dev: device for this controller
287aeb068c5SPierre-Yves MORDRET  * @base: virtual memory area
288aeb068c5SPierre-Yves MORDRET  * @complete: completion of I2C message
289aeb068c5SPierre-Yves MORDRET  * @clk: hw i2c clock
290aeb068c5SPierre-Yves MORDRET  * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+
291aeb068c5SPierre-Yves MORDRET  * @msg: Pointer to data to be written
292aeb068c5SPierre-Yves MORDRET  * @msg_num: number of I2C messages to be executed
293aeb068c5SPierre-Yves MORDRET  * @msg_id: message identifiant
294aeb068c5SPierre-Yves MORDRET  * @f7_msg: customized i2c msg for driver usage
295aeb068c5SPierre-Yves MORDRET  * @setup: I2C timing input setup
296aeb068c5SPierre-Yves MORDRET  * @timing: I2C computed timings
29760d609f3SPierre-Yves MORDRET  * @slave: list of slave devices registered on the I2C bus
29860d609f3SPierre-Yves MORDRET  * @slave_running: slave device currently used
299ea6dd25dSAlain Volmat  * @backup_regs: backup of i2c controller registers (for suspend/resume)
30060d609f3SPierre-Yves MORDRET  * @slave_dir: transfer direction for the current slave device
30160d609f3SPierre-Yves MORDRET  * @master_mode: boolean to know in which mode the I2C is running (master or
30260d609f3SPierre-Yves MORDRET  * slave)
3037ecc8cfdSPierre-Yves MORDRET  * @dma: dma data
3047ecc8cfdSPierre-Yves MORDRET  * @use_dma: boolean to know if dma is used in the current transfer
305cb944fb9SPierre-Yves MORDRET  * @regmap: holds SYSCFG phandle for Fast Mode Plus bits
306*419be8e1SAlain Volmat  * @wakeup_src: boolean to know if the device is a wakeup source
307aeb068c5SPierre-Yves MORDRET  */
308aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_dev {
309aeb068c5SPierre-Yves MORDRET 	struct i2c_adapter adap;
310aeb068c5SPierre-Yves MORDRET 	struct device *dev;
311aeb068c5SPierre-Yves MORDRET 	void __iomem *base;
312aeb068c5SPierre-Yves MORDRET 	struct completion complete;
313aeb068c5SPierre-Yves MORDRET 	struct clk *clk;
314aeb068c5SPierre-Yves MORDRET 	int speed;
315aeb068c5SPierre-Yves MORDRET 	struct i2c_msg *msg;
316aeb068c5SPierre-Yves MORDRET 	unsigned int msg_num;
317aeb068c5SPierre-Yves MORDRET 	unsigned int msg_id;
318aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg f7_msg;
319463a9215SPierre-Yves MORDRET 	struct stm32f7_i2c_setup setup;
320aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_timings timing;
32160d609f3SPierre-Yves MORDRET 	struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE];
32260d609f3SPierre-Yves MORDRET 	struct i2c_client *slave_running;
323ea6dd25dSAlain Volmat 	struct stm32f7_i2c_regs backup_regs;
32460d609f3SPierre-Yves MORDRET 	u32 slave_dir;
32560d609f3SPierre-Yves MORDRET 	bool master_mode;
3267ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma;
3277ecc8cfdSPierre-Yves MORDRET 	bool use_dma;
328cb944fb9SPierre-Yves MORDRET 	struct regmap *regmap;
329*419be8e1SAlain Volmat 	bool wakeup_src;
330aeb068c5SPierre-Yves MORDRET };
331aeb068c5SPierre-Yves MORDRET 
332348e46fbSAlain Volmat /*
333aeb068c5SPierre-Yves MORDRET  * All these values are coming from I2C Specification, Version 6.0, 4th of
334aeb068c5SPierre-Yves MORDRET  * April 2014.
335aeb068c5SPierre-Yves MORDRET  *
336aeb068c5SPierre-Yves MORDRET  * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast,
337aeb068c5SPierre-Yves MORDRET  * and Fast-mode Plus I2C-bus devices
338aeb068c5SPierre-Yves MORDRET  */
339aeb068c5SPierre-Yves MORDRET static struct stm32f7_i2c_spec i2c_specs[] = {
340aeb068c5SPierre-Yves MORDRET 	[STM32_I2C_SPEED_STANDARD] = {
341aeb068c5SPierre-Yves MORDRET 		.rate = 100000,
342aeb068c5SPierre-Yves MORDRET 		.rate_min = 80000,
343aeb068c5SPierre-Yves MORDRET 		.rate_max = 100000,
344aeb068c5SPierre-Yves MORDRET 		.fall_max = 300,
345aeb068c5SPierre-Yves MORDRET 		.rise_max = 1000,
346aeb068c5SPierre-Yves MORDRET 		.hddat_min = 0,
347aeb068c5SPierre-Yves MORDRET 		.vddat_max = 3450,
348aeb068c5SPierre-Yves MORDRET 		.sudat_min = 250,
349aeb068c5SPierre-Yves MORDRET 		.l_min = 4700,
350aeb068c5SPierre-Yves MORDRET 		.h_min = 4000,
351aeb068c5SPierre-Yves MORDRET 	},
352aeb068c5SPierre-Yves MORDRET 	[STM32_I2C_SPEED_FAST] = {
353aeb068c5SPierre-Yves MORDRET 		.rate = 400000,
354aeb068c5SPierre-Yves MORDRET 		.rate_min = 320000,
355aeb068c5SPierre-Yves MORDRET 		.rate_max = 400000,
356aeb068c5SPierre-Yves MORDRET 		.fall_max = 300,
357aeb068c5SPierre-Yves MORDRET 		.rise_max = 300,
358aeb068c5SPierre-Yves MORDRET 		.hddat_min = 0,
359aeb068c5SPierre-Yves MORDRET 		.vddat_max = 900,
360aeb068c5SPierre-Yves MORDRET 		.sudat_min = 100,
361aeb068c5SPierre-Yves MORDRET 		.l_min = 1300,
362aeb068c5SPierre-Yves MORDRET 		.h_min = 600,
363aeb068c5SPierre-Yves MORDRET 	},
364aeb068c5SPierre-Yves MORDRET 	[STM32_I2C_SPEED_FAST_PLUS] = {
365aeb068c5SPierre-Yves MORDRET 		.rate = 1000000,
366aeb068c5SPierre-Yves MORDRET 		.rate_min = 800000,
367aeb068c5SPierre-Yves MORDRET 		.rate_max = 1000000,
368aeb068c5SPierre-Yves MORDRET 		.fall_max = 100,
369aeb068c5SPierre-Yves MORDRET 		.rise_max = 120,
370aeb068c5SPierre-Yves MORDRET 		.hddat_min = 0,
371aeb068c5SPierre-Yves MORDRET 		.vddat_max = 450,
372aeb068c5SPierre-Yves MORDRET 		.sudat_min = 50,
373aeb068c5SPierre-Yves MORDRET 		.l_min = 500,
374aeb068c5SPierre-Yves MORDRET 		.h_min = 260,
375aeb068c5SPierre-Yves MORDRET 	},
376aeb068c5SPierre-Yves MORDRET };
377aeb068c5SPierre-Yves MORDRET 
37825f2f440SColin Ian King static const struct stm32f7_i2c_setup stm32f7_setup = {
379aeb068c5SPierre-Yves MORDRET 	.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
380aeb068c5SPierre-Yves MORDRET 	.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
381aeb068c5SPierre-Yves MORDRET 	.dnf = STM32F7_I2C_DNF_DEFAULT,
382aeb068c5SPierre-Yves MORDRET 	.analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE,
383aeb068c5SPierre-Yves MORDRET };
384aeb068c5SPierre-Yves MORDRET 
385aeb068c5SPierre-Yves MORDRET static inline void stm32f7_i2c_set_bits(void __iomem *reg, u32 mask)
386aeb068c5SPierre-Yves MORDRET {
387aeb068c5SPierre-Yves MORDRET 	writel_relaxed(readl_relaxed(reg) | mask, reg);
388aeb068c5SPierre-Yves MORDRET }
389aeb068c5SPierre-Yves MORDRET 
390aeb068c5SPierre-Yves MORDRET static inline void stm32f7_i2c_clr_bits(void __iomem *reg, u32 mask)
391aeb068c5SPierre-Yves MORDRET {
392aeb068c5SPierre-Yves MORDRET 	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
393aeb068c5SPierre-Yves MORDRET }
394aeb068c5SPierre-Yves MORDRET 
39560d609f3SPierre-Yves MORDRET static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask)
39660d609f3SPierre-Yves MORDRET {
39760d609f3SPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask);
39860d609f3SPierre-Yves MORDRET }
39960d609f3SPierre-Yves MORDRET 
400aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
401aeb068c5SPierre-Yves MORDRET 				      struct stm32f7_i2c_setup *setup,
402aeb068c5SPierre-Yves MORDRET 				      struct stm32f7_i2c_timings *output)
403aeb068c5SPierre-Yves MORDRET {
404aeb068c5SPierre-Yves MORDRET 	u32 p_prev = STM32F7_PRESC_MAX;
405aeb068c5SPierre-Yves MORDRET 	u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC,
406aeb068c5SPierre-Yves MORDRET 				       setup->clock_src);
407aeb068c5SPierre-Yves MORDRET 	u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC,
408aeb068c5SPierre-Yves MORDRET 				       setup->speed_freq);
409aeb068c5SPierre-Yves MORDRET 	u32 clk_error_prev = i2cbus;
410aeb068c5SPierre-Yves MORDRET 	u32 tsync;
411aeb068c5SPierre-Yves MORDRET 	u32 af_delay_min, af_delay_max;
412aeb068c5SPierre-Yves MORDRET 	u32 dnf_delay;
413aeb068c5SPierre-Yves MORDRET 	u32 clk_min, clk_max;
414aeb068c5SPierre-Yves MORDRET 	int sdadel_min, sdadel_max;
415aeb068c5SPierre-Yves MORDRET 	int scldel_min;
416aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_timings *v, *_v, *s;
417aeb068c5SPierre-Yves MORDRET 	struct list_head solutions;
418aeb068c5SPierre-Yves MORDRET 	u16 p, l, a, h;
419aeb068c5SPierre-Yves MORDRET 	int ret = 0;
420aeb068c5SPierre-Yves MORDRET 
421aeb068c5SPierre-Yves MORDRET 	if (setup->speed >= STM32_I2C_SPEED_END) {
422aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "speed out of bound {%d/%d}\n",
423aeb068c5SPierre-Yves MORDRET 			setup->speed, STM32_I2C_SPEED_END - 1);
424aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
425aeb068c5SPierre-Yves MORDRET 	}
426aeb068c5SPierre-Yves MORDRET 
427aeb068c5SPierre-Yves MORDRET 	if ((setup->rise_time > i2c_specs[setup->speed].rise_max) ||
428aeb068c5SPierre-Yves MORDRET 	    (setup->fall_time > i2c_specs[setup->speed].fall_max)) {
429aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev,
430aeb068c5SPierre-Yves MORDRET 			"timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
431aeb068c5SPierre-Yves MORDRET 			setup->rise_time, i2c_specs[setup->speed].rise_max,
432aeb068c5SPierre-Yves MORDRET 			setup->fall_time, i2c_specs[setup->speed].fall_max);
433aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
434aeb068c5SPierre-Yves MORDRET 	}
435aeb068c5SPierre-Yves MORDRET 
436aeb068c5SPierre-Yves MORDRET 	if (setup->dnf > STM32F7_I2C_DNF_MAX) {
437aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev,
438aeb068c5SPierre-Yves MORDRET 			"DNF out of bound %d/%d\n",
439aeb068c5SPierre-Yves MORDRET 			setup->dnf, STM32F7_I2C_DNF_MAX);
440aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
441aeb068c5SPierre-Yves MORDRET 	}
442aeb068c5SPierre-Yves MORDRET 
443aeb068c5SPierre-Yves MORDRET 	if (setup->speed_freq > i2c_specs[setup->speed].rate) {
444aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "ERROR: Freq {%d/%d}\n",
445aeb068c5SPierre-Yves MORDRET 			setup->speed_freq, i2c_specs[setup->speed].rate);
446aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
447aeb068c5SPierre-Yves MORDRET 	}
448aeb068c5SPierre-Yves MORDRET 
449aeb068c5SPierre-Yves MORDRET 	/*  Analog and Digital Filters */
450aeb068c5SPierre-Yves MORDRET 	af_delay_min =
451aeb068c5SPierre-Yves MORDRET 		(setup->analog_filter ?
452aeb068c5SPierre-Yves MORDRET 		 STM32F7_I2C_ANALOG_FILTER_DELAY_MIN : 0);
453aeb068c5SPierre-Yves MORDRET 	af_delay_max =
454aeb068c5SPierre-Yves MORDRET 		(setup->analog_filter ?
455aeb068c5SPierre-Yves MORDRET 		 STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);
456aeb068c5SPierre-Yves MORDRET 	dnf_delay = setup->dnf * i2cclk;
457aeb068c5SPierre-Yves MORDRET 
458c86da50cSNicolas Le Bayon 	sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -
459aeb068c5SPierre-Yves MORDRET 		af_delay_min - (setup->dnf + 3) * i2cclk;
460aeb068c5SPierre-Yves MORDRET 
461aeb068c5SPierre-Yves MORDRET 	sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -
462aeb068c5SPierre-Yves MORDRET 		af_delay_max - (setup->dnf + 4) * i2cclk;
463aeb068c5SPierre-Yves MORDRET 
464aeb068c5SPierre-Yves MORDRET 	scldel_min = setup->rise_time + i2c_specs[setup->speed].sudat_min;
465aeb068c5SPierre-Yves MORDRET 
466aeb068c5SPierre-Yves MORDRET 	if (sdadel_min < 0)
467aeb068c5SPierre-Yves MORDRET 		sdadel_min = 0;
468aeb068c5SPierre-Yves MORDRET 	if (sdadel_max < 0)
469aeb068c5SPierre-Yves MORDRET 		sdadel_max = 0;
470aeb068c5SPierre-Yves MORDRET 
471aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "SDADEL(min/max): %i/%i, SCLDEL(Min): %i\n",
472aeb068c5SPierre-Yves MORDRET 		sdadel_min, sdadel_max, scldel_min);
473aeb068c5SPierre-Yves MORDRET 
474aeb068c5SPierre-Yves MORDRET 	INIT_LIST_HEAD(&solutions);
475aeb068c5SPierre-Yves MORDRET 	/* Compute possible values for PRESC, SCLDEL and SDADEL */
476aeb068c5SPierre-Yves MORDRET 	for (p = 0; p < STM32F7_PRESC_MAX; p++) {
477aeb068c5SPierre-Yves MORDRET 		for (l = 0; l < STM32F7_SCLDEL_MAX; l++) {
478aeb068c5SPierre-Yves MORDRET 			u32 scldel = (l + 1) * (p + 1) * i2cclk;
479aeb068c5SPierre-Yves MORDRET 
480aeb068c5SPierre-Yves MORDRET 			if (scldel < scldel_min)
481aeb068c5SPierre-Yves MORDRET 				continue;
482aeb068c5SPierre-Yves MORDRET 
483aeb068c5SPierre-Yves MORDRET 			for (a = 0; a < STM32F7_SDADEL_MAX; a++) {
484aeb068c5SPierre-Yves MORDRET 				u32 sdadel = (a * (p + 1) + 1) * i2cclk;
485aeb068c5SPierre-Yves MORDRET 
486aeb068c5SPierre-Yves MORDRET 				if (((sdadel >= sdadel_min) &&
487aeb068c5SPierre-Yves MORDRET 				     (sdadel <= sdadel_max)) &&
488aeb068c5SPierre-Yves MORDRET 				    (p != p_prev)) {
489aeb068c5SPierre-Yves MORDRET 					v = kmalloc(sizeof(*v), GFP_KERNEL);
490aeb068c5SPierre-Yves MORDRET 					if (!v) {
491aeb068c5SPierre-Yves MORDRET 						ret = -ENOMEM;
492aeb068c5SPierre-Yves MORDRET 						goto exit;
493aeb068c5SPierre-Yves MORDRET 					}
494aeb068c5SPierre-Yves MORDRET 
495aeb068c5SPierre-Yves MORDRET 					v->presc = p;
496aeb068c5SPierre-Yves MORDRET 					v->scldel = l;
497aeb068c5SPierre-Yves MORDRET 					v->sdadel = a;
498aeb068c5SPierre-Yves MORDRET 					p_prev = p;
499aeb068c5SPierre-Yves MORDRET 
500aeb068c5SPierre-Yves MORDRET 					list_add_tail(&v->node,
501aeb068c5SPierre-Yves MORDRET 						      &solutions);
5020d735031SNicolas Le Bayon 					break;
503aeb068c5SPierre-Yves MORDRET 				}
504aeb068c5SPierre-Yves MORDRET 			}
5050d735031SNicolas Le Bayon 
5060d735031SNicolas Le Bayon 			if (p_prev == p)
5070d735031SNicolas Le Bayon 				break;
508aeb068c5SPierre-Yves MORDRET 		}
509aeb068c5SPierre-Yves MORDRET 	}
510aeb068c5SPierre-Yves MORDRET 
511aeb068c5SPierre-Yves MORDRET 	if (list_empty(&solutions)) {
512aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "no Prescaler solution\n");
513aeb068c5SPierre-Yves MORDRET 		ret = -EPERM;
514aeb068c5SPierre-Yves MORDRET 		goto exit;
515aeb068c5SPierre-Yves MORDRET 	}
516aeb068c5SPierre-Yves MORDRET 
517aeb068c5SPierre-Yves MORDRET 	tsync = af_delay_min + dnf_delay + (2 * i2cclk);
518aeb068c5SPierre-Yves MORDRET 	s = NULL;
519aeb068c5SPierre-Yves MORDRET 	clk_max = NSEC_PER_SEC / i2c_specs[setup->speed].rate_min;
520aeb068c5SPierre-Yves MORDRET 	clk_min = NSEC_PER_SEC / i2c_specs[setup->speed].rate_max;
521aeb068c5SPierre-Yves MORDRET 
522aeb068c5SPierre-Yves MORDRET 	/*
523aeb068c5SPierre-Yves MORDRET 	 * Among Prescaler possibilities discovered above figures out SCL Low
524aeb068c5SPierre-Yves MORDRET 	 * and High Period. Provided:
525aeb068c5SPierre-Yves MORDRET 	 * - SCL Low Period has to be higher than SCL Clock Low Period
526aeb068c5SPierre-Yves MORDRET 	 *   defined by I2C Specification. I2C Clock has to be lower than
527aeb068c5SPierre-Yves MORDRET 	 *   (SCL Low Period - Analog/Digital filters) / 4.
528aeb068c5SPierre-Yves MORDRET 	 * - SCL High Period has to be lower than SCL Clock High Period
529aeb068c5SPierre-Yves MORDRET 	 *   defined by I2C Specification
530aeb068c5SPierre-Yves MORDRET 	 * - I2C Clock has to be lower than SCL High Period
531aeb068c5SPierre-Yves MORDRET 	 */
532aeb068c5SPierre-Yves MORDRET 	list_for_each_entry(v, &solutions, node) {
533aeb068c5SPierre-Yves MORDRET 		u32 prescaler = (v->presc + 1) * i2cclk;
534aeb068c5SPierre-Yves MORDRET 
535aeb068c5SPierre-Yves MORDRET 		for (l = 0; l < STM32F7_SCLL_MAX; l++) {
536aeb068c5SPierre-Yves MORDRET 			u32 tscl_l = (l + 1) * prescaler + tsync;
537aeb068c5SPierre-Yves MORDRET 
538aeb068c5SPierre-Yves MORDRET 			if ((tscl_l < i2c_specs[setup->speed].l_min) ||
539aeb068c5SPierre-Yves MORDRET 			    (i2cclk >=
540aeb068c5SPierre-Yves MORDRET 			     ((tscl_l - af_delay_min - dnf_delay) / 4))) {
541aeb068c5SPierre-Yves MORDRET 				continue;
542aeb068c5SPierre-Yves MORDRET 			}
543aeb068c5SPierre-Yves MORDRET 
544aeb068c5SPierre-Yves MORDRET 			for (h = 0; h < STM32F7_SCLH_MAX; h++) {
545aeb068c5SPierre-Yves MORDRET 				u32 tscl_h = (h + 1) * prescaler + tsync;
546aeb068c5SPierre-Yves MORDRET 				u32 tscl = tscl_l + tscl_h +
547aeb068c5SPierre-Yves MORDRET 					setup->rise_time + setup->fall_time;
548aeb068c5SPierre-Yves MORDRET 
549aeb068c5SPierre-Yves MORDRET 				if ((tscl >= clk_min) && (tscl <= clk_max) &&
550aeb068c5SPierre-Yves MORDRET 				    (tscl_h >= i2c_specs[setup->speed].h_min) &&
551aeb068c5SPierre-Yves MORDRET 				    (i2cclk < tscl_h)) {
552aeb068c5SPierre-Yves MORDRET 					int clk_error = tscl - i2cbus;
553aeb068c5SPierre-Yves MORDRET 
554aeb068c5SPierre-Yves MORDRET 					if (clk_error < 0)
555aeb068c5SPierre-Yves MORDRET 						clk_error = -clk_error;
556aeb068c5SPierre-Yves MORDRET 
557aeb068c5SPierre-Yves MORDRET 					if (clk_error < clk_error_prev) {
558aeb068c5SPierre-Yves MORDRET 						clk_error_prev = clk_error;
559aeb068c5SPierre-Yves MORDRET 						v->scll = l;
560aeb068c5SPierre-Yves MORDRET 						v->sclh = h;
561aeb068c5SPierre-Yves MORDRET 						s = v;
562aeb068c5SPierre-Yves MORDRET 					}
563aeb068c5SPierre-Yves MORDRET 				}
564aeb068c5SPierre-Yves MORDRET 			}
565aeb068c5SPierre-Yves MORDRET 		}
566aeb068c5SPierre-Yves MORDRET 	}
567aeb068c5SPierre-Yves MORDRET 
568aeb068c5SPierre-Yves MORDRET 	if (!s) {
569aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "no solution at all\n");
570aeb068c5SPierre-Yves MORDRET 		ret = -EPERM;
571aeb068c5SPierre-Yves MORDRET 		goto exit;
572aeb068c5SPierre-Yves MORDRET 	}
573aeb068c5SPierre-Yves MORDRET 
574aeb068c5SPierre-Yves MORDRET 	output->presc = s->presc;
575aeb068c5SPierre-Yves MORDRET 	output->scldel = s->scldel;
576aeb068c5SPierre-Yves MORDRET 	output->sdadel = s->sdadel;
577aeb068c5SPierre-Yves MORDRET 	output->scll = s->scll;
578aeb068c5SPierre-Yves MORDRET 	output->sclh = s->sclh;
579aeb068c5SPierre-Yves MORDRET 
580aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev,
581aeb068c5SPierre-Yves MORDRET 		"Presc: %i, scldel: %i, sdadel: %i, scll: %i, sclh: %i\n",
582aeb068c5SPierre-Yves MORDRET 		output->presc,
583aeb068c5SPierre-Yves MORDRET 		output->scldel, output->sdadel,
584aeb068c5SPierre-Yves MORDRET 		output->scll, output->sclh);
585aeb068c5SPierre-Yves MORDRET 
586aeb068c5SPierre-Yves MORDRET exit:
587aeb068c5SPierre-Yves MORDRET 	/* Release list and memory */
588aeb068c5SPierre-Yves MORDRET 	list_for_each_entry_safe(v, _v, &solutions, node) {
589aeb068c5SPierre-Yves MORDRET 		list_del(&v->node);
590aeb068c5SPierre-Yves MORDRET 		kfree(v);
591aeb068c5SPierre-Yves MORDRET 	}
592aeb068c5SPierre-Yves MORDRET 
593aeb068c5SPierre-Yves MORDRET 	return ret;
594aeb068c5SPierre-Yves MORDRET }
595aeb068c5SPierre-Yves MORDRET 
596aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
597aeb068c5SPierre-Yves MORDRET 				    struct stm32f7_i2c_setup *setup)
598aeb068c5SPierre-Yves MORDRET {
599aeb068c5SPierre-Yves MORDRET 	int ret = 0;
600aeb068c5SPierre-Yves MORDRET 
601aeb068c5SPierre-Yves MORDRET 	setup->speed = i2c_dev->speed;
602aeb068c5SPierre-Yves MORDRET 	setup->speed_freq = i2c_specs[setup->speed].rate;
603aeb068c5SPierre-Yves MORDRET 	setup->clock_src = clk_get_rate(i2c_dev->clk);
604aeb068c5SPierre-Yves MORDRET 
605aeb068c5SPierre-Yves MORDRET 	if (!setup->clock_src) {
606aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "clock rate is 0\n");
607aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
608aeb068c5SPierre-Yves MORDRET 	}
609aeb068c5SPierre-Yves MORDRET 
610aeb068c5SPierre-Yves MORDRET 	do {
611aeb068c5SPierre-Yves MORDRET 		ret = stm32f7_i2c_compute_timing(i2c_dev, setup,
612aeb068c5SPierre-Yves MORDRET 						 &i2c_dev->timing);
613aeb068c5SPierre-Yves MORDRET 		if (ret) {
614aeb068c5SPierre-Yves MORDRET 			dev_err(i2c_dev->dev,
615aeb068c5SPierre-Yves MORDRET 				"failed to compute I2C timings.\n");
616aeb068c5SPierre-Yves MORDRET 			if (i2c_dev->speed > STM32_I2C_SPEED_STANDARD) {
617aeb068c5SPierre-Yves MORDRET 				i2c_dev->speed--;
618aeb068c5SPierre-Yves MORDRET 				setup->speed = i2c_dev->speed;
619aeb068c5SPierre-Yves MORDRET 				setup->speed_freq =
620aeb068c5SPierre-Yves MORDRET 					i2c_specs[setup->speed].rate;
621aeb068c5SPierre-Yves MORDRET 				dev_warn(i2c_dev->dev,
622aeb068c5SPierre-Yves MORDRET 					 "downgrade I2C Speed Freq to (%i)\n",
623aeb068c5SPierre-Yves MORDRET 					 i2c_specs[setup->speed].rate);
624aeb068c5SPierre-Yves MORDRET 			} else {
625aeb068c5SPierre-Yves MORDRET 				break;
626aeb068c5SPierre-Yves MORDRET 			}
627aeb068c5SPierre-Yves MORDRET 		}
628aeb068c5SPierre-Yves MORDRET 	} while (ret);
629aeb068c5SPierre-Yves MORDRET 
630aeb068c5SPierre-Yves MORDRET 	if (ret) {
631aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Impossible to compute I2C timings.\n");
632aeb068c5SPierre-Yves MORDRET 		return ret;
633aeb068c5SPierre-Yves MORDRET 	}
634aeb068c5SPierre-Yves MORDRET 
635aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "I2C Speed(%i), Freq(%i), Clk Source(%i)\n",
636aeb068c5SPierre-Yves MORDRET 		setup->speed, setup->speed_freq, setup->clock_src);
637aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",
638aeb068c5SPierre-Yves MORDRET 		setup->rise_time, setup->fall_time);
639aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n",
640aeb068c5SPierre-Yves MORDRET 		(setup->analog_filter ? "On" : "Off"), setup->dnf);
641aeb068c5SPierre-Yves MORDRET 
642aeb068c5SPierre-Yves MORDRET 	return 0;
643aeb068c5SPierre-Yves MORDRET }
644aeb068c5SPierre-Yves MORDRET 
6457ecc8cfdSPierre-Yves MORDRET static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)
6467ecc8cfdSPierre-Yves MORDRET {
6477ecc8cfdSPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
6487ecc8cfdSPierre-Yves MORDRET 	u32 mask = STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN;
6497ecc8cfdSPierre-Yves MORDRET 
6507ecc8cfdSPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
6517ecc8cfdSPierre-Yves MORDRET }
6527ecc8cfdSPierre-Yves MORDRET 
6537ecc8cfdSPierre-Yves MORDRET static void stm32f7_i2c_dma_callback(void *arg)
6547ecc8cfdSPierre-Yves MORDRET {
6557ecc8cfdSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg;
6567ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
6577ecc8cfdSPierre-Yves MORDRET 	struct device *dev = dma->chan_using->device->dev;
6587ecc8cfdSPierre-Yves MORDRET 
6597ecc8cfdSPierre-Yves MORDRET 	stm32f7_i2c_disable_dma_req(i2c_dev);
6607ecc8cfdSPierre-Yves MORDRET 	dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir);
6617ecc8cfdSPierre-Yves MORDRET 	complete(&dma->dma_complete);
6627ecc8cfdSPierre-Yves MORDRET }
6637ecc8cfdSPierre-Yves MORDRET 
664aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
665aeb068c5SPierre-Yves MORDRET {
666aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_timings *t = &i2c_dev->timing;
667aeb068c5SPierre-Yves MORDRET 	u32 timing = 0;
668aeb068c5SPierre-Yves MORDRET 
669aeb068c5SPierre-Yves MORDRET 	/* Timing settings */
670aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_PRESC(t->presc);
671aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SCLDEL(t->scldel);
672aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SDADEL(t->sdadel);
673aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SCLH(t->sclh);
674aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SCLL(t->scll);
675aeb068c5SPierre-Yves MORDRET 	writel_relaxed(timing, i2c_dev->base + STM32F7_I2C_TIMINGR);
676aeb068c5SPierre-Yves MORDRET 
677aeb068c5SPierre-Yves MORDRET 	/* Enable I2C */
678463a9215SPierre-Yves MORDRET 	if (i2c_dev->setup.analog_filter)
679aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
680aeb068c5SPierre-Yves MORDRET 				     STM32F7_I2C_CR1_ANFOFF);
681aeb068c5SPierre-Yves MORDRET 	else
682aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
683aeb068c5SPierre-Yves MORDRET 				     STM32F7_I2C_CR1_ANFOFF);
684aeb068c5SPierre-Yves MORDRET 	stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
685aeb068c5SPierre-Yves MORDRET 			     STM32F7_I2C_CR1_PE);
686aeb068c5SPierre-Yves MORDRET }
687aeb068c5SPierre-Yves MORDRET 
688aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_write_tx_data(struct stm32f7_i2c_dev *i2c_dev)
689aeb068c5SPierre-Yves MORDRET {
690aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
691aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
692aeb068c5SPierre-Yves MORDRET 
693aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count) {
694aeb068c5SPierre-Yves MORDRET 		writeb_relaxed(*f7_msg->buf++, base + STM32F7_I2C_TXDR);
695aeb068c5SPierre-Yves MORDRET 		f7_msg->count--;
696aeb068c5SPierre-Yves MORDRET 	}
697aeb068c5SPierre-Yves MORDRET }
698aeb068c5SPierre-Yves MORDRET 
699aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_read_rx_data(struct stm32f7_i2c_dev *i2c_dev)
700aeb068c5SPierre-Yves MORDRET {
701aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
702aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
703aeb068c5SPierre-Yves MORDRET 
704aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count) {
705aeb068c5SPierre-Yves MORDRET 		*f7_msg->buf++ = readb_relaxed(base + STM32F7_I2C_RXDR);
706aeb068c5SPierre-Yves MORDRET 		f7_msg->count--;
70760d609f3SPierre-Yves MORDRET 	} else {
70860d609f3SPierre-Yves MORDRET 		/* Flush RX buffer has no data is expected */
70960d609f3SPierre-Yves MORDRET 		readb_relaxed(base + STM32F7_I2C_RXDR);
710aeb068c5SPierre-Yves MORDRET 	}
711aeb068c5SPierre-Yves MORDRET }
712aeb068c5SPierre-Yves MORDRET 
713aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
714aeb068c5SPierre-Yves MORDRET {
715aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
716aeb068c5SPierre-Yves MORDRET 	u32 cr2;
717aeb068c5SPierre-Yves MORDRET 
7187ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->use_dma)
7197ecc8cfdSPierre-Yves MORDRET 		f7_msg->count -= STM32F7_I2C_MAX_LEN;
7207ecc8cfdSPierre-Yves MORDRET 
721aeb068c5SPierre-Yves MORDRET 	cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
722aeb068c5SPierre-Yves MORDRET 
723aeb068c5SPierre-Yves MORDRET 	cr2 &= ~STM32F7_I2C_CR2_NBYTES_MASK;
724aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count > STM32F7_I2C_MAX_LEN) {
725aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(STM32F7_I2C_MAX_LEN);
726aeb068c5SPierre-Yves MORDRET 	} else {
727aeb068c5SPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_RELOAD;
728aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
729aeb068c5SPierre-Yves MORDRET 	}
730aeb068c5SPierre-Yves MORDRET 
731aeb068c5SPierre-Yves MORDRET 	writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
732aeb068c5SPierre-Yves MORDRET }
733aeb068c5SPierre-Yves MORDRET 
7349e48155fSPierre-Yves MORDRET static void stm32f7_i2c_smbus_reload(struct stm32f7_i2c_dev *i2c_dev)
7359e48155fSPierre-Yves MORDRET {
7369e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
7379e48155fSPierre-Yves MORDRET 	u32 cr2;
7389e48155fSPierre-Yves MORDRET 	u8 *val;
7399e48155fSPierre-Yves MORDRET 
7409e48155fSPierre-Yves MORDRET 	/*
7419e48155fSPierre-Yves MORDRET 	 * For I2C_SMBUS_BLOCK_DATA && I2C_SMBUS_BLOCK_PROC_CALL, the first
7429e48155fSPierre-Yves MORDRET 	 * data received inform us how many data will follow.
7439e48155fSPierre-Yves MORDRET 	 */
7449e48155fSPierre-Yves MORDRET 	stm32f7_i2c_read_rx_data(i2c_dev);
7459e48155fSPierre-Yves MORDRET 
7469e48155fSPierre-Yves MORDRET 	/*
7479e48155fSPierre-Yves MORDRET 	 * Update NBYTES with the value read to continue the transfer
7489e48155fSPierre-Yves MORDRET 	 */
7499e48155fSPierre-Yves MORDRET 	val = f7_msg->buf - sizeof(u8);
7509e48155fSPierre-Yves MORDRET 	f7_msg->count = *val;
7519e48155fSPierre-Yves MORDRET 	cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
7529e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
7539e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
7549e48155fSPierre-Yves MORDRET 	writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
7559e48155fSPierre-Yves MORDRET }
7569e48155fSPierre-Yves MORDRET 
757562de4ffSPierre-Yves MORDRET static int stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap)
758562de4ffSPierre-Yves MORDRET {
759562de4ffSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
760562de4ffSPierre-Yves MORDRET 
761562de4ffSPierre-Yves MORDRET 	dev_info(i2c_dev->dev, "Trying to recover bus\n");
762562de4ffSPierre-Yves MORDRET 
763562de4ffSPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
764562de4ffSPierre-Yves MORDRET 			     STM32F7_I2C_CR1_PE);
765562de4ffSPierre-Yves MORDRET 
766562de4ffSPierre-Yves MORDRET 	stm32f7_i2c_hw_config(i2c_dev);
767562de4ffSPierre-Yves MORDRET 
768562de4ffSPierre-Yves MORDRET 	return 0;
769562de4ffSPierre-Yves MORDRET }
770562de4ffSPierre-Yves MORDRET 
771aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
772aeb068c5SPierre-Yves MORDRET {
773aeb068c5SPierre-Yves MORDRET 	u32 status;
774aeb068c5SPierre-Yves MORDRET 	int ret;
775aeb068c5SPierre-Yves MORDRET 
776aeb068c5SPierre-Yves MORDRET 	ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F7_I2C_ISR,
777aeb068c5SPierre-Yves MORDRET 					 status,
778aeb068c5SPierre-Yves MORDRET 					 !(status & STM32F7_I2C_ISR_BUSY),
779aeb068c5SPierre-Yves MORDRET 					 10, 1000);
780562de4ffSPierre-Yves MORDRET 	if (!ret)
781562de4ffSPierre-Yves MORDRET 		return 0;
782562de4ffSPierre-Yves MORDRET 
783562de4ffSPierre-Yves MORDRET 	dev_info(i2c_dev->dev, "bus busy\n");
784562de4ffSPierre-Yves MORDRET 
785562de4ffSPierre-Yves MORDRET 	ret = stm32f7_i2c_release_bus(&i2c_dev->adap);
786aeb068c5SPierre-Yves MORDRET 	if (ret) {
787562de4ffSPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
788562de4ffSPierre-Yves MORDRET 		return ret;
789aeb068c5SPierre-Yves MORDRET 	}
790aeb068c5SPierre-Yves MORDRET 
791562de4ffSPierre-Yves MORDRET 	return -EBUSY;
792aeb068c5SPierre-Yves MORDRET }
793aeb068c5SPierre-Yves MORDRET 
794aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
795aeb068c5SPierre-Yves MORDRET 				 struct i2c_msg *msg)
796aeb068c5SPierre-Yves MORDRET {
797aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
798aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
799aeb068c5SPierre-Yves MORDRET 	u32 cr1, cr2;
8007ecc8cfdSPierre-Yves MORDRET 	int ret;
801aeb068c5SPierre-Yves MORDRET 
802aeb068c5SPierre-Yves MORDRET 	f7_msg->addr = msg->addr;
803aeb068c5SPierre-Yves MORDRET 	f7_msg->buf = msg->buf;
804aeb068c5SPierre-Yves MORDRET 	f7_msg->count = msg->len;
805aeb068c5SPierre-Yves MORDRET 	f7_msg->result = 0;
806aeb068c5SPierre-Yves MORDRET 	f7_msg->stop = (i2c_dev->msg_id >= i2c_dev->msg_num - 1);
807aeb068c5SPierre-Yves MORDRET 
808aeb068c5SPierre-Yves MORDRET 	reinit_completion(&i2c_dev->complete);
809aeb068c5SPierre-Yves MORDRET 
810aeb068c5SPierre-Yves MORDRET 	cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
811aeb068c5SPierre-Yves MORDRET 	cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
812aeb068c5SPierre-Yves MORDRET 
813aeb068c5SPierre-Yves MORDRET 	/* Set transfer direction */
814aeb068c5SPierre-Yves MORDRET 	cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
815aeb068c5SPierre-Yves MORDRET 	if (msg->flags & I2C_M_RD)
816aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RD_WRN;
817aeb068c5SPierre-Yves MORDRET 
818aeb068c5SPierre-Yves MORDRET 	/* Set slave address */
8198c7ecc99SPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_HEAD10R | STM32F7_I2C_CR2_ADD10);
8208c7ecc99SPierre-Yves MORDRET 	if (msg->flags & I2C_M_TEN) {
8218c7ecc99SPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_SADD10_MASK;
8228c7ecc99SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_SADD10(f7_msg->addr);
8238c7ecc99SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_ADD10;
8248c7ecc99SPierre-Yves MORDRET 	} else {
825aeb068c5SPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_SADD7_MASK;
826aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
8278c7ecc99SPierre-Yves MORDRET 	}
828aeb068c5SPierre-Yves MORDRET 
829aeb068c5SPierre-Yves MORDRET 	/* Set nb bytes to transfer and reload if needed */
830aeb068c5SPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
831aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count > STM32F7_I2C_MAX_LEN) {
832aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(STM32F7_I2C_MAX_LEN);
833aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RELOAD;
834aeb068c5SPierre-Yves MORDRET 	} else {
835aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
836aeb068c5SPierre-Yves MORDRET 	}
837aeb068c5SPierre-Yves MORDRET 
838aeb068c5SPierre-Yves MORDRET 	/* Enable NACK, STOP, error and transfer complete interrupts */
839aeb068c5SPierre-Yves MORDRET 	cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
840aeb068c5SPierre-Yves MORDRET 		STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
841aeb068c5SPierre-Yves MORDRET 
8427ecc8cfdSPierre-Yves MORDRET 	/* Clear DMA req and TX/RX interrupt */
8437ecc8cfdSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
8447ecc8cfdSPierre-Yves MORDRET 			STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
845aeb068c5SPierre-Yves MORDRET 
8467ecc8cfdSPierre-Yves MORDRET 	/* Configure DMA or enable RX/TX interrupt */
8477ecc8cfdSPierre-Yves MORDRET 	i2c_dev->use_dma = false;
8487ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
8497ecc8cfdSPierre-Yves MORDRET 		ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
8507ecc8cfdSPierre-Yves MORDRET 					      msg->flags & I2C_M_RD,
8517ecc8cfdSPierre-Yves MORDRET 					      f7_msg->count, f7_msg->buf,
8527ecc8cfdSPierre-Yves MORDRET 					      stm32f7_i2c_dma_callback,
8537ecc8cfdSPierre-Yves MORDRET 					      i2c_dev);
8547ecc8cfdSPierre-Yves MORDRET 		if (!ret)
8557ecc8cfdSPierre-Yves MORDRET 			i2c_dev->use_dma = true;
8567ecc8cfdSPierre-Yves MORDRET 		else
8577ecc8cfdSPierre-Yves MORDRET 			dev_warn(i2c_dev->dev, "can't use DMA\n");
8587ecc8cfdSPierre-Yves MORDRET 	}
8597ecc8cfdSPierre-Yves MORDRET 
8607ecc8cfdSPierre-Yves MORDRET 	if (!i2c_dev->use_dma) {
861aeb068c5SPierre-Yves MORDRET 		if (msg->flags & I2C_M_RD)
862aeb068c5SPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXIE;
863aeb068c5SPierre-Yves MORDRET 		else
864aeb068c5SPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXIE;
8657ecc8cfdSPierre-Yves MORDRET 	} else {
8667ecc8cfdSPierre-Yves MORDRET 		if (msg->flags & I2C_M_RD)
8677ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXDMAEN;
8687ecc8cfdSPierre-Yves MORDRET 		else
8697ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXDMAEN;
8707ecc8cfdSPierre-Yves MORDRET 	}
871aeb068c5SPierre-Yves MORDRET 
872aeb068c5SPierre-Yves MORDRET 	/* Configure Start/Repeated Start */
873aeb068c5SPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_START;
874aeb068c5SPierre-Yves MORDRET 
87560d609f3SPierre-Yves MORDRET 	i2c_dev->master_mode = true;
87660d609f3SPierre-Yves MORDRET 
877aeb068c5SPierre-Yves MORDRET 	/* Write configurations registers */
878aeb068c5SPierre-Yves MORDRET 	writel_relaxed(cr1, base + STM32F7_I2C_CR1);
879aeb068c5SPierre-Yves MORDRET 	writel_relaxed(cr2, base + STM32F7_I2C_CR2);
880aeb068c5SPierre-Yves MORDRET }
881aeb068c5SPierre-Yves MORDRET 
8829e48155fSPierre-Yves MORDRET static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
8839e48155fSPierre-Yves MORDRET 				      unsigned short flags, u8 command,
8849e48155fSPierre-Yves MORDRET 				      union i2c_smbus_data *data)
8859e48155fSPierre-Yves MORDRET {
8869e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
8879e48155fSPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
8889e48155fSPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
8899e48155fSPierre-Yves MORDRET 	u32 cr1, cr2;
8907ecc8cfdSPierre-Yves MORDRET 	int i, ret;
8919e48155fSPierre-Yves MORDRET 
8929e48155fSPierre-Yves MORDRET 	f7_msg->result = 0;
8939e48155fSPierre-Yves MORDRET 	reinit_completion(&i2c_dev->complete);
8949e48155fSPierre-Yves MORDRET 
8959e48155fSPierre-Yves MORDRET 	cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
8969e48155fSPierre-Yves MORDRET 	cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
8979e48155fSPierre-Yves MORDRET 
8989e48155fSPierre-Yves MORDRET 	/* Set transfer direction */
8999e48155fSPierre-Yves MORDRET 	cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9009e48155fSPierre-Yves MORDRET 	if (f7_msg->read_write)
9019e48155fSPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RD_WRN;
9029e48155fSPierre-Yves MORDRET 
9039e48155fSPierre-Yves MORDRET 	/* Set slave address */
9049e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_ADD10 | STM32F7_I2C_CR2_SADD7_MASK);
9059e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
9069e48155fSPierre-Yves MORDRET 
9079e48155fSPierre-Yves MORDRET 	f7_msg->smbus_buf[0] = command;
9089e48155fSPierre-Yves MORDRET 	switch (f7_msg->size) {
9099e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_QUICK:
9109e48155fSPierre-Yves MORDRET 		f7_msg->stop = true;
9119e48155fSPierre-Yves MORDRET 		f7_msg->count = 0;
9129e48155fSPierre-Yves MORDRET 		break;
9139e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE:
9149e48155fSPierre-Yves MORDRET 		f7_msg->stop = true;
9159e48155fSPierre-Yves MORDRET 		f7_msg->count = 1;
9169e48155fSPierre-Yves MORDRET 		break;
9179e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE_DATA:
9189e48155fSPierre-Yves MORDRET 		if (f7_msg->read_write) {
9199e48155fSPierre-Yves MORDRET 			f7_msg->stop = false;
9209e48155fSPierre-Yves MORDRET 			f7_msg->count = 1;
9219e48155fSPierre-Yves MORDRET 			cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9229e48155fSPierre-Yves MORDRET 		} else {
9239e48155fSPierre-Yves MORDRET 			f7_msg->stop = true;
9249e48155fSPierre-Yves MORDRET 			f7_msg->count = 2;
9259e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[1] = data->byte;
9269e48155fSPierre-Yves MORDRET 		}
9279e48155fSPierre-Yves MORDRET 		break;
9289e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_WORD_DATA:
9299e48155fSPierre-Yves MORDRET 		if (f7_msg->read_write) {
9309e48155fSPierre-Yves MORDRET 			f7_msg->stop = false;
9319e48155fSPierre-Yves MORDRET 			f7_msg->count = 1;
9329e48155fSPierre-Yves MORDRET 			cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9339e48155fSPierre-Yves MORDRET 		} else {
9349e48155fSPierre-Yves MORDRET 			f7_msg->stop = true;
9359e48155fSPierre-Yves MORDRET 			f7_msg->count = 3;
9369e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[1] = data->word & 0xff;
9379e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[2] = data->word >> 8;
9389e48155fSPierre-Yves MORDRET 		}
9399e48155fSPierre-Yves MORDRET 		break;
9409e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_DATA:
9419e48155fSPierre-Yves MORDRET 		if (f7_msg->read_write) {
9429e48155fSPierre-Yves MORDRET 			f7_msg->stop = false;
9439e48155fSPierre-Yves MORDRET 			f7_msg->count = 1;
9449e48155fSPierre-Yves MORDRET 			cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9459e48155fSPierre-Yves MORDRET 		} else {
9469e48155fSPierre-Yves MORDRET 			f7_msg->stop = true;
9479e48155fSPierre-Yves MORDRET 			if (data->block[0] > I2C_SMBUS_BLOCK_MAX ||
9489e48155fSPierre-Yves MORDRET 			    !data->block[0]) {
9499e48155fSPierre-Yves MORDRET 				dev_err(dev, "Invalid block write size %d\n",
9509e48155fSPierre-Yves MORDRET 					data->block[0]);
9519e48155fSPierre-Yves MORDRET 				return -EINVAL;
9529e48155fSPierre-Yves MORDRET 			}
9539e48155fSPierre-Yves MORDRET 			f7_msg->count = data->block[0] + 2;
9549e48155fSPierre-Yves MORDRET 			for (i = 1; i < f7_msg->count; i++)
9559e48155fSPierre-Yves MORDRET 				f7_msg->smbus_buf[i] = data->block[i - 1];
9569e48155fSPierre-Yves MORDRET 		}
9579e48155fSPierre-Yves MORDRET 		break;
9589e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_PROC_CALL:
9599e48155fSPierre-Yves MORDRET 		f7_msg->stop = false;
9609e48155fSPierre-Yves MORDRET 		f7_msg->count = 3;
9619e48155fSPierre-Yves MORDRET 		f7_msg->smbus_buf[1] = data->word & 0xff;
9629e48155fSPierre-Yves MORDRET 		f7_msg->smbus_buf[2] = data->word >> 8;
9639e48155fSPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9649e48155fSPierre-Yves MORDRET 		f7_msg->read_write = I2C_SMBUS_READ;
9659e48155fSPierre-Yves MORDRET 		break;
9669e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_PROC_CALL:
9679e48155fSPierre-Yves MORDRET 		f7_msg->stop = false;
9689e48155fSPierre-Yves MORDRET 		if (data->block[0] > I2C_SMBUS_BLOCK_MAX - 1) {
9699e48155fSPierre-Yves MORDRET 			dev_err(dev, "Invalid block write size %d\n",
9709e48155fSPierre-Yves MORDRET 				data->block[0]);
9719e48155fSPierre-Yves MORDRET 			return -EINVAL;
9729e48155fSPierre-Yves MORDRET 		}
9739e48155fSPierre-Yves MORDRET 		f7_msg->count = data->block[0] + 2;
9749e48155fSPierre-Yves MORDRET 		for (i = 1; i < f7_msg->count; i++)
9759e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[i] = data->block[i - 1];
9769e48155fSPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9779e48155fSPierre-Yves MORDRET 		f7_msg->read_write = I2C_SMBUS_READ;
9789e48155fSPierre-Yves MORDRET 		break;
979473fbdf7SFabrice Gasnier 	case I2C_SMBUS_I2C_BLOCK_DATA:
980473fbdf7SFabrice Gasnier 		/* Rely on emulated i2c transfer (through master_xfer) */
981473fbdf7SFabrice Gasnier 		return -EOPNOTSUPP;
9829e48155fSPierre-Yves MORDRET 	default:
9839e48155fSPierre-Yves MORDRET 		dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
9849e48155fSPierre-Yves MORDRET 		return -EOPNOTSUPP;
9859e48155fSPierre-Yves MORDRET 	}
9869e48155fSPierre-Yves MORDRET 
9879e48155fSPierre-Yves MORDRET 	f7_msg->buf = f7_msg->smbus_buf;
9889e48155fSPierre-Yves MORDRET 
9899e48155fSPierre-Yves MORDRET 	/* Configure PEC */
9909e48155fSPierre-Yves MORDRET 	if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
9919e48155fSPierre-Yves MORDRET 		cr1 |= STM32F7_I2C_CR1_PECEN;
9929e48155fSPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_PECBYTE;
9939e48155fSPierre-Yves MORDRET 		if (!f7_msg->read_write)
9949e48155fSPierre-Yves MORDRET 			f7_msg->count++;
9959e48155fSPierre-Yves MORDRET 	} else {
9969e48155fSPierre-Yves MORDRET 		cr1 &= ~STM32F7_I2C_CR1_PECEN;
9979e48155fSPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_PECBYTE;
9989e48155fSPierre-Yves MORDRET 	}
9999e48155fSPierre-Yves MORDRET 
10009e48155fSPierre-Yves MORDRET 	/* Set number of bytes to be transferred */
10019e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
10029e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
10039e48155fSPierre-Yves MORDRET 
10049e48155fSPierre-Yves MORDRET 	/* Enable NACK, STOP, error and transfer complete interrupts */
10059e48155fSPierre-Yves MORDRET 	cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
10069e48155fSPierre-Yves MORDRET 		STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
10079e48155fSPierre-Yves MORDRET 
10087ecc8cfdSPierre-Yves MORDRET 	/* Clear DMA req and TX/RX interrupt */
10097ecc8cfdSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
10107ecc8cfdSPierre-Yves MORDRET 			STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
10119e48155fSPierre-Yves MORDRET 
10127ecc8cfdSPierre-Yves MORDRET 	/* Configure DMA or enable RX/TX interrupt */
10137ecc8cfdSPierre-Yves MORDRET 	i2c_dev->use_dma = false;
10147ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
10157ecc8cfdSPierre-Yves MORDRET 		ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
10167ecc8cfdSPierre-Yves MORDRET 					      cr2 & STM32F7_I2C_CR2_RD_WRN,
10177ecc8cfdSPierre-Yves MORDRET 					      f7_msg->count, f7_msg->buf,
10187ecc8cfdSPierre-Yves MORDRET 					      stm32f7_i2c_dma_callback,
10197ecc8cfdSPierre-Yves MORDRET 					      i2c_dev);
10207ecc8cfdSPierre-Yves MORDRET 		if (!ret)
10217ecc8cfdSPierre-Yves MORDRET 			i2c_dev->use_dma = true;
10227ecc8cfdSPierre-Yves MORDRET 		else
10237ecc8cfdSPierre-Yves MORDRET 			dev_warn(i2c_dev->dev, "can't use DMA\n");
10247ecc8cfdSPierre-Yves MORDRET 	}
10257ecc8cfdSPierre-Yves MORDRET 
10267ecc8cfdSPierre-Yves MORDRET 	if (!i2c_dev->use_dma) {
10279e48155fSPierre-Yves MORDRET 		if (cr2 & STM32F7_I2C_CR2_RD_WRN)
10289e48155fSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXIE;
10299e48155fSPierre-Yves MORDRET 		else
10309e48155fSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXIE;
10317ecc8cfdSPierre-Yves MORDRET 	} else {
10327ecc8cfdSPierre-Yves MORDRET 		if (cr2 & STM32F7_I2C_CR2_RD_WRN)
10337ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXDMAEN;
10347ecc8cfdSPierre-Yves MORDRET 		else
10357ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXDMAEN;
10367ecc8cfdSPierre-Yves MORDRET 	}
10379e48155fSPierre-Yves MORDRET 
10389e48155fSPierre-Yves MORDRET 	/* Set Start bit */
10399e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_START;
10409e48155fSPierre-Yves MORDRET 
10419e48155fSPierre-Yves MORDRET 	i2c_dev->master_mode = true;
10429e48155fSPierre-Yves MORDRET 
10439e48155fSPierre-Yves MORDRET 	/* Write configurations registers */
10449e48155fSPierre-Yves MORDRET 	writel_relaxed(cr1, base + STM32F7_I2C_CR1);
10459e48155fSPierre-Yves MORDRET 	writel_relaxed(cr2, base + STM32F7_I2C_CR2);
10469e48155fSPierre-Yves MORDRET 
10479e48155fSPierre-Yves MORDRET 	return 0;
10489e48155fSPierre-Yves MORDRET }
10499e48155fSPierre-Yves MORDRET 
10509e48155fSPierre-Yves MORDRET static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev)
10519e48155fSPierre-Yves MORDRET {
10529e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
10539e48155fSPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
10549e48155fSPierre-Yves MORDRET 	u32 cr1, cr2;
10557ecc8cfdSPierre-Yves MORDRET 	int ret;
10569e48155fSPierre-Yves MORDRET 
10579e48155fSPierre-Yves MORDRET 	cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
10589e48155fSPierre-Yves MORDRET 	cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
10599e48155fSPierre-Yves MORDRET 
10609e48155fSPierre-Yves MORDRET 	/* Set transfer direction */
10619e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_RD_WRN;
10629e48155fSPierre-Yves MORDRET 
10639e48155fSPierre-Yves MORDRET 	switch (f7_msg->size) {
10649e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE_DATA:
10659e48155fSPierre-Yves MORDRET 		f7_msg->count = 1;
10669e48155fSPierre-Yves MORDRET 		break;
10679e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_WORD_DATA:
10689e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_PROC_CALL:
10699e48155fSPierre-Yves MORDRET 		f7_msg->count = 2;
10709e48155fSPierre-Yves MORDRET 		break;
10719e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_DATA:
10729e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_PROC_CALL:
10739e48155fSPierre-Yves MORDRET 		f7_msg->count = 1;
10749e48155fSPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RELOAD;
10759e48155fSPierre-Yves MORDRET 		break;
10769e48155fSPierre-Yves MORDRET 	}
10779e48155fSPierre-Yves MORDRET 
10789e48155fSPierre-Yves MORDRET 	f7_msg->buf = f7_msg->smbus_buf;
10799e48155fSPierre-Yves MORDRET 	f7_msg->stop = true;
10809e48155fSPierre-Yves MORDRET 
10819e48155fSPierre-Yves MORDRET 	/* Add one byte for PEC if needed */
10829e48155fSPierre-Yves MORDRET 	if (cr1 & STM32F7_I2C_CR1_PECEN)
10839e48155fSPierre-Yves MORDRET 		f7_msg->count++;
10849e48155fSPierre-Yves MORDRET 
10859e48155fSPierre-Yves MORDRET 	/* Set number of bytes to be transferred */
10869e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK);
10879e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
10889e48155fSPierre-Yves MORDRET 
10899e48155fSPierre-Yves MORDRET 	/*
10909e48155fSPierre-Yves MORDRET 	 * Configure RX/TX interrupt:
10919e48155fSPierre-Yves MORDRET 	 */
10929e48155fSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE);
10939e48155fSPierre-Yves MORDRET 	cr1 |= STM32F7_I2C_CR1_RXIE;
10949e48155fSPierre-Yves MORDRET 
10957ecc8cfdSPierre-Yves MORDRET 	/*
10967ecc8cfdSPierre-Yves MORDRET 	 * Configure DMA or enable RX/TX interrupt:
10977ecc8cfdSPierre-Yves MORDRET 	 * For I2C_SMBUS_BLOCK_DATA and I2C_SMBUS_BLOCK_PROC_CALL we don't use
10987ecc8cfdSPierre-Yves MORDRET 	 * dma as we don't know in advance how many data will be received
10997ecc8cfdSPierre-Yves MORDRET 	 */
11007ecc8cfdSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
11017ecc8cfdSPierre-Yves MORDRET 		 STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
11027ecc8cfdSPierre-Yves MORDRET 
11037ecc8cfdSPierre-Yves MORDRET 	i2c_dev->use_dma = false;
11047ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN &&
11057ecc8cfdSPierre-Yves MORDRET 	    f7_msg->size != I2C_SMBUS_BLOCK_DATA &&
11067ecc8cfdSPierre-Yves MORDRET 	    f7_msg->size != I2C_SMBUS_BLOCK_PROC_CALL) {
11077ecc8cfdSPierre-Yves MORDRET 		ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
11087ecc8cfdSPierre-Yves MORDRET 					      cr2 & STM32F7_I2C_CR2_RD_WRN,
11097ecc8cfdSPierre-Yves MORDRET 					      f7_msg->count, f7_msg->buf,
11107ecc8cfdSPierre-Yves MORDRET 					      stm32f7_i2c_dma_callback,
11117ecc8cfdSPierre-Yves MORDRET 					      i2c_dev);
11127ecc8cfdSPierre-Yves MORDRET 
11137ecc8cfdSPierre-Yves MORDRET 		if (!ret)
11147ecc8cfdSPierre-Yves MORDRET 			i2c_dev->use_dma = true;
11157ecc8cfdSPierre-Yves MORDRET 		else
11167ecc8cfdSPierre-Yves MORDRET 			dev_warn(i2c_dev->dev, "can't use DMA\n");
11177ecc8cfdSPierre-Yves MORDRET 	}
11187ecc8cfdSPierre-Yves MORDRET 
11197ecc8cfdSPierre-Yves MORDRET 	if (!i2c_dev->use_dma)
11207ecc8cfdSPierre-Yves MORDRET 		cr1 |= STM32F7_I2C_CR1_RXIE;
11217ecc8cfdSPierre-Yves MORDRET 	else
11227ecc8cfdSPierre-Yves MORDRET 		cr1 |= STM32F7_I2C_CR1_RXDMAEN;
11237ecc8cfdSPierre-Yves MORDRET 
11249e48155fSPierre-Yves MORDRET 	/* Configure Repeated Start */
11259e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_START;
11269e48155fSPierre-Yves MORDRET 
11279e48155fSPierre-Yves MORDRET 	/* Write configurations registers */
11289e48155fSPierre-Yves MORDRET 	writel_relaxed(cr1, base + STM32F7_I2C_CR1);
11299e48155fSPierre-Yves MORDRET 	writel_relaxed(cr2, base + STM32F7_I2C_CR2);
11309e48155fSPierre-Yves MORDRET }
11319e48155fSPierre-Yves MORDRET 
11329e48155fSPierre-Yves MORDRET static int stm32f7_i2c_smbus_check_pec(struct stm32f7_i2c_dev *i2c_dev)
11339e48155fSPierre-Yves MORDRET {
11349e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
11359e48155fSPierre-Yves MORDRET 	u8 count, internal_pec, received_pec;
11369e48155fSPierre-Yves MORDRET 
11379e48155fSPierre-Yves MORDRET 	internal_pec = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
11389e48155fSPierre-Yves MORDRET 
11399e48155fSPierre-Yves MORDRET 	switch (f7_msg->size) {
11409e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE:
11419e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE_DATA:
11429e48155fSPierre-Yves MORDRET 		received_pec = f7_msg->smbus_buf[1];
11439e48155fSPierre-Yves MORDRET 		break;
11449e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_WORD_DATA:
11459e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_PROC_CALL:
11469e48155fSPierre-Yves MORDRET 		received_pec = f7_msg->smbus_buf[2];
11479e48155fSPierre-Yves MORDRET 		break;
11489e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_DATA:
11499e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_PROC_CALL:
11509e48155fSPierre-Yves MORDRET 		count = f7_msg->smbus_buf[0];
11519e48155fSPierre-Yves MORDRET 		received_pec = f7_msg->smbus_buf[count];
11529e48155fSPierre-Yves MORDRET 		break;
11539e48155fSPierre-Yves MORDRET 	default:
11549e48155fSPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Unsupported smbus protocol for PEC\n");
11559e48155fSPierre-Yves MORDRET 		return -EINVAL;
11569e48155fSPierre-Yves MORDRET 	}
11579e48155fSPierre-Yves MORDRET 
11589e48155fSPierre-Yves MORDRET 	if (internal_pec != received_pec) {
11599e48155fSPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Bad PEC 0x%02x vs. 0x%02x\n",
11609e48155fSPierre-Yves MORDRET 			internal_pec, received_pec);
11619e48155fSPierre-Yves MORDRET 		return -EBADMSG;
11629e48155fSPierre-Yves MORDRET 	}
11639e48155fSPierre-Yves MORDRET 
11649e48155fSPierre-Yves MORDRET 	return 0;
11659e48155fSPierre-Yves MORDRET }
11669e48155fSPierre-Yves MORDRET 
116760d609f3SPierre-Yves MORDRET static bool stm32f7_i2c_is_addr_match(struct i2c_client *slave, u32 addcode)
1168aeb068c5SPierre-Yves MORDRET {
116960d609f3SPierre-Yves MORDRET 	u32 addr;
117060d609f3SPierre-Yves MORDRET 
117160d609f3SPierre-Yves MORDRET 	if (!slave)
117260d609f3SPierre-Yves MORDRET 		return false;
117360d609f3SPierre-Yves MORDRET 
117460d609f3SPierre-Yves MORDRET 	if (slave->flags & I2C_CLIENT_TEN) {
117560d609f3SPierre-Yves MORDRET 		/*
117660d609f3SPierre-Yves MORDRET 		 * For 10-bit addr, addcode = 11110XY with
117760d609f3SPierre-Yves MORDRET 		 * X = Bit 9 of slave address
117860d609f3SPierre-Yves MORDRET 		 * Y = Bit 8 of slave address
117960d609f3SPierre-Yves MORDRET 		 */
118060d609f3SPierre-Yves MORDRET 		addr = slave->addr >> 8;
118160d609f3SPierre-Yves MORDRET 		addr |= 0x78;
118260d609f3SPierre-Yves MORDRET 		if (addr == addcode)
118360d609f3SPierre-Yves MORDRET 			return true;
118460d609f3SPierre-Yves MORDRET 	} else {
118560d609f3SPierre-Yves MORDRET 		addr = slave->addr & 0x7f;
118660d609f3SPierre-Yves MORDRET 		if (addr == addcode)
118760d609f3SPierre-Yves MORDRET 			return true;
118860d609f3SPierre-Yves MORDRET 	}
118960d609f3SPierre-Yves MORDRET 
119060d609f3SPierre-Yves MORDRET 	return false;
119160d609f3SPierre-Yves MORDRET }
119260d609f3SPierre-Yves MORDRET 
119360d609f3SPierre-Yves MORDRET static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
119460d609f3SPierre-Yves MORDRET {
119560d609f3SPierre-Yves MORDRET 	struct i2c_client *slave = i2c_dev->slave_running;
119660d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
119760d609f3SPierre-Yves MORDRET 	u32 mask;
119860d609f3SPierre-Yves MORDRET 	u8 value = 0;
119960d609f3SPierre-Yves MORDRET 
120060d609f3SPierre-Yves MORDRET 	if (i2c_dev->slave_dir) {
120160d609f3SPierre-Yves MORDRET 		/* Notify i2c slave that new read transfer is starting */
120260d609f3SPierre-Yves MORDRET 		i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
120360d609f3SPierre-Yves MORDRET 
120460d609f3SPierre-Yves MORDRET 		/*
120560d609f3SPierre-Yves MORDRET 		 * Disable slave TX config in case of I2C combined message
120660d609f3SPierre-Yves MORDRET 		 * (I2C Write followed by I2C Read)
120760d609f3SPierre-Yves MORDRET 		 */
120860d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_CR2_RELOAD;
120960d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, mask);
121060d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
121160d609f3SPierre-Yves MORDRET 		       STM32F7_I2C_CR1_TCIE;
121260d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
121360d609f3SPierre-Yves MORDRET 
121460d609f3SPierre-Yves MORDRET 		/* Enable TX empty, STOP, NACK interrupts */
121560d609f3SPierre-Yves MORDRET 		mask =  STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
121660d609f3SPierre-Yves MORDRET 			STM32F7_I2C_CR1_TXIE;
121760d609f3SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
121860d609f3SPierre-Yves MORDRET 
121902e64276SFabrice Gasnier 		/* Write 1st data byte */
122002e64276SFabrice Gasnier 		writel_relaxed(value, base + STM32F7_I2C_TXDR);
122160d609f3SPierre-Yves MORDRET 	} else {
122260d609f3SPierre-Yves MORDRET 		/* Notify i2c slave that new write transfer is starting */
122360d609f3SPierre-Yves MORDRET 		i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
122460d609f3SPierre-Yves MORDRET 
122560d609f3SPierre-Yves MORDRET 		/* Set reload mode to be able to ACK/NACK each received byte */
122660d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_CR2_RELOAD;
122760d609f3SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
122860d609f3SPierre-Yves MORDRET 
122960d609f3SPierre-Yves MORDRET 		/*
123060d609f3SPierre-Yves MORDRET 		 * Set STOP, NACK, RX empty and transfer complete interrupts.*
123160d609f3SPierre-Yves MORDRET 		 * Set Slave Byte Control to be able to ACK/NACK each data
123260d609f3SPierre-Yves MORDRET 		 * byte received
123360d609f3SPierre-Yves MORDRET 		 */
123460d609f3SPierre-Yves MORDRET 		mask =  STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
123560d609f3SPierre-Yves MORDRET 			STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
123660d609f3SPierre-Yves MORDRET 			STM32F7_I2C_CR1_TCIE;
123760d609f3SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
123860d609f3SPierre-Yves MORDRET 	}
123960d609f3SPierre-Yves MORDRET }
124060d609f3SPierre-Yves MORDRET 
124160d609f3SPierre-Yves MORDRET static void stm32f7_i2c_slave_addr(struct stm32f7_i2c_dev *i2c_dev)
124260d609f3SPierre-Yves MORDRET {
124360d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
124460d609f3SPierre-Yves MORDRET 	u32 isr, addcode, dir, mask;
124560d609f3SPierre-Yves MORDRET 	int i;
124660d609f3SPierre-Yves MORDRET 
124760d609f3SPierre-Yves MORDRET 	isr = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
124860d609f3SPierre-Yves MORDRET 	addcode = STM32F7_I2C_ISR_ADDCODE_GET(isr);
124960d609f3SPierre-Yves MORDRET 	dir = isr & STM32F7_I2C_ISR_DIR;
125060d609f3SPierre-Yves MORDRET 
125160d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
125260d609f3SPierre-Yves MORDRET 		if (stm32f7_i2c_is_addr_match(i2c_dev->slave[i], addcode)) {
125360d609f3SPierre-Yves MORDRET 			i2c_dev->slave_running = i2c_dev->slave[i];
125460d609f3SPierre-Yves MORDRET 			i2c_dev->slave_dir = dir;
125560d609f3SPierre-Yves MORDRET 
125660d609f3SPierre-Yves MORDRET 			/* Start I2C slave processing */
125760d609f3SPierre-Yves MORDRET 			stm32f7_i2c_slave_start(i2c_dev);
125860d609f3SPierre-Yves MORDRET 
125960d609f3SPierre-Yves MORDRET 			/* Clear ADDR flag */
126060d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ICR_ADDRCF;
126160d609f3SPierre-Yves MORDRET 			writel_relaxed(mask, base + STM32F7_I2C_ICR);
126260d609f3SPierre-Yves MORDRET 			break;
126360d609f3SPierre-Yves MORDRET 		}
126460d609f3SPierre-Yves MORDRET 	}
126560d609f3SPierre-Yves MORDRET }
126660d609f3SPierre-Yves MORDRET 
126760d609f3SPierre-Yves MORDRET static int stm32f7_i2c_get_slave_id(struct stm32f7_i2c_dev *i2c_dev,
126860d609f3SPierre-Yves MORDRET 				    struct i2c_client *slave, int *id)
126960d609f3SPierre-Yves MORDRET {
127060d609f3SPierre-Yves MORDRET 	int i;
127160d609f3SPierre-Yves MORDRET 
127260d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
127360d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave[i] == slave) {
127460d609f3SPierre-Yves MORDRET 			*id = i;
127560d609f3SPierre-Yves MORDRET 			return 0;
127660d609f3SPierre-Yves MORDRET 		}
127760d609f3SPierre-Yves MORDRET 	}
127860d609f3SPierre-Yves MORDRET 
127960d609f3SPierre-Yves MORDRET 	dev_err(i2c_dev->dev, "Slave 0x%x not registered\n", slave->addr);
128060d609f3SPierre-Yves MORDRET 
128160d609f3SPierre-Yves MORDRET 	return -ENODEV;
128260d609f3SPierre-Yves MORDRET }
128360d609f3SPierre-Yves MORDRET 
128460d609f3SPierre-Yves MORDRET static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev,
128560d609f3SPierre-Yves MORDRET 					 struct i2c_client *slave, int *id)
128660d609f3SPierre-Yves MORDRET {
128760d609f3SPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
128860d609f3SPierre-Yves MORDRET 	int i;
128960d609f3SPierre-Yves MORDRET 
129060d609f3SPierre-Yves MORDRET 	/*
129160d609f3SPierre-Yves MORDRET 	 * slave[0] supports 7-bit and 10-bit slave address
129260d609f3SPierre-Yves MORDRET 	 * slave[1] supports 7-bit slave address only
129360d609f3SPierre-Yves MORDRET 	 */
129452d3be71SAlain Volmat 	for (i = STM32F7_I2C_MAX_SLAVE - 1; i >= 0; i--) {
12957787657dSAlain Volmat 		if (i == 1 && (slave->flags & I2C_CLIENT_TEN))
129660d609f3SPierre-Yves MORDRET 			continue;
129760d609f3SPierre-Yves MORDRET 		if (!i2c_dev->slave[i]) {
129860d609f3SPierre-Yves MORDRET 			*id = i;
129960d609f3SPierre-Yves MORDRET 			return 0;
130060d609f3SPierre-Yves MORDRET 		}
130160d609f3SPierre-Yves MORDRET 	}
130260d609f3SPierre-Yves MORDRET 
130360d609f3SPierre-Yves MORDRET 	dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr);
130460d609f3SPierre-Yves MORDRET 
130560d609f3SPierre-Yves MORDRET 	return -EINVAL;
130660d609f3SPierre-Yves MORDRET }
130760d609f3SPierre-Yves MORDRET 
130860d609f3SPierre-Yves MORDRET static bool stm32f7_i2c_is_slave_registered(struct stm32f7_i2c_dev *i2c_dev)
130960d609f3SPierre-Yves MORDRET {
131060d609f3SPierre-Yves MORDRET 	int i;
131160d609f3SPierre-Yves MORDRET 
131260d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
131360d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave[i])
131460d609f3SPierre-Yves MORDRET 			return true;
131560d609f3SPierre-Yves MORDRET 	}
131660d609f3SPierre-Yves MORDRET 
131760d609f3SPierre-Yves MORDRET 	return false;
131860d609f3SPierre-Yves MORDRET }
131960d609f3SPierre-Yves MORDRET 
132060d609f3SPierre-Yves MORDRET static bool stm32f7_i2c_is_slave_busy(struct stm32f7_i2c_dev *i2c_dev)
132160d609f3SPierre-Yves MORDRET {
132260d609f3SPierre-Yves MORDRET 	int i, busy;
132360d609f3SPierre-Yves MORDRET 
132460d609f3SPierre-Yves MORDRET 	busy = 0;
132560d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
132660d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave[i])
132760d609f3SPierre-Yves MORDRET 			busy++;
132860d609f3SPierre-Yves MORDRET 	}
132960d609f3SPierre-Yves MORDRET 
133060d609f3SPierre-Yves MORDRET 	return i == busy;
133160d609f3SPierre-Yves MORDRET }
133260d609f3SPierre-Yves MORDRET 
133360d609f3SPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
133460d609f3SPierre-Yves MORDRET {
133560d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
133660d609f3SPierre-Yves MORDRET 	u32 cr2, status, mask;
133760d609f3SPierre-Yves MORDRET 	u8 val;
133860d609f3SPierre-Yves MORDRET 	int ret;
133960d609f3SPierre-Yves MORDRET 
134060d609f3SPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
134160d609f3SPierre-Yves MORDRET 
134260d609f3SPierre-Yves MORDRET 	/* Slave transmitter mode */
134360d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TXIS) {
134460d609f3SPierre-Yves MORDRET 		i2c_slave_event(i2c_dev->slave_running,
134560d609f3SPierre-Yves MORDRET 				I2C_SLAVE_READ_PROCESSED,
134660d609f3SPierre-Yves MORDRET 				&val);
134760d609f3SPierre-Yves MORDRET 
134860d609f3SPierre-Yves MORDRET 		/* Write data byte */
134960d609f3SPierre-Yves MORDRET 		writel_relaxed(val, base + STM32F7_I2C_TXDR);
135060d609f3SPierre-Yves MORDRET 	}
135160d609f3SPierre-Yves MORDRET 
135260d609f3SPierre-Yves MORDRET 	/* Transfer Complete Reload for Slave receiver mode */
135360d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TCR || status & STM32F7_I2C_ISR_RXNE) {
135460d609f3SPierre-Yves MORDRET 		/*
135560d609f3SPierre-Yves MORDRET 		 * Read data byte then set NBYTES to receive next byte or NACK
135660d609f3SPierre-Yves MORDRET 		 * the current received byte
135760d609f3SPierre-Yves MORDRET 		 */
135860d609f3SPierre-Yves MORDRET 		val = readb_relaxed(i2c_dev->base + STM32F7_I2C_RXDR);
135960d609f3SPierre-Yves MORDRET 		ret = i2c_slave_event(i2c_dev->slave_running,
136060d609f3SPierre-Yves MORDRET 				      I2C_SLAVE_WRITE_RECEIVED,
136160d609f3SPierre-Yves MORDRET 				      &val);
136260d609f3SPierre-Yves MORDRET 		if (!ret) {
136360d609f3SPierre-Yves MORDRET 			cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
136460d609f3SPierre-Yves MORDRET 			cr2 |= STM32F7_I2C_CR2_NBYTES(1);
136560d609f3SPierre-Yves MORDRET 			writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
136660d609f3SPierre-Yves MORDRET 		} else {
136760d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_CR2_NACK;
136860d609f3SPierre-Yves MORDRET 			stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
136960d609f3SPierre-Yves MORDRET 		}
137060d609f3SPierre-Yves MORDRET 	}
137160d609f3SPierre-Yves MORDRET 
137260d609f3SPierre-Yves MORDRET 	/* NACK received */
137360d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_NACKF) {
137460d609f3SPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
137560d609f3SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
137660d609f3SPierre-Yves MORDRET 	}
137760d609f3SPierre-Yves MORDRET 
137860d609f3SPierre-Yves MORDRET 	/* STOP received */
137960d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_STOPF) {
138060d609f3SPierre-Yves MORDRET 		/* Disable interrupts */
138160d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_XFER_IRQ_MASK);
138260d609f3SPierre-Yves MORDRET 
138360d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave_dir) {
138460d609f3SPierre-Yves MORDRET 			/*
138560d609f3SPierre-Yves MORDRET 			 * Flush TX buffer in order to not used the byte in
138660d609f3SPierre-Yves MORDRET 			 * TXDR for the next transfer
138760d609f3SPierre-Yves MORDRET 			 */
138860d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ISR_TXE;
138960d609f3SPierre-Yves MORDRET 			stm32f7_i2c_set_bits(base + STM32F7_I2C_ISR, mask);
139060d609f3SPierre-Yves MORDRET 		}
139160d609f3SPierre-Yves MORDRET 
139260d609f3SPierre-Yves MORDRET 		/* Clear STOP flag */
139360d609f3SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
139460d609f3SPierre-Yves MORDRET 
139560d609f3SPierre-Yves MORDRET 		/* Notify i2c slave that a STOP flag has been detected */
139660d609f3SPierre-Yves MORDRET 		i2c_slave_event(i2c_dev->slave_running, I2C_SLAVE_STOP, &val);
139760d609f3SPierre-Yves MORDRET 
139860d609f3SPierre-Yves MORDRET 		i2c_dev->slave_running = NULL;
139960d609f3SPierre-Yves MORDRET 	}
140060d609f3SPierre-Yves MORDRET 
140160d609f3SPierre-Yves MORDRET 	/* Address match received */
140260d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_ADDR)
140360d609f3SPierre-Yves MORDRET 		stm32f7_i2c_slave_addr(i2c_dev);
140460d609f3SPierre-Yves MORDRET 
140560d609f3SPierre-Yves MORDRET 	return IRQ_HANDLED;
1406aeb068c5SPierre-Yves MORDRET }
1407aeb068c5SPierre-Yves MORDRET 
1408aeb068c5SPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
1409aeb068c5SPierre-Yves MORDRET {
1410aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = data;
1411aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1412aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
1413aeb068c5SPierre-Yves MORDRET 	u32 status, mask;
14147ecc8cfdSPierre-Yves MORDRET 	int ret = IRQ_HANDLED;
141560d609f3SPierre-Yves MORDRET 
141660d609f3SPierre-Yves MORDRET 	/* Check if the interrupt if for a slave device */
141760d609f3SPierre-Yves MORDRET 	if (!i2c_dev->master_mode) {
141860d609f3SPierre-Yves MORDRET 		ret = stm32f7_i2c_slave_isr_event(i2c_dev);
141960d609f3SPierre-Yves MORDRET 		return ret;
142060d609f3SPierre-Yves MORDRET 	}
1421aeb068c5SPierre-Yves MORDRET 
1422aeb068c5SPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
1423aeb068c5SPierre-Yves MORDRET 
1424aeb068c5SPierre-Yves MORDRET 	/* Tx empty */
1425aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TXIS)
1426aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_write_tx_data(i2c_dev);
1427aeb068c5SPierre-Yves MORDRET 
1428aeb068c5SPierre-Yves MORDRET 	/* RX not empty */
1429aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_RXNE)
1430aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_read_rx_data(i2c_dev);
1431aeb068c5SPierre-Yves MORDRET 
1432aeb068c5SPierre-Yves MORDRET 	/* NACK received */
1433aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_NACKF) {
1434aeb068c5SPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
1435aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
1436aeb068c5SPierre-Yves MORDRET 		f7_msg->result = -ENXIO;
1437aeb068c5SPierre-Yves MORDRET 	}
1438aeb068c5SPierre-Yves MORDRET 
1439aeb068c5SPierre-Yves MORDRET 	/* STOP detection flag */
1440aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_STOPF) {
1441aeb068c5SPierre-Yves MORDRET 		/* Disable interrupts */
144260d609f3SPierre-Yves MORDRET 		if (stm32f7_i2c_is_slave_registered(i2c_dev))
144360d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_XFER_IRQ_MASK;
144460d609f3SPierre-Yves MORDRET 		else
144560d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ALL_IRQ_MASK;
144660d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, mask);
1447aeb068c5SPierre-Yves MORDRET 
1448aeb068c5SPierre-Yves MORDRET 		/* Clear STOP flag */
1449aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
1450aeb068c5SPierre-Yves MORDRET 
14517ecc8cfdSPierre-Yves MORDRET 		if (i2c_dev->use_dma) {
14527ecc8cfdSPierre-Yves MORDRET 			ret = IRQ_WAKE_THREAD;
14537ecc8cfdSPierre-Yves MORDRET 		} else {
145460d609f3SPierre-Yves MORDRET 			i2c_dev->master_mode = false;
1455aeb068c5SPierre-Yves MORDRET 			complete(&i2c_dev->complete);
1456aeb068c5SPierre-Yves MORDRET 		}
14577ecc8cfdSPierre-Yves MORDRET 	}
1458aeb068c5SPierre-Yves MORDRET 
1459aeb068c5SPierre-Yves MORDRET 	/* Transfer complete */
1460aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TC) {
1461aeb068c5SPierre-Yves MORDRET 		if (f7_msg->stop) {
1462aeb068c5SPierre-Yves MORDRET 			mask = STM32F7_I2C_CR2_STOP;
1463aeb068c5SPierre-Yves MORDRET 			stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
14647ecc8cfdSPierre-Yves MORDRET 		} else if (i2c_dev->use_dma) {
14657ecc8cfdSPierre-Yves MORDRET 			ret = IRQ_WAKE_THREAD;
14669e48155fSPierre-Yves MORDRET 		} else if (f7_msg->smbus) {
14679e48155fSPierre-Yves MORDRET 			stm32f7_i2c_smbus_rep_start(i2c_dev);
1468aeb068c5SPierre-Yves MORDRET 		} else {
1469aeb068c5SPierre-Yves MORDRET 			i2c_dev->msg_id++;
1470aeb068c5SPierre-Yves MORDRET 			i2c_dev->msg++;
1471aeb068c5SPierre-Yves MORDRET 			stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
1472aeb068c5SPierre-Yves MORDRET 		}
1473aeb068c5SPierre-Yves MORDRET 	}
1474aeb068c5SPierre-Yves MORDRET 
14759e48155fSPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TCR) {
14769e48155fSPierre-Yves MORDRET 		if (f7_msg->smbus)
14779e48155fSPierre-Yves MORDRET 			stm32f7_i2c_smbus_reload(i2c_dev);
14789e48155fSPierre-Yves MORDRET 		else
1479aeb068c5SPierre-Yves MORDRET 			stm32f7_i2c_reload(i2c_dev);
14809e48155fSPierre-Yves MORDRET 	}
1481aeb068c5SPierre-Yves MORDRET 
14827ecc8cfdSPierre-Yves MORDRET 	return ret;
14837ecc8cfdSPierre-Yves MORDRET }
14847ecc8cfdSPierre-Yves MORDRET 
14857ecc8cfdSPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
14867ecc8cfdSPierre-Yves MORDRET {
14877ecc8cfdSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = data;
14887ecc8cfdSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
14897ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
14907ecc8cfdSPierre-Yves MORDRET 	u32 status;
14917ecc8cfdSPierre-Yves MORDRET 	int ret;
14927ecc8cfdSPierre-Yves MORDRET 
14937ecc8cfdSPierre-Yves MORDRET 	/*
14947ecc8cfdSPierre-Yves MORDRET 	 * Wait for dma transfer completion before sending next message or
14957ecc8cfdSPierre-Yves MORDRET 	 * notity the end of xfer to the client
14967ecc8cfdSPierre-Yves MORDRET 	 */
14977ecc8cfdSPierre-Yves MORDRET 	ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
14987ecc8cfdSPierre-Yves MORDRET 	if (!ret) {
14997ecc8cfdSPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
15007ecc8cfdSPierre-Yves MORDRET 		stm32f7_i2c_disable_dma_req(i2c_dev);
15017ecc8cfdSPierre-Yves MORDRET 		dmaengine_terminate_all(dma->chan_using);
15027ecc8cfdSPierre-Yves MORDRET 		f7_msg->result = -ETIMEDOUT;
15037ecc8cfdSPierre-Yves MORDRET 	}
15047ecc8cfdSPierre-Yves MORDRET 
15057ecc8cfdSPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
15067ecc8cfdSPierre-Yves MORDRET 
15077ecc8cfdSPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TC) {
15087ecc8cfdSPierre-Yves MORDRET 		if (f7_msg->smbus) {
15097ecc8cfdSPierre-Yves MORDRET 			stm32f7_i2c_smbus_rep_start(i2c_dev);
15107ecc8cfdSPierre-Yves MORDRET 		} else {
15117ecc8cfdSPierre-Yves MORDRET 			i2c_dev->msg_id++;
15127ecc8cfdSPierre-Yves MORDRET 			i2c_dev->msg++;
15137ecc8cfdSPierre-Yves MORDRET 			stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
15147ecc8cfdSPierre-Yves MORDRET 		}
15157ecc8cfdSPierre-Yves MORDRET 	} else {
15167ecc8cfdSPierre-Yves MORDRET 		i2c_dev->master_mode = false;
15177ecc8cfdSPierre-Yves MORDRET 		complete(&i2c_dev->complete);
15187ecc8cfdSPierre-Yves MORDRET 	}
15197ecc8cfdSPierre-Yves MORDRET 
1520aeb068c5SPierre-Yves MORDRET 	return IRQ_HANDLED;
1521aeb068c5SPierre-Yves MORDRET }
1522aeb068c5SPierre-Yves MORDRET 
1523aeb068c5SPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
1524aeb068c5SPierre-Yves MORDRET {
1525aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = data;
1526aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1527aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
1528aeb068c5SPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
15297ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
15306d6b0d0dSFabrice Gasnier 	u32 status;
1531aeb068c5SPierre-Yves MORDRET 
1532aeb068c5SPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
1533aeb068c5SPierre-Yves MORDRET 
1534aeb068c5SPierre-Yves MORDRET 	/* Bus error */
1535aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_BERR) {
1536aeb068c5SPierre-Yves MORDRET 		dev_err(dev, "<%s>: Bus error\n", __func__);
1537aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
1538562de4ffSPierre-Yves MORDRET 		stm32f7_i2c_release_bus(&i2c_dev->adap);
1539aeb068c5SPierre-Yves MORDRET 		f7_msg->result = -EIO;
1540aeb068c5SPierre-Yves MORDRET 	}
1541aeb068c5SPierre-Yves MORDRET 
1542aeb068c5SPierre-Yves MORDRET 	/* Arbitration loss */
1543aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_ARLO) {
1544aeb068c5SPierre-Yves MORDRET 		dev_dbg(dev, "<%s>: Arbitration loss\n", __func__);
1545aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR);
1546aeb068c5SPierre-Yves MORDRET 		f7_msg->result = -EAGAIN;
1547aeb068c5SPierre-Yves MORDRET 	}
1548aeb068c5SPierre-Yves MORDRET 
15499e48155fSPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_PECERR) {
15509e48155fSPierre-Yves MORDRET 		dev_err(dev, "<%s>: PEC error in reception\n", __func__);
15519e48155fSPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
15529e48155fSPierre-Yves MORDRET 		f7_msg->result = -EINVAL;
15539e48155fSPierre-Yves MORDRET 	}
15549e48155fSPierre-Yves MORDRET 
15556d6b0d0dSFabrice Gasnier 	if (!i2c_dev->slave_running) {
15566d6b0d0dSFabrice Gasnier 		u32 mask;
155760d609f3SPierre-Yves MORDRET 		/* Disable interrupts */
155860d609f3SPierre-Yves MORDRET 		if (stm32f7_i2c_is_slave_registered(i2c_dev))
155960d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_XFER_IRQ_MASK;
156060d609f3SPierre-Yves MORDRET 		else
156160d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ALL_IRQ_MASK;
156260d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, mask);
15636d6b0d0dSFabrice Gasnier 	}
1564aeb068c5SPierre-Yves MORDRET 
15657ecc8cfdSPierre-Yves MORDRET 	/* Disable dma */
15667ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->use_dma) {
15677ecc8cfdSPierre-Yves MORDRET 		stm32f7_i2c_disable_dma_req(i2c_dev);
15687ecc8cfdSPierre-Yves MORDRET 		dmaengine_terminate_all(dma->chan_using);
15697ecc8cfdSPierre-Yves MORDRET 	}
15707ecc8cfdSPierre-Yves MORDRET 
157160d609f3SPierre-Yves MORDRET 	i2c_dev->master_mode = false;
1572aeb068c5SPierre-Yves MORDRET 	complete(&i2c_dev->complete);
1573aeb068c5SPierre-Yves MORDRET 
1574aeb068c5SPierre-Yves MORDRET 	return IRQ_HANDLED;
1575aeb068c5SPierre-Yves MORDRET }
1576aeb068c5SPierre-Yves MORDRET 
1577aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
1578aeb068c5SPierre-Yves MORDRET 			    struct i2c_msg msgs[], int num)
1579aeb068c5SPierre-Yves MORDRET {
1580aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
1581aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
15827ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
1583aeb068c5SPierre-Yves MORDRET 	unsigned long time_left;
1584aeb068c5SPierre-Yves MORDRET 	int ret;
1585aeb068c5SPierre-Yves MORDRET 
1586aeb068c5SPierre-Yves MORDRET 	i2c_dev->msg = msgs;
1587aeb068c5SPierre-Yves MORDRET 	i2c_dev->msg_num = num;
1588aeb068c5SPierre-Yves MORDRET 	i2c_dev->msg_id = 0;
15899e48155fSPierre-Yves MORDRET 	f7_msg->smbus = false;
1590aeb068c5SPierre-Yves MORDRET 
15914e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(i2c_dev->dev);
15924e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
1593aeb068c5SPierre-Yves MORDRET 		return ret;
1594aeb068c5SPierre-Yves MORDRET 
1595aeb068c5SPierre-Yves MORDRET 	ret = stm32f7_i2c_wait_free_bus(i2c_dev);
1596aeb068c5SPierre-Yves MORDRET 	if (ret)
15974e7bca6fSPierre-Yves MORDRET 		goto pm_free;
1598aeb068c5SPierre-Yves MORDRET 
1599aeb068c5SPierre-Yves MORDRET 	stm32f7_i2c_xfer_msg(i2c_dev, msgs);
1600aeb068c5SPierre-Yves MORDRET 
1601aeb068c5SPierre-Yves MORDRET 	time_left = wait_for_completion_timeout(&i2c_dev->complete,
1602aeb068c5SPierre-Yves MORDRET 						i2c_dev->adap.timeout);
1603aeb068c5SPierre-Yves MORDRET 	ret = f7_msg->result;
1604aeb068c5SPierre-Yves MORDRET 
1605aeb068c5SPierre-Yves MORDRET 	if (!time_left) {
1606aeb068c5SPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
1607aeb068c5SPierre-Yves MORDRET 			i2c_dev->msg->addr);
16087ecc8cfdSPierre-Yves MORDRET 		if (i2c_dev->use_dma)
16097ecc8cfdSPierre-Yves MORDRET 			dmaengine_terminate_all(dma->chan_using);
1610aeb068c5SPierre-Yves MORDRET 		ret = -ETIMEDOUT;
1611aeb068c5SPierre-Yves MORDRET 	}
1612aeb068c5SPierre-Yves MORDRET 
16134e7bca6fSPierre-Yves MORDRET pm_free:
16144e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(i2c_dev->dev);
16154e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(i2c_dev->dev);
1616aeb068c5SPierre-Yves MORDRET 
1617aeb068c5SPierre-Yves MORDRET 	return (ret < 0) ? ret : num;
1618aeb068c5SPierre-Yves MORDRET }
1619aeb068c5SPierre-Yves MORDRET 
16209e48155fSPierre-Yves MORDRET static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
16219e48155fSPierre-Yves MORDRET 				  unsigned short flags, char read_write,
16229e48155fSPierre-Yves MORDRET 				  u8 command, int size,
16239e48155fSPierre-Yves MORDRET 				  union i2c_smbus_data *data)
16249e48155fSPierre-Yves MORDRET {
16259e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adapter);
16269e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
16277ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
16289e48155fSPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
16299e48155fSPierre-Yves MORDRET 	unsigned long timeout;
16309e48155fSPierre-Yves MORDRET 	int i, ret;
16319e48155fSPierre-Yves MORDRET 
16329e48155fSPierre-Yves MORDRET 	f7_msg->addr = addr;
16339e48155fSPierre-Yves MORDRET 	f7_msg->size = size;
16349e48155fSPierre-Yves MORDRET 	f7_msg->read_write = read_write;
16359e48155fSPierre-Yves MORDRET 	f7_msg->smbus = true;
16369e48155fSPierre-Yves MORDRET 
16374e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(dev);
16384e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
16399e48155fSPierre-Yves MORDRET 		return ret;
16409e48155fSPierre-Yves MORDRET 
16419e48155fSPierre-Yves MORDRET 	ret = stm32f7_i2c_wait_free_bus(i2c_dev);
16429e48155fSPierre-Yves MORDRET 	if (ret)
16434e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16449e48155fSPierre-Yves MORDRET 
16459e48155fSPierre-Yves MORDRET 	ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
16469e48155fSPierre-Yves MORDRET 	if (ret)
16474e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16489e48155fSPierre-Yves MORDRET 
16499e48155fSPierre-Yves MORDRET 	timeout = wait_for_completion_timeout(&i2c_dev->complete,
16509e48155fSPierre-Yves MORDRET 					      i2c_dev->adap.timeout);
16519e48155fSPierre-Yves MORDRET 	ret = f7_msg->result;
16529e48155fSPierre-Yves MORDRET 	if (ret)
16534e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16549e48155fSPierre-Yves MORDRET 
16559e48155fSPierre-Yves MORDRET 	if (!timeout) {
16569e48155fSPierre-Yves MORDRET 		dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
16577ecc8cfdSPierre-Yves MORDRET 		if (i2c_dev->use_dma)
16587ecc8cfdSPierre-Yves MORDRET 			dmaengine_terminate_all(dma->chan_using);
16599e48155fSPierre-Yves MORDRET 		ret = -ETIMEDOUT;
16604e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16619e48155fSPierre-Yves MORDRET 	}
16629e48155fSPierre-Yves MORDRET 
16639e48155fSPierre-Yves MORDRET 	/* Check PEC */
16649e48155fSPierre-Yves MORDRET 	if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
16659e48155fSPierre-Yves MORDRET 		ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
16669e48155fSPierre-Yves MORDRET 		if (ret)
16674e7bca6fSPierre-Yves MORDRET 			goto pm_free;
16689e48155fSPierre-Yves MORDRET 	}
16699e48155fSPierre-Yves MORDRET 
16709e48155fSPierre-Yves MORDRET 	if (read_write && size != I2C_SMBUS_QUICK) {
16719e48155fSPierre-Yves MORDRET 		switch (size) {
16729e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BYTE:
16739e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BYTE_DATA:
16749e48155fSPierre-Yves MORDRET 			data->byte = f7_msg->smbus_buf[0];
16759e48155fSPierre-Yves MORDRET 		break;
16769e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_WORD_DATA:
16779e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_PROC_CALL:
16789e48155fSPierre-Yves MORDRET 			data->word = f7_msg->smbus_buf[0] |
16799e48155fSPierre-Yves MORDRET 				(f7_msg->smbus_buf[1] << 8);
16809e48155fSPierre-Yves MORDRET 		break;
16819e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BLOCK_DATA:
16829e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BLOCK_PROC_CALL:
16839e48155fSPierre-Yves MORDRET 		for (i = 0; i <= f7_msg->smbus_buf[0]; i++)
16849e48155fSPierre-Yves MORDRET 			data->block[i] = f7_msg->smbus_buf[i];
16859e48155fSPierre-Yves MORDRET 		break;
16869e48155fSPierre-Yves MORDRET 		default:
16879e48155fSPierre-Yves MORDRET 			dev_err(dev, "Unsupported smbus transaction\n");
16889e48155fSPierre-Yves MORDRET 			ret = -EINVAL;
16899e48155fSPierre-Yves MORDRET 		}
16909e48155fSPierre-Yves MORDRET 	}
16919e48155fSPierre-Yves MORDRET 
16924e7bca6fSPierre-Yves MORDRET pm_free:
16934e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(dev);
16944e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(dev);
16959e48155fSPierre-Yves MORDRET 	return ret;
16969e48155fSPierre-Yves MORDRET }
16979e48155fSPierre-Yves MORDRET 
1698*419be8e1SAlain Volmat static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev,
1699*419be8e1SAlain Volmat 				      bool enable)
1700*419be8e1SAlain Volmat {
1701*419be8e1SAlain Volmat 	void __iomem *base = i2c_dev->base;
1702*419be8e1SAlain Volmat 	u32 mask = STM32F7_I2C_CR1_WUPEN;
1703*419be8e1SAlain Volmat 
1704*419be8e1SAlain Volmat 	if (!i2c_dev->wakeup_src)
1705*419be8e1SAlain Volmat 		return;
1706*419be8e1SAlain Volmat 
1707*419be8e1SAlain Volmat 	if (enable) {
1708*419be8e1SAlain Volmat 		device_set_wakeup_enable(i2c_dev->dev, true);
1709*419be8e1SAlain Volmat 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
1710*419be8e1SAlain Volmat 	} else {
1711*419be8e1SAlain Volmat 		device_set_wakeup_enable(i2c_dev->dev, false);
1712*419be8e1SAlain Volmat 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
1713*419be8e1SAlain Volmat 	}
1714*419be8e1SAlain Volmat }
1715*419be8e1SAlain Volmat 
171660d609f3SPierre-Yves MORDRET static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
171760d609f3SPierre-Yves MORDRET {
171860d609f3SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
171960d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
172060d609f3SPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
172160d609f3SPierre-Yves MORDRET 	u32 oar1, oar2, mask;
172260d609f3SPierre-Yves MORDRET 	int id, ret;
172360d609f3SPierre-Yves MORDRET 
172460d609f3SPierre-Yves MORDRET 	if (slave->flags & I2C_CLIENT_PEC) {
172560d609f3SPierre-Yves MORDRET 		dev_err(dev, "SMBus PEC not supported in slave mode\n");
172660d609f3SPierre-Yves MORDRET 		return -EINVAL;
172760d609f3SPierre-Yves MORDRET 	}
172860d609f3SPierre-Yves MORDRET 
172960d609f3SPierre-Yves MORDRET 	if (stm32f7_i2c_is_slave_busy(i2c_dev)) {
173060d609f3SPierre-Yves MORDRET 		dev_err(dev, "Too much slave registered\n");
173160d609f3SPierre-Yves MORDRET 		return -EBUSY;
173260d609f3SPierre-Yves MORDRET 	}
173360d609f3SPierre-Yves MORDRET 
173460d609f3SPierre-Yves MORDRET 	ret = stm32f7_i2c_get_free_slave_id(i2c_dev, slave, &id);
173560d609f3SPierre-Yves MORDRET 	if (ret)
173660d609f3SPierre-Yves MORDRET 		return ret;
173760d609f3SPierre-Yves MORDRET 
17384e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(dev);
17394e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
174060d609f3SPierre-Yves MORDRET 		return ret;
174160d609f3SPierre-Yves MORDRET 
1742*419be8e1SAlain Volmat 	if (!stm32f7_i2c_is_slave_registered(i2c_dev))
1743*419be8e1SAlain Volmat 		stm32f7_i2c_enable_wakeup(i2c_dev, true);
1744*419be8e1SAlain Volmat 
174560d609f3SPierre-Yves MORDRET 	if (id == 0) {
174660d609f3SPierre-Yves MORDRET 		/* Configure Own Address 1 */
174760d609f3SPierre-Yves MORDRET 		oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
174860d609f3SPierre-Yves MORDRET 		oar1 &= ~STM32F7_I2C_OAR1_MASK;
174960d609f3SPierre-Yves MORDRET 		if (slave->flags & I2C_CLIENT_TEN) {
175060d609f3SPierre-Yves MORDRET 			oar1 |= STM32F7_I2C_OAR1_OA1_10(slave->addr);
175160d609f3SPierre-Yves MORDRET 			oar1 |= STM32F7_I2C_OAR1_OA1MODE;
175260d609f3SPierre-Yves MORDRET 		} else {
175360d609f3SPierre-Yves MORDRET 			oar1 |= STM32F7_I2C_OAR1_OA1_7(slave->addr);
175460d609f3SPierre-Yves MORDRET 		}
175560d609f3SPierre-Yves MORDRET 		oar1 |= STM32F7_I2C_OAR1_OA1EN;
175660d609f3SPierre-Yves MORDRET 		i2c_dev->slave[id] = slave;
175760d609f3SPierre-Yves MORDRET 		writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1);
175860d609f3SPierre-Yves MORDRET 	} else if (id == 1) {
175960d609f3SPierre-Yves MORDRET 		/* Configure Own Address 2 */
176060d609f3SPierre-Yves MORDRET 		oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
176160d609f3SPierre-Yves MORDRET 		oar2 &= ~STM32F7_I2C_OAR2_MASK;
176260d609f3SPierre-Yves MORDRET 		if (slave->flags & I2C_CLIENT_TEN) {
176360d609f3SPierre-Yves MORDRET 			ret = -EOPNOTSUPP;
17644e7bca6fSPierre-Yves MORDRET 			goto pm_free;
176560d609f3SPierre-Yves MORDRET 		}
176660d609f3SPierre-Yves MORDRET 
176760d609f3SPierre-Yves MORDRET 		oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
176860d609f3SPierre-Yves MORDRET 		oar2 |= STM32F7_I2C_OAR2_OA2EN;
176960d609f3SPierre-Yves MORDRET 		i2c_dev->slave[id] = slave;
177060d609f3SPierre-Yves MORDRET 		writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
177160d609f3SPierre-Yves MORDRET 	} else {
177260d609f3SPierre-Yves MORDRET 		ret = -ENODEV;
17734e7bca6fSPierre-Yves MORDRET 		goto pm_free;
177460d609f3SPierre-Yves MORDRET 	}
177560d609f3SPierre-Yves MORDRET 
177660d609f3SPierre-Yves MORDRET 	/* Enable ACK */
177760d609f3SPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, STM32F7_I2C_CR2_NACK);
177860d609f3SPierre-Yves MORDRET 
177960d609f3SPierre-Yves MORDRET 	/* Enable Address match interrupt, error interrupt and enable I2C  */
178060d609f3SPierre-Yves MORDRET 	mask = STM32F7_I2C_CR1_ADDRIE | STM32F7_I2C_CR1_ERRIE |
178160d609f3SPierre-Yves MORDRET 		STM32F7_I2C_CR1_PE;
178260d609f3SPierre-Yves MORDRET 	stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
178360d609f3SPierre-Yves MORDRET 
17844e7bca6fSPierre-Yves MORDRET 	ret = 0;
17854e7bca6fSPierre-Yves MORDRET pm_free:
1786*419be8e1SAlain Volmat 	if (!stm32f7_i2c_is_slave_registered(i2c_dev))
1787*419be8e1SAlain Volmat 		stm32f7_i2c_enable_wakeup(i2c_dev, false);
1788*419be8e1SAlain Volmat 
17894e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(dev);
17904e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(dev);
179160d609f3SPierre-Yves MORDRET 
179260d609f3SPierre-Yves MORDRET 	return ret;
179360d609f3SPierre-Yves MORDRET }
179460d609f3SPierre-Yves MORDRET 
179560d609f3SPierre-Yves MORDRET static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
179660d609f3SPierre-Yves MORDRET {
179760d609f3SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
179860d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
179960d609f3SPierre-Yves MORDRET 	u32 mask;
180060d609f3SPierre-Yves MORDRET 	int id, ret;
180160d609f3SPierre-Yves MORDRET 
180260d609f3SPierre-Yves MORDRET 	ret = stm32f7_i2c_get_slave_id(i2c_dev, slave, &id);
180360d609f3SPierre-Yves MORDRET 	if (ret)
180460d609f3SPierre-Yves MORDRET 		return ret;
180560d609f3SPierre-Yves MORDRET 
180660d609f3SPierre-Yves MORDRET 	WARN_ON(!i2c_dev->slave[id]);
180760d609f3SPierre-Yves MORDRET 
18084e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(i2c_dev->dev);
18094e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
18104e7bca6fSPierre-Yves MORDRET 		return ret;
18114e7bca6fSPierre-Yves MORDRET 
181260d609f3SPierre-Yves MORDRET 	if (id == 0) {
181360d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_OAR1_OA1EN;
181460d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
181560d609f3SPierre-Yves MORDRET 	} else {
181660d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_OAR2_OA2EN;
181760d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask);
181860d609f3SPierre-Yves MORDRET 	}
181960d609f3SPierre-Yves MORDRET 
182060d609f3SPierre-Yves MORDRET 	i2c_dev->slave[id] = NULL;
182160d609f3SPierre-Yves MORDRET 
1822*419be8e1SAlain Volmat 	if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
182360d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
1824*419be8e1SAlain Volmat 		stm32f7_i2c_enable_wakeup(i2c_dev, false);
1825*419be8e1SAlain Volmat 	}
18264e7bca6fSPierre-Yves MORDRET 
18274e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(i2c_dev->dev);
18284e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(i2c_dev->dev);
182960d609f3SPierre-Yves MORDRET 
183060d609f3SPierre-Yves MORDRET 	return 0;
183160d609f3SPierre-Yves MORDRET }
183260d609f3SPierre-Yves MORDRET 
1833cb944fb9SPierre-Yves MORDRET static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev,
1834cb944fb9SPierre-Yves MORDRET 					  struct stm32f7_i2c_dev *i2c_dev)
1835cb944fb9SPierre-Yves MORDRET {
1836cb944fb9SPierre-Yves MORDRET 	struct device_node *np = pdev->dev.of_node;
1837cb944fb9SPierre-Yves MORDRET 	int ret;
1838cb944fb9SPierre-Yves MORDRET 	u32 reg, mask;
1839cb944fb9SPierre-Yves MORDRET 
1840cb944fb9SPierre-Yves MORDRET 	i2c_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp");
1841cb944fb9SPierre-Yves MORDRET 	if (IS_ERR(i2c_dev->regmap)) {
1842cb944fb9SPierre-Yves MORDRET 		/* Optional */
1843cb944fb9SPierre-Yves MORDRET 		return 0;
1844cb944fb9SPierre-Yves MORDRET 	}
1845cb944fb9SPierre-Yves MORDRET 
1846cb944fb9SPierre-Yves MORDRET 	ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, &reg);
1847cb944fb9SPierre-Yves MORDRET 	if (ret)
1848cb944fb9SPierre-Yves MORDRET 		return ret;
1849cb944fb9SPierre-Yves MORDRET 
1850cb944fb9SPierre-Yves MORDRET 	ret = of_property_read_u32_index(np, "st,syscfg-fmp", 2, &mask);
1851cb944fb9SPierre-Yves MORDRET 	if (ret)
1852cb944fb9SPierre-Yves MORDRET 		return ret;
1853cb944fb9SPierre-Yves MORDRET 
1854cb944fb9SPierre-Yves MORDRET 	return regmap_update_bits(i2c_dev->regmap, reg, mask, mask);
1855cb944fb9SPierre-Yves MORDRET }
1856cb944fb9SPierre-Yves MORDRET 
1857aeb068c5SPierre-Yves MORDRET static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
1858aeb068c5SPierre-Yves MORDRET {
18599e48155fSPierre-Yves MORDRET 	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
18609e48155fSPierre-Yves MORDRET 		I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
18619e48155fSPierre-Yves MORDRET 		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
18629e48155fSPierre-Yves MORDRET 		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
1863473fbdf7SFabrice Gasnier 		I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
1864473fbdf7SFabrice Gasnier 		I2C_FUNC_SMBUS_I2C_BLOCK;
1865aeb068c5SPierre-Yves MORDRET }
1866aeb068c5SPierre-Yves MORDRET 
18672252c317SNishka Dasgupta static const struct i2c_algorithm stm32f7_i2c_algo = {
1868aeb068c5SPierre-Yves MORDRET 	.master_xfer = stm32f7_i2c_xfer,
18699e48155fSPierre-Yves MORDRET 	.smbus_xfer = stm32f7_i2c_smbus_xfer,
1870aeb068c5SPierre-Yves MORDRET 	.functionality = stm32f7_i2c_func,
187160d609f3SPierre-Yves MORDRET 	.reg_slave = stm32f7_i2c_reg_slave,
187260d609f3SPierre-Yves MORDRET 	.unreg_slave = stm32f7_i2c_unreg_slave,
1873aeb068c5SPierre-Yves MORDRET };
1874aeb068c5SPierre-Yves MORDRET 
1875aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_probe(struct platform_device *pdev)
1876aeb068c5SPierre-Yves MORDRET {
1877aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev;
1878aeb068c5SPierre-Yves MORDRET 	const struct stm32f7_i2c_setup *setup;
1879aeb068c5SPierre-Yves MORDRET 	struct resource *res;
188079b44995SFabrice Gasnier 	u32 clk_rate, rise_time, fall_time;
1881aeb068c5SPierre-Yves MORDRET 	struct i2c_adapter *adap;
1882aeb068c5SPierre-Yves MORDRET 	struct reset_control *rst;
18837ecc8cfdSPierre-Yves MORDRET 	dma_addr_t phy_addr;
188479b44995SFabrice Gasnier 	int irq_error, irq_event, ret;
1885aeb068c5SPierre-Yves MORDRET 
1886aeb068c5SPierre-Yves MORDRET 	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
1887aeb068c5SPierre-Yves MORDRET 	if (!i2c_dev)
1888aeb068c5SPierre-Yves MORDRET 		return -ENOMEM;
1889aeb068c5SPierre-Yves MORDRET 
1890aeb068c5SPierre-Yves MORDRET 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1891aeb068c5SPierre-Yves MORDRET 	i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
1892aeb068c5SPierre-Yves MORDRET 	if (IS_ERR(i2c_dev->base))
1893aeb068c5SPierre-Yves MORDRET 		return PTR_ERR(i2c_dev->base);
18947ecc8cfdSPierre-Yves MORDRET 	phy_addr = (dma_addr_t)res->start;
1895aeb068c5SPierre-Yves MORDRET 
189679b44995SFabrice Gasnier 	irq_event = platform_get_irq(pdev, 0);
189779b44995SFabrice Gasnier 	if (irq_event <= 0) {
189879b44995SFabrice Gasnier 		if (irq_event != -EPROBE_DEFER)
189979b44995SFabrice Gasnier 			dev_err(&pdev->dev, "Failed to get IRQ event: %d\n",
190079b44995SFabrice Gasnier 				irq_event);
190179b44995SFabrice Gasnier 		return irq_event ? : -ENOENT;
1902aeb068c5SPierre-Yves MORDRET 	}
1903aeb068c5SPierre-Yves MORDRET 
190479b44995SFabrice Gasnier 	irq_error = platform_get_irq(pdev, 1);
190579b44995SFabrice Gasnier 	if (irq_error <= 0) {
190679b44995SFabrice Gasnier 		if (irq_error != -EPROBE_DEFER)
190779b44995SFabrice Gasnier 			dev_err(&pdev->dev, "Failed to get IRQ error: %d\n",
190879b44995SFabrice Gasnier 				irq_error);
190979b44995SFabrice Gasnier 		return irq_error ? : -ENOENT;
1910aeb068c5SPierre-Yves MORDRET 	}
1911aeb068c5SPierre-Yves MORDRET 
1912*419be8e1SAlain Volmat 	i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node,
1913*419be8e1SAlain Volmat 						    "wakeup-source");
1914*419be8e1SAlain Volmat 
1915aeb068c5SPierre-Yves MORDRET 	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
1916aeb068c5SPierre-Yves MORDRET 	if (IS_ERR(i2c_dev->clk)) {
1917aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Error: Missing controller clock\n");
1918aeb068c5SPierre-Yves MORDRET 		return PTR_ERR(i2c_dev->clk);
1919aeb068c5SPierre-Yves MORDRET 	}
19204e7bca6fSPierre-Yves MORDRET 
1921aeb068c5SPierre-Yves MORDRET 	ret = clk_prepare_enable(i2c_dev->clk);
1922aeb068c5SPierre-Yves MORDRET 	if (ret) {
1923aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
1924aeb068c5SPierre-Yves MORDRET 		return ret;
1925aeb068c5SPierre-Yves MORDRET 	}
1926aeb068c5SPierre-Yves MORDRET 
1927aeb068c5SPierre-Yves MORDRET 	i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1928aeb068c5SPierre-Yves MORDRET 	ret = device_property_read_u32(&pdev->dev, "clock-frequency",
1929aeb068c5SPierre-Yves MORDRET 				       &clk_rate);
1930cb944fb9SPierre-Yves MORDRET 	if (!ret && clk_rate >= 1000000) {
1931aeb068c5SPierre-Yves MORDRET 		i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
1932cb944fb9SPierre-Yves MORDRET 		ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
1933cb944fb9SPierre-Yves MORDRET 		if (ret)
1934cb944fb9SPierre-Yves MORDRET 			goto clk_free;
1935cb944fb9SPierre-Yves MORDRET 	} else if (!ret && clk_rate >= 400000) {
1936aeb068c5SPierre-Yves MORDRET 		i2c_dev->speed = STM32_I2C_SPEED_FAST;
1937cb944fb9SPierre-Yves MORDRET 	} else if (!ret && clk_rate >= 100000) {
1938aeb068c5SPierre-Yves MORDRET 		i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1939cb944fb9SPierre-Yves MORDRET 	}
1940aeb068c5SPierre-Yves MORDRET 
1941aeb068c5SPierre-Yves MORDRET 	rst = devm_reset_control_get(&pdev->dev, NULL);
1942aeb068c5SPierre-Yves MORDRET 	if (IS_ERR(rst)) {
1943aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Error: Missing controller reset\n");
1944aeb068c5SPierre-Yves MORDRET 		ret = PTR_ERR(rst);
1945aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1946aeb068c5SPierre-Yves MORDRET 	}
1947aeb068c5SPierre-Yves MORDRET 	reset_control_assert(rst);
1948aeb068c5SPierre-Yves MORDRET 	udelay(2);
1949aeb068c5SPierre-Yves MORDRET 	reset_control_deassert(rst);
1950aeb068c5SPierre-Yves MORDRET 
1951aeb068c5SPierre-Yves MORDRET 	i2c_dev->dev = &pdev->dev;
1952aeb068c5SPierre-Yves MORDRET 
19537ecc8cfdSPierre-Yves MORDRET 	ret = devm_request_threaded_irq(&pdev->dev, irq_event,
19547ecc8cfdSPierre-Yves MORDRET 					stm32f7_i2c_isr_event,
19557ecc8cfdSPierre-Yves MORDRET 					stm32f7_i2c_isr_event_thread,
19567ecc8cfdSPierre-Yves MORDRET 					IRQF_ONESHOT,
1957aeb068c5SPierre-Yves MORDRET 					pdev->name, i2c_dev);
1958aeb068c5SPierre-Yves MORDRET 	if (ret) {
1959aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Failed to request irq event %i\n",
1960aeb068c5SPierre-Yves MORDRET 			irq_event);
1961aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1962aeb068c5SPierre-Yves MORDRET 	}
1963aeb068c5SPierre-Yves MORDRET 
1964aeb068c5SPierre-Yves MORDRET 	ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
1965aeb068c5SPierre-Yves MORDRET 			       pdev->name, i2c_dev);
1966aeb068c5SPierre-Yves MORDRET 	if (ret) {
1967aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Failed to request irq error %i\n",
1968aeb068c5SPierre-Yves MORDRET 			irq_error);
1969aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1970aeb068c5SPierre-Yves MORDRET 	}
1971aeb068c5SPierre-Yves MORDRET 
1972aeb068c5SPierre-Yves MORDRET 	setup = of_device_get_match_data(&pdev->dev);
1973771b7bf0SPierre-Yves MORDRET 	if (!setup) {
1974771b7bf0SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Can't get device data\n");
1975771b7bf0SPierre-Yves MORDRET 		ret = -ENODEV;
1976771b7bf0SPierre-Yves MORDRET 		goto clk_free;
1977771b7bf0SPierre-Yves MORDRET 	}
1978463a9215SPierre-Yves MORDRET 	i2c_dev->setup = *setup;
1979aeb068c5SPierre-Yves MORDRET 
1980aeb068c5SPierre-Yves MORDRET 	ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-rising-time-ns",
1981aeb068c5SPierre-Yves MORDRET 				       &rise_time);
1982aeb068c5SPierre-Yves MORDRET 	if (!ret)
1983463a9215SPierre-Yves MORDRET 		i2c_dev->setup.rise_time = rise_time;
1984aeb068c5SPierre-Yves MORDRET 
1985aeb068c5SPierre-Yves MORDRET 	ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-falling-time-ns",
1986aeb068c5SPierre-Yves MORDRET 				       &fall_time);
1987aeb068c5SPierre-Yves MORDRET 	if (!ret)
1988463a9215SPierre-Yves MORDRET 		i2c_dev->setup.fall_time = fall_time;
1989aeb068c5SPierre-Yves MORDRET 
1990463a9215SPierre-Yves MORDRET 	ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
1991aeb068c5SPierre-Yves MORDRET 	if (ret)
1992aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1993aeb068c5SPierre-Yves MORDRET 
1994aeb068c5SPierre-Yves MORDRET 	adap = &i2c_dev->adap;
1995aeb068c5SPierre-Yves MORDRET 	i2c_set_adapdata(adap, i2c_dev);
1996aeb068c5SPierre-Yves MORDRET 	snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
1997aeb068c5SPierre-Yves MORDRET 		 &res->start);
1998aeb068c5SPierre-Yves MORDRET 	adap->owner = THIS_MODULE;
1999aeb068c5SPierre-Yves MORDRET 	adap->timeout = 2 * HZ;
2000aeb068c5SPierre-Yves MORDRET 	adap->retries = 3;
2001aeb068c5SPierre-Yves MORDRET 	adap->algo = &stm32f7_i2c_algo;
2002aeb068c5SPierre-Yves MORDRET 	adap->dev.parent = &pdev->dev;
2003aeb068c5SPierre-Yves MORDRET 	adap->dev.of_node = pdev->dev.of_node;
2004aeb068c5SPierre-Yves MORDRET 
2005aeb068c5SPierre-Yves MORDRET 	init_completion(&i2c_dev->complete);
2006aeb068c5SPierre-Yves MORDRET 
20077ecc8cfdSPierre-Yves MORDRET 	/* Init DMA config if supported */
20087ecc8cfdSPierre-Yves MORDRET 	i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
20097ecc8cfdSPierre-Yves MORDRET 					     STM32F7_I2C_TXDR,
20107ecc8cfdSPierre-Yves MORDRET 					     STM32F7_I2C_RXDR);
2011d77eceb2SAlain Volmat 	if (PTR_ERR(i2c_dev->dma) == -ENODEV)
2012d77eceb2SAlain Volmat 		i2c_dev->dma = NULL;
2013d77eceb2SAlain Volmat 	else if (IS_ERR(i2c_dev->dma)) {
2014d77eceb2SAlain Volmat 		ret = PTR_ERR(i2c_dev->dma);
2015d77eceb2SAlain Volmat 		if (ret != -EPROBE_DEFER)
2016d77eceb2SAlain Volmat 			dev_err(&pdev->dev,
2017d77eceb2SAlain Volmat 				"Failed to request dma error %i\n", ret);
2018d77eceb2SAlain Volmat 		goto clk_free;
2019d77eceb2SAlain Volmat 	}
20207ecc8cfdSPierre-Yves MORDRET 
2021*419be8e1SAlain Volmat 	if (i2c_dev->wakeup_src) {
2022*419be8e1SAlain Volmat 		device_set_wakeup_capable(i2c_dev->dev, true);
2023*419be8e1SAlain Volmat 
2024*419be8e1SAlain Volmat 		ret = dev_pm_set_wake_irq(i2c_dev->dev, irq_event);
2025*419be8e1SAlain Volmat 		if (ret) {
2026*419be8e1SAlain Volmat 			dev_err(i2c_dev->dev, "Failed to set wake up irq\n");
2027*419be8e1SAlain Volmat 			goto clr_wakeup_capable;
2028*419be8e1SAlain Volmat 		}
2029*419be8e1SAlain Volmat 	}
2030*419be8e1SAlain Volmat 
2031aeb068c5SPierre-Yves MORDRET 	platform_set_drvdata(pdev, i2c_dev);
2032aeb068c5SPierre-Yves MORDRET 
20334e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_autosuspend_delay(i2c_dev->dev,
20344e7bca6fSPierre-Yves MORDRET 					 STM32F7_AUTOSUSPEND_DELAY);
20354e7bca6fSPierre-Yves MORDRET 	pm_runtime_use_autosuspend(i2c_dev->dev);
20364e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_active(i2c_dev->dev);
20374e7bca6fSPierre-Yves MORDRET 	pm_runtime_enable(i2c_dev->dev);
20384e7bca6fSPierre-Yves MORDRET 
20394e7bca6fSPierre-Yves MORDRET 	pm_runtime_get_noresume(&pdev->dev);
20404e7bca6fSPierre-Yves MORDRET 
20414e7bca6fSPierre-Yves MORDRET 	stm32f7_i2c_hw_config(i2c_dev);
20424e7bca6fSPierre-Yves MORDRET 
20434e7bca6fSPierre-Yves MORDRET 	ret = i2c_add_adapter(adap);
20444e7bca6fSPierre-Yves MORDRET 	if (ret)
20454e7bca6fSPierre-Yves MORDRET 		goto pm_disable;
2046aeb068c5SPierre-Yves MORDRET 
2047aeb068c5SPierre-Yves MORDRET 	dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
2048aeb068c5SPierre-Yves MORDRET 
20494e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(i2c_dev->dev);
20504e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(i2c_dev->dev);
20514e7bca6fSPierre-Yves MORDRET 
2052aeb068c5SPierre-Yves MORDRET 	return 0;
2053aeb068c5SPierre-Yves MORDRET 
20544e7bca6fSPierre-Yves MORDRET pm_disable:
20554e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_noidle(i2c_dev->dev);
20564e7bca6fSPierre-Yves MORDRET 	pm_runtime_disable(i2c_dev->dev);
20574e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_suspended(i2c_dev->dev);
20584e7bca6fSPierre-Yves MORDRET 	pm_runtime_dont_use_autosuspend(i2c_dev->dev);
20594e7bca6fSPierre-Yves MORDRET 
2060*419be8e1SAlain Volmat 	if (i2c_dev->wakeup_src)
2061*419be8e1SAlain Volmat 		dev_pm_clear_wake_irq(i2c_dev->dev);
2062*419be8e1SAlain Volmat 
2063*419be8e1SAlain Volmat clr_wakeup_capable:
2064*419be8e1SAlain Volmat 	if (i2c_dev->wakeup_src)
2065*419be8e1SAlain Volmat 		device_set_wakeup_capable(i2c_dev->dev, false);
2066*419be8e1SAlain Volmat 
206753aaaa5dSAlain Volmat 	if (i2c_dev->dma) {
206853aaaa5dSAlain Volmat 		stm32_i2c_dma_free(i2c_dev->dma);
206953aaaa5dSAlain Volmat 		i2c_dev->dma = NULL;
207053aaaa5dSAlain Volmat 	}
207153aaaa5dSAlain Volmat 
2072aeb068c5SPierre-Yves MORDRET clk_free:
2073aeb068c5SPierre-Yves MORDRET 	clk_disable_unprepare(i2c_dev->clk);
2074aeb068c5SPierre-Yves MORDRET 
2075aeb068c5SPierre-Yves MORDRET 	return ret;
2076aeb068c5SPierre-Yves MORDRET }
2077aeb068c5SPierre-Yves MORDRET 
2078aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_remove(struct platform_device *pdev)
2079aeb068c5SPierre-Yves MORDRET {
2080aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
2081aeb068c5SPierre-Yves MORDRET 
2082aeb068c5SPierre-Yves MORDRET 	i2c_del_adapter(&i2c_dev->adap);
20834e7bca6fSPierre-Yves MORDRET 	pm_runtime_get_sync(i2c_dev->dev);
2084aeb068c5SPierre-Yves MORDRET 
2085*419be8e1SAlain Volmat 	if (i2c_dev->wakeup_src) {
2086*419be8e1SAlain Volmat 		dev_pm_clear_wake_irq(i2c_dev->dev);
2087*419be8e1SAlain Volmat 		/*
2088*419be8e1SAlain Volmat 		 * enforce that wakeup is disabled and that the device
2089*419be8e1SAlain Volmat 		 * is marked as non wakeup capable
2090*419be8e1SAlain Volmat 		 */
2091*419be8e1SAlain Volmat 		device_init_wakeup(i2c_dev->dev, false);
2092*419be8e1SAlain Volmat 	}
2093*419be8e1SAlain Volmat 
20944e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_noidle(i2c_dev->dev);
20954e7bca6fSPierre-Yves MORDRET 	pm_runtime_disable(i2c_dev->dev);
20964e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_suspended(i2c_dev->dev);
20974e7bca6fSPierre-Yves MORDRET 	pm_runtime_dont_use_autosuspend(i2c_dev->dev);
2098aeb068c5SPierre-Yves MORDRET 
209953aaaa5dSAlain Volmat 	if (i2c_dev->dma) {
210053aaaa5dSAlain Volmat 		stm32_i2c_dma_free(i2c_dev->dma);
210153aaaa5dSAlain Volmat 		i2c_dev->dma = NULL;
210253aaaa5dSAlain Volmat 	}
210353aaaa5dSAlain Volmat 
210453aaaa5dSAlain Volmat 	clk_disable_unprepare(i2c_dev->clk);
210553aaaa5dSAlain Volmat 
2106aeb068c5SPierre-Yves MORDRET 	return 0;
2107aeb068c5SPierre-Yves MORDRET }
2108aeb068c5SPierre-Yves MORDRET 
2109ea6dd25dSAlain Volmat static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev)
21104e7bca6fSPierre-Yves MORDRET {
21114e7bca6fSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
21124e7bca6fSPierre-Yves MORDRET 
21134e7bca6fSPierre-Yves MORDRET 	if (!stm32f7_i2c_is_slave_registered(i2c_dev))
21144e7bca6fSPierre-Yves MORDRET 		clk_disable_unprepare(i2c_dev->clk);
21154e7bca6fSPierre-Yves MORDRET 
21164e7bca6fSPierre-Yves MORDRET 	return 0;
21174e7bca6fSPierre-Yves MORDRET }
21184e7bca6fSPierre-Yves MORDRET 
2119ea6dd25dSAlain Volmat static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev)
21204e7bca6fSPierre-Yves MORDRET {
21214e7bca6fSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
21224e7bca6fSPierre-Yves MORDRET 	int ret;
21234e7bca6fSPierre-Yves MORDRET 
21244e7bca6fSPierre-Yves MORDRET 	if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
21254e7bca6fSPierre-Yves MORDRET 		ret = clk_prepare_enable(i2c_dev->clk);
21264e7bca6fSPierre-Yves MORDRET 		if (ret) {
21274e7bca6fSPierre-Yves MORDRET 			dev_err(dev, "failed to prepare_enable clock\n");
21284e7bca6fSPierre-Yves MORDRET 			return ret;
21294e7bca6fSPierre-Yves MORDRET 		}
21304e7bca6fSPierre-Yves MORDRET 	}
21314e7bca6fSPierre-Yves MORDRET 
21324e7bca6fSPierre-Yves MORDRET 	return 0;
21334e7bca6fSPierre-Yves MORDRET }
2134ea6dd25dSAlain Volmat 
2135*419be8e1SAlain Volmat #ifdef CONFIG_PM_SLEEP
2136*419be8e1SAlain Volmat static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev)
2137ea6dd25dSAlain Volmat {
2138ea6dd25dSAlain Volmat 	int ret;
2139ea6dd25dSAlain Volmat 	struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs;
2140ea6dd25dSAlain Volmat 
2141ea6dd25dSAlain Volmat 	ret = pm_runtime_get_sync(i2c_dev->dev);
2142ea6dd25dSAlain Volmat 	if (ret < 0)
2143ea6dd25dSAlain Volmat 		return ret;
2144ea6dd25dSAlain Volmat 
2145ea6dd25dSAlain Volmat 	backup_regs->cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1);
2146ea6dd25dSAlain Volmat 	backup_regs->cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
2147ea6dd25dSAlain Volmat 	backup_regs->oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
2148ea6dd25dSAlain Volmat 	backup_regs->oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
2149ea6dd25dSAlain Volmat 	backup_regs->pecr = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
2150ea6dd25dSAlain Volmat 	backup_regs->tmgr = readl_relaxed(i2c_dev->base + STM32F7_I2C_TIMINGR);
2151ea6dd25dSAlain Volmat 
2152ea6dd25dSAlain Volmat 	pm_runtime_put_sync(i2c_dev->dev);
2153ea6dd25dSAlain Volmat 
2154ea6dd25dSAlain Volmat 	return ret;
2155ea6dd25dSAlain Volmat }
2156ea6dd25dSAlain Volmat 
2157*419be8e1SAlain Volmat static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev)
2158ea6dd25dSAlain Volmat {
2159ea6dd25dSAlain Volmat 	u32 cr1;
2160ea6dd25dSAlain Volmat 	int ret;
2161ea6dd25dSAlain Volmat 	struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs;
2162ea6dd25dSAlain Volmat 
2163ea6dd25dSAlain Volmat 	ret = pm_runtime_get_sync(i2c_dev->dev);
2164ea6dd25dSAlain Volmat 	if (ret < 0)
2165ea6dd25dSAlain Volmat 		return ret;
2166ea6dd25dSAlain Volmat 
2167ea6dd25dSAlain Volmat 	cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1);
2168ea6dd25dSAlain Volmat 	if (cr1 & STM32F7_I2C_CR1_PE)
2169ea6dd25dSAlain Volmat 		stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
2170ea6dd25dSAlain Volmat 				     STM32F7_I2C_CR1_PE);
2171ea6dd25dSAlain Volmat 
2172ea6dd25dSAlain Volmat 	writel_relaxed(backup_regs->tmgr, i2c_dev->base + STM32F7_I2C_TIMINGR);
2173ea6dd25dSAlain Volmat 	writel_relaxed(backup_regs->cr1 & ~STM32F7_I2C_CR1_PE,
2174ea6dd25dSAlain Volmat 		       i2c_dev->base + STM32F7_I2C_CR1);
2175ea6dd25dSAlain Volmat 	if (backup_regs->cr1 & STM32F7_I2C_CR1_PE)
2176ea6dd25dSAlain Volmat 		stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
2177ea6dd25dSAlain Volmat 				     STM32F7_I2C_CR1_PE);
2178ea6dd25dSAlain Volmat 	writel_relaxed(backup_regs->cr2, i2c_dev->base + STM32F7_I2C_CR2);
2179ea6dd25dSAlain Volmat 	writel_relaxed(backup_regs->oar1, i2c_dev->base + STM32F7_I2C_OAR1);
2180ea6dd25dSAlain Volmat 	writel_relaxed(backup_regs->oar2, i2c_dev->base + STM32F7_I2C_OAR2);
2181ea6dd25dSAlain Volmat 	writel_relaxed(backup_regs->pecr, i2c_dev->base + STM32F7_I2C_PECR);
2182ea6dd25dSAlain Volmat 
2183ea6dd25dSAlain Volmat 	pm_runtime_put_sync(i2c_dev->dev);
2184ea6dd25dSAlain Volmat 
2185ea6dd25dSAlain Volmat 	return ret;
2186ea6dd25dSAlain Volmat }
2187ea6dd25dSAlain Volmat 
2188*419be8e1SAlain Volmat static int stm32f7_i2c_suspend(struct device *dev)
2189ea6dd25dSAlain Volmat {
2190ea6dd25dSAlain Volmat 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
2191ea6dd25dSAlain Volmat 	int ret;
2192ea6dd25dSAlain Volmat 
2193ea6dd25dSAlain Volmat 	i2c_mark_adapter_suspended(&i2c_dev->adap);
2194*419be8e1SAlain Volmat 
2195*419be8e1SAlain Volmat 	if (!device_may_wakeup(dev) && !dev->power.wakeup_path) {
2196ea6dd25dSAlain Volmat 		ret = stm32f7_i2c_regs_backup(i2c_dev);
2197ea6dd25dSAlain Volmat 		if (ret < 0) {
2198ea6dd25dSAlain Volmat 			i2c_mark_adapter_resumed(&i2c_dev->adap);
2199ea6dd25dSAlain Volmat 			return ret;
2200ea6dd25dSAlain Volmat 		}
2201ea6dd25dSAlain Volmat 
2202ea6dd25dSAlain Volmat 		pinctrl_pm_select_sleep_state(dev);
2203ea6dd25dSAlain Volmat 		pm_runtime_force_suspend(dev);
2204*419be8e1SAlain Volmat 	}
2205ea6dd25dSAlain Volmat 
2206ea6dd25dSAlain Volmat 	return 0;
2207ea6dd25dSAlain Volmat }
2208ea6dd25dSAlain Volmat 
2209*419be8e1SAlain Volmat static int stm32f7_i2c_resume(struct device *dev)
2210ea6dd25dSAlain Volmat {
2211ea6dd25dSAlain Volmat 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
2212ea6dd25dSAlain Volmat 	int ret;
2213ea6dd25dSAlain Volmat 
2214*419be8e1SAlain Volmat 	if (!device_may_wakeup(dev) && !dev->power.wakeup_path) {
2215ea6dd25dSAlain Volmat 		ret = pm_runtime_force_resume(dev);
2216ea6dd25dSAlain Volmat 		if (ret < 0)
2217ea6dd25dSAlain Volmat 			return ret;
2218ea6dd25dSAlain Volmat 		pinctrl_pm_select_default_state(dev);
2219ea6dd25dSAlain Volmat 
2220ea6dd25dSAlain Volmat 		ret = stm32f7_i2c_regs_restore(i2c_dev);
2221ea6dd25dSAlain Volmat 		if (ret < 0)
2222ea6dd25dSAlain Volmat 			return ret;
2223*419be8e1SAlain Volmat 	}
2224*419be8e1SAlain Volmat 
2225ea6dd25dSAlain Volmat 	i2c_mark_adapter_resumed(&i2c_dev->adap);
2226ea6dd25dSAlain Volmat 
2227ea6dd25dSAlain Volmat 	return 0;
2228ea6dd25dSAlain Volmat }
2229*419be8e1SAlain Volmat #endif
22304e7bca6fSPierre-Yves MORDRET 
22314e7bca6fSPierre-Yves MORDRET static const struct dev_pm_ops stm32f7_i2c_pm_ops = {
22324e7bca6fSPierre-Yves MORDRET 	SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend,
22334e7bca6fSPierre-Yves MORDRET 			   stm32f7_i2c_runtime_resume, NULL)
2234ea6dd25dSAlain Volmat 	SET_SYSTEM_SLEEP_PM_OPS(stm32f7_i2c_suspend, stm32f7_i2c_resume)
22354e7bca6fSPierre-Yves MORDRET };
22364e7bca6fSPierre-Yves MORDRET 
2237aeb068c5SPierre-Yves MORDRET static const struct of_device_id stm32f7_i2c_match[] = {
2238aeb068c5SPierre-Yves MORDRET 	{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
2239aeb068c5SPierre-Yves MORDRET 	{},
2240aeb068c5SPierre-Yves MORDRET };
2241aeb068c5SPierre-Yves MORDRET MODULE_DEVICE_TABLE(of, stm32f7_i2c_match);
2242aeb068c5SPierre-Yves MORDRET 
2243aeb068c5SPierre-Yves MORDRET static struct platform_driver stm32f7_i2c_driver = {
2244aeb068c5SPierre-Yves MORDRET 	.driver = {
2245aeb068c5SPierre-Yves MORDRET 		.name = "stm32f7-i2c",
2246aeb068c5SPierre-Yves MORDRET 		.of_match_table = stm32f7_i2c_match,
22474e7bca6fSPierre-Yves MORDRET 		.pm = &stm32f7_i2c_pm_ops,
2248aeb068c5SPierre-Yves MORDRET 	},
2249aeb068c5SPierre-Yves MORDRET 	.probe = stm32f7_i2c_probe,
2250aeb068c5SPierre-Yves MORDRET 	.remove = stm32f7_i2c_remove,
2251aeb068c5SPierre-Yves MORDRET };
2252aeb068c5SPierre-Yves MORDRET 
2253aeb068c5SPierre-Yves MORDRET module_platform_driver(stm32f7_i2c_driver);
2254aeb068c5SPierre-Yves MORDRET 
2255aeb068c5SPierre-Yves MORDRET MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>");
2256aeb068c5SPierre-Yves MORDRET MODULE_DESCRIPTION("STMicroelectronics STM32F7 I2C driver");
2257aeb068c5SPierre-Yves MORDRET MODULE_LICENSE("GPL v2");
2258