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, ®); 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); 19537ecc8cfdSPierre-Yves MORDRET 1954aeb068c5SPierre-Yves MORDRET platform_set_drvdata(pdev, i2c_dev); 1955aeb068c5SPierre-Yves MORDRET 19564e7bca6fSPierre-Yves MORDRET pm_runtime_set_autosuspend_delay(i2c_dev->dev, 19574e7bca6fSPierre-Yves MORDRET STM32F7_AUTOSUSPEND_DELAY); 19584e7bca6fSPierre-Yves MORDRET pm_runtime_use_autosuspend(i2c_dev->dev); 19594e7bca6fSPierre-Yves MORDRET pm_runtime_set_active(i2c_dev->dev); 19604e7bca6fSPierre-Yves MORDRET pm_runtime_enable(i2c_dev->dev); 19614e7bca6fSPierre-Yves MORDRET 19624e7bca6fSPierre-Yves MORDRET pm_runtime_get_noresume(&pdev->dev); 19634e7bca6fSPierre-Yves MORDRET 19644e7bca6fSPierre-Yves MORDRET stm32f7_i2c_hw_config(i2c_dev); 19654e7bca6fSPierre-Yves MORDRET 19664e7bca6fSPierre-Yves MORDRET ret = i2c_add_adapter(adap); 19674e7bca6fSPierre-Yves MORDRET if (ret) 19684e7bca6fSPierre-Yves MORDRET goto pm_disable; 1969aeb068c5SPierre-Yves MORDRET 1970aeb068c5SPierre-Yves MORDRET dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr); 1971aeb068c5SPierre-Yves MORDRET 19724e7bca6fSPierre-Yves MORDRET pm_runtime_mark_last_busy(i2c_dev->dev); 19734e7bca6fSPierre-Yves MORDRET pm_runtime_put_autosuspend(i2c_dev->dev); 19744e7bca6fSPierre-Yves MORDRET 1975aeb068c5SPierre-Yves MORDRET return 0; 1976aeb068c5SPierre-Yves MORDRET 19774e7bca6fSPierre-Yves MORDRET pm_disable: 19784e7bca6fSPierre-Yves MORDRET pm_runtime_put_noidle(i2c_dev->dev); 19794e7bca6fSPierre-Yves MORDRET pm_runtime_disable(i2c_dev->dev); 19804e7bca6fSPierre-Yves MORDRET pm_runtime_set_suspended(i2c_dev->dev); 19814e7bca6fSPierre-Yves MORDRET pm_runtime_dont_use_autosuspend(i2c_dev->dev); 19824e7bca6fSPierre-Yves MORDRET 1983aeb068c5SPierre-Yves MORDRET clk_free: 1984aeb068c5SPierre-Yves MORDRET clk_disable_unprepare(i2c_dev->clk); 1985aeb068c5SPierre-Yves MORDRET 1986aeb068c5SPierre-Yves MORDRET return ret; 1987aeb068c5SPierre-Yves MORDRET } 1988aeb068c5SPierre-Yves MORDRET 1989aeb068c5SPierre-Yves MORDRET static int stm32f7_i2c_remove(struct platform_device *pdev) 1990aeb068c5SPierre-Yves MORDRET { 1991aeb068c5SPierre-Yves MORDRET struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); 1992aeb068c5SPierre-Yves MORDRET 19937ecc8cfdSPierre-Yves MORDRET if (i2c_dev->dma) { 19947ecc8cfdSPierre-Yves MORDRET stm32_i2c_dma_free(i2c_dev->dma); 19957ecc8cfdSPierre-Yves MORDRET i2c_dev->dma = NULL; 19967ecc8cfdSPierre-Yves MORDRET } 19977ecc8cfdSPierre-Yves MORDRET 1998aeb068c5SPierre-Yves MORDRET i2c_del_adapter(&i2c_dev->adap); 19994e7bca6fSPierre-Yves MORDRET pm_runtime_get_sync(i2c_dev->dev); 2000aeb068c5SPierre-Yves MORDRET 20014e7bca6fSPierre-Yves MORDRET clk_disable_unprepare(i2c_dev->clk); 20024e7bca6fSPierre-Yves MORDRET 20034e7bca6fSPierre-Yves MORDRET pm_runtime_put_noidle(i2c_dev->dev); 20044e7bca6fSPierre-Yves MORDRET pm_runtime_disable(i2c_dev->dev); 20054e7bca6fSPierre-Yves MORDRET pm_runtime_set_suspended(i2c_dev->dev); 20064e7bca6fSPierre-Yves MORDRET pm_runtime_dont_use_autosuspend(i2c_dev->dev); 2007aeb068c5SPierre-Yves MORDRET 2008aeb068c5SPierre-Yves MORDRET return 0; 2009aeb068c5SPierre-Yves MORDRET } 2010aeb068c5SPierre-Yves MORDRET 20114e7bca6fSPierre-Yves MORDRET #ifdef CONFIG_PM 20124e7bca6fSPierre-Yves MORDRET static int stm32f7_i2c_runtime_suspend(struct device *dev) 20134e7bca6fSPierre-Yves MORDRET { 20144e7bca6fSPierre-Yves MORDRET struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); 20154e7bca6fSPierre-Yves MORDRET 20164e7bca6fSPierre-Yves MORDRET if (!stm32f7_i2c_is_slave_registered(i2c_dev)) 20174e7bca6fSPierre-Yves MORDRET clk_disable_unprepare(i2c_dev->clk); 20184e7bca6fSPierre-Yves MORDRET 20194e7bca6fSPierre-Yves MORDRET return 0; 20204e7bca6fSPierre-Yves MORDRET } 20214e7bca6fSPierre-Yves MORDRET 20224e7bca6fSPierre-Yves MORDRET static int stm32f7_i2c_runtime_resume(struct device *dev) 20234e7bca6fSPierre-Yves MORDRET { 20244e7bca6fSPierre-Yves MORDRET struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); 20254e7bca6fSPierre-Yves MORDRET int ret; 20264e7bca6fSPierre-Yves MORDRET 20274e7bca6fSPierre-Yves MORDRET if (!stm32f7_i2c_is_slave_registered(i2c_dev)) { 20284e7bca6fSPierre-Yves MORDRET ret = clk_prepare_enable(i2c_dev->clk); 20294e7bca6fSPierre-Yves MORDRET if (ret) { 20304e7bca6fSPierre-Yves MORDRET dev_err(dev, "failed to prepare_enable clock\n"); 20314e7bca6fSPierre-Yves MORDRET return ret; 20324e7bca6fSPierre-Yves MORDRET } 20334e7bca6fSPierre-Yves MORDRET } 20344e7bca6fSPierre-Yves MORDRET 20354e7bca6fSPierre-Yves MORDRET return 0; 20364e7bca6fSPierre-Yves MORDRET } 20374e7bca6fSPierre-Yves MORDRET #endif 20384e7bca6fSPierre-Yves MORDRET 20394e7bca6fSPierre-Yves MORDRET static const struct dev_pm_ops stm32f7_i2c_pm_ops = { 20404e7bca6fSPierre-Yves MORDRET SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend, 20414e7bca6fSPierre-Yves MORDRET stm32f7_i2c_runtime_resume, NULL) 20424e7bca6fSPierre-Yves MORDRET }; 20434e7bca6fSPierre-Yves MORDRET 2044aeb068c5SPierre-Yves MORDRET static const struct of_device_id stm32f7_i2c_match[] = { 2045aeb068c5SPierre-Yves MORDRET { .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup}, 2046aeb068c5SPierre-Yves MORDRET {}, 2047aeb068c5SPierre-Yves MORDRET }; 2048aeb068c5SPierre-Yves MORDRET MODULE_DEVICE_TABLE(of, stm32f7_i2c_match); 2049aeb068c5SPierre-Yves MORDRET 2050aeb068c5SPierre-Yves MORDRET static struct platform_driver stm32f7_i2c_driver = { 2051aeb068c5SPierre-Yves MORDRET .driver = { 2052aeb068c5SPierre-Yves MORDRET .name = "stm32f7-i2c", 2053aeb068c5SPierre-Yves MORDRET .of_match_table = stm32f7_i2c_match, 20544e7bca6fSPierre-Yves MORDRET .pm = &stm32f7_i2c_pm_ops, 2055aeb068c5SPierre-Yves MORDRET }, 2056aeb068c5SPierre-Yves MORDRET .probe = stm32f7_i2c_probe, 2057aeb068c5SPierre-Yves MORDRET .remove = stm32f7_i2c_remove, 2058aeb068c5SPierre-Yves MORDRET }; 2059aeb068c5SPierre-Yves MORDRET 2060aeb068c5SPierre-Yves MORDRET module_platform_driver(stm32f7_i2c_driver); 2061aeb068c5SPierre-Yves MORDRET 2062aeb068c5SPierre-Yves MORDRET MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>"); 2063aeb068c5SPierre-Yves MORDRET MODULE_DESCRIPTION("STMicroelectronics STM32F7 I2C driver"); 2064aeb068c5SPierre-Yves MORDRET MODULE_LICENSE("GPL v2"); 2065