xref: /openbmc/linux/drivers/i2c/busses/i2c-stm32f7.c (revision d77eceb2)
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>
32cb944fb9SPierre-Yves MORDRET #include <linux/regmap.h>
33aeb068c5SPierre-Yves MORDRET #include <linux/reset.h>
34aeb068c5SPierre-Yves MORDRET #include <linux/slab.h>
35aeb068c5SPierre-Yves MORDRET 
36aeb068c5SPierre-Yves MORDRET #include "i2c-stm32.h"
37aeb068c5SPierre-Yves MORDRET 
38aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C registers */
39aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1				0x00
40aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2				0x04
4160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1			0x08
4260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2			0x0C
439e48155fSPierre-Yves MORDRET #define STM32F7_I2C_PECR			0x20
44aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR			0x10
45aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR				0x18
46aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR				0x1C
47aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_RXDR			0x24
48aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TXDR			0x28
49aeb068c5SPierre-Yves MORDRET 
50aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C control 1 */
519e48155fSPierre-Yves MORDRET #define STM32F7_I2C_CR1_PECEN			BIT(23)
5260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_CR1_SBC			BIT(16)
537ecc8cfdSPierre-Yves MORDRET #define STM32F7_I2C_CR1_RXDMAEN			BIT(15)
547ecc8cfdSPierre-Yves MORDRET #define STM32F7_I2C_CR1_TXDMAEN			BIT(14)
55aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_ANFOFF			BIT(12)
56aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_ERRIE			BIT(7)
57aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_TCIE			BIT(6)
58aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_STOPIE			BIT(5)
59aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_NACKIE			BIT(4)
60aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_ADDRIE			BIT(3)
61aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_RXIE			BIT(2)
62aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_TXIE			BIT(1)
63aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR1_PE			BIT(0)
64aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ALL_IRQ_MASK		(STM32F7_I2C_CR1_ERRIE \
65aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_TCIE \
66aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_STOPIE \
67aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_NACKIE \
68aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_RXIE \
69aeb068c5SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_TXIE)
7060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_XFER_IRQ_MASK		(STM32F7_I2C_CR1_TCIE \
7160d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_STOPIE \
7260d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_NACKIE \
7360d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_RXIE \
7460d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_CR1_TXIE)
75aeb068c5SPierre-Yves MORDRET 
76aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C control 2 */
779e48155fSPierre-Yves MORDRET #define STM32F7_I2C_CR2_PECBYTE			BIT(26)
78aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_RELOAD			BIT(24)
79aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_NBYTES_MASK		GENMASK(23, 16)
80aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_NBYTES(n)		(((n) & 0xff) << 16)
81aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_NACK			BIT(15)
82aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_STOP			BIT(14)
83aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_START			BIT(13)
848c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_HEAD10R			BIT(12)
858c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_ADD10			BIT(11)
86aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_RD_WRN			BIT(10)
878c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD10_MASK		GENMASK(9, 0)
888c7ecc99SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD10(n)		(((n) & \
898c7ecc99SPierre-Yves MORDRET 						STM32F7_I2C_CR2_SADD10_MASK))
90aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD7_MASK		GENMASK(7, 1)
91aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_CR2_SADD7(n)		(((n) & 0x7f) << 1)
92aeb068c5SPierre-Yves MORDRET 
9360d609f3SPierre-Yves MORDRET /* STM32F7 I2C Own Address 1 */
9460d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1EN			BIT(15)
9560d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1MODE		BIT(10)
9660d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_10_MASK		GENMASK(9, 0)
9760d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_10(n)		(((n) & \
9860d609f3SPierre-Yves MORDRET 						STM32F7_I2C_OAR1_OA1_10_MASK))
9960d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_7_MASK		GENMASK(7, 1)
10060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_OA1_7(n)		(((n) & 0x7f) << 1)
10160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR1_MASK			(STM32F7_I2C_OAR1_OA1_7_MASK \
10260d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR1_OA1_10_MASK \
10360d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR1_OA1EN \
10460d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR1_OA1MODE)
10560d609f3SPierre-Yves MORDRET 
10660d609f3SPierre-Yves MORDRET /* STM32F7 I2C Own Address 2 */
10760d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2EN			BIT(15)
10860d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2MSK_MASK		GENMASK(10, 8)
10960d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2MSK(n)		(((n) & 0x7) << 8)
11060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2_7_MASK		GENMASK(7, 1)
11160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_OA2_7(n)		(((n) & 0x7f) << 1)
11260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_OAR2_MASK			(STM32F7_I2C_OAR2_OA2MSK_MASK \
11360d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR2_OA2_7_MASK \
11460d609f3SPierre-Yves MORDRET 						| STM32F7_I2C_OAR2_OA2EN)
11560d609f3SPierre-Yves MORDRET 
116aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C Interrupt Status */
11760d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ADDCODE_MASK		GENMASK(23, 17)
11860d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ADDCODE_GET(n) \
11960d609f3SPierre-Yves MORDRET 				(((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17)
12060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_DIR			BIT(16)
121aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_BUSY			BIT(15)
1229e48155fSPierre-Yves MORDRET #define STM32F7_I2C_ISR_PECERR			BIT(11)
123aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ARLO			BIT(9)
124aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_BERR			BIT(8)
125aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TCR			BIT(7)
126aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TC			BIT(6)
127aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_STOPF			BIT(5)
128aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_NACKF			BIT(4)
12960d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_ADDR			BIT(3)
130aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_RXNE			BIT(2)
131aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TXIS			BIT(1)
13260d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ISR_TXE			BIT(0)
133aeb068c5SPierre-Yves MORDRET 
134aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C Interrupt Clear */
1359e48155fSPierre-Yves MORDRET #define STM32F7_I2C_ICR_PECCF			BIT(11)
136aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_ARLOCF			BIT(9)
137aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_BERRCF			BIT(8)
138aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_STOPCF			BIT(5)
139aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ICR_NACKCF			BIT(4)
14060d609f3SPierre-Yves MORDRET #define STM32F7_I2C_ICR_ADDRCF			BIT(3)
141aeb068c5SPierre-Yves MORDRET 
142aeb068c5SPierre-Yves MORDRET /* STM32F7 I2C Timing */
143aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_PRESC(n)		(((n) & 0xf) << 28)
144aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SCLDEL(n)		(((n) & 0xf) << 20)
145aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SDADEL(n)		(((n) & 0xf) << 16)
146aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SCLH(n)		(((n) & 0xff) << 8)
147aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_TIMINGR_SCLL(n)		((n) & 0xff)
148aeb068c5SPierre-Yves MORDRET 
149aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_MAX_LEN			0xff
1507ecc8cfdSPierre-Yves MORDRET #define STM32F7_I2C_DMA_LEN_MIN			0x16
15160d609f3SPierre-Yves MORDRET #define STM32F7_I2C_MAX_SLAVE			0x2
152aeb068c5SPierre-Yves MORDRET 
153aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_DNF_DEFAULT			0
154aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_DNF_MAX			16
155aeb068c5SPierre-Yves MORDRET 
156aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ANALOG_FILTER_ENABLE	1
157aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ANALOG_FILTER_DELAY_MIN	50	/* ns */
158aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_ANALOG_FILTER_DELAY_MAX	260	/* ns */
159aeb068c5SPierre-Yves MORDRET 
160aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_RISE_TIME_DEFAULT		25	/* ns */
161aeb068c5SPierre-Yves MORDRET #define STM32F7_I2C_FALL_TIME_DEFAULT		10	/* ns */
162aeb068c5SPierre-Yves MORDRET 
163aeb068c5SPierre-Yves MORDRET #define STM32F7_PRESC_MAX			BIT(4)
164aeb068c5SPierre-Yves MORDRET #define STM32F7_SCLDEL_MAX			BIT(4)
165aeb068c5SPierre-Yves MORDRET #define STM32F7_SDADEL_MAX			BIT(4)
166aeb068c5SPierre-Yves MORDRET #define STM32F7_SCLH_MAX			BIT(8)
167aeb068c5SPierre-Yves MORDRET #define STM32F7_SCLL_MAX			BIT(8)
168aeb068c5SPierre-Yves MORDRET 
1694e7bca6fSPierre-Yves MORDRET #define STM32F7_AUTOSUSPEND_DELAY		(HZ / 100)
1704e7bca6fSPierre-Yves MORDRET 
171aeb068c5SPierre-Yves MORDRET /**
172aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_spec - private i2c specification timing
173aeb068c5SPierre-Yves MORDRET  * @rate: I2C bus speed (Hz)
174aeb068c5SPierre-Yves MORDRET  * @rate_min: 80% of I2C bus speed (Hz)
175aeb068c5SPierre-Yves MORDRET  * @rate_max: 100% of I2C bus speed (Hz)
176aeb068c5SPierre-Yves MORDRET  * @fall_max: Max fall time of both SDA and SCL signals (ns)
177aeb068c5SPierre-Yves MORDRET  * @rise_max: Max rise time of both SDA and SCL signals (ns)
178aeb068c5SPierre-Yves MORDRET  * @hddat_min: Min data hold time (ns)
179aeb068c5SPierre-Yves MORDRET  * @vddat_max: Max data valid time (ns)
180aeb068c5SPierre-Yves MORDRET  * @sudat_min: Min data setup time (ns)
181aeb068c5SPierre-Yves MORDRET  * @l_min: Min low period of the SCL clock (ns)
182aeb068c5SPierre-Yves MORDRET  * @h_min: Min high period of the SCL clock (ns)
183aeb068c5SPierre-Yves MORDRET  */
184aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_spec {
185aeb068c5SPierre-Yves MORDRET 	u32 rate;
186aeb068c5SPierre-Yves MORDRET 	u32 rate_min;
187aeb068c5SPierre-Yves MORDRET 	u32 rate_max;
188aeb068c5SPierre-Yves MORDRET 	u32 fall_max;
189aeb068c5SPierre-Yves MORDRET 	u32 rise_max;
190aeb068c5SPierre-Yves MORDRET 	u32 hddat_min;
191aeb068c5SPierre-Yves MORDRET 	u32 vddat_max;
192aeb068c5SPierre-Yves MORDRET 	u32 sudat_min;
193aeb068c5SPierre-Yves MORDRET 	u32 l_min;
194aeb068c5SPierre-Yves MORDRET 	u32 h_min;
195aeb068c5SPierre-Yves MORDRET };
196aeb068c5SPierre-Yves MORDRET 
197aeb068c5SPierre-Yves MORDRET /**
198aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_setup - private I2C timing setup parameters
199aeb068c5SPierre-Yves MORDRET  * @speed: I2C speed mode (standard, Fast Plus)
200aeb068c5SPierre-Yves MORDRET  * @speed_freq: I2C speed frequency  (Hz)
201aeb068c5SPierre-Yves MORDRET  * @clock_src: I2C clock source frequency (Hz)
202aeb068c5SPierre-Yves MORDRET  * @rise_time: Rise time (ns)
203aeb068c5SPierre-Yves MORDRET  * @fall_time: Fall time (ns)
204aeb068c5SPierre-Yves MORDRET  * @dnf: Digital filter coefficient (0-16)
205aeb068c5SPierre-Yves MORDRET  * @analog_filter: Analog filter delay (On/Off)
206aeb068c5SPierre-Yves MORDRET  */
207aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_setup {
208aeb068c5SPierre-Yves MORDRET 	enum stm32_i2c_speed speed;
209aeb068c5SPierre-Yves MORDRET 	u32 speed_freq;
210aeb068c5SPierre-Yves MORDRET 	u32 clock_src;
211aeb068c5SPierre-Yves MORDRET 	u32 rise_time;
212aeb068c5SPierre-Yves MORDRET 	u32 fall_time;
213aeb068c5SPierre-Yves MORDRET 	u8 dnf;
214aeb068c5SPierre-Yves MORDRET 	bool analog_filter;
215aeb068c5SPierre-Yves MORDRET };
216aeb068c5SPierre-Yves MORDRET 
217aeb068c5SPierre-Yves MORDRET /**
218aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_timings - private I2C output parameters
219c599eb4fSPierre-Yves MORDRET  * @node: List entry
220c599eb4fSPierre-Yves MORDRET  * @presc: Prescaler value
221aeb068c5SPierre-Yves MORDRET  * @scldel: Data setup time
222aeb068c5SPierre-Yves MORDRET  * @sdadel: Data hold time
223aeb068c5SPierre-Yves MORDRET  * @sclh: SCL high period (master mode)
224c599eb4fSPierre-Yves MORDRET  * @scll: SCL low period (master mode)
225aeb068c5SPierre-Yves MORDRET  */
226aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_timings {
227aeb068c5SPierre-Yves MORDRET 	struct list_head node;
228aeb068c5SPierre-Yves MORDRET 	u8 presc;
229aeb068c5SPierre-Yves MORDRET 	u8 scldel;
230aeb068c5SPierre-Yves MORDRET 	u8 sdadel;
231aeb068c5SPierre-Yves MORDRET 	u8 sclh;
232aeb068c5SPierre-Yves MORDRET 	u8 scll;
233aeb068c5SPierre-Yves MORDRET };
234aeb068c5SPierre-Yves MORDRET 
235aeb068c5SPierre-Yves MORDRET /**
236aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_msg - client specific data
2378c7ecc99SPierre-Yves MORDRET  * @addr: 8-bit or 10-bit slave addr, including r/w bit
238aeb068c5SPierre-Yves MORDRET  * @count: number of bytes to be transferred
239aeb068c5SPierre-Yves MORDRET  * @buf: data buffer
240aeb068c5SPierre-Yves MORDRET  * @result: result of the transfer
241aeb068c5SPierre-Yves MORDRET  * @stop: last I2C msg to be sent, i.e. STOP to be generated
2429e48155fSPierre-Yves MORDRET  * @smbus: boolean to know if the I2C IP is used in SMBus mode
2439e48155fSPierre-Yves MORDRET  * @size: type of SMBus protocol
2449e48155fSPierre-Yves MORDRET  * @read_write: direction of SMBus protocol
2459e48155fSPierre-Yves MORDRET  * SMBus block read and SMBus block write - block read process call protocols
246c599eb4fSPierre-Yves MORDRET  * @smbus_buf: buffer to be used for SMBus protocol transfer. It will
2479e48155fSPierre-Yves MORDRET  * contain a maximum of 32 bytes of data + byte command + byte count + PEC
2489e48155fSPierre-Yves MORDRET  * This buffer has to be 32-bit aligned to be compliant with memory address
2499e48155fSPierre-Yves MORDRET  * register in DMA mode.
250aeb068c5SPierre-Yves MORDRET  */
251aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_msg {
2528c7ecc99SPierre-Yves MORDRET 	u16 addr;
253aeb068c5SPierre-Yves MORDRET 	u32 count;
254aeb068c5SPierre-Yves MORDRET 	u8 *buf;
255aeb068c5SPierre-Yves MORDRET 	int result;
256aeb068c5SPierre-Yves MORDRET 	bool stop;
2579e48155fSPierre-Yves MORDRET 	bool smbus;
2589e48155fSPierre-Yves MORDRET 	int size;
2599e48155fSPierre-Yves MORDRET 	char read_write;
2609e48155fSPierre-Yves MORDRET 	u8 smbus_buf[I2C_SMBUS_BLOCK_MAX + 3] __aligned(4);
261aeb068c5SPierre-Yves MORDRET };
262aeb068c5SPierre-Yves MORDRET 
263aeb068c5SPierre-Yves MORDRET /**
264aeb068c5SPierre-Yves MORDRET  * struct stm32f7_i2c_dev - private data of the controller
265aeb068c5SPierre-Yves MORDRET  * @adap: I2C adapter for this controller
266aeb068c5SPierre-Yves MORDRET  * @dev: device for this controller
267aeb068c5SPierre-Yves MORDRET  * @base: virtual memory area
268aeb068c5SPierre-Yves MORDRET  * @complete: completion of I2C message
269aeb068c5SPierre-Yves MORDRET  * @clk: hw i2c clock
270aeb068c5SPierre-Yves MORDRET  * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+
271aeb068c5SPierre-Yves MORDRET  * @msg: Pointer to data to be written
272aeb068c5SPierre-Yves MORDRET  * @msg_num: number of I2C messages to be executed
273aeb068c5SPierre-Yves MORDRET  * @msg_id: message identifiant
274aeb068c5SPierre-Yves MORDRET  * @f7_msg: customized i2c msg for driver usage
275aeb068c5SPierre-Yves MORDRET  * @setup: I2C timing input setup
276aeb068c5SPierre-Yves MORDRET  * @timing: I2C computed timings
27760d609f3SPierre-Yves MORDRET  * @slave: list of slave devices registered on the I2C bus
27860d609f3SPierre-Yves MORDRET  * @slave_running: slave device currently used
27960d609f3SPierre-Yves MORDRET  * @slave_dir: transfer direction for the current slave device
28060d609f3SPierre-Yves MORDRET  * @master_mode: boolean to know in which mode the I2C is running (master or
28160d609f3SPierre-Yves MORDRET  * slave)
2827ecc8cfdSPierre-Yves MORDRET  * @dma: dma data
2837ecc8cfdSPierre-Yves MORDRET  * @use_dma: boolean to know if dma is used in the current transfer
284cb944fb9SPierre-Yves MORDRET  * @regmap: holds SYSCFG phandle for Fast Mode Plus bits
285aeb068c5SPierre-Yves MORDRET  */
286aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_dev {
287aeb068c5SPierre-Yves MORDRET 	struct i2c_adapter adap;
288aeb068c5SPierre-Yves MORDRET 	struct device *dev;
289aeb068c5SPierre-Yves MORDRET 	void __iomem *base;
290aeb068c5SPierre-Yves MORDRET 	struct completion complete;
291aeb068c5SPierre-Yves MORDRET 	struct clk *clk;
292aeb068c5SPierre-Yves MORDRET 	int speed;
293aeb068c5SPierre-Yves MORDRET 	struct i2c_msg *msg;
294aeb068c5SPierre-Yves MORDRET 	unsigned int msg_num;
295aeb068c5SPierre-Yves MORDRET 	unsigned int msg_id;
296aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg f7_msg;
297463a9215SPierre-Yves MORDRET 	struct stm32f7_i2c_setup setup;
298aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_timings timing;
29960d609f3SPierre-Yves MORDRET 	struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE];
30060d609f3SPierre-Yves MORDRET 	struct i2c_client *slave_running;
30160d609f3SPierre-Yves MORDRET 	u32 slave_dir;
30260d609f3SPierre-Yves MORDRET 	bool master_mode;
3037ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma;
3047ecc8cfdSPierre-Yves MORDRET 	bool use_dma;
305cb944fb9SPierre-Yves MORDRET 	struct regmap *regmap;
306aeb068c5SPierre-Yves MORDRET };
307aeb068c5SPierre-Yves MORDRET 
308aeb068c5SPierre-Yves MORDRET /**
309aeb068c5SPierre-Yves MORDRET  * All these values are coming from I2C Specification, Version 6.0, 4th of
310aeb068c5SPierre-Yves MORDRET  * April 2014.
311aeb068c5SPierre-Yves MORDRET  *
312aeb068c5SPierre-Yves MORDRET  * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast,
313aeb068c5SPierre-Yves MORDRET  * and Fast-mode Plus I2C-bus devices
314aeb068c5SPierre-Yves MORDRET  */
315aeb068c5SPierre-Yves MORDRET static struct stm32f7_i2c_spec i2c_specs[] = {
316aeb068c5SPierre-Yves MORDRET 	[STM32_I2C_SPEED_STANDARD] = {
317aeb068c5SPierre-Yves MORDRET 		.rate = 100000,
318aeb068c5SPierre-Yves MORDRET 		.rate_min = 80000,
319aeb068c5SPierre-Yves MORDRET 		.rate_max = 100000,
320aeb068c5SPierre-Yves MORDRET 		.fall_max = 300,
321aeb068c5SPierre-Yves MORDRET 		.rise_max = 1000,
322aeb068c5SPierre-Yves MORDRET 		.hddat_min = 0,
323aeb068c5SPierre-Yves MORDRET 		.vddat_max = 3450,
324aeb068c5SPierre-Yves MORDRET 		.sudat_min = 250,
325aeb068c5SPierre-Yves MORDRET 		.l_min = 4700,
326aeb068c5SPierre-Yves MORDRET 		.h_min = 4000,
327aeb068c5SPierre-Yves MORDRET 	},
328aeb068c5SPierre-Yves MORDRET 	[STM32_I2C_SPEED_FAST] = {
329aeb068c5SPierre-Yves MORDRET 		.rate = 400000,
330aeb068c5SPierre-Yves MORDRET 		.rate_min = 320000,
331aeb068c5SPierre-Yves MORDRET 		.rate_max = 400000,
332aeb068c5SPierre-Yves MORDRET 		.fall_max = 300,
333aeb068c5SPierre-Yves MORDRET 		.rise_max = 300,
334aeb068c5SPierre-Yves MORDRET 		.hddat_min = 0,
335aeb068c5SPierre-Yves MORDRET 		.vddat_max = 900,
336aeb068c5SPierre-Yves MORDRET 		.sudat_min = 100,
337aeb068c5SPierre-Yves MORDRET 		.l_min = 1300,
338aeb068c5SPierre-Yves MORDRET 		.h_min = 600,
339aeb068c5SPierre-Yves MORDRET 	},
340aeb068c5SPierre-Yves MORDRET 	[STM32_I2C_SPEED_FAST_PLUS] = {
341aeb068c5SPierre-Yves MORDRET 		.rate = 1000000,
342aeb068c5SPierre-Yves MORDRET 		.rate_min = 800000,
343aeb068c5SPierre-Yves MORDRET 		.rate_max = 1000000,
344aeb068c5SPierre-Yves MORDRET 		.fall_max = 100,
345aeb068c5SPierre-Yves MORDRET 		.rise_max = 120,
346aeb068c5SPierre-Yves MORDRET 		.hddat_min = 0,
347aeb068c5SPierre-Yves MORDRET 		.vddat_max = 450,
348aeb068c5SPierre-Yves MORDRET 		.sudat_min = 50,
349aeb068c5SPierre-Yves MORDRET 		.l_min = 500,
350aeb068c5SPierre-Yves MORDRET 		.h_min = 260,
351aeb068c5SPierre-Yves MORDRET 	},
352aeb068c5SPierre-Yves MORDRET };
353aeb068c5SPierre-Yves MORDRET 
35425f2f440SColin Ian King static const struct stm32f7_i2c_setup stm32f7_setup = {
355aeb068c5SPierre-Yves MORDRET 	.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
356aeb068c5SPierre-Yves MORDRET 	.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
357aeb068c5SPierre-Yves MORDRET 	.dnf = STM32F7_I2C_DNF_DEFAULT,
358aeb068c5SPierre-Yves MORDRET 	.analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE,
359aeb068c5SPierre-Yves MORDRET };
360aeb068c5SPierre-Yves MORDRET 
361aeb068c5SPierre-Yves MORDRET static inline void stm32f7_i2c_set_bits(void __iomem *reg, u32 mask)
362aeb068c5SPierre-Yves MORDRET {
363aeb068c5SPierre-Yves MORDRET 	writel_relaxed(readl_relaxed(reg) | mask, reg);
364aeb068c5SPierre-Yves MORDRET }
365aeb068c5SPierre-Yves MORDRET 
366aeb068c5SPierre-Yves MORDRET static inline void stm32f7_i2c_clr_bits(void __iomem *reg, u32 mask)
367aeb068c5SPierre-Yves MORDRET {
368aeb068c5SPierre-Yves MORDRET 	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
369aeb068c5SPierre-Yves MORDRET }
370aeb068c5SPierre-Yves MORDRET 
37160d609f3SPierre-Yves MORDRET static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask)
37260d609f3SPierre-Yves MORDRET {
37360d609f3SPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask);
37460d609f3SPierre-Yves MORDRET }
37560d609f3SPierre-Yves MORDRET 
376aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
377aeb068c5SPierre-Yves MORDRET 				      struct stm32f7_i2c_setup *setup,
378aeb068c5SPierre-Yves MORDRET 				      struct stm32f7_i2c_timings *output)
379aeb068c5SPierre-Yves MORDRET {
380aeb068c5SPierre-Yves MORDRET 	u32 p_prev = STM32F7_PRESC_MAX;
381aeb068c5SPierre-Yves MORDRET 	u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC,
382aeb068c5SPierre-Yves MORDRET 				       setup->clock_src);
383aeb068c5SPierre-Yves MORDRET 	u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC,
384aeb068c5SPierre-Yves MORDRET 				       setup->speed_freq);
385aeb068c5SPierre-Yves MORDRET 	u32 clk_error_prev = i2cbus;
386aeb068c5SPierre-Yves MORDRET 	u32 tsync;
387aeb068c5SPierre-Yves MORDRET 	u32 af_delay_min, af_delay_max;
388aeb068c5SPierre-Yves MORDRET 	u32 dnf_delay;
389aeb068c5SPierre-Yves MORDRET 	u32 clk_min, clk_max;
390aeb068c5SPierre-Yves MORDRET 	int sdadel_min, sdadel_max;
391aeb068c5SPierre-Yves MORDRET 	int scldel_min;
392aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_timings *v, *_v, *s;
393aeb068c5SPierre-Yves MORDRET 	struct list_head solutions;
394aeb068c5SPierre-Yves MORDRET 	u16 p, l, a, h;
395aeb068c5SPierre-Yves MORDRET 	int ret = 0;
396aeb068c5SPierre-Yves MORDRET 
397aeb068c5SPierre-Yves MORDRET 	if (setup->speed >= STM32_I2C_SPEED_END) {
398aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "speed out of bound {%d/%d}\n",
399aeb068c5SPierre-Yves MORDRET 			setup->speed, STM32_I2C_SPEED_END - 1);
400aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
401aeb068c5SPierre-Yves MORDRET 	}
402aeb068c5SPierre-Yves MORDRET 
403aeb068c5SPierre-Yves MORDRET 	if ((setup->rise_time > i2c_specs[setup->speed].rise_max) ||
404aeb068c5SPierre-Yves MORDRET 	    (setup->fall_time > i2c_specs[setup->speed].fall_max)) {
405aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev,
406aeb068c5SPierre-Yves MORDRET 			"timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
407aeb068c5SPierre-Yves MORDRET 			setup->rise_time, i2c_specs[setup->speed].rise_max,
408aeb068c5SPierre-Yves MORDRET 			setup->fall_time, i2c_specs[setup->speed].fall_max);
409aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
410aeb068c5SPierre-Yves MORDRET 	}
411aeb068c5SPierre-Yves MORDRET 
412aeb068c5SPierre-Yves MORDRET 	if (setup->dnf > STM32F7_I2C_DNF_MAX) {
413aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev,
414aeb068c5SPierre-Yves MORDRET 			"DNF out of bound %d/%d\n",
415aeb068c5SPierre-Yves MORDRET 			setup->dnf, STM32F7_I2C_DNF_MAX);
416aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
417aeb068c5SPierre-Yves MORDRET 	}
418aeb068c5SPierre-Yves MORDRET 
419aeb068c5SPierre-Yves MORDRET 	if (setup->speed_freq > i2c_specs[setup->speed].rate) {
420aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "ERROR: Freq {%d/%d}\n",
421aeb068c5SPierre-Yves MORDRET 			setup->speed_freq, i2c_specs[setup->speed].rate);
422aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
423aeb068c5SPierre-Yves MORDRET 	}
424aeb068c5SPierre-Yves MORDRET 
425aeb068c5SPierre-Yves MORDRET 	/*  Analog and Digital Filters */
426aeb068c5SPierre-Yves MORDRET 	af_delay_min =
427aeb068c5SPierre-Yves MORDRET 		(setup->analog_filter ?
428aeb068c5SPierre-Yves MORDRET 		 STM32F7_I2C_ANALOG_FILTER_DELAY_MIN : 0);
429aeb068c5SPierre-Yves MORDRET 	af_delay_max =
430aeb068c5SPierre-Yves MORDRET 		(setup->analog_filter ?
431aeb068c5SPierre-Yves MORDRET 		 STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);
432aeb068c5SPierre-Yves MORDRET 	dnf_delay = setup->dnf * i2cclk;
433aeb068c5SPierre-Yves MORDRET 
434c86da50cSNicolas Le Bayon 	sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -
435aeb068c5SPierre-Yves MORDRET 		af_delay_min - (setup->dnf + 3) * i2cclk;
436aeb068c5SPierre-Yves MORDRET 
437aeb068c5SPierre-Yves MORDRET 	sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -
438aeb068c5SPierre-Yves MORDRET 		af_delay_max - (setup->dnf + 4) * i2cclk;
439aeb068c5SPierre-Yves MORDRET 
440aeb068c5SPierre-Yves MORDRET 	scldel_min = setup->rise_time + i2c_specs[setup->speed].sudat_min;
441aeb068c5SPierre-Yves MORDRET 
442aeb068c5SPierre-Yves MORDRET 	if (sdadel_min < 0)
443aeb068c5SPierre-Yves MORDRET 		sdadel_min = 0;
444aeb068c5SPierre-Yves MORDRET 	if (sdadel_max < 0)
445aeb068c5SPierre-Yves MORDRET 		sdadel_max = 0;
446aeb068c5SPierre-Yves MORDRET 
447aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "SDADEL(min/max): %i/%i, SCLDEL(Min): %i\n",
448aeb068c5SPierre-Yves MORDRET 		sdadel_min, sdadel_max, scldel_min);
449aeb068c5SPierre-Yves MORDRET 
450aeb068c5SPierre-Yves MORDRET 	INIT_LIST_HEAD(&solutions);
451aeb068c5SPierre-Yves MORDRET 	/* Compute possible values for PRESC, SCLDEL and SDADEL */
452aeb068c5SPierre-Yves MORDRET 	for (p = 0; p < STM32F7_PRESC_MAX; p++) {
453aeb068c5SPierre-Yves MORDRET 		for (l = 0; l < STM32F7_SCLDEL_MAX; l++) {
454aeb068c5SPierre-Yves MORDRET 			u32 scldel = (l + 1) * (p + 1) * i2cclk;
455aeb068c5SPierre-Yves MORDRET 
456aeb068c5SPierre-Yves MORDRET 			if (scldel < scldel_min)
457aeb068c5SPierre-Yves MORDRET 				continue;
458aeb068c5SPierre-Yves MORDRET 
459aeb068c5SPierre-Yves MORDRET 			for (a = 0; a < STM32F7_SDADEL_MAX; a++) {
460aeb068c5SPierre-Yves MORDRET 				u32 sdadel = (a * (p + 1) + 1) * i2cclk;
461aeb068c5SPierre-Yves MORDRET 
462aeb068c5SPierre-Yves MORDRET 				if (((sdadel >= sdadel_min) &&
463aeb068c5SPierre-Yves MORDRET 				     (sdadel <= sdadel_max)) &&
464aeb068c5SPierre-Yves MORDRET 				    (p != p_prev)) {
465aeb068c5SPierre-Yves MORDRET 					v = kmalloc(sizeof(*v), GFP_KERNEL);
466aeb068c5SPierre-Yves MORDRET 					if (!v) {
467aeb068c5SPierre-Yves MORDRET 						ret = -ENOMEM;
468aeb068c5SPierre-Yves MORDRET 						goto exit;
469aeb068c5SPierre-Yves MORDRET 					}
470aeb068c5SPierre-Yves MORDRET 
471aeb068c5SPierre-Yves MORDRET 					v->presc = p;
472aeb068c5SPierre-Yves MORDRET 					v->scldel = l;
473aeb068c5SPierre-Yves MORDRET 					v->sdadel = a;
474aeb068c5SPierre-Yves MORDRET 					p_prev = p;
475aeb068c5SPierre-Yves MORDRET 
476aeb068c5SPierre-Yves MORDRET 					list_add_tail(&v->node,
477aeb068c5SPierre-Yves MORDRET 						      &solutions);
4780d735031SNicolas Le Bayon 					break;
479aeb068c5SPierre-Yves MORDRET 				}
480aeb068c5SPierre-Yves MORDRET 			}
4810d735031SNicolas Le Bayon 
4820d735031SNicolas Le Bayon 			if (p_prev == p)
4830d735031SNicolas Le Bayon 				break;
484aeb068c5SPierre-Yves MORDRET 		}
485aeb068c5SPierre-Yves MORDRET 	}
486aeb068c5SPierre-Yves MORDRET 
487aeb068c5SPierre-Yves MORDRET 	if (list_empty(&solutions)) {
488aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "no Prescaler solution\n");
489aeb068c5SPierre-Yves MORDRET 		ret = -EPERM;
490aeb068c5SPierre-Yves MORDRET 		goto exit;
491aeb068c5SPierre-Yves MORDRET 	}
492aeb068c5SPierre-Yves MORDRET 
493aeb068c5SPierre-Yves MORDRET 	tsync = af_delay_min + dnf_delay + (2 * i2cclk);
494aeb068c5SPierre-Yves MORDRET 	s = NULL;
495aeb068c5SPierre-Yves MORDRET 	clk_max = NSEC_PER_SEC / i2c_specs[setup->speed].rate_min;
496aeb068c5SPierre-Yves MORDRET 	clk_min = NSEC_PER_SEC / i2c_specs[setup->speed].rate_max;
497aeb068c5SPierre-Yves MORDRET 
498aeb068c5SPierre-Yves MORDRET 	/*
499aeb068c5SPierre-Yves MORDRET 	 * Among Prescaler possibilities discovered above figures out SCL Low
500aeb068c5SPierre-Yves MORDRET 	 * and High Period. Provided:
501aeb068c5SPierre-Yves MORDRET 	 * - SCL Low Period has to be higher than SCL Clock Low Period
502aeb068c5SPierre-Yves MORDRET 	 *   defined by I2C Specification. I2C Clock has to be lower than
503aeb068c5SPierre-Yves MORDRET 	 *   (SCL Low Period - Analog/Digital filters) / 4.
504aeb068c5SPierre-Yves MORDRET 	 * - SCL High Period has to be lower than SCL Clock High Period
505aeb068c5SPierre-Yves MORDRET 	 *   defined by I2C Specification
506aeb068c5SPierre-Yves MORDRET 	 * - I2C Clock has to be lower than SCL High Period
507aeb068c5SPierre-Yves MORDRET 	 */
508aeb068c5SPierre-Yves MORDRET 	list_for_each_entry(v, &solutions, node) {
509aeb068c5SPierre-Yves MORDRET 		u32 prescaler = (v->presc + 1) * i2cclk;
510aeb068c5SPierre-Yves MORDRET 
511aeb068c5SPierre-Yves MORDRET 		for (l = 0; l < STM32F7_SCLL_MAX; l++) {
512aeb068c5SPierre-Yves MORDRET 			u32 tscl_l = (l + 1) * prescaler + tsync;
513aeb068c5SPierre-Yves MORDRET 
514aeb068c5SPierre-Yves MORDRET 			if ((tscl_l < i2c_specs[setup->speed].l_min) ||
515aeb068c5SPierre-Yves MORDRET 			    (i2cclk >=
516aeb068c5SPierre-Yves MORDRET 			     ((tscl_l - af_delay_min - dnf_delay) / 4))) {
517aeb068c5SPierre-Yves MORDRET 				continue;
518aeb068c5SPierre-Yves MORDRET 			}
519aeb068c5SPierre-Yves MORDRET 
520aeb068c5SPierre-Yves MORDRET 			for (h = 0; h < STM32F7_SCLH_MAX; h++) {
521aeb068c5SPierre-Yves MORDRET 				u32 tscl_h = (h + 1) * prescaler + tsync;
522aeb068c5SPierre-Yves MORDRET 				u32 tscl = tscl_l + tscl_h +
523aeb068c5SPierre-Yves MORDRET 					setup->rise_time + setup->fall_time;
524aeb068c5SPierre-Yves MORDRET 
525aeb068c5SPierre-Yves MORDRET 				if ((tscl >= clk_min) && (tscl <= clk_max) &&
526aeb068c5SPierre-Yves MORDRET 				    (tscl_h >= i2c_specs[setup->speed].h_min) &&
527aeb068c5SPierre-Yves MORDRET 				    (i2cclk < tscl_h)) {
528aeb068c5SPierre-Yves MORDRET 					int clk_error = tscl - i2cbus;
529aeb068c5SPierre-Yves MORDRET 
530aeb068c5SPierre-Yves MORDRET 					if (clk_error < 0)
531aeb068c5SPierre-Yves MORDRET 						clk_error = -clk_error;
532aeb068c5SPierre-Yves MORDRET 
533aeb068c5SPierre-Yves MORDRET 					if (clk_error < clk_error_prev) {
534aeb068c5SPierre-Yves MORDRET 						clk_error_prev = clk_error;
535aeb068c5SPierre-Yves MORDRET 						v->scll = l;
536aeb068c5SPierre-Yves MORDRET 						v->sclh = h;
537aeb068c5SPierre-Yves MORDRET 						s = v;
538aeb068c5SPierre-Yves MORDRET 					}
539aeb068c5SPierre-Yves MORDRET 				}
540aeb068c5SPierre-Yves MORDRET 			}
541aeb068c5SPierre-Yves MORDRET 		}
542aeb068c5SPierre-Yves MORDRET 	}
543aeb068c5SPierre-Yves MORDRET 
544aeb068c5SPierre-Yves MORDRET 	if (!s) {
545aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "no solution at all\n");
546aeb068c5SPierre-Yves MORDRET 		ret = -EPERM;
547aeb068c5SPierre-Yves MORDRET 		goto exit;
548aeb068c5SPierre-Yves MORDRET 	}
549aeb068c5SPierre-Yves MORDRET 
550aeb068c5SPierre-Yves MORDRET 	output->presc = s->presc;
551aeb068c5SPierre-Yves MORDRET 	output->scldel = s->scldel;
552aeb068c5SPierre-Yves MORDRET 	output->sdadel = s->sdadel;
553aeb068c5SPierre-Yves MORDRET 	output->scll = s->scll;
554aeb068c5SPierre-Yves MORDRET 	output->sclh = s->sclh;
555aeb068c5SPierre-Yves MORDRET 
556aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev,
557aeb068c5SPierre-Yves MORDRET 		"Presc: %i, scldel: %i, sdadel: %i, scll: %i, sclh: %i\n",
558aeb068c5SPierre-Yves MORDRET 		output->presc,
559aeb068c5SPierre-Yves MORDRET 		output->scldel, output->sdadel,
560aeb068c5SPierre-Yves MORDRET 		output->scll, output->sclh);
561aeb068c5SPierre-Yves MORDRET 
562aeb068c5SPierre-Yves MORDRET exit:
563aeb068c5SPierre-Yves MORDRET 	/* Release list and memory */
564aeb068c5SPierre-Yves MORDRET 	list_for_each_entry_safe(v, _v, &solutions, node) {
565aeb068c5SPierre-Yves MORDRET 		list_del(&v->node);
566aeb068c5SPierre-Yves MORDRET 		kfree(v);
567aeb068c5SPierre-Yves MORDRET 	}
568aeb068c5SPierre-Yves MORDRET 
569aeb068c5SPierre-Yves MORDRET 	return ret;
570aeb068c5SPierre-Yves MORDRET }
571aeb068c5SPierre-Yves MORDRET 
572aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
573aeb068c5SPierre-Yves MORDRET 				    struct stm32f7_i2c_setup *setup)
574aeb068c5SPierre-Yves MORDRET {
575aeb068c5SPierre-Yves MORDRET 	int ret = 0;
576aeb068c5SPierre-Yves MORDRET 
577aeb068c5SPierre-Yves MORDRET 	setup->speed = i2c_dev->speed;
578aeb068c5SPierre-Yves MORDRET 	setup->speed_freq = i2c_specs[setup->speed].rate;
579aeb068c5SPierre-Yves MORDRET 	setup->clock_src = clk_get_rate(i2c_dev->clk);
580aeb068c5SPierre-Yves MORDRET 
581aeb068c5SPierre-Yves MORDRET 	if (!setup->clock_src) {
582aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "clock rate is 0\n");
583aeb068c5SPierre-Yves MORDRET 		return -EINVAL;
584aeb068c5SPierre-Yves MORDRET 	}
585aeb068c5SPierre-Yves MORDRET 
586aeb068c5SPierre-Yves MORDRET 	do {
587aeb068c5SPierre-Yves MORDRET 		ret = stm32f7_i2c_compute_timing(i2c_dev, setup,
588aeb068c5SPierre-Yves MORDRET 						 &i2c_dev->timing);
589aeb068c5SPierre-Yves MORDRET 		if (ret) {
590aeb068c5SPierre-Yves MORDRET 			dev_err(i2c_dev->dev,
591aeb068c5SPierre-Yves MORDRET 				"failed to compute I2C timings.\n");
592aeb068c5SPierre-Yves MORDRET 			if (i2c_dev->speed > STM32_I2C_SPEED_STANDARD) {
593aeb068c5SPierre-Yves MORDRET 				i2c_dev->speed--;
594aeb068c5SPierre-Yves MORDRET 				setup->speed = i2c_dev->speed;
595aeb068c5SPierre-Yves MORDRET 				setup->speed_freq =
596aeb068c5SPierre-Yves MORDRET 					i2c_specs[setup->speed].rate;
597aeb068c5SPierre-Yves MORDRET 				dev_warn(i2c_dev->dev,
598aeb068c5SPierre-Yves MORDRET 					 "downgrade I2C Speed Freq to (%i)\n",
599aeb068c5SPierre-Yves MORDRET 					 i2c_specs[setup->speed].rate);
600aeb068c5SPierre-Yves MORDRET 			} else {
601aeb068c5SPierre-Yves MORDRET 				break;
602aeb068c5SPierre-Yves MORDRET 			}
603aeb068c5SPierre-Yves MORDRET 		}
604aeb068c5SPierre-Yves MORDRET 	} while (ret);
605aeb068c5SPierre-Yves MORDRET 
606aeb068c5SPierre-Yves MORDRET 	if (ret) {
607aeb068c5SPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Impossible to compute I2C timings.\n");
608aeb068c5SPierre-Yves MORDRET 		return ret;
609aeb068c5SPierre-Yves MORDRET 	}
610aeb068c5SPierre-Yves MORDRET 
611aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "I2C Speed(%i), Freq(%i), Clk Source(%i)\n",
612aeb068c5SPierre-Yves MORDRET 		setup->speed, setup->speed_freq, setup->clock_src);
613aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",
614aeb068c5SPierre-Yves MORDRET 		setup->rise_time, setup->fall_time);
615aeb068c5SPierre-Yves MORDRET 	dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n",
616aeb068c5SPierre-Yves MORDRET 		(setup->analog_filter ? "On" : "Off"), setup->dnf);
617aeb068c5SPierre-Yves MORDRET 
618aeb068c5SPierre-Yves MORDRET 	return 0;
619aeb068c5SPierre-Yves MORDRET }
620aeb068c5SPierre-Yves MORDRET 
6217ecc8cfdSPierre-Yves MORDRET static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)
6227ecc8cfdSPierre-Yves MORDRET {
6237ecc8cfdSPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
6247ecc8cfdSPierre-Yves MORDRET 	u32 mask = STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN;
6257ecc8cfdSPierre-Yves MORDRET 
6267ecc8cfdSPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
6277ecc8cfdSPierre-Yves MORDRET }
6287ecc8cfdSPierre-Yves MORDRET 
6297ecc8cfdSPierre-Yves MORDRET static void stm32f7_i2c_dma_callback(void *arg)
6307ecc8cfdSPierre-Yves MORDRET {
6317ecc8cfdSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg;
6327ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
6337ecc8cfdSPierre-Yves MORDRET 	struct device *dev = dma->chan_using->device->dev;
6347ecc8cfdSPierre-Yves MORDRET 
6357ecc8cfdSPierre-Yves MORDRET 	stm32f7_i2c_disable_dma_req(i2c_dev);
6367ecc8cfdSPierre-Yves MORDRET 	dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir);
6377ecc8cfdSPierre-Yves MORDRET 	complete(&dma->dma_complete);
6387ecc8cfdSPierre-Yves MORDRET }
6397ecc8cfdSPierre-Yves MORDRET 
640aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
641aeb068c5SPierre-Yves MORDRET {
642aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_timings *t = &i2c_dev->timing;
643aeb068c5SPierre-Yves MORDRET 	u32 timing = 0;
644aeb068c5SPierre-Yves MORDRET 
645aeb068c5SPierre-Yves MORDRET 	/* Timing settings */
646aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_PRESC(t->presc);
647aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SCLDEL(t->scldel);
648aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SDADEL(t->sdadel);
649aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SCLH(t->sclh);
650aeb068c5SPierre-Yves MORDRET 	timing |= STM32F7_I2C_TIMINGR_SCLL(t->scll);
651aeb068c5SPierre-Yves MORDRET 	writel_relaxed(timing, i2c_dev->base + STM32F7_I2C_TIMINGR);
652aeb068c5SPierre-Yves MORDRET 
653aeb068c5SPierre-Yves MORDRET 	/* Enable I2C */
654463a9215SPierre-Yves MORDRET 	if (i2c_dev->setup.analog_filter)
655aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
656aeb068c5SPierre-Yves MORDRET 				     STM32F7_I2C_CR1_ANFOFF);
657aeb068c5SPierre-Yves MORDRET 	else
658aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
659aeb068c5SPierre-Yves MORDRET 				     STM32F7_I2C_CR1_ANFOFF);
660aeb068c5SPierre-Yves MORDRET 	stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
661aeb068c5SPierre-Yves MORDRET 			     STM32F7_I2C_CR1_PE);
662aeb068c5SPierre-Yves MORDRET }
663aeb068c5SPierre-Yves MORDRET 
664aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_write_tx_data(struct stm32f7_i2c_dev *i2c_dev)
665aeb068c5SPierre-Yves MORDRET {
666aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
667aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
668aeb068c5SPierre-Yves MORDRET 
669aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count) {
670aeb068c5SPierre-Yves MORDRET 		writeb_relaxed(*f7_msg->buf++, base + STM32F7_I2C_TXDR);
671aeb068c5SPierre-Yves MORDRET 		f7_msg->count--;
672aeb068c5SPierre-Yves MORDRET 	}
673aeb068c5SPierre-Yves MORDRET }
674aeb068c5SPierre-Yves MORDRET 
675aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_read_rx_data(struct stm32f7_i2c_dev *i2c_dev)
676aeb068c5SPierre-Yves MORDRET {
677aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
678aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
679aeb068c5SPierre-Yves MORDRET 
680aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count) {
681aeb068c5SPierre-Yves MORDRET 		*f7_msg->buf++ = readb_relaxed(base + STM32F7_I2C_RXDR);
682aeb068c5SPierre-Yves MORDRET 		f7_msg->count--;
68360d609f3SPierre-Yves MORDRET 	} else {
68460d609f3SPierre-Yves MORDRET 		/* Flush RX buffer has no data is expected */
68560d609f3SPierre-Yves MORDRET 		readb_relaxed(base + STM32F7_I2C_RXDR);
686aeb068c5SPierre-Yves MORDRET 	}
687aeb068c5SPierre-Yves MORDRET }
688aeb068c5SPierre-Yves MORDRET 
689aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
690aeb068c5SPierre-Yves MORDRET {
691aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
692aeb068c5SPierre-Yves MORDRET 	u32 cr2;
693aeb068c5SPierre-Yves MORDRET 
6947ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->use_dma)
6957ecc8cfdSPierre-Yves MORDRET 		f7_msg->count -= STM32F7_I2C_MAX_LEN;
6967ecc8cfdSPierre-Yves MORDRET 
697aeb068c5SPierre-Yves MORDRET 	cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
698aeb068c5SPierre-Yves MORDRET 
699aeb068c5SPierre-Yves MORDRET 	cr2 &= ~STM32F7_I2C_CR2_NBYTES_MASK;
700aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count > STM32F7_I2C_MAX_LEN) {
701aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(STM32F7_I2C_MAX_LEN);
702aeb068c5SPierre-Yves MORDRET 	} else {
703aeb068c5SPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_RELOAD;
704aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
705aeb068c5SPierre-Yves MORDRET 	}
706aeb068c5SPierre-Yves MORDRET 
707aeb068c5SPierre-Yves MORDRET 	writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
708aeb068c5SPierre-Yves MORDRET }
709aeb068c5SPierre-Yves MORDRET 
7109e48155fSPierre-Yves MORDRET static void stm32f7_i2c_smbus_reload(struct stm32f7_i2c_dev *i2c_dev)
7119e48155fSPierre-Yves MORDRET {
7129e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
7139e48155fSPierre-Yves MORDRET 	u32 cr2;
7149e48155fSPierre-Yves MORDRET 	u8 *val;
7159e48155fSPierre-Yves MORDRET 
7169e48155fSPierre-Yves MORDRET 	/*
7179e48155fSPierre-Yves MORDRET 	 * For I2C_SMBUS_BLOCK_DATA && I2C_SMBUS_BLOCK_PROC_CALL, the first
7189e48155fSPierre-Yves MORDRET 	 * data received inform us how many data will follow.
7199e48155fSPierre-Yves MORDRET 	 */
7209e48155fSPierre-Yves MORDRET 	stm32f7_i2c_read_rx_data(i2c_dev);
7219e48155fSPierre-Yves MORDRET 
7229e48155fSPierre-Yves MORDRET 	/*
7239e48155fSPierre-Yves MORDRET 	 * Update NBYTES with the value read to continue the transfer
7249e48155fSPierre-Yves MORDRET 	 */
7259e48155fSPierre-Yves MORDRET 	val = f7_msg->buf - sizeof(u8);
7269e48155fSPierre-Yves MORDRET 	f7_msg->count = *val;
7279e48155fSPierre-Yves MORDRET 	cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
7289e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
7299e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
7309e48155fSPierre-Yves MORDRET 	writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
7319e48155fSPierre-Yves MORDRET }
7329e48155fSPierre-Yves MORDRET 
733562de4ffSPierre-Yves MORDRET static int stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap)
734562de4ffSPierre-Yves MORDRET {
735562de4ffSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
736562de4ffSPierre-Yves MORDRET 
737562de4ffSPierre-Yves MORDRET 	dev_info(i2c_dev->dev, "Trying to recover bus\n");
738562de4ffSPierre-Yves MORDRET 
739562de4ffSPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
740562de4ffSPierre-Yves MORDRET 			     STM32F7_I2C_CR1_PE);
741562de4ffSPierre-Yves MORDRET 
742562de4ffSPierre-Yves MORDRET 	stm32f7_i2c_hw_config(i2c_dev);
743562de4ffSPierre-Yves MORDRET 
744562de4ffSPierre-Yves MORDRET 	return 0;
745562de4ffSPierre-Yves MORDRET }
746562de4ffSPierre-Yves MORDRET 
747aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
748aeb068c5SPierre-Yves MORDRET {
749aeb068c5SPierre-Yves MORDRET 	u32 status;
750aeb068c5SPierre-Yves MORDRET 	int ret;
751aeb068c5SPierre-Yves MORDRET 
752aeb068c5SPierre-Yves MORDRET 	ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F7_I2C_ISR,
753aeb068c5SPierre-Yves MORDRET 					 status,
754aeb068c5SPierre-Yves MORDRET 					 !(status & STM32F7_I2C_ISR_BUSY),
755aeb068c5SPierre-Yves MORDRET 					 10, 1000);
756562de4ffSPierre-Yves MORDRET 	if (!ret)
757562de4ffSPierre-Yves MORDRET 		return 0;
758562de4ffSPierre-Yves MORDRET 
759562de4ffSPierre-Yves MORDRET 	dev_info(i2c_dev->dev, "bus busy\n");
760562de4ffSPierre-Yves MORDRET 
761562de4ffSPierre-Yves MORDRET 	ret = stm32f7_i2c_release_bus(&i2c_dev->adap);
762aeb068c5SPierre-Yves MORDRET 	if (ret) {
763562de4ffSPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
764562de4ffSPierre-Yves MORDRET 		return ret;
765aeb068c5SPierre-Yves MORDRET 	}
766aeb068c5SPierre-Yves MORDRET 
767562de4ffSPierre-Yves MORDRET 	return -EBUSY;
768aeb068c5SPierre-Yves MORDRET }
769aeb068c5SPierre-Yves MORDRET 
770aeb068c5SPierre-Yves MORDRET static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
771aeb068c5SPierre-Yves MORDRET 				 struct i2c_msg *msg)
772aeb068c5SPierre-Yves MORDRET {
773aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
774aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
775aeb068c5SPierre-Yves MORDRET 	u32 cr1, cr2;
7767ecc8cfdSPierre-Yves MORDRET 	int ret;
777aeb068c5SPierre-Yves MORDRET 
778aeb068c5SPierre-Yves MORDRET 	f7_msg->addr = msg->addr;
779aeb068c5SPierre-Yves MORDRET 	f7_msg->buf = msg->buf;
780aeb068c5SPierre-Yves MORDRET 	f7_msg->count = msg->len;
781aeb068c5SPierre-Yves MORDRET 	f7_msg->result = 0;
782aeb068c5SPierre-Yves MORDRET 	f7_msg->stop = (i2c_dev->msg_id >= i2c_dev->msg_num - 1);
783aeb068c5SPierre-Yves MORDRET 
784aeb068c5SPierre-Yves MORDRET 	reinit_completion(&i2c_dev->complete);
785aeb068c5SPierre-Yves MORDRET 
786aeb068c5SPierre-Yves MORDRET 	cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
787aeb068c5SPierre-Yves MORDRET 	cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
788aeb068c5SPierre-Yves MORDRET 
789aeb068c5SPierre-Yves MORDRET 	/* Set transfer direction */
790aeb068c5SPierre-Yves MORDRET 	cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
791aeb068c5SPierre-Yves MORDRET 	if (msg->flags & I2C_M_RD)
792aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RD_WRN;
793aeb068c5SPierre-Yves MORDRET 
794aeb068c5SPierre-Yves MORDRET 	/* Set slave address */
7958c7ecc99SPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_HEAD10R | STM32F7_I2C_CR2_ADD10);
7968c7ecc99SPierre-Yves MORDRET 	if (msg->flags & I2C_M_TEN) {
7978c7ecc99SPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_SADD10_MASK;
7988c7ecc99SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_SADD10(f7_msg->addr);
7998c7ecc99SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_ADD10;
8008c7ecc99SPierre-Yves MORDRET 	} else {
801aeb068c5SPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_SADD7_MASK;
802aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
8038c7ecc99SPierre-Yves MORDRET 	}
804aeb068c5SPierre-Yves MORDRET 
805aeb068c5SPierre-Yves MORDRET 	/* Set nb bytes to transfer and reload if needed */
806aeb068c5SPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
807aeb068c5SPierre-Yves MORDRET 	if (f7_msg->count > STM32F7_I2C_MAX_LEN) {
808aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(STM32F7_I2C_MAX_LEN);
809aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RELOAD;
810aeb068c5SPierre-Yves MORDRET 	} else {
811aeb068c5SPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
812aeb068c5SPierre-Yves MORDRET 	}
813aeb068c5SPierre-Yves MORDRET 
814aeb068c5SPierre-Yves MORDRET 	/* Enable NACK, STOP, error and transfer complete interrupts */
815aeb068c5SPierre-Yves MORDRET 	cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
816aeb068c5SPierre-Yves MORDRET 		STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
817aeb068c5SPierre-Yves MORDRET 
8187ecc8cfdSPierre-Yves MORDRET 	/* Clear DMA req and TX/RX interrupt */
8197ecc8cfdSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
8207ecc8cfdSPierre-Yves MORDRET 			STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
821aeb068c5SPierre-Yves MORDRET 
8227ecc8cfdSPierre-Yves MORDRET 	/* Configure DMA or enable RX/TX interrupt */
8237ecc8cfdSPierre-Yves MORDRET 	i2c_dev->use_dma = false;
8247ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
8257ecc8cfdSPierre-Yves MORDRET 		ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
8267ecc8cfdSPierre-Yves MORDRET 					      msg->flags & I2C_M_RD,
8277ecc8cfdSPierre-Yves MORDRET 					      f7_msg->count, f7_msg->buf,
8287ecc8cfdSPierre-Yves MORDRET 					      stm32f7_i2c_dma_callback,
8297ecc8cfdSPierre-Yves MORDRET 					      i2c_dev);
8307ecc8cfdSPierre-Yves MORDRET 		if (!ret)
8317ecc8cfdSPierre-Yves MORDRET 			i2c_dev->use_dma = true;
8327ecc8cfdSPierre-Yves MORDRET 		else
8337ecc8cfdSPierre-Yves MORDRET 			dev_warn(i2c_dev->dev, "can't use DMA\n");
8347ecc8cfdSPierre-Yves MORDRET 	}
8357ecc8cfdSPierre-Yves MORDRET 
8367ecc8cfdSPierre-Yves MORDRET 	if (!i2c_dev->use_dma) {
837aeb068c5SPierre-Yves MORDRET 		if (msg->flags & I2C_M_RD)
838aeb068c5SPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXIE;
839aeb068c5SPierre-Yves MORDRET 		else
840aeb068c5SPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXIE;
8417ecc8cfdSPierre-Yves MORDRET 	} else {
8427ecc8cfdSPierre-Yves MORDRET 		if (msg->flags & I2C_M_RD)
8437ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXDMAEN;
8447ecc8cfdSPierre-Yves MORDRET 		else
8457ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXDMAEN;
8467ecc8cfdSPierre-Yves MORDRET 	}
847aeb068c5SPierre-Yves MORDRET 
848aeb068c5SPierre-Yves MORDRET 	/* Configure Start/Repeated Start */
849aeb068c5SPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_START;
850aeb068c5SPierre-Yves MORDRET 
85160d609f3SPierre-Yves MORDRET 	i2c_dev->master_mode = true;
85260d609f3SPierre-Yves MORDRET 
853aeb068c5SPierre-Yves MORDRET 	/* Write configurations registers */
854aeb068c5SPierre-Yves MORDRET 	writel_relaxed(cr1, base + STM32F7_I2C_CR1);
855aeb068c5SPierre-Yves MORDRET 	writel_relaxed(cr2, base + STM32F7_I2C_CR2);
856aeb068c5SPierre-Yves MORDRET }
857aeb068c5SPierre-Yves MORDRET 
8589e48155fSPierre-Yves MORDRET static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
8599e48155fSPierre-Yves MORDRET 				      unsigned short flags, u8 command,
8609e48155fSPierre-Yves MORDRET 				      union i2c_smbus_data *data)
8619e48155fSPierre-Yves MORDRET {
8629e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
8639e48155fSPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
8649e48155fSPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
8659e48155fSPierre-Yves MORDRET 	u32 cr1, cr2;
8667ecc8cfdSPierre-Yves MORDRET 	int i, ret;
8679e48155fSPierre-Yves MORDRET 
8689e48155fSPierre-Yves MORDRET 	f7_msg->result = 0;
8699e48155fSPierre-Yves MORDRET 	reinit_completion(&i2c_dev->complete);
8709e48155fSPierre-Yves MORDRET 
8719e48155fSPierre-Yves MORDRET 	cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
8729e48155fSPierre-Yves MORDRET 	cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
8739e48155fSPierre-Yves MORDRET 
8749e48155fSPierre-Yves MORDRET 	/* Set transfer direction */
8759e48155fSPierre-Yves MORDRET 	cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
8769e48155fSPierre-Yves MORDRET 	if (f7_msg->read_write)
8779e48155fSPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RD_WRN;
8789e48155fSPierre-Yves MORDRET 
8799e48155fSPierre-Yves MORDRET 	/* Set slave address */
8809e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_ADD10 | STM32F7_I2C_CR2_SADD7_MASK);
8819e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
8829e48155fSPierre-Yves MORDRET 
8839e48155fSPierre-Yves MORDRET 	f7_msg->smbus_buf[0] = command;
8849e48155fSPierre-Yves MORDRET 	switch (f7_msg->size) {
8859e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_QUICK:
8869e48155fSPierre-Yves MORDRET 		f7_msg->stop = true;
8879e48155fSPierre-Yves MORDRET 		f7_msg->count = 0;
8889e48155fSPierre-Yves MORDRET 		break;
8899e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE:
8909e48155fSPierre-Yves MORDRET 		f7_msg->stop = true;
8919e48155fSPierre-Yves MORDRET 		f7_msg->count = 1;
8929e48155fSPierre-Yves MORDRET 		break;
8939e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE_DATA:
8949e48155fSPierre-Yves MORDRET 		if (f7_msg->read_write) {
8959e48155fSPierre-Yves MORDRET 			f7_msg->stop = false;
8969e48155fSPierre-Yves MORDRET 			f7_msg->count = 1;
8979e48155fSPierre-Yves MORDRET 			cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
8989e48155fSPierre-Yves MORDRET 		} else {
8999e48155fSPierre-Yves MORDRET 			f7_msg->stop = true;
9009e48155fSPierre-Yves MORDRET 			f7_msg->count = 2;
9019e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[1] = data->byte;
9029e48155fSPierre-Yves MORDRET 		}
9039e48155fSPierre-Yves MORDRET 		break;
9049e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_WORD_DATA:
9059e48155fSPierre-Yves MORDRET 		if (f7_msg->read_write) {
9069e48155fSPierre-Yves MORDRET 			f7_msg->stop = false;
9079e48155fSPierre-Yves MORDRET 			f7_msg->count = 1;
9089e48155fSPierre-Yves MORDRET 			cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9099e48155fSPierre-Yves MORDRET 		} else {
9109e48155fSPierre-Yves MORDRET 			f7_msg->stop = true;
9119e48155fSPierre-Yves MORDRET 			f7_msg->count = 3;
9129e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[1] = data->word & 0xff;
9139e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[2] = data->word >> 8;
9149e48155fSPierre-Yves MORDRET 		}
9159e48155fSPierre-Yves MORDRET 		break;
9169e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_DATA:
9179e48155fSPierre-Yves MORDRET 		if (f7_msg->read_write) {
9189e48155fSPierre-Yves MORDRET 			f7_msg->stop = false;
9199e48155fSPierre-Yves MORDRET 			f7_msg->count = 1;
9209e48155fSPierre-Yves MORDRET 			cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9219e48155fSPierre-Yves MORDRET 		} else {
9229e48155fSPierre-Yves MORDRET 			f7_msg->stop = true;
9239e48155fSPierre-Yves MORDRET 			if (data->block[0] > I2C_SMBUS_BLOCK_MAX ||
9249e48155fSPierre-Yves MORDRET 			    !data->block[0]) {
9259e48155fSPierre-Yves MORDRET 				dev_err(dev, "Invalid block write size %d\n",
9269e48155fSPierre-Yves MORDRET 					data->block[0]);
9279e48155fSPierre-Yves MORDRET 				return -EINVAL;
9289e48155fSPierre-Yves MORDRET 			}
9299e48155fSPierre-Yves MORDRET 			f7_msg->count = data->block[0] + 2;
9309e48155fSPierre-Yves MORDRET 			for (i = 1; i < f7_msg->count; i++)
9319e48155fSPierre-Yves MORDRET 				f7_msg->smbus_buf[i] = data->block[i - 1];
9329e48155fSPierre-Yves MORDRET 		}
9339e48155fSPierre-Yves MORDRET 		break;
9349e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_PROC_CALL:
9359e48155fSPierre-Yves MORDRET 		f7_msg->stop = false;
9369e48155fSPierre-Yves MORDRET 		f7_msg->count = 3;
9379e48155fSPierre-Yves MORDRET 		f7_msg->smbus_buf[1] = data->word & 0xff;
9389e48155fSPierre-Yves MORDRET 		f7_msg->smbus_buf[2] = data->word >> 8;
9399e48155fSPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9409e48155fSPierre-Yves MORDRET 		f7_msg->read_write = I2C_SMBUS_READ;
9419e48155fSPierre-Yves MORDRET 		break;
9429e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_PROC_CALL:
9439e48155fSPierre-Yves MORDRET 		f7_msg->stop = false;
9449e48155fSPierre-Yves MORDRET 		if (data->block[0] > I2C_SMBUS_BLOCK_MAX - 1) {
9459e48155fSPierre-Yves MORDRET 			dev_err(dev, "Invalid block write size %d\n",
9469e48155fSPierre-Yves MORDRET 				data->block[0]);
9479e48155fSPierre-Yves MORDRET 			return -EINVAL;
9489e48155fSPierre-Yves MORDRET 		}
9499e48155fSPierre-Yves MORDRET 		f7_msg->count = data->block[0] + 2;
9509e48155fSPierre-Yves MORDRET 		for (i = 1; i < f7_msg->count; i++)
9519e48155fSPierre-Yves MORDRET 			f7_msg->smbus_buf[i] = data->block[i - 1];
9529e48155fSPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
9539e48155fSPierre-Yves MORDRET 		f7_msg->read_write = I2C_SMBUS_READ;
9549e48155fSPierre-Yves MORDRET 		break;
955473fbdf7SFabrice Gasnier 	case I2C_SMBUS_I2C_BLOCK_DATA:
956473fbdf7SFabrice Gasnier 		/* Rely on emulated i2c transfer (through master_xfer) */
957473fbdf7SFabrice Gasnier 		return -EOPNOTSUPP;
9589e48155fSPierre-Yves MORDRET 	default:
9599e48155fSPierre-Yves MORDRET 		dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
9609e48155fSPierre-Yves MORDRET 		return -EOPNOTSUPP;
9619e48155fSPierre-Yves MORDRET 	}
9629e48155fSPierre-Yves MORDRET 
9639e48155fSPierre-Yves MORDRET 	f7_msg->buf = f7_msg->smbus_buf;
9649e48155fSPierre-Yves MORDRET 
9659e48155fSPierre-Yves MORDRET 	/* Configure PEC */
9669e48155fSPierre-Yves MORDRET 	if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
9679e48155fSPierre-Yves MORDRET 		cr1 |= STM32F7_I2C_CR1_PECEN;
9689e48155fSPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_PECBYTE;
9699e48155fSPierre-Yves MORDRET 		if (!f7_msg->read_write)
9709e48155fSPierre-Yves MORDRET 			f7_msg->count++;
9719e48155fSPierre-Yves MORDRET 	} else {
9729e48155fSPierre-Yves MORDRET 		cr1 &= ~STM32F7_I2C_CR1_PECEN;
9739e48155fSPierre-Yves MORDRET 		cr2 &= ~STM32F7_I2C_CR2_PECBYTE;
9749e48155fSPierre-Yves MORDRET 	}
9759e48155fSPierre-Yves MORDRET 
9769e48155fSPierre-Yves MORDRET 	/* Set number of bytes to be transferred */
9779e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
9789e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
9799e48155fSPierre-Yves MORDRET 
9809e48155fSPierre-Yves MORDRET 	/* Enable NACK, STOP, error and transfer complete interrupts */
9819e48155fSPierre-Yves MORDRET 	cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
9829e48155fSPierre-Yves MORDRET 		STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
9839e48155fSPierre-Yves MORDRET 
9847ecc8cfdSPierre-Yves MORDRET 	/* Clear DMA req and TX/RX interrupt */
9857ecc8cfdSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
9867ecc8cfdSPierre-Yves MORDRET 			STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
9879e48155fSPierre-Yves MORDRET 
9887ecc8cfdSPierre-Yves MORDRET 	/* Configure DMA or enable RX/TX interrupt */
9897ecc8cfdSPierre-Yves MORDRET 	i2c_dev->use_dma = false;
9907ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
9917ecc8cfdSPierre-Yves MORDRET 		ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
9927ecc8cfdSPierre-Yves MORDRET 					      cr2 & STM32F7_I2C_CR2_RD_WRN,
9937ecc8cfdSPierre-Yves MORDRET 					      f7_msg->count, f7_msg->buf,
9947ecc8cfdSPierre-Yves MORDRET 					      stm32f7_i2c_dma_callback,
9957ecc8cfdSPierre-Yves MORDRET 					      i2c_dev);
9967ecc8cfdSPierre-Yves MORDRET 		if (!ret)
9977ecc8cfdSPierre-Yves MORDRET 			i2c_dev->use_dma = true;
9987ecc8cfdSPierre-Yves MORDRET 		else
9997ecc8cfdSPierre-Yves MORDRET 			dev_warn(i2c_dev->dev, "can't use DMA\n");
10007ecc8cfdSPierre-Yves MORDRET 	}
10017ecc8cfdSPierre-Yves MORDRET 
10027ecc8cfdSPierre-Yves MORDRET 	if (!i2c_dev->use_dma) {
10039e48155fSPierre-Yves MORDRET 		if (cr2 & STM32F7_I2C_CR2_RD_WRN)
10049e48155fSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXIE;
10059e48155fSPierre-Yves MORDRET 		else
10069e48155fSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXIE;
10077ecc8cfdSPierre-Yves MORDRET 	} else {
10087ecc8cfdSPierre-Yves MORDRET 		if (cr2 & STM32F7_I2C_CR2_RD_WRN)
10097ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_RXDMAEN;
10107ecc8cfdSPierre-Yves MORDRET 		else
10117ecc8cfdSPierre-Yves MORDRET 			cr1 |= STM32F7_I2C_CR1_TXDMAEN;
10127ecc8cfdSPierre-Yves MORDRET 	}
10139e48155fSPierre-Yves MORDRET 
10149e48155fSPierre-Yves MORDRET 	/* Set Start bit */
10159e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_START;
10169e48155fSPierre-Yves MORDRET 
10179e48155fSPierre-Yves MORDRET 	i2c_dev->master_mode = true;
10189e48155fSPierre-Yves MORDRET 
10199e48155fSPierre-Yves MORDRET 	/* Write configurations registers */
10209e48155fSPierre-Yves MORDRET 	writel_relaxed(cr1, base + STM32F7_I2C_CR1);
10219e48155fSPierre-Yves MORDRET 	writel_relaxed(cr2, base + STM32F7_I2C_CR2);
10229e48155fSPierre-Yves MORDRET 
10239e48155fSPierre-Yves MORDRET 	return 0;
10249e48155fSPierre-Yves MORDRET }
10259e48155fSPierre-Yves MORDRET 
10269e48155fSPierre-Yves MORDRET static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev)
10279e48155fSPierre-Yves MORDRET {
10289e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
10299e48155fSPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
10309e48155fSPierre-Yves MORDRET 	u32 cr1, cr2;
10317ecc8cfdSPierre-Yves MORDRET 	int ret;
10329e48155fSPierre-Yves MORDRET 
10339e48155fSPierre-Yves MORDRET 	cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
10349e48155fSPierre-Yves MORDRET 	cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
10359e48155fSPierre-Yves MORDRET 
10369e48155fSPierre-Yves MORDRET 	/* Set transfer direction */
10379e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_RD_WRN;
10389e48155fSPierre-Yves MORDRET 
10399e48155fSPierre-Yves MORDRET 	switch (f7_msg->size) {
10409e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE_DATA:
10419e48155fSPierre-Yves MORDRET 		f7_msg->count = 1;
10429e48155fSPierre-Yves MORDRET 		break;
10439e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_WORD_DATA:
10449e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_PROC_CALL:
10459e48155fSPierre-Yves MORDRET 		f7_msg->count = 2;
10469e48155fSPierre-Yves MORDRET 		break;
10479e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_DATA:
10489e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_PROC_CALL:
10499e48155fSPierre-Yves MORDRET 		f7_msg->count = 1;
10509e48155fSPierre-Yves MORDRET 		cr2 |= STM32F7_I2C_CR2_RELOAD;
10519e48155fSPierre-Yves MORDRET 		break;
10529e48155fSPierre-Yves MORDRET 	}
10539e48155fSPierre-Yves MORDRET 
10549e48155fSPierre-Yves MORDRET 	f7_msg->buf = f7_msg->smbus_buf;
10559e48155fSPierre-Yves MORDRET 	f7_msg->stop = true;
10569e48155fSPierre-Yves MORDRET 
10579e48155fSPierre-Yves MORDRET 	/* Add one byte for PEC if needed */
10589e48155fSPierre-Yves MORDRET 	if (cr1 & STM32F7_I2C_CR1_PECEN)
10599e48155fSPierre-Yves MORDRET 		f7_msg->count++;
10609e48155fSPierre-Yves MORDRET 
10619e48155fSPierre-Yves MORDRET 	/* Set number of bytes to be transferred */
10629e48155fSPierre-Yves MORDRET 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK);
10639e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
10649e48155fSPierre-Yves MORDRET 
10659e48155fSPierre-Yves MORDRET 	/*
10669e48155fSPierre-Yves MORDRET 	 * Configure RX/TX interrupt:
10679e48155fSPierre-Yves MORDRET 	 */
10689e48155fSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE);
10699e48155fSPierre-Yves MORDRET 	cr1 |= STM32F7_I2C_CR1_RXIE;
10709e48155fSPierre-Yves MORDRET 
10717ecc8cfdSPierre-Yves MORDRET 	/*
10727ecc8cfdSPierre-Yves MORDRET 	 * Configure DMA or enable RX/TX interrupt:
10737ecc8cfdSPierre-Yves MORDRET 	 * For I2C_SMBUS_BLOCK_DATA and I2C_SMBUS_BLOCK_PROC_CALL we don't use
10747ecc8cfdSPierre-Yves MORDRET 	 * dma as we don't know in advance how many data will be received
10757ecc8cfdSPierre-Yves MORDRET 	 */
10767ecc8cfdSPierre-Yves MORDRET 	cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
10777ecc8cfdSPierre-Yves MORDRET 		 STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
10787ecc8cfdSPierre-Yves MORDRET 
10797ecc8cfdSPierre-Yves MORDRET 	i2c_dev->use_dma = false;
10807ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN &&
10817ecc8cfdSPierre-Yves MORDRET 	    f7_msg->size != I2C_SMBUS_BLOCK_DATA &&
10827ecc8cfdSPierre-Yves MORDRET 	    f7_msg->size != I2C_SMBUS_BLOCK_PROC_CALL) {
10837ecc8cfdSPierre-Yves MORDRET 		ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
10847ecc8cfdSPierre-Yves MORDRET 					      cr2 & STM32F7_I2C_CR2_RD_WRN,
10857ecc8cfdSPierre-Yves MORDRET 					      f7_msg->count, f7_msg->buf,
10867ecc8cfdSPierre-Yves MORDRET 					      stm32f7_i2c_dma_callback,
10877ecc8cfdSPierre-Yves MORDRET 					      i2c_dev);
10887ecc8cfdSPierre-Yves MORDRET 
10897ecc8cfdSPierre-Yves MORDRET 		if (!ret)
10907ecc8cfdSPierre-Yves MORDRET 			i2c_dev->use_dma = true;
10917ecc8cfdSPierre-Yves MORDRET 		else
10927ecc8cfdSPierre-Yves MORDRET 			dev_warn(i2c_dev->dev, "can't use DMA\n");
10937ecc8cfdSPierre-Yves MORDRET 	}
10947ecc8cfdSPierre-Yves MORDRET 
10957ecc8cfdSPierre-Yves MORDRET 	if (!i2c_dev->use_dma)
10967ecc8cfdSPierre-Yves MORDRET 		cr1 |= STM32F7_I2C_CR1_RXIE;
10977ecc8cfdSPierre-Yves MORDRET 	else
10987ecc8cfdSPierre-Yves MORDRET 		cr1 |= STM32F7_I2C_CR1_RXDMAEN;
10997ecc8cfdSPierre-Yves MORDRET 
11009e48155fSPierre-Yves MORDRET 	/* Configure Repeated Start */
11019e48155fSPierre-Yves MORDRET 	cr2 |= STM32F7_I2C_CR2_START;
11029e48155fSPierre-Yves MORDRET 
11039e48155fSPierre-Yves MORDRET 	/* Write configurations registers */
11049e48155fSPierre-Yves MORDRET 	writel_relaxed(cr1, base + STM32F7_I2C_CR1);
11059e48155fSPierre-Yves MORDRET 	writel_relaxed(cr2, base + STM32F7_I2C_CR2);
11069e48155fSPierre-Yves MORDRET }
11079e48155fSPierre-Yves MORDRET 
11089e48155fSPierre-Yves MORDRET static int stm32f7_i2c_smbus_check_pec(struct stm32f7_i2c_dev *i2c_dev)
11099e48155fSPierre-Yves MORDRET {
11109e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
11119e48155fSPierre-Yves MORDRET 	u8 count, internal_pec, received_pec;
11129e48155fSPierre-Yves MORDRET 
11139e48155fSPierre-Yves MORDRET 	internal_pec = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
11149e48155fSPierre-Yves MORDRET 
11159e48155fSPierre-Yves MORDRET 	switch (f7_msg->size) {
11169e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE:
11179e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BYTE_DATA:
11189e48155fSPierre-Yves MORDRET 		received_pec = f7_msg->smbus_buf[1];
11199e48155fSPierre-Yves MORDRET 		break;
11209e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_WORD_DATA:
11219e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_PROC_CALL:
11229e48155fSPierre-Yves MORDRET 		received_pec = f7_msg->smbus_buf[2];
11239e48155fSPierre-Yves MORDRET 		break;
11249e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_DATA:
11259e48155fSPierre-Yves MORDRET 	case I2C_SMBUS_BLOCK_PROC_CALL:
11269e48155fSPierre-Yves MORDRET 		count = f7_msg->smbus_buf[0];
11279e48155fSPierre-Yves MORDRET 		received_pec = f7_msg->smbus_buf[count];
11289e48155fSPierre-Yves MORDRET 		break;
11299e48155fSPierre-Yves MORDRET 	default:
11309e48155fSPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Unsupported smbus protocol for PEC\n");
11319e48155fSPierre-Yves MORDRET 		return -EINVAL;
11329e48155fSPierre-Yves MORDRET 	}
11339e48155fSPierre-Yves MORDRET 
11349e48155fSPierre-Yves MORDRET 	if (internal_pec != received_pec) {
11359e48155fSPierre-Yves MORDRET 		dev_err(i2c_dev->dev, "Bad PEC 0x%02x vs. 0x%02x\n",
11369e48155fSPierre-Yves MORDRET 			internal_pec, received_pec);
11379e48155fSPierre-Yves MORDRET 		return -EBADMSG;
11389e48155fSPierre-Yves MORDRET 	}
11399e48155fSPierre-Yves MORDRET 
11409e48155fSPierre-Yves MORDRET 	return 0;
11419e48155fSPierre-Yves MORDRET }
11429e48155fSPierre-Yves MORDRET 
114360d609f3SPierre-Yves MORDRET static bool stm32f7_i2c_is_addr_match(struct i2c_client *slave, u32 addcode)
1144aeb068c5SPierre-Yves MORDRET {
114560d609f3SPierre-Yves MORDRET 	u32 addr;
114660d609f3SPierre-Yves MORDRET 
114760d609f3SPierre-Yves MORDRET 	if (!slave)
114860d609f3SPierre-Yves MORDRET 		return false;
114960d609f3SPierre-Yves MORDRET 
115060d609f3SPierre-Yves MORDRET 	if (slave->flags & I2C_CLIENT_TEN) {
115160d609f3SPierre-Yves MORDRET 		/*
115260d609f3SPierre-Yves MORDRET 		 * For 10-bit addr, addcode = 11110XY with
115360d609f3SPierre-Yves MORDRET 		 * X = Bit 9 of slave address
115460d609f3SPierre-Yves MORDRET 		 * Y = Bit 8 of slave address
115560d609f3SPierre-Yves MORDRET 		 */
115660d609f3SPierre-Yves MORDRET 		addr = slave->addr >> 8;
115760d609f3SPierre-Yves MORDRET 		addr |= 0x78;
115860d609f3SPierre-Yves MORDRET 		if (addr == addcode)
115960d609f3SPierre-Yves MORDRET 			return true;
116060d609f3SPierre-Yves MORDRET 	} else {
116160d609f3SPierre-Yves MORDRET 		addr = slave->addr & 0x7f;
116260d609f3SPierre-Yves MORDRET 		if (addr == addcode)
116360d609f3SPierre-Yves MORDRET 			return true;
116460d609f3SPierre-Yves MORDRET 	}
116560d609f3SPierre-Yves MORDRET 
116660d609f3SPierre-Yves MORDRET 	return false;
116760d609f3SPierre-Yves MORDRET }
116860d609f3SPierre-Yves MORDRET 
116960d609f3SPierre-Yves MORDRET static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
117060d609f3SPierre-Yves MORDRET {
117160d609f3SPierre-Yves MORDRET 	struct i2c_client *slave = i2c_dev->slave_running;
117260d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
117360d609f3SPierre-Yves MORDRET 	u32 mask;
117460d609f3SPierre-Yves MORDRET 	u8 value = 0;
117560d609f3SPierre-Yves MORDRET 
117660d609f3SPierre-Yves MORDRET 	if (i2c_dev->slave_dir) {
117760d609f3SPierre-Yves MORDRET 		/* Notify i2c slave that new read transfer is starting */
117860d609f3SPierre-Yves MORDRET 		i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
117960d609f3SPierre-Yves MORDRET 
118060d609f3SPierre-Yves MORDRET 		/*
118160d609f3SPierre-Yves MORDRET 		 * Disable slave TX config in case of I2C combined message
118260d609f3SPierre-Yves MORDRET 		 * (I2C Write followed by I2C Read)
118360d609f3SPierre-Yves MORDRET 		 */
118460d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_CR2_RELOAD;
118560d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, mask);
118660d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
118760d609f3SPierre-Yves MORDRET 		       STM32F7_I2C_CR1_TCIE;
118860d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
118960d609f3SPierre-Yves MORDRET 
119060d609f3SPierre-Yves MORDRET 		/* Enable TX empty, STOP, NACK interrupts */
119160d609f3SPierre-Yves MORDRET 		mask =  STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
119260d609f3SPierre-Yves MORDRET 			STM32F7_I2C_CR1_TXIE;
119360d609f3SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
119460d609f3SPierre-Yves MORDRET 
119560d609f3SPierre-Yves MORDRET 	} else {
119660d609f3SPierre-Yves MORDRET 		/* Notify i2c slave that new write transfer is starting */
119760d609f3SPierre-Yves MORDRET 		i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
119860d609f3SPierre-Yves MORDRET 
119960d609f3SPierre-Yves MORDRET 		/* Set reload mode to be able to ACK/NACK each received byte */
120060d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_CR2_RELOAD;
120160d609f3SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
120260d609f3SPierre-Yves MORDRET 
120360d609f3SPierre-Yves MORDRET 		/*
120460d609f3SPierre-Yves MORDRET 		 * Set STOP, NACK, RX empty and transfer complete interrupts.*
120560d609f3SPierre-Yves MORDRET 		 * Set Slave Byte Control to be able to ACK/NACK each data
120660d609f3SPierre-Yves MORDRET 		 * byte received
120760d609f3SPierre-Yves MORDRET 		 */
120860d609f3SPierre-Yves MORDRET 		mask =  STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
120960d609f3SPierre-Yves MORDRET 			STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
121060d609f3SPierre-Yves MORDRET 			STM32F7_I2C_CR1_TCIE;
121160d609f3SPierre-Yves MORDRET 		stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
121260d609f3SPierre-Yves MORDRET 	}
121360d609f3SPierre-Yves MORDRET }
121460d609f3SPierre-Yves MORDRET 
121560d609f3SPierre-Yves MORDRET static void stm32f7_i2c_slave_addr(struct stm32f7_i2c_dev *i2c_dev)
121660d609f3SPierre-Yves MORDRET {
121760d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
121860d609f3SPierre-Yves MORDRET 	u32 isr, addcode, dir, mask;
121960d609f3SPierre-Yves MORDRET 	int i;
122060d609f3SPierre-Yves MORDRET 
122160d609f3SPierre-Yves MORDRET 	isr = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
122260d609f3SPierre-Yves MORDRET 	addcode = STM32F7_I2C_ISR_ADDCODE_GET(isr);
122360d609f3SPierre-Yves MORDRET 	dir = isr & STM32F7_I2C_ISR_DIR;
122460d609f3SPierre-Yves MORDRET 
122560d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
122660d609f3SPierre-Yves MORDRET 		if (stm32f7_i2c_is_addr_match(i2c_dev->slave[i], addcode)) {
122760d609f3SPierre-Yves MORDRET 			i2c_dev->slave_running = i2c_dev->slave[i];
122860d609f3SPierre-Yves MORDRET 			i2c_dev->slave_dir = dir;
122960d609f3SPierre-Yves MORDRET 
123060d609f3SPierre-Yves MORDRET 			/* Start I2C slave processing */
123160d609f3SPierre-Yves MORDRET 			stm32f7_i2c_slave_start(i2c_dev);
123260d609f3SPierre-Yves MORDRET 
123360d609f3SPierre-Yves MORDRET 			/* Clear ADDR flag */
123460d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ICR_ADDRCF;
123560d609f3SPierre-Yves MORDRET 			writel_relaxed(mask, base + STM32F7_I2C_ICR);
123660d609f3SPierre-Yves MORDRET 			break;
123760d609f3SPierre-Yves MORDRET 		}
123860d609f3SPierre-Yves MORDRET 	}
123960d609f3SPierre-Yves MORDRET }
124060d609f3SPierre-Yves MORDRET 
124160d609f3SPierre-Yves MORDRET static int stm32f7_i2c_get_slave_id(struct stm32f7_i2c_dev *i2c_dev,
124260d609f3SPierre-Yves MORDRET 				    struct i2c_client *slave, int *id)
124360d609f3SPierre-Yves MORDRET {
124460d609f3SPierre-Yves MORDRET 	int i;
124560d609f3SPierre-Yves MORDRET 
124660d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
124760d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave[i] == slave) {
124860d609f3SPierre-Yves MORDRET 			*id = i;
124960d609f3SPierre-Yves MORDRET 			return 0;
125060d609f3SPierre-Yves MORDRET 		}
125160d609f3SPierre-Yves MORDRET 	}
125260d609f3SPierre-Yves MORDRET 
125360d609f3SPierre-Yves MORDRET 	dev_err(i2c_dev->dev, "Slave 0x%x not registered\n", slave->addr);
125460d609f3SPierre-Yves MORDRET 
125560d609f3SPierre-Yves MORDRET 	return -ENODEV;
125660d609f3SPierre-Yves MORDRET }
125760d609f3SPierre-Yves MORDRET 
125860d609f3SPierre-Yves MORDRET static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev,
125960d609f3SPierre-Yves MORDRET 					 struct i2c_client *slave, int *id)
126060d609f3SPierre-Yves MORDRET {
126160d609f3SPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
126260d609f3SPierre-Yves MORDRET 	int i;
126360d609f3SPierre-Yves MORDRET 
126460d609f3SPierre-Yves MORDRET 	/*
126560d609f3SPierre-Yves MORDRET 	 * slave[0] supports 7-bit and 10-bit slave address
126660d609f3SPierre-Yves MORDRET 	 * slave[1] supports 7-bit slave address only
126760d609f3SPierre-Yves MORDRET 	 */
126852d3be71SAlain Volmat 	for (i = STM32F7_I2C_MAX_SLAVE - 1; i >= 0; i--) {
126960d609f3SPierre-Yves MORDRET 		if (i == 1 && (slave->flags & I2C_CLIENT_PEC))
127060d609f3SPierre-Yves MORDRET 			continue;
127160d609f3SPierre-Yves MORDRET 		if (!i2c_dev->slave[i]) {
127260d609f3SPierre-Yves MORDRET 			*id = i;
127360d609f3SPierre-Yves MORDRET 			return 0;
127460d609f3SPierre-Yves MORDRET 		}
127560d609f3SPierre-Yves MORDRET 	}
127660d609f3SPierre-Yves MORDRET 
127760d609f3SPierre-Yves MORDRET 	dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr);
127860d609f3SPierre-Yves MORDRET 
127960d609f3SPierre-Yves MORDRET 	return -EINVAL;
128060d609f3SPierre-Yves MORDRET }
128160d609f3SPierre-Yves MORDRET 
128260d609f3SPierre-Yves MORDRET static bool stm32f7_i2c_is_slave_registered(struct stm32f7_i2c_dev *i2c_dev)
128360d609f3SPierre-Yves MORDRET {
128460d609f3SPierre-Yves MORDRET 	int i;
128560d609f3SPierre-Yves MORDRET 
128660d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
128760d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave[i])
128860d609f3SPierre-Yves MORDRET 			return true;
128960d609f3SPierre-Yves MORDRET 	}
129060d609f3SPierre-Yves MORDRET 
129160d609f3SPierre-Yves MORDRET 	return false;
129260d609f3SPierre-Yves MORDRET }
129360d609f3SPierre-Yves MORDRET 
129460d609f3SPierre-Yves MORDRET static bool stm32f7_i2c_is_slave_busy(struct stm32f7_i2c_dev *i2c_dev)
129560d609f3SPierre-Yves MORDRET {
129660d609f3SPierre-Yves MORDRET 	int i, busy;
129760d609f3SPierre-Yves MORDRET 
129860d609f3SPierre-Yves MORDRET 	busy = 0;
129960d609f3SPierre-Yves MORDRET 	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
130060d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave[i])
130160d609f3SPierre-Yves MORDRET 			busy++;
130260d609f3SPierre-Yves MORDRET 	}
130360d609f3SPierre-Yves MORDRET 
130460d609f3SPierre-Yves MORDRET 	return i == busy;
130560d609f3SPierre-Yves MORDRET }
130660d609f3SPierre-Yves MORDRET 
130760d609f3SPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
130860d609f3SPierre-Yves MORDRET {
130960d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
131060d609f3SPierre-Yves MORDRET 	u32 cr2, status, mask;
131160d609f3SPierre-Yves MORDRET 	u8 val;
131260d609f3SPierre-Yves MORDRET 	int ret;
131360d609f3SPierre-Yves MORDRET 
131460d609f3SPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
131560d609f3SPierre-Yves MORDRET 
131660d609f3SPierre-Yves MORDRET 	/* Slave transmitter mode */
131760d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TXIS) {
131860d609f3SPierre-Yves MORDRET 		i2c_slave_event(i2c_dev->slave_running,
131960d609f3SPierre-Yves MORDRET 				I2C_SLAVE_READ_PROCESSED,
132060d609f3SPierre-Yves MORDRET 				&val);
132160d609f3SPierre-Yves MORDRET 
132260d609f3SPierre-Yves MORDRET 		/* Write data byte */
132360d609f3SPierre-Yves MORDRET 		writel_relaxed(val, base + STM32F7_I2C_TXDR);
132460d609f3SPierre-Yves MORDRET 	}
132560d609f3SPierre-Yves MORDRET 
132660d609f3SPierre-Yves MORDRET 	/* Transfer Complete Reload for Slave receiver mode */
132760d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TCR || status & STM32F7_I2C_ISR_RXNE) {
132860d609f3SPierre-Yves MORDRET 		/*
132960d609f3SPierre-Yves MORDRET 		 * Read data byte then set NBYTES to receive next byte or NACK
133060d609f3SPierre-Yves MORDRET 		 * the current received byte
133160d609f3SPierre-Yves MORDRET 		 */
133260d609f3SPierre-Yves MORDRET 		val = readb_relaxed(i2c_dev->base + STM32F7_I2C_RXDR);
133360d609f3SPierre-Yves MORDRET 		ret = i2c_slave_event(i2c_dev->slave_running,
133460d609f3SPierre-Yves MORDRET 				      I2C_SLAVE_WRITE_RECEIVED,
133560d609f3SPierre-Yves MORDRET 				      &val);
133660d609f3SPierre-Yves MORDRET 		if (!ret) {
133760d609f3SPierre-Yves MORDRET 			cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
133860d609f3SPierre-Yves MORDRET 			cr2 |= STM32F7_I2C_CR2_NBYTES(1);
133960d609f3SPierre-Yves MORDRET 			writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
134060d609f3SPierre-Yves MORDRET 		} else {
134160d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_CR2_NACK;
134260d609f3SPierre-Yves MORDRET 			stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
134360d609f3SPierre-Yves MORDRET 		}
134460d609f3SPierre-Yves MORDRET 	}
134560d609f3SPierre-Yves MORDRET 
134660d609f3SPierre-Yves MORDRET 	/* NACK received */
134760d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_NACKF) {
134860d609f3SPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
134960d609f3SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
135060d609f3SPierre-Yves MORDRET 	}
135160d609f3SPierre-Yves MORDRET 
135260d609f3SPierre-Yves MORDRET 	/* STOP received */
135360d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_STOPF) {
135460d609f3SPierre-Yves MORDRET 		/* Disable interrupts */
135560d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_XFER_IRQ_MASK);
135660d609f3SPierre-Yves MORDRET 
135760d609f3SPierre-Yves MORDRET 		if (i2c_dev->slave_dir) {
135860d609f3SPierre-Yves MORDRET 			/*
135960d609f3SPierre-Yves MORDRET 			 * Flush TX buffer in order to not used the byte in
136060d609f3SPierre-Yves MORDRET 			 * TXDR for the next transfer
136160d609f3SPierre-Yves MORDRET 			 */
136260d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ISR_TXE;
136360d609f3SPierre-Yves MORDRET 			stm32f7_i2c_set_bits(base + STM32F7_I2C_ISR, mask);
136460d609f3SPierre-Yves MORDRET 		}
136560d609f3SPierre-Yves MORDRET 
136660d609f3SPierre-Yves MORDRET 		/* Clear STOP flag */
136760d609f3SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
136860d609f3SPierre-Yves MORDRET 
136960d609f3SPierre-Yves MORDRET 		/* Notify i2c slave that a STOP flag has been detected */
137060d609f3SPierre-Yves MORDRET 		i2c_slave_event(i2c_dev->slave_running, I2C_SLAVE_STOP, &val);
137160d609f3SPierre-Yves MORDRET 
137260d609f3SPierre-Yves MORDRET 		i2c_dev->slave_running = NULL;
137360d609f3SPierre-Yves MORDRET 	}
137460d609f3SPierre-Yves MORDRET 
137560d609f3SPierre-Yves MORDRET 	/* Address match received */
137660d609f3SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_ADDR)
137760d609f3SPierre-Yves MORDRET 		stm32f7_i2c_slave_addr(i2c_dev);
137860d609f3SPierre-Yves MORDRET 
137960d609f3SPierre-Yves MORDRET 	return IRQ_HANDLED;
1380aeb068c5SPierre-Yves MORDRET }
1381aeb068c5SPierre-Yves MORDRET 
1382aeb068c5SPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
1383aeb068c5SPierre-Yves MORDRET {
1384aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = data;
1385aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1386aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
1387aeb068c5SPierre-Yves MORDRET 	u32 status, mask;
13887ecc8cfdSPierre-Yves MORDRET 	int ret = IRQ_HANDLED;
138960d609f3SPierre-Yves MORDRET 
139060d609f3SPierre-Yves MORDRET 	/* Check if the interrupt if for a slave device */
139160d609f3SPierre-Yves MORDRET 	if (!i2c_dev->master_mode) {
139260d609f3SPierre-Yves MORDRET 		ret = stm32f7_i2c_slave_isr_event(i2c_dev);
139360d609f3SPierre-Yves MORDRET 		return ret;
139460d609f3SPierre-Yves MORDRET 	}
1395aeb068c5SPierre-Yves MORDRET 
1396aeb068c5SPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
1397aeb068c5SPierre-Yves MORDRET 
1398aeb068c5SPierre-Yves MORDRET 	/* Tx empty */
1399aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TXIS)
1400aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_write_tx_data(i2c_dev);
1401aeb068c5SPierre-Yves MORDRET 
1402aeb068c5SPierre-Yves MORDRET 	/* RX not empty */
1403aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_RXNE)
1404aeb068c5SPierre-Yves MORDRET 		stm32f7_i2c_read_rx_data(i2c_dev);
1405aeb068c5SPierre-Yves MORDRET 
1406aeb068c5SPierre-Yves MORDRET 	/* NACK received */
1407aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_NACKF) {
1408aeb068c5SPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
1409aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
1410aeb068c5SPierre-Yves MORDRET 		f7_msg->result = -ENXIO;
1411aeb068c5SPierre-Yves MORDRET 	}
1412aeb068c5SPierre-Yves MORDRET 
1413aeb068c5SPierre-Yves MORDRET 	/* STOP detection flag */
1414aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_STOPF) {
1415aeb068c5SPierre-Yves MORDRET 		/* Disable interrupts */
141660d609f3SPierre-Yves MORDRET 		if (stm32f7_i2c_is_slave_registered(i2c_dev))
141760d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_XFER_IRQ_MASK;
141860d609f3SPierre-Yves MORDRET 		else
141960d609f3SPierre-Yves MORDRET 			mask = STM32F7_I2C_ALL_IRQ_MASK;
142060d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, mask);
1421aeb068c5SPierre-Yves MORDRET 
1422aeb068c5SPierre-Yves MORDRET 		/* Clear STOP flag */
1423aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
1424aeb068c5SPierre-Yves MORDRET 
14257ecc8cfdSPierre-Yves MORDRET 		if (i2c_dev->use_dma) {
14267ecc8cfdSPierre-Yves MORDRET 			ret = IRQ_WAKE_THREAD;
14277ecc8cfdSPierre-Yves MORDRET 		} else {
142860d609f3SPierre-Yves MORDRET 			i2c_dev->master_mode = false;
1429aeb068c5SPierre-Yves MORDRET 			complete(&i2c_dev->complete);
1430aeb068c5SPierre-Yves MORDRET 		}
14317ecc8cfdSPierre-Yves MORDRET 	}
1432aeb068c5SPierre-Yves MORDRET 
1433aeb068c5SPierre-Yves MORDRET 	/* Transfer complete */
1434aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TC) {
1435aeb068c5SPierre-Yves MORDRET 		if (f7_msg->stop) {
1436aeb068c5SPierre-Yves MORDRET 			mask = STM32F7_I2C_CR2_STOP;
1437aeb068c5SPierre-Yves MORDRET 			stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
14387ecc8cfdSPierre-Yves MORDRET 		} else if (i2c_dev->use_dma) {
14397ecc8cfdSPierre-Yves MORDRET 			ret = IRQ_WAKE_THREAD;
14409e48155fSPierre-Yves MORDRET 		} else if (f7_msg->smbus) {
14419e48155fSPierre-Yves MORDRET 			stm32f7_i2c_smbus_rep_start(i2c_dev);
1442aeb068c5SPierre-Yves MORDRET 		} else {
1443aeb068c5SPierre-Yves MORDRET 			i2c_dev->msg_id++;
1444aeb068c5SPierre-Yves MORDRET 			i2c_dev->msg++;
1445aeb068c5SPierre-Yves MORDRET 			stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
1446aeb068c5SPierre-Yves MORDRET 		}
1447aeb068c5SPierre-Yves MORDRET 	}
1448aeb068c5SPierre-Yves MORDRET 
14499e48155fSPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TCR) {
14509e48155fSPierre-Yves MORDRET 		if (f7_msg->smbus)
14519e48155fSPierre-Yves MORDRET 			stm32f7_i2c_smbus_reload(i2c_dev);
14529e48155fSPierre-Yves MORDRET 		else
1453aeb068c5SPierre-Yves MORDRET 			stm32f7_i2c_reload(i2c_dev);
14549e48155fSPierre-Yves MORDRET 	}
1455aeb068c5SPierre-Yves MORDRET 
14567ecc8cfdSPierre-Yves MORDRET 	return ret;
14577ecc8cfdSPierre-Yves MORDRET }
14587ecc8cfdSPierre-Yves MORDRET 
14597ecc8cfdSPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
14607ecc8cfdSPierre-Yves MORDRET {
14617ecc8cfdSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = data;
14627ecc8cfdSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
14637ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
14647ecc8cfdSPierre-Yves MORDRET 	u32 status;
14657ecc8cfdSPierre-Yves MORDRET 	int ret;
14667ecc8cfdSPierre-Yves MORDRET 
14677ecc8cfdSPierre-Yves MORDRET 	/*
14687ecc8cfdSPierre-Yves MORDRET 	 * Wait for dma transfer completion before sending next message or
14697ecc8cfdSPierre-Yves MORDRET 	 * notity the end of xfer to the client
14707ecc8cfdSPierre-Yves MORDRET 	 */
14717ecc8cfdSPierre-Yves MORDRET 	ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
14727ecc8cfdSPierre-Yves MORDRET 	if (!ret) {
14737ecc8cfdSPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
14747ecc8cfdSPierre-Yves MORDRET 		stm32f7_i2c_disable_dma_req(i2c_dev);
14757ecc8cfdSPierre-Yves MORDRET 		dmaengine_terminate_all(dma->chan_using);
14767ecc8cfdSPierre-Yves MORDRET 		f7_msg->result = -ETIMEDOUT;
14777ecc8cfdSPierre-Yves MORDRET 	}
14787ecc8cfdSPierre-Yves MORDRET 
14797ecc8cfdSPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
14807ecc8cfdSPierre-Yves MORDRET 
14817ecc8cfdSPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_TC) {
14827ecc8cfdSPierre-Yves MORDRET 		if (f7_msg->smbus) {
14837ecc8cfdSPierre-Yves MORDRET 			stm32f7_i2c_smbus_rep_start(i2c_dev);
14847ecc8cfdSPierre-Yves MORDRET 		} else {
14857ecc8cfdSPierre-Yves MORDRET 			i2c_dev->msg_id++;
14867ecc8cfdSPierre-Yves MORDRET 			i2c_dev->msg++;
14877ecc8cfdSPierre-Yves MORDRET 			stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
14887ecc8cfdSPierre-Yves MORDRET 		}
14897ecc8cfdSPierre-Yves MORDRET 	} else {
14907ecc8cfdSPierre-Yves MORDRET 		i2c_dev->master_mode = false;
14917ecc8cfdSPierre-Yves MORDRET 		complete(&i2c_dev->complete);
14927ecc8cfdSPierre-Yves MORDRET 	}
14937ecc8cfdSPierre-Yves MORDRET 
1494aeb068c5SPierre-Yves MORDRET 	return IRQ_HANDLED;
1495aeb068c5SPierre-Yves MORDRET }
1496aeb068c5SPierre-Yves MORDRET 
1497aeb068c5SPierre-Yves MORDRET static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
1498aeb068c5SPierre-Yves MORDRET {
1499aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = data;
1500aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1501aeb068c5SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
1502aeb068c5SPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
15037ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
150460d609f3SPierre-Yves MORDRET 	u32 mask, status;
1505aeb068c5SPierre-Yves MORDRET 
1506aeb068c5SPierre-Yves MORDRET 	status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
1507aeb068c5SPierre-Yves MORDRET 
1508aeb068c5SPierre-Yves MORDRET 	/* Bus error */
1509aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_BERR) {
1510aeb068c5SPierre-Yves MORDRET 		dev_err(dev, "<%s>: Bus error\n", __func__);
1511aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
1512562de4ffSPierre-Yves MORDRET 		stm32f7_i2c_release_bus(&i2c_dev->adap);
1513aeb068c5SPierre-Yves MORDRET 		f7_msg->result = -EIO;
1514aeb068c5SPierre-Yves MORDRET 	}
1515aeb068c5SPierre-Yves MORDRET 
1516aeb068c5SPierre-Yves MORDRET 	/* Arbitration loss */
1517aeb068c5SPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_ARLO) {
1518aeb068c5SPierre-Yves MORDRET 		dev_dbg(dev, "<%s>: Arbitration loss\n", __func__);
1519aeb068c5SPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR);
1520aeb068c5SPierre-Yves MORDRET 		f7_msg->result = -EAGAIN;
1521aeb068c5SPierre-Yves MORDRET 	}
1522aeb068c5SPierre-Yves MORDRET 
15239e48155fSPierre-Yves MORDRET 	if (status & STM32F7_I2C_ISR_PECERR) {
15249e48155fSPierre-Yves MORDRET 		dev_err(dev, "<%s>: PEC error in reception\n", __func__);
15259e48155fSPierre-Yves MORDRET 		writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
15269e48155fSPierre-Yves MORDRET 		f7_msg->result = -EINVAL;
15279e48155fSPierre-Yves MORDRET 	}
15289e48155fSPierre-Yves MORDRET 
152960d609f3SPierre-Yves MORDRET 	/* Disable interrupts */
153060d609f3SPierre-Yves MORDRET 	if (stm32f7_i2c_is_slave_registered(i2c_dev))
153160d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_XFER_IRQ_MASK;
153260d609f3SPierre-Yves MORDRET 	else
153360d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_ALL_IRQ_MASK;
153460d609f3SPierre-Yves MORDRET 	stm32f7_i2c_disable_irq(i2c_dev, mask);
1535aeb068c5SPierre-Yves MORDRET 
15367ecc8cfdSPierre-Yves MORDRET 	/* Disable dma */
15377ecc8cfdSPierre-Yves MORDRET 	if (i2c_dev->use_dma) {
15387ecc8cfdSPierre-Yves MORDRET 		stm32f7_i2c_disable_dma_req(i2c_dev);
15397ecc8cfdSPierre-Yves MORDRET 		dmaengine_terminate_all(dma->chan_using);
15407ecc8cfdSPierre-Yves MORDRET 	}
15417ecc8cfdSPierre-Yves MORDRET 
154260d609f3SPierre-Yves MORDRET 	i2c_dev->master_mode = false;
1543aeb068c5SPierre-Yves MORDRET 	complete(&i2c_dev->complete);
1544aeb068c5SPierre-Yves MORDRET 
1545aeb068c5SPierre-Yves MORDRET 	return IRQ_HANDLED;
1546aeb068c5SPierre-Yves MORDRET }
1547aeb068c5SPierre-Yves MORDRET 
1548aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
1549aeb068c5SPierre-Yves MORDRET 			    struct i2c_msg msgs[], int num)
1550aeb068c5SPierre-Yves MORDRET {
1551aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
1552aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
15537ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
1554aeb068c5SPierre-Yves MORDRET 	unsigned long time_left;
1555aeb068c5SPierre-Yves MORDRET 	int ret;
1556aeb068c5SPierre-Yves MORDRET 
1557aeb068c5SPierre-Yves MORDRET 	i2c_dev->msg = msgs;
1558aeb068c5SPierre-Yves MORDRET 	i2c_dev->msg_num = num;
1559aeb068c5SPierre-Yves MORDRET 	i2c_dev->msg_id = 0;
15609e48155fSPierre-Yves MORDRET 	f7_msg->smbus = false;
1561aeb068c5SPierre-Yves MORDRET 
15624e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(i2c_dev->dev);
15634e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
1564aeb068c5SPierre-Yves MORDRET 		return ret;
1565aeb068c5SPierre-Yves MORDRET 
1566aeb068c5SPierre-Yves MORDRET 	ret = stm32f7_i2c_wait_free_bus(i2c_dev);
1567aeb068c5SPierre-Yves MORDRET 	if (ret)
15684e7bca6fSPierre-Yves MORDRET 		goto pm_free;
1569aeb068c5SPierre-Yves MORDRET 
1570aeb068c5SPierre-Yves MORDRET 	stm32f7_i2c_xfer_msg(i2c_dev, msgs);
1571aeb068c5SPierre-Yves MORDRET 
1572aeb068c5SPierre-Yves MORDRET 	time_left = wait_for_completion_timeout(&i2c_dev->complete,
1573aeb068c5SPierre-Yves MORDRET 						i2c_dev->adap.timeout);
1574aeb068c5SPierre-Yves MORDRET 	ret = f7_msg->result;
1575aeb068c5SPierre-Yves MORDRET 
1576aeb068c5SPierre-Yves MORDRET 	if (!time_left) {
1577aeb068c5SPierre-Yves MORDRET 		dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
1578aeb068c5SPierre-Yves MORDRET 			i2c_dev->msg->addr);
15797ecc8cfdSPierre-Yves MORDRET 		if (i2c_dev->use_dma)
15807ecc8cfdSPierre-Yves MORDRET 			dmaengine_terminate_all(dma->chan_using);
1581aeb068c5SPierre-Yves MORDRET 		ret = -ETIMEDOUT;
1582aeb068c5SPierre-Yves MORDRET 	}
1583aeb068c5SPierre-Yves MORDRET 
15844e7bca6fSPierre-Yves MORDRET pm_free:
15854e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(i2c_dev->dev);
15864e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(i2c_dev->dev);
1587aeb068c5SPierre-Yves MORDRET 
1588aeb068c5SPierre-Yves MORDRET 	return (ret < 0) ? ret : num;
1589aeb068c5SPierre-Yves MORDRET }
1590aeb068c5SPierre-Yves MORDRET 
15919e48155fSPierre-Yves MORDRET static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
15929e48155fSPierre-Yves MORDRET 				  unsigned short flags, char read_write,
15939e48155fSPierre-Yves MORDRET 				  u8 command, int size,
15949e48155fSPierre-Yves MORDRET 				  union i2c_smbus_data *data)
15959e48155fSPierre-Yves MORDRET {
15969e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adapter);
15979e48155fSPierre-Yves MORDRET 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
15987ecc8cfdSPierre-Yves MORDRET 	struct stm32_i2c_dma *dma = i2c_dev->dma;
15999e48155fSPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
16009e48155fSPierre-Yves MORDRET 	unsigned long timeout;
16019e48155fSPierre-Yves MORDRET 	int i, ret;
16029e48155fSPierre-Yves MORDRET 
16039e48155fSPierre-Yves MORDRET 	f7_msg->addr = addr;
16049e48155fSPierre-Yves MORDRET 	f7_msg->size = size;
16059e48155fSPierre-Yves MORDRET 	f7_msg->read_write = read_write;
16069e48155fSPierre-Yves MORDRET 	f7_msg->smbus = true;
16079e48155fSPierre-Yves MORDRET 
16084e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(dev);
16094e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
16109e48155fSPierre-Yves MORDRET 		return ret;
16119e48155fSPierre-Yves MORDRET 
16129e48155fSPierre-Yves MORDRET 	ret = stm32f7_i2c_wait_free_bus(i2c_dev);
16139e48155fSPierre-Yves MORDRET 	if (ret)
16144e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16159e48155fSPierre-Yves MORDRET 
16169e48155fSPierre-Yves MORDRET 	ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
16179e48155fSPierre-Yves MORDRET 	if (ret)
16184e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16199e48155fSPierre-Yves MORDRET 
16209e48155fSPierre-Yves MORDRET 	timeout = wait_for_completion_timeout(&i2c_dev->complete,
16219e48155fSPierre-Yves MORDRET 					      i2c_dev->adap.timeout);
16229e48155fSPierre-Yves MORDRET 	ret = f7_msg->result;
16239e48155fSPierre-Yves MORDRET 	if (ret)
16244e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16259e48155fSPierre-Yves MORDRET 
16269e48155fSPierre-Yves MORDRET 	if (!timeout) {
16279e48155fSPierre-Yves MORDRET 		dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
16287ecc8cfdSPierre-Yves MORDRET 		if (i2c_dev->use_dma)
16297ecc8cfdSPierre-Yves MORDRET 			dmaengine_terminate_all(dma->chan_using);
16309e48155fSPierre-Yves MORDRET 		ret = -ETIMEDOUT;
16314e7bca6fSPierre-Yves MORDRET 		goto pm_free;
16329e48155fSPierre-Yves MORDRET 	}
16339e48155fSPierre-Yves MORDRET 
16349e48155fSPierre-Yves MORDRET 	/* Check PEC */
16359e48155fSPierre-Yves MORDRET 	if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
16369e48155fSPierre-Yves MORDRET 		ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
16379e48155fSPierre-Yves MORDRET 		if (ret)
16384e7bca6fSPierre-Yves MORDRET 			goto pm_free;
16399e48155fSPierre-Yves MORDRET 	}
16409e48155fSPierre-Yves MORDRET 
16419e48155fSPierre-Yves MORDRET 	if (read_write && size != I2C_SMBUS_QUICK) {
16429e48155fSPierre-Yves MORDRET 		switch (size) {
16439e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BYTE:
16449e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BYTE_DATA:
16459e48155fSPierre-Yves MORDRET 			data->byte = f7_msg->smbus_buf[0];
16469e48155fSPierre-Yves MORDRET 		break;
16479e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_WORD_DATA:
16489e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_PROC_CALL:
16499e48155fSPierre-Yves MORDRET 			data->word = f7_msg->smbus_buf[0] |
16509e48155fSPierre-Yves MORDRET 				(f7_msg->smbus_buf[1] << 8);
16519e48155fSPierre-Yves MORDRET 		break;
16529e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BLOCK_DATA:
16539e48155fSPierre-Yves MORDRET 		case I2C_SMBUS_BLOCK_PROC_CALL:
16549e48155fSPierre-Yves MORDRET 		for (i = 0; i <= f7_msg->smbus_buf[0]; i++)
16559e48155fSPierre-Yves MORDRET 			data->block[i] = f7_msg->smbus_buf[i];
16569e48155fSPierre-Yves MORDRET 		break;
16579e48155fSPierre-Yves MORDRET 		default:
16589e48155fSPierre-Yves MORDRET 			dev_err(dev, "Unsupported smbus transaction\n");
16599e48155fSPierre-Yves MORDRET 			ret = -EINVAL;
16609e48155fSPierre-Yves MORDRET 		}
16619e48155fSPierre-Yves MORDRET 	}
16629e48155fSPierre-Yves MORDRET 
16634e7bca6fSPierre-Yves MORDRET pm_free:
16644e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(dev);
16654e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(dev);
16669e48155fSPierre-Yves MORDRET 	return ret;
16679e48155fSPierre-Yves MORDRET }
16689e48155fSPierre-Yves MORDRET 
166960d609f3SPierre-Yves MORDRET static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
167060d609f3SPierre-Yves MORDRET {
167160d609f3SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
167260d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
167360d609f3SPierre-Yves MORDRET 	struct device *dev = i2c_dev->dev;
167460d609f3SPierre-Yves MORDRET 	u32 oar1, oar2, mask;
167560d609f3SPierre-Yves MORDRET 	int id, ret;
167660d609f3SPierre-Yves MORDRET 
167760d609f3SPierre-Yves MORDRET 	if (slave->flags & I2C_CLIENT_PEC) {
167860d609f3SPierre-Yves MORDRET 		dev_err(dev, "SMBus PEC not supported in slave mode\n");
167960d609f3SPierre-Yves MORDRET 		return -EINVAL;
168060d609f3SPierre-Yves MORDRET 	}
168160d609f3SPierre-Yves MORDRET 
168260d609f3SPierre-Yves MORDRET 	if (stm32f7_i2c_is_slave_busy(i2c_dev)) {
168360d609f3SPierre-Yves MORDRET 		dev_err(dev, "Too much slave registered\n");
168460d609f3SPierre-Yves MORDRET 		return -EBUSY;
168560d609f3SPierre-Yves MORDRET 	}
168660d609f3SPierre-Yves MORDRET 
168760d609f3SPierre-Yves MORDRET 	ret = stm32f7_i2c_get_free_slave_id(i2c_dev, slave, &id);
168860d609f3SPierre-Yves MORDRET 	if (ret)
168960d609f3SPierre-Yves MORDRET 		return ret;
169060d609f3SPierre-Yves MORDRET 
16914e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(dev);
16924e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
169360d609f3SPierre-Yves MORDRET 		return ret;
169460d609f3SPierre-Yves MORDRET 
169560d609f3SPierre-Yves MORDRET 	if (id == 0) {
169660d609f3SPierre-Yves MORDRET 		/* Configure Own Address 1 */
169760d609f3SPierre-Yves MORDRET 		oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
169860d609f3SPierre-Yves MORDRET 		oar1 &= ~STM32F7_I2C_OAR1_MASK;
169960d609f3SPierre-Yves MORDRET 		if (slave->flags & I2C_CLIENT_TEN) {
170060d609f3SPierre-Yves MORDRET 			oar1 |= STM32F7_I2C_OAR1_OA1_10(slave->addr);
170160d609f3SPierre-Yves MORDRET 			oar1 |= STM32F7_I2C_OAR1_OA1MODE;
170260d609f3SPierre-Yves MORDRET 		} else {
170360d609f3SPierre-Yves MORDRET 			oar1 |= STM32F7_I2C_OAR1_OA1_7(slave->addr);
170460d609f3SPierre-Yves MORDRET 		}
170560d609f3SPierre-Yves MORDRET 		oar1 |= STM32F7_I2C_OAR1_OA1EN;
170660d609f3SPierre-Yves MORDRET 		i2c_dev->slave[id] = slave;
170760d609f3SPierre-Yves MORDRET 		writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1);
170860d609f3SPierre-Yves MORDRET 	} else if (id == 1) {
170960d609f3SPierre-Yves MORDRET 		/* Configure Own Address 2 */
171060d609f3SPierre-Yves MORDRET 		oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
171160d609f3SPierre-Yves MORDRET 		oar2 &= ~STM32F7_I2C_OAR2_MASK;
171260d609f3SPierre-Yves MORDRET 		if (slave->flags & I2C_CLIENT_TEN) {
171360d609f3SPierre-Yves MORDRET 			ret = -EOPNOTSUPP;
17144e7bca6fSPierre-Yves MORDRET 			goto pm_free;
171560d609f3SPierre-Yves MORDRET 		}
171660d609f3SPierre-Yves MORDRET 
171760d609f3SPierre-Yves MORDRET 		oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
171860d609f3SPierre-Yves MORDRET 		oar2 |= STM32F7_I2C_OAR2_OA2EN;
171960d609f3SPierre-Yves MORDRET 		i2c_dev->slave[id] = slave;
172060d609f3SPierre-Yves MORDRET 		writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
172160d609f3SPierre-Yves MORDRET 	} else {
172260d609f3SPierre-Yves MORDRET 		ret = -ENODEV;
17234e7bca6fSPierre-Yves MORDRET 		goto pm_free;
172460d609f3SPierre-Yves MORDRET 	}
172560d609f3SPierre-Yves MORDRET 
172660d609f3SPierre-Yves MORDRET 	/* Enable ACK */
172760d609f3SPierre-Yves MORDRET 	stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, STM32F7_I2C_CR2_NACK);
172860d609f3SPierre-Yves MORDRET 
172960d609f3SPierre-Yves MORDRET 	/* Enable Address match interrupt, error interrupt and enable I2C  */
173060d609f3SPierre-Yves MORDRET 	mask = STM32F7_I2C_CR1_ADDRIE | STM32F7_I2C_CR1_ERRIE |
173160d609f3SPierre-Yves MORDRET 		STM32F7_I2C_CR1_PE;
173260d609f3SPierre-Yves MORDRET 	stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
173360d609f3SPierre-Yves MORDRET 
17344e7bca6fSPierre-Yves MORDRET 	ret = 0;
17354e7bca6fSPierre-Yves MORDRET pm_free:
17364e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(dev);
17374e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(dev);
173860d609f3SPierre-Yves MORDRET 
173960d609f3SPierre-Yves MORDRET 	return ret;
174060d609f3SPierre-Yves MORDRET }
174160d609f3SPierre-Yves MORDRET 
174260d609f3SPierre-Yves MORDRET static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
174360d609f3SPierre-Yves MORDRET {
174460d609f3SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
174560d609f3SPierre-Yves MORDRET 	void __iomem *base = i2c_dev->base;
174660d609f3SPierre-Yves MORDRET 	u32 mask;
174760d609f3SPierre-Yves MORDRET 	int id, ret;
174860d609f3SPierre-Yves MORDRET 
174960d609f3SPierre-Yves MORDRET 	ret = stm32f7_i2c_get_slave_id(i2c_dev, slave, &id);
175060d609f3SPierre-Yves MORDRET 	if (ret)
175160d609f3SPierre-Yves MORDRET 		return ret;
175260d609f3SPierre-Yves MORDRET 
175360d609f3SPierre-Yves MORDRET 	WARN_ON(!i2c_dev->slave[id]);
175460d609f3SPierre-Yves MORDRET 
17554e7bca6fSPierre-Yves MORDRET 	ret = pm_runtime_get_sync(i2c_dev->dev);
17564e7bca6fSPierre-Yves MORDRET 	if (ret < 0)
17574e7bca6fSPierre-Yves MORDRET 		return ret;
17584e7bca6fSPierre-Yves MORDRET 
175960d609f3SPierre-Yves MORDRET 	if (id == 0) {
176060d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_OAR1_OA1EN;
176160d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
176260d609f3SPierre-Yves MORDRET 	} else {
176360d609f3SPierre-Yves MORDRET 		mask = STM32F7_I2C_OAR2_OA2EN;
176460d609f3SPierre-Yves MORDRET 		stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask);
176560d609f3SPierre-Yves MORDRET 	}
176660d609f3SPierre-Yves MORDRET 
176760d609f3SPierre-Yves MORDRET 	i2c_dev->slave[id] = NULL;
176860d609f3SPierre-Yves MORDRET 
17694e7bca6fSPierre-Yves MORDRET 	if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
177060d609f3SPierre-Yves MORDRET 		stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
17714e7bca6fSPierre-Yves MORDRET 
17724e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(i2c_dev->dev);
17734e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(i2c_dev->dev);
177460d609f3SPierre-Yves MORDRET 
177560d609f3SPierre-Yves MORDRET 	return 0;
177660d609f3SPierre-Yves MORDRET }
177760d609f3SPierre-Yves MORDRET 
1778cb944fb9SPierre-Yves MORDRET static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev,
1779cb944fb9SPierre-Yves MORDRET 					  struct stm32f7_i2c_dev *i2c_dev)
1780cb944fb9SPierre-Yves MORDRET {
1781cb944fb9SPierre-Yves MORDRET 	struct device_node *np = pdev->dev.of_node;
1782cb944fb9SPierre-Yves MORDRET 	int ret;
1783cb944fb9SPierre-Yves MORDRET 	u32 reg, mask;
1784cb944fb9SPierre-Yves MORDRET 
1785cb944fb9SPierre-Yves MORDRET 	i2c_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp");
1786cb944fb9SPierre-Yves MORDRET 	if (IS_ERR(i2c_dev->regmap)) {
1787cb944fb9SPierre-Yves MORDRET 		/* Optional */
1788cb944fb9SPierre-Yves MORDRET 		return 0;
1789cb944fb9SPierre-Yves MORDRET 	}
1790cb944fb9SPierre-Yves MORDRET 
1791cb944fb9SPierre-Yves MORDRET 	ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, &reg);
1792cb944fb9SPierre-Yves MORDRET 	if (ret)
1793cb944fb9SPierre-Yves MORDRET 		return ret;
1794cb944fb9SPierre-Yves MORDRET 
1795cb944fb9SPierre-Yves MORDRET 	ret = of_property_read_u32_index(np, "st,syscfg-fmp", 2, &mask);
1796cb944fb9SPierre-Yves MORDRET 	if (ret)
1797cb944fb9SPierre-Yves MORDRET 		return ret;
1798cb944fb9SPierre-Yves MORDRET 
1799cb944fb9SPierre-Yves MORDRET 	return regmap_update_bits(i2c_dev->regmap, reg, mask, mask);
1800cb944fb9SPierre-Yves MORDRET }
1801cb944fb9SPierre-Yves MORDRET 
1802aeb068c5SPierre-Yves MORDRET static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
1803aeb068c5SPierre-Yves MORDRET {
18049e48155fSPierre-Yves MORDRET 	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
18059e48155fSPierre-Yves MORDRET 		I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
18069e48155fSPierre-Yves MORDRET 		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
18079e48155fSPierre-Yves MORDRET 		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
1808473fbdf7SFabrice Gasnier 		I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
1809473fbdf7SFabrice Gasnier 		I2C_FUNC_SMBUS_I2C_BLOCK;
1810aeb068c5SPierre-Yves MORDRET }
1811aeb068c5SPierre-Yves MORDRET 
18122252c317SNishka Dasgupta static const struct i2c_algorithm stm32f7_i2c_algo = {
1813aeb068c5SPierre-Yves MORDRET 	.master_xfer = stm32f7_i2c_xfer,
18149e48155fSPierre-Yves MORDRET 	.smbus_xfer = stm32f7_i2c_smbus_xfer,
1815aeb068c5SPierre-Yves MORDRET 	.functionality = stm32f7_i2c_func,
181660d609f3SPierre-Yves MORDRET 	.reg_slave = stm32f7_i2c_reg_slave,
181760d609f3SPierre-Yves MORDRET 	.unreg_slave = stm32f7_i2c_unreg_slave,
1818aeb068c5SPierre-Yves MORDRET };
1819aeb068c5SPierre-Yves MORDRET 
1820aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_probe(struct platform_device *pdev)
1821aeb068c5SPierre-Yves MORDRET {
1822aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev;
1823aeb068c5SPierre-Yves MORDRET 	const struct stm32f7_i2c_setup *setup;
1824aeb068c5SPierre-Yves MORDRET 	struct resource *res;
182579b44995SFabrice Gasnier 	u32 clk_rate, rise_time, fall_time;
1826aeb068c5SPierre-Yves MORDRET 	struct i2c_adapter *adap;
1827aeb068c5SPierre-Yves MORDRET 	struct reset_control *rst;
18287ecc8cfdSPierre-Yves MORDRET 	dma_addr_t phy_addr;
182979b44995SFabrice Gasnier 	int irq_error, irq_event, ret;
1830aeb068c5SPierre-Yves MORDRET 
1831aeb068c5SPierre-Yves MORDRET 	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
1832aeb068c5SPierre-Yves MORDRET 	if (!i2c_dev)
1833aeb068c5SPierre-Yves MORDRET 		return -ENOMEM;
1834aeb068c5SPierre-Yves MORDRET 
1835aeb068c5SPierre-Yves MORDRET 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1836aeb068c5SPierre-Yves MORDRET 	i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
1837aeb068c5SPierre-Yves MORDRET 	if (IS_ERR(i2c_dev->base))
1838aeb068c5SPierre-Yves MORDRET 		return PTR_ERR(i2c_dev->base);
18397ecc8cfdSPierre-Yves MORDRET 	phy_addr = (dma_addr_t)res->start;
1840aeb068c5SPierre-Yves MORDRET 
184179b44995SFabrice Gasnier 	irq_event = platform_get_irq(pdev, 0);
184279b44995SFabrice Gasnier 	if (irq_event <= 0) {
184379b44995SFabrice Gasnier 		if (irq_event != -EPROBE_DEFER)
184479b44995SFabrice Gasnier 			dev_err(&pdev->dev, "Failed to get IRQ event: %d\n",
184579b44995SFabrice Gasnier 				irq_event);
184679b44995SFabrice Gasnier 		return irq_event ? : -ENOENT;
1847aeb068c5SPierre-Yves MORDRET 	}
1848aeb068c5SPierre-Yves MORDRET 
184979b44995SFabrice Gasnier 	irq_error = platform_get_irq(pdev, 1);
185079b44995SFabrice Gasnier 	if (irq_error <= 0) {
185179b44995SFabrice Gasnier 		if (irq_error != -EPROBE_DEFER)
185279b44995SFabrice Gasnier 			dev_err(&pdev->dev, "Failed to get IRQ error: %d\n",
185379b44995SFabrice Gasnier 				irq_error);
185479b44995SFabrice Gasnier 		return irq_error ? : -ENOENT;
1855aeb068c5SPierre-Yves MORDRET 	}
1856aeb068c5SPierre-Yves MORDRET 
1857aeb068c5SPierre-Yves MORDRET 	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
1858aeb068c5SPierre-Yves MORDRET 	if (IS_ERR(i2c_dev->clk)) {
1859aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Error: Missing controller clock\n");
1860aeb068c5SPierre-Yves MORDRET 		return PTR_ERR(i2c_dev->clk);
1861aeb068c5SPierre-Yves MORDRET 	}
18624e7bca6fSPierre-Yves MORDRET 
1863aeb068c5SPierre-Yves MORDRET 	ret = clk_prepare_enable(i2c_dev->clk);
1864aeb068c5SPierre-Yves MORDRET 	if (ret) {
1865aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
1866aeb068c5SPierre-Yves MORDRET 		return ret;
1867aeb068c5SPierre-Yves MORDRET 	}
1868aeb068c5SPierre-Yves MORDRET 
1869aeb068c5SPierre-Yves MORDRET 	i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1870aeb068c5SPierre-Yves MORDRET 	ret = device_property_read_u32(&pdev->dev, "clock-frequency",
1871aeb068c5SPierre-Yves MORDRET 				       &clk_rate);
1872cb944fb9SPierre-Yves MORDRET 	if (!ret && clk_rate >= 1000000) {
1873aeb068c5SPierre-Yves MORDRET 		i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
1874cb944fb9SPierre-Yves MORDRET 		ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
1875cb944fb9SPierre-Yves MORDRET 		if (ret)
1876cb944fb9SPierre-Yves MORDRET 			goto clk_free;
1877cb944fb9SPierre-Yves MORDRET 	} else if (!ret && clk_rate >= 400000) {
1878aeb068c5SPierre-Yves MORDRET 		i2c_dev->speed = STM32_I2C_SPEED_FAST;
1879cb944fb9SPierre-Yves MORDRET 	} else if (!ret && clk_rate >= 100000) {
1880aeb068c5SPierre-Yves MORDRET 		i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
1881cb944fb9SPierre-Yves MORDRET 	}
1882aeb068c5SPierre-Yves MORDRET 
1883aeb068c5SPierre-Yves MORDRET 	rst = devm_reset_control_get(&pdev->dev, NULL);
1884aeb068c5SPierre-Yves MORDRET 	if (IS_ERR(rst)) {
1885aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Error: Missing controller reset\n");
1886aeb068c5SPierre-Yves MORDRET 		ret = PTR_ERR(rst);
1887aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1888aeb068c5SPierre-Yves MORDRET 	}
1889aeb068c5SPierre-Yves MORDRET 	reset_control_assert(rst);
1890aeb068c5SPierre-Yves MORDRET 	udelay(2);
1891aeb068c5SPierre-Yves MORDRET 	reset_control_deassert(rst);
1892aeb068c5SPierre-Yves MORDRET 
1893aeb068c5SPierre-Yves MORDRET 	i2c_dev->dev = &pdev->dev;
1894aeb068c5SPierre-Yves MORDRET 
18957ecc8cfdSPierre-Yves MORDRET 	ret = devm_request_threaded_irq(&pdev->dev, irq_event,
18967ecc8cfdSPierre-Yves MORDRET 					stm32f7_i2c_isr_event,
18977ecc8cfdSPierre-Yves MORDRET 					stm32f7_i2c_isr_event_thread,
18987ecc8cfdSPierre-Yves MORDRET 					IRQF_ONESHOT,
1899aeb068c5SPierre-Yves MORDRET 					pdev->name, i2c_dev);
1900aeb068c5SPierre-Yves MORDRET 	if (ret) {
1901aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Failed to request irq event %i\n",
1902aeb068c5SPierre-Yves MORDRET 			irq_event);
1903aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1904aeb068c5SPierre-Yves MORDRET 	}
1905aeb068c5SPierre-Yves MORDRET 
1906aeb068c5SPierre-Yves MORDRET 	ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
1907aeb068c5SPierre-Yves MORDRET 			       pdev->name, i2c_dev);
1908aeb068c5SPierre-Yves MORDRET 	if (ret) {
1909aeb068c5SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Failed to request irq error %i\n",
1910aeb068c5SPierre-Yves MORDRET 			irq_error);
1911aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1912aeb068c5SPierre-Yves MORDRET 	}
1913aeb068c5SPierre-Yves MORDRET 
1914aeb068c5SPierre-Yves MORDRET 	setup = of_device_get_match_data(&pdev->dev);
1915771b7bf0SPierre-Yves MORDRET 	if (!setup) {
1916771b7bf0SPierre-Yves MORDRET 		dev_err(&pdev->dev, "Can't get device data\n");
1917771b7bf0SPierre-Yves MORDRET 		ret = -ENODEV;
1918771b7bf0SPierre-Yves MORDRET 		goto clk_free;
1919771b7bf0SPierre-Yves MORDRET 	}
1920463a9215SPierre-Yves MORDRET 	i2c_dev->setup = *setup;
1921aeb068c5SPierre-Yves MORDRET 
1922aeb068c5SPierre-Yves MORDRET 	ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-rising-time-ns",
1923aeb068c5SPierre-Yves MORDRET 				       &rise_time);
1924aeb068c5SPierre-Yves MORDRET 	if (!ret)
1925463a9215SPierre-Yves MORDRET 		i2c_dev->setup.rise_time = rise_time;
1926aeb068c5SPierre-Yves MORDRET 
1927aeb068c5SPierre-Yves MORDRET 	ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-falling-time-ns",
1928aeb068c5SPierre-Yves MORDRET 				       &fall_time);
1929aeb068c5SPierre-Yves MORDRET 	if (!ret)
1930463a9215SPierre-Yves MORDRET 		i2c_dev->setup.fall_time = fall_time;
1931aeb068c5SPierre-Yves MORDRET 
1932463a9215SPierre-Yves MORDRET 	ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
1933aeb068c5SPierre-Yves MORDRET 	if (ret)
1934aeb068c5SPierre-Yves MORDRET 		goto clk_free;
1935aeb068c5SPierre-Yves MORDRET 
1936aeb068c5SPierre-Yves MORDRET 	adap = &i2c_dev->adap;
1937aeb068c5SPierre-Yves MORDRET 	i2c_set_adapdata(adap, i2c_dev);
1938aeb068c5SPierre-Yves MORDRET 	snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
1939aeb068c5SPierre-Yves MORDRET 		 &res->start);
1940aeb068c5SPierre-Yves MORDRET 	adap->owner = THIS_MODULE;
1941aeb068c5SPierre-Yves MORDRET 	adap->timeout = 2 * HZ;
1942aeb068c5SPierre-Yves MORDRET 	adap->retries = 3;
1943aeb068c5SPierre-Yves MORDRET 	adap->algo = &stm32f7_i2c_algo;
1944aeb068c5SPierre-Yves MORDRET 	adap->dev.parent = &pdev->dev;
1945aeb068c5SPierre-Yves MORDRET 	adap->dev.of_node = pdev->dev.of_node;
1946aeb068c5SPierre-Yves MORDRET 
1947aeb068c5SPierre-Yves MORDRET 	init_completion(&i2c_dev->complete);
1948aeb068c5SPierre-Yves MORDRET 
19497ecc8cfdSPierre-Yves MORDRET 	/* Init DMA config if supported */
19507ecc8cfdSPierre-Yves MORDRET 	i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
19517ecc8cfdSPierre-Yves MORDRET 					     STM32F7_I2C_TXDR,
19527ecc8cfdSPierre-Yves MORDRET 					     STM32F7_I2C_RXDR);
1953d77eceb2SAlain Volmat 	if (PTR_ERR(i2c_dev->dma) == -ENODEV)
1954d77eceb2SAlain Volmat 		i2c_dev->dma = NULL;
1955d77eceb2SAlain Volmat 	else if (IS_ERR(i2c_dev->dma)) {
1956d77eceb2SAlain Volmat 		ret = PTR_ERR(i2c_dev->dma);
1957d77eceb2SAlain Volmat 		if (ret != -EPROBE_DEFER)
1958d77eceb2SAlain Volmat 			dev_err(&pdev->dev,
1959d77eceb2SAlain Volmat 				"Failed to request dma error %i\n", ret);
1960d77eceb2SAlain Volmat 		goto clk_free;
1961d77eceb2SAlain Volmat 	}
19627ecc8cfdSPierre-Yves MORDRET 
1963aeb068c5SPierre-Yves MORDRET 	platform_set_drvdata(pdev, i2c_dev);
1964aeb068c5SPierre-Yves MORDRET 
19654e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_autosuspend_delay(i2c_dev->dev,
19664e7bca6fSPierre-Yves MORDRET 					 STM32F7_AUTOSUSPEND_DELAY);
19674e7bca6fSPierre-Yves MORDRET 	pm_runtime_use_autosuspend(i2c_dev->dev);
19684e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_active(i2c_dev->dev);
19694e7bca6fSPierre-Yves MORDRET 	pm_runtime_enable(i2c_dev->dev);
19704e7bca6fSPierre-Yves MORDRET 
19714e7bca6fSPierre-Yves MORDRET 	pm_runtime_get_noresume(&pdev->dev);
19724e7bca6fSPierre-Yves MORDRET 
19734e7bca6fSPierre-Yves MORDRET 	stm32f7_i2c_hw_config(i2c_dev);
19744e7bca6fSPierre-Yves MORDRET 
19754e7bca6fSPierre-Yves MORDRET 	ret = i2c_add_adapter(adap);
19764e7bca6fSPierre-Yves MORDRET 	if (ret)
19774e7bca6fSPierre-Yves MORDRET 		goto pm_disable;
1978aeb068c5SPierre-Yves MORDRET 
1979aeb068c5SPierre-Yves MORDRET 	dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
1980aeb068c5SPierre-Yves MORDRET 
19814e7bca6fSPierre-Yves MORDRET 	pm_runtime_mark_last_busy(i2c_dev->dev);
19824e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_autosuspend(i2c_dev->dev);
19834e7bca6fSPierre-Yves MORDRET 
1984aeb068c5SPierre-Yves MORDRET 	return 0;
1985aeb068c5SPierre-Yves MORDRET 
19864e7bca6fSPierre-Yves MORDRET pm_disable:
19874e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_noidle(i2c_dev->dev);
19884e7bca6fSPierre-Yves MORDRET 	pm_runtime_disable(i2c_dev->dev);
19894e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_suspended(i2c_dev->dev);
19904e7bca6fSPierre-Yves MORDRET 	pm_runtime_dont_use_autosuspend(i2c_dev->dev);
19914e7bca6fSPierre-Yves MORDRET 
199253aaaa5dSAlain Volmat 	if (i2c_dev->dma) {
199353aaaa5dSAlain Volmat 		stm32_i2c_dma_free(i2c_dev->dma);
199453aaaa5dSAlain Volmat 		i2c_dev->dma = NULL;
199553aaaa5dSAlain Volmat 	}
199653aaaa5dSAlain Volmat 
1997aeb068c5SPierre-Yves MORDRET clk_free:
1998aeb068c5SPierre-Yves MORDRET 	clk_disable_unprepare(i2c_dev->clk);
1999aeb068c5SPierre-Yves MORDRET 
2000aeb068c5SPierre-Yves MORDRET 	return ret;
2001aeb068c5SPierre-Yves MORDRET }
2002aeb068c5SPierre-Yves MORDRET 
2003aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_remove(struct platform_device *pdev)
2004aeb068c5SPierre-Yves MORDRET {
2005aeb068c5SPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
2006aeb068c5SPierre-Yves MORDRET 
2007aeb068c5SPierre-Yves MORDRET 	i2c_del_adapter(&i2c_dev->adap);
20084e7bca6fSPierre-Yves MORDRET 	pm_runtime_get_sync(i2c_dev->dev);
2009aeb068c5SPierre-Yves MORDRET 
20104e7bca6fSPierre-Yves MORDRET 	pm_runtime_put_noidle(i2c_dev->dev);
20114e7bca6fSPierre-Yves MORDRET 	pm_runtime_disable(i2c_dev->dev);
20124e7bca6fSPierre-Yves MORDRET 	pm_runtime_set_suspended(i2c_dev->dev);
20134e7bca6fSPierre-Yves MORDRET 	pm_runtime_dont_use_autosuspend(i2c_dev->dev);
2014aeb068c5SPierre-Yves MORDRET 
201553aaaa5dSAlain Volmat 	if (i2c_dev->dma) {
201653aaaa5dSAlain Volmat 		stm32_i2c_dma_free(i2c_dev->dma);
201753aaaa5dSAlain Volmat 		i2c_dev->dma = NULL;
201853aaaa5dSAlain Volmat 	}
201953aaaa5dSAlain Volmat 
202053aaaa5dSAlain Volmat 	clk_disable_unprepare(i2c_dev->clk);
202153aaaa5dSAlain Volmat 
2022aeb068c5SPierre-Yves MORDRET 	return 0;
2023aeb068c5SPierre-Yves MORDRET }
2024aeb068c5SPierre-Yves MORDRET 
20254e7bca6fSPierre-Yves MORDRET #ifdef CONFIG_PM
20264e7bca6fSPierre-Yves MORDRET static int stm32f7_i2c_runtime_suspend(struct device *dev)
20274e7bca6fSPierre-Yves MORDRET {
20284e7bca6fSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
20294e7bca6fSPierre-Yves MORDRET 
20304e7bca6fSPierre-Yves MORDRET 	if (!stm32f7_i2c_is_slave_registered(i2c_dev))
20314e7bca6fSPierre-Yves MORDRET 		clk_disable_unprepare(i2c_dev->clk);
20324e7bca6fSPierre-Yves MORDRET 
20334e7bca6fSPierre-Yves MORDRET 	return 0;
20344e7bca6fSPierre-Yves MORDRET }
20354e7bca6fSPierre-Yves MORDRET 
20364e7bca6fSPierre-Yves MORDRET static int stm32f7_i2c_runtime_resume(struct device *dev)
20374e7bca6fSPierre-Yves MORDRET {
20384e7bca6fSPierre-Yves MORDRET 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
20394e7bca6fSPierre-Yves MORDRET 	int ret;
20404e7bca6fSPierre-Yves MORDRET 
20414e7bca6fSPierre-Yves MORDRET 	if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
20424e7bca6fSPierre-Yves MORDRET 		ret = clk_prepare_enable(i2c_dev->clk);
20434e7bca6fSPierre-Yves MORDRET 		if (ret) {
20444e7bca6fSPierre-Yves MORDRET 			dev_err(dev, "failed to prepare_enable clock\n");
20454e7bca6fSPierre-Yves MORDRET 			return ret;
20464e7bca6fSPierre-Yves MORDRET 		}
20474e7bca6fSPierre-Yves MORDRET 	}
20484e7bca6fSPierre-Yves MORDRET 
20494e7bca6fSPierre-Yves MORDRET 	return 0;
20504e7bca6fSPierre-Yves MORDRET }
20514e7bca6fSPierre-Yves MORDRET #endif
20524e7bca6fSPierre-Yves MORDRET 
20534e7bca6fSPierre-Yves MORDRET static const struct dev_pm_ops stm32f7_i2c_pm_ops = {
20544e7bca6fSPierre-Yves MORDRET 	SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend,
20554e7bca6fSPierre-Yves MORDRET 			   stm32f7_i2c_runtime_resume, NULL)
20564e7bca6fSPierre-Yves MORDRET };
20574e7bca6fSPierre-Yves MORDRET 
2058aeb068c5SPierre-Yves MORDRET static const struct of_device_id stm32f7_i2c_match[] = {
2059aeb068c5SPierre-Yves MORDRET 	{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
2060aeb068c5SPierre-Yves MORDRET 	{},
2061aeb068c5SPierre-Yves MORDRET };
2062aeb068c5SPierre-Yves MORDRET MODULE_DEVICE_TABLE(of, stm32f7_i2c_match);
2063aeb068c5SPierre-Yves MORDRET 
2064aeb068c5SPierre-Yves MORDRET static struct platform_driver stm32f7_i2c_driver = {
2065aeb068c5SPierre-Yves MORDRET 	.driver = {
2066aeb068c5SPierre-Yves MORDRET 		.name = "stm32f7-i2c",
2067aeb068c5SPierre-Yves MORDRET 		.of_match_table = stm32f7_i2c_match,
20684e7bca6fSPierre-Yves MORDRET 		.pm = &stm32f7_i2c_pm_ops,
2069aeb068c5SPierre-Yves MORDRET 	},
2070aeb068c5SPierre-Yves MORDRET 	.probe = stm32f7_i2c_probe,
2071aeb068c5SPierre-Yves MORDRET 	.remove = stm32f7_i2c_remove,
2072aeb068c5SPierre-Yves MORDRET };
2073aeb068c5SPierre-Yves MORDRET 
2074aeb068c5SPierre-Yves MORDRET module_platform_driver(stm32f7_i2c_driver);
2075aeb068c5SPierre-Yves MORDRET 
2076aeb068c5SPierre-Yves MORDRET MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>");
2077aeb068c5SPierre-Yves MORDRET MODULE_DESCRIPTION("STMicroelectronics STM32F7 I2C driver");
2078aeb068c5SPierre-Yves MORDRET MODULE_LICENSE("GPL v2");
2079