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