18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2013 STMicroelectronics 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * I2C master mode controller driver, used in STMicroelectronics devices. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Maxime Coquelin <maxime.coquelin@st.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/clk.h> 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/err.h> 138c2ecf20Sopenharmony_ci#include <linux/i2c.h> 148c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 158c2ecf20Sopenharmony_ci#include <linux/io.h> 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/of_address.h> 188c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 198c2ecf20Sopenharmony_ci#include <linux/of.h> 208c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 218c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* SSC registers */ 248c2ecf20Sopenharmony_ci#define SSC_BRG 0x000 258c2ecf20Sopenharmony_ci#define SSC_TBUF 0x004 268c2ecf20Sopenharmony_ci#define SSC_RBUF 0x008 278c2ecf20Sopenharmony_ci#define SSC_CTL 0x00C 288c2ecf20Sopenharmony_ci#define SSC_IEN 0x010 298c2ecf20Sopenharmony_ci#define SSC_STA 0x014 308c2ecf20Sopenharmony_ci#define SSC_I2C 0x018 318c2ecf20Sopenharmony_ci#define SSC_SLAD 0x01C 328c2ecf20Sopenharmony_ci#define SSC_REP_START_HOLD 0x020 338c2ecf20Sopenharmony_ci#define SSC_START_HOLD 0x024 348c2ecf20Sopenharmony_ci#define SSC_REP_START_SETUP 0x028 358c2ecf20Sopenharmony_ci#define SSC_DATA_SETUP 0x02C 368c2ecf20Sopenharmony_ci#define SSC_STOP_SETUP 0x030 378c2ecf20Sopenharmony_ci#define SSC_BUS_FREE 0x034 388c2ecf20Sopenharmony_ci#define SSC_TX_FSTAT 0x038 398c2ecf20Sopenharmony_ci#define SSC_RX_FSTAT 0x03C 408c2ecf20Sopenharmony_ci#define SSC_PRE_SCALER_BRG 0x040 418c2ecf20Sopenharmony_ci#define SSC_CLR 0x080 428c2ecf20Sopenharmony_ci#define SSC_NOISE_SUPP_WIDTH 0x100 438c2ecf20Sopenharmony_ci#define SSC_PRSCALER 0x104 448c2ecf20Sopenharmony_ci#define SSC_NOISE_SUPP_WIDTH_DATAOUT 0x108 458c2ecf20Sopenharmony_ci#define SSC_PRSCALER_DATAOUT 0x10c 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* SSC Control */ 488c2ecf20Sopenharmony_ci#define SSC_CTL_DATA_WIDTH_9 0x8 498c2ecf20Sopenharmony_ci#define SSC_CTL_DATA_WIDTH_MSK 0xf 508c2ecf20Sopenharmony_ci#define SSC_CTL_BM 0xf 518c2ecf20Sopenharmony_ci#define SSC_CTL_HB BIT(4) 528c2ecf20Sopenharmony_ci#define SSC_CTL_PH BIT(5) 538c2ecf20Sopenharmony_ci#define SSC_CTL_PO BIT(6) 548c2ecf20Sopenharmony_ci#define SSC_CTL_SR BIT(7) 558c2ecf20Sopenharmony_ci#define SSC_CTL_MS BIT(8) 568c2ecf20Sopenharmony_ci#define SSC_CTL_EN BIT(9) 578c2ecf20Sopenharmony_ci#define SSC_CTL_LPB BIT(10) 588c2ecf20Sopenharmony_ci#define SSC_CTL_EN_TX_FIFO BIT(11) 598c2ecf20Sopenharmony_ci#define SSC_CTL_EN_RX_FIFO BIT(12) 608c2ecf20Sopenharmony_ci#define SSC_CTL_EN_CLST_RX BIT(13) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* SSC Interrupt Enable */ 638c2ecf20Sopenharmony_ci#define SSC_IEN_RIEN BIT(0) 648c2ecf20Sopenharmony_ci#define SSC_IEN_TIEN BIT(1) 658c2ecf20Sopenharmony_ci#define SSC_IEN_TEEN BIT(2) 668c2ecf20Sopenharmony_ci#define SSC_IEN_REEN BIT(3) 678c2ecf20Sopenharmony_ci#define SSC_IEN_PEEN BIT(4) 688c2ecf20Sopenharmony_ci#define SSC_IEN_AASEN BIT(6) 698c2ecf20Sopenharmony_ci#define SSC_IEN_STOPEN BIT(7) 708c2ecf20Sopenharmony_ci#define SSC_IEN_ARBLEN BIT(8) 718c2ecf20Sopenharmony_ci#define SSC_IEN_NACKEN BIT(10) 728c2ecf20Sopenharmony_ci#define SSC_IEN_REPSTRTEN BIT(11) 738c2ecf20Sopenharmony_ci#define SSC_IEN_TX_FIFO_HALF BIT(12) 748c2ecf20Sopenharmony_ci#define SSC_IEN_RX_FIFO_HALF_FULL BIT(14) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* SSC Status */ 778c2ecf20Sopenharmony_ci#define SSC_STA_RIR BIT(0) 788c2ecf20Sopenharmony_ci#define SSC_STA_TIR BIT(1) 798c2ecf20Sopenharmony_ci#define SSC_STA_TE BIT(2) 808c2ecf20Sopenharmony_ci#define SSC_STA_RE BIT(3) 818c2ecf20Sopenharmony_ci#define SSC_STA_PE BIT(4) 828c2ecf20Sopenharmony_ci#define SSC_STA_CLST BIT(5) 838c2ecf20Sopenharmony_ci#define SSC_STA_AAS BIT(6) 848c2ecf20Sopenharmony_ci#define SSC_STA_STOP BIT(7) 858c2ecf20Sopenharmony_ci#define SSC_STA_ARBL BIT(8) 868c2ecf20Sopenharmony_ci#define SSC_STA_BUSY BIT(9) 878c2ecf20Sopenharmony_ci#define SSC_STA_NACK BIT(10) 888c2ecf20Sopenharmony_ci#define SSC_STA_REPSTRT BIT(11) 898c2ecf20Sopenharmony_ci#define SSC_STA_TX_FIFO_HALF BIT(12) 908c2ecf20Sopenharmony_ci#define SSC_STA_TX_FIFO_FULL BIT(13) 918c2ecf20Sopenharmony_ci#define SSC_STA_RX_FIFO_HALF BIT(14) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* SSC I2C Control */ 948c2ecf20Sopenharmony_ci#define SSC_I2C_I2CM BIT(0) 958c2ecf20Sopenharmony_ci#define SSC_I2C_STRTG BIT(1) 968c2ecf20Sopenharmony_ci#define SSC_I2C_STOPG BIT(2) 978c2ecf20Sopenharmony_ci#define SSC_I2C_ACKG BIT(3) 988c2ecf20Sopenharmony_ci#define SSC_I2C_AD10 BIT(4) 998c2ecf20Sopenharmony_ci#define SSC_I2C_TXENB BIT(5) 1008c2ecf20Sopenharmony_ci#define SSC_I2C_REPSTRTG BIT(11) 1018c2ecf20Sopenharmony_ci#define SSC_I2C_SLAVE_DISABLE BIT(12) 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* SSC Tx FIFO Status */ 1048c2ecf20Sopenharmony_ci#define SSC_TX_FSTAT_STATUS 0x07 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* SSC Rx FIFO Status */ 1078c2ecf20Sopenharmony_ci#define SSC_RX_FSTAT_STATUS 0x07 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* SSC Clear bit operation */ 1108c2ecf20Sopenharmony_ci#define SSC_CLR_SSCAAS BIT(6) 1118c2ecf20Sopenharmony_ci#define SSC_CLR_SSCSTOP BIT(7) 1128c2ecf20Sopenharmony_ci#define SSC_CLR_SSCARBL BIT(8) 1138c2ecf20Sopenharmony_ci#define SSC_CLR_NACK BIT(10) 1148c2ecf20Sopenharmony_ci#define SSC_CLR_REPSTRT BIT(11) 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* SSC Clock Prescaler */ 1178c2ecf20Sopenharmony_ci#define SSC_PRSC_VALUE 0x0f 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define SSC_TXFIFO_SIZE 0x8 1218c2ecf20Sopenharmony_ci#define SSC_RXFIFO_SIZE 0x8 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cienum st_i2c_mode { 1248c2ecf20Sopenharmony_ci I2C_MODE_STANDARD, 1258c2ecf20Sopenharmony_ci I2C_MODE_FAST, 1268c2ecf20Sopenharmony_ci I2C_MODE_END, 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/** 1308c2ecf20Sopenharmony_ci * struct st_i2c_timings - per-Mode tuning parameters 1318c2ecf20Sopenharmony_ci * @rate: I2C bus rate 1328c2ecf20Sopenharmony_ci * @rep_start_hold: I2C repeated start hold time requirement 1338c2ecf20Sopenharmony_ci * @rep_start_setup: I2C repeated start set up time requirement 1348c2ecf20Sopenharmony_ci * @start_hold: I2C start hold time requirement 1358c2ecf20Sopenharmony_ci * @data_setup_time: I2C data set up time requirement 1368c2ecf20Sopenharmony_ci * @stop_setup_time: I2C stop set up time requirement 1378c2ecf20Sopenharmony_ci * @bus_free_time: I2C bus free time requirement 1388c2ecf20Sopenharmony_ci * @sda_pulse_min_limit: I2C SDA pulse mini width limit 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_cistruct st_i2c_timings { 1418c2ecf20Sopenharmony_ci u32 rate; 1428c2ecf20Sopenharmony_ci u32 rep_start_hold; 1438c2ecf20Sopenharmony_ci u32 rep_start_setup; 1448c2ecf20Sopenharmony_ci u32 start_hold; 1458c2ecf20Sopenharmony_ci u32 data_setup_time; 1468c2ecf20Sopenharmony_ci u32 stop_setup_time; 1478c2ecf20Sopenharmony_ci u32 bus_free_time; 1488c2ecf20Sopenharmony_ci u32 sda_pulse_min_limit; 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/** 1528c2ecf20Sopenharmony_ci * struct st_i2c_client - client specific data 1538c2ecf20Sopenharmony_ci * @addr: 8-bit slave addr, including r/w bit 1548c2ecf20Sopenharmony_ci * @count: number of bytes to be transfered 1558c2ecf20Sopenharmony_ci * @xfered: number of bytes already transferred 1568c2ecf20Sopenharmony_ci * @buf: data buffer 1578c2ecf20Sopenharmony_ci * @result: result of the transfer 1588c2ecf20Sopenharmony_ci * @stop: last I2C msg to be sent, i.e. STOP to be generated 1598c2ecf20Sopenharmony_ci */ 1608c2ecf20Sopenharmony_cistruct st_i2c_client { 1618c2ecf20Sopenharmony_ci u8 addr; 1628c2ecf20Sopenharmony_ci u32 count; 1638c2ecf20Sopenharmony_ci u32 xfered; 1648c2ecf20Sopenharmony_ci u8 *buf; 1658c2ecf20Sopenharmony_ci int result; 1668c2ecf20Sopenharmony_ci bool stop; 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci/** 1708c2ecf20Sopenharmony_ci * struct st_i2c_dev - private data of the controller 1718c2ecf20Sopenharmony_ci * @adap: I2C adapter for this controller 1728c2ecf20Sopenharmony_ci * @dev: device for this controller 1738c2ecf20Sopenharmony_ci * @base: virtual memory area 1748c2ecf20Sopenharmony_ci * @complete: completion of I2C message 1758c2ecf20Sopenharmony_ci * @irq: interrupt line for th controller 1768c2ecf20Sopenharmony_ci * @clk: hw ssc block clock 1778c2ecf20Sopenharmony_ci * @mode: I2C mode of the controller. Standard or Fast only supported 1788c2ecf20Sopenharmony_ci * @scl_min_width_us: SCL line minimum pulse width in us 1798c2ecf20Sopenharmony_ci * @sda_min_width_us: SDA line minimum pulse width in us 1808c2ecf20Sopenharmony_ci * @client: I2C transfert information 1818c2ecf20Sopenharmony_ci * @busy: I2C transfer on-going 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_cistruct st_i2c_dev { 1848c2ecf20Sopenharmony_ci struct i2c_adapter adap; 1858c2ecf20Sopenharmony_ci struct device *dev; 1868c2ecf20Sopenharmony_ci void __iomem *base; 1878c2ecf20Sopenharmony_ci struct completion complete; 1888c2ecf20Sopenharmony_ci int irq; 1898c2ecf20Sopenharmony_ci struct clk *clk; 1908c2ecf20Sopenharmony_ci int mode; 1918c2ecf20Sopenharmony_ci u32 scl_min_width_us; 1928c2ecf20Sopenharmony_ci u32 sda_min_width_us; 1938c2ecf20Sopenharmony_ci struct st_i2c_client client; 1948c2ecf20Sopenharmony_ci bool busy; 1958c2ecf20Sopenharmony_ci}; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic inline void st_i2c_set_bits(void __iomem *reg, u32 mask) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci writel_relaxed(readl_relaxed(reg) | mask, reg); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic inline void st_i2c_clr_bits(void __iomem *reg, u32 mask) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci writel_relaxed(readl_relaxed(reg) & ~mask, reg); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/* 2088c2ecf20Sopenharmony_ci * From I2C Specifications v0.5. 2098c2ecf20Sopenharmony_ci * 2108c2ecf20Sopenharmony_ci * All the values below have +10% margin added to be 2118c2ecf20Sopenharmony_ci * compatible with some out-of-spec devices, 2128c2ecf20Sopenharmony_ci * like HDMI link of the Toshiba 19AV600 TV. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_cistatic struct st_i2c_timings i2c_timings[] = { 2158c2ecf20Sopenharmony_ci [I2C_MODE_STANDARD] = { 2168c2ecf20Sopenharmony_ci .rate = I2C_MAX_STANDARD_MODE_FREQ, 2178c2ecf20Sopenharmony_ci .rep_start_hold = 4400, 2188c2ecf20Sopenharmony_ci .rep_start_setup = 5170, 2198c2ecf20Sopenharmony_ci .start_hold = 4400, 2208c2ecf20Sopenharmony_ci .data_setup_time = 275, 2218c2ecf20Sopenharmony_ci .stop_setup_time = 4400, 2228c2ecf20Sopenharmony_ci .bus_free_time = 5170, 2238c2ecf20Sopenharmony_ci }, 2248c2ecf20Sopenharmony_ci [I2C_MODE_FAST] = { 2258c2ecf20Sopenharmony_ci .rate = I2C_MAX_FAST_MODE_FREQ, 2268c2ecf20Sopenharmony_ci .rep_start_hold = 660, 2278c2ecf20Sopenharmony_ci .rep_start_setup = 660, 2288c2ecf20Sopenharmony_ci .start_hold = 660, 2298c2ecf20Sopenharmony_ci .data_setup_time = 110, 2308c2ecf20Sopenharmony_ci .stop_setup_time = 660, 2318c2ecf20Sopenharmony_ci .bus_free_time = 1430, 2328c2ecf20Sopenharmony_ci }, 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic void st_i2c_flush_rx_fifo(struct st_i2c_dev *i2c_dev) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci int count, i; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* 2408c2ecf20Sopenharmony_ci * Counter only counts up to 7 but fifo size is 8... 2418c2ecf20Sopenharmony_ci * When fifo is full, counter is 0 and RIR bit of status register is 2428c2ecf20Sopenharmony_ci * set 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_ci if (readl_relaxed(i2c_dev->base + SSC_STA) & SSC_STA_RIR) 2458c2ecf20Sopenharmony_ci count = SSC_RXFIFO_SIZE; 2468c2ecf20Sopenharmony_ci else 2478c2ecf20Sopenharmony_ci count = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT) & 2488c2ecf20Sopenharmony_ci SSC_RX_FSTAT_STATUS; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) 2518c2ecf20Sopenharmony_ci readl_relaxed(i2c_dev->base + SSC_RBUF); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic void st_i2c_soft_reset(struct st_i2c_dev *i2c_dev) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci /* 2578c2ecf20Sopenharmony_ci * FIFO needs to be emptied before reseting the IP, 2588c2ecf20Sopenharmony_ci * else the controller raises a BUSY error. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci st_i2c_flush_rx_fifo(i2c_dev); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR); 2638c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/** 2678c2ecf20Sopenharmony_ci * st_i2c_hw_config() - Prepare SSC block, calculate and apply tuning timings 2688c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 2698c2ecf20Sopenharmony_ci */ 2708c2ecf20Sopenharmony_cistatic void st_i2c_hw_config(struct st_i2c_dev *i2c_dev) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci unsigned long rate; 2738c2ecf20Sopenharmony_ci u32 val, ns_per_clk; 2748c2ecf20Sopenharmony_ci struct st_i2c_timings *t = &i2c_timings[i2c_dev->mode]; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci st_i2c_soft_reset(i2c_dev); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci val = SSC_CLR_REPSTRT | SSC_CLR_NACK | SSC_CLR_SSCARBL | 2798c2ecf20Sopenharmony_ci SSC_CLR_SSCAAS | SSC_CLR_SSCSTOP; 2808c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_CLR); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* SSC Control register setup */ 2838c2ecf20Sopenharmony_ci val = SSC_CTL_PO | SSC_CTL_PH | SSC_CTL_HB | SSC_CTL_DATA_WIDTH_9; 2848c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_CTL); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci rate = clk_get_rate(i2c_dev->clk); 2878c2ecf20Sopenharmony_ci ns_per_clk = 1000000000 / rate; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* Baudrate */ 2908c2ecf20Sopenharmony_ci val = rate / (2 * t->rate); 2918c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_BRG); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* Pre-scaler baudrate */ 2948c2ecf20Sopenharmony_ci writel_relaxed(1, i2c_dev->base + SSC_PRE_SCALER_BRG); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* Enable I2C mode */ 2978c2ecf20Sopenharmony_ci writel_relaxed(SSC_I2C_I2CM, i2c_dev->base + SSC_I2C); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci /* Repeated start hold time */ 3008c2ecf20Sopenharmony_ci val = t->rep_start_hold / ns_per_clk; 3018c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_REP_START_HOLD); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* Repeated start set up time */ 3048c2ecf20Sopenharmony_ci val = t->rep_start_setup / ns_per_clk; 3058c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_REP_START_SETUP); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* Start hold time */ 3088c2ecf20Sopenharmony_ci val = t->start_hold / ns_per_clk; 3098c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_START_HOLD); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* Data set up time */ 3128c2ecf20Sopenharmony_ci val = t->data_setup_time / ns_per_clk; 3138c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_DATA_SETUP); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* Stop set up time */ 3168c2ecf20Sopenharmony_ci val = t->stop_setup_time / ns_per_clk; 3178c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_STOP_SETUP); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* Bus free time */ 3208c2ecf20Sopenharmony_ci val = t->bus_free_time / ns_per_clk; 3218c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_BUS_FREE); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* Prescalers set up */ 3248c2ecf20Sopenharmony_ci val = rate / 10000000; 3258c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_PRSCALER); 3268c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_PRSCALER_DATAOUT); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Noise suppression witdh */ 3298c2ecf20Sopenharmony_ci val = i2c_dev->scl_min_width_us * rate / 100000000; 3308c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* Noise suppression max output data delay width */ 3338c2ecf20Sopenharmony_ci val = i2c_dev->sda_min_width_us * rate / 100000000; 3348c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic int st_i2c_recover_bus(struct i2c_adapter *i2c_adap) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); 3408c2ecf20Sopenharmony_ci u32 ctl; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci dev_dbg(i2c_dev->dev, "Trying to recover bus\n"); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* 3458c2ecf20Sopenharmony_ci * SSP IP is dual role SPI/I2C to generate 9 clock pulses 3468c2ecf20Sopenharmony_ci * we switch to SPI node, 9 bit words and write a 0. This 3478c2ecf20Sopenharmony_ci * has been validate with a oscilloscope and is easier 3488c2ecf20Sopenharmony_ci * than switching to GPIO mode. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* Disable interrupts */ 3528c2ecf20Sopenharmony_ci writel_relaxed(0, i2c_dev->base + SSC_IEN); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci st_i2c_hw_config(i2c_dev); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci ctl = SSC_CTL_EN | SSC_CTL_MS | SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO; 3578c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM); 3608c2ecf20Sopenharmony_ci usleep_range(8000, 10000); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci writel_relaxed(0, i2c_dev->base + SSC_TBUF); 3638c2ecf20Sopenharmony_ci usleep_range(2000, 4000); 3648c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci return 0; 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci u32 sta; 3728c2ecf20Sopenharmony_ci int i, ret; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 3758c2ecf20Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 3768c2ecf20Sopenharmony_ci if (!(sta & SSC_STA_BUSY)) 3778c2ecf20Sopenharmony_ci return 0; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci usleep_range(2000, 4000); 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci ret = i2c_recover_bus(&i2c_dev->adap); 3858c2ecf20Sopenharmony_ci if (ret) { 3868c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret); 3878c2ecf20Sopenharmony_ci return ret; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci return -EBUSY; 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci/** 3948c2ecf20Sopenharmony_ci * st_i2c_write_tx_fifo() - Write a byte in the Tx FIFO 3958c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 3968c2ecf20Sopenharmony_ci * @byte: Data to write in the Tx FIFO 3978c2ecf20Sopenharmony_ci */ 3988c2ecf20Sopenharmony_cistatic inline void st_i2c_write_tx_fifo(struct st_i2c_dev *i2c_dev, u8 byte) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci u16 tbuf = byte << 1; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci writel_relaxed(tbuf | 1, i2c_dev->base + SSC_TBUF); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci/** 4068c2ecf20Sopenharmony_ci * st_i2c_wr_fill_tx_fifo() - Fill the Tx FIFO in write mode 4078c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 4088c2ecf20Sopenharmony_ci * 4098c2ecf20Sopenharmony_ci * This functions fills the Tx FIFO with I2C transfert buffer when 4108c2ecf20Sopenharmony_ci * in write mode. 4118c2ecf20Sopenharmony_ci */ 4128c2ecf20Sopenharmony_cistatic void st_i2c_wr_fill_tx_fifo(struct st_i2c_dev *i2c_dev) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 4158c2ecf20Sopenharmony_ci u32 tx_fstat, sta; 4168c2ecf20Sopenharmony_ci int i; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 4198c2ecf20Sopenharmony_ci if (sta & SSC_STA_TX_FIFO_FULL) 4208c2ecf20Sopenharmony_ci return; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); 4238c2ecf20Sopenharmony_ci tx_fstat &= SSC_TX_FSTAT_STATUS; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (c->count < (SSC_TXFIFO_SIZE - tx_fstat)) 4268c2ecf20Sopenharmony_ci i = c->count; 4278c2ecf20Sopenharmony_ci else 4288c2ecf20Sopenharmony_ci i = SSC_TXFIFO_SIZE - tx_fstat; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci for (; i > 0; i--, c->count--, c->buf++) 4318c2ecf20Sopenharmony_ci st_i2c_write_tx_fifo(i2c_dev, *c->buf); 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci/** 4358c2ecf20Sopenharmony_ci * st_i2c_rd_fill_tx_fifo() - Fill the Tx FIFO in read mode 4368c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 4378c2ecf20Sopenharmony_ci * @max: Maximum amount of data to fill into the Tx FIFO 4388c2ecf20Sopenharmony_ci * 4398c2ecf20Sopenharmony_ci * This functions fills the Tx FIFO with fixed pattern when 4408c2ecf20Sopenharmony_ci * in read mode to trigger clock. 4418c2ecf20Sopenharmony_ci */ 4428c2ecf20Sopenharmony_cistatic void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, int max) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 4458c2ecf20Sopenharmony_ci u32 tx_fstat, sta; 4468c2ecf20Sopenharmony_ci int i; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 4498c2ecf20Sopenharmony_ci if (sta & SSC_STA_TX_FIFO_FULL) 4508c2ecf20Sopenharmony_ci return; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); 4538c2ecf20Sopenharmony_ci tx_fstat &= SSC_TX_FSTAT_STATUS; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (max < (SSC_TXFIFO_SIZE - tx_fstat)) 4568c2ecf20Sopenharmony_ci i = max; 4578c2ecf20Sopenharmony_ci else 4588c2ecf20Sopenharmony_ci i = SSC_TXFIFO_SIZE - tx_fstat; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci for (; i > 0; i--, c->xfered++) 4618c2ecf20Sopenharmony_ci st_i2c_write_tx_fifo(i2c_dev, 0xff); 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic void st_i2c_read_rx_fifo(struct st_i2c_dev *i2c_dev) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 4678c2ecf20Sopenharmony_ci u32 i, sta; 4688c2ecf20Sopenharmony_ci u16 rbuf; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 4718c2ecf20Sopenharmony_ci if (sta & SSC_STA_RIR) { 4728c2ecf20Sopenharmony_ci i = SSC_RXFIFO_SIZE; 4738c2ecf20Sopenharmony_ci } else { 4748c2ecf20Sopenharmony_ci i = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT); 4758c2ecf20Sopenharmony_ci i &= SSC_RX_FSTAT_STATUS; 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci for (; (i > 0) && (c->count > 0); i--, c->count--) { 4798c2ecf20Sopenharmony_ci rbuf = readl_relaxed(i2c_dev->base + SSC_RBUF) >> 1; 4808c2ecf20Sopenharmony_ci *c->buf++ = (u8)rbuf & 0xff; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (i) { 4848c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "Unexpected %d bytes in rx fifo\n", i); 4858c2ecf20Sopenharmony_ci st_i2c_flush_rx_fifo(i2c_dev); 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/** 4908c2ecf20Sopenharmony_ci * st_i2c_terminate_xfer() - Send either STOP or REPSTART condition 4918c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 4928c2ecf20Sopenharmony_ci */ 4938c2ecf20Sopenharmony_cistatic void st_i2c_terminate_xfer(struct st_i2c_dev *i2c_dev) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_IEN, SSC_IEN_TEEN); 4988c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (c->stop) { 5018c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_STOPEN); 5028c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); 5038c2ecf20Sopenharmony_ci } else { 5048c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_REPSTRTEN); 5058c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_REPSTRTG); 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci/** 5108c2ecf20Sopenharmony_ci * st_i2c_handle_write() - Handle FIFO empty interrupt in case of write 5118c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_cistatic void st_i2c_handle_write(struct st_i2c_dev *i2c_dev) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci st_i2c_flush_rx_fifo(i2c_dev); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (!c->count) 5208c2ecf20Sopenharmony_ci /* End of xfer, send stop or repstart */ 5218c2ecf20Sopenharmony_ci st_i2c_terminate_xfer(i2c_dev); 5228c2ecf20Sopenharmony_ci else 5238c2ecf20Sopenharmony_ci st_i2c_wr_fill_tx_fifo(i2c_dev); 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci/** 5278c2ecf20Sopenharmony_ci * st_i2c_handle_write() - Handle FIFO enmpty interrupt in case of read 5288c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 5298c2ecf20Sopenharmony_ci */ 5308c2ecf20Sopenharmony_cistatic void st_i2c_handle_read(struct st_i2c_dev *i2c_dev) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 5338c2ecf20Sopenharmony_ci u32 ien; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Trash the address read back */ 5368c2ecf20Sopenharmony_ci if (!c->xfered) { 5378c2ecf20Sopenharmony_ci readl_relaxed(i2c_dev->base + SSC_RBUF); 5388c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_TXENB); 5398c2ecf20Sopenharmony_ci } else { 5408c2ecf20Sopenharmony_ci st_i2c_read_rx_fifo(i2c_dev); 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci if (!c->count) { 5448c2ecf20Sopenharmony_ci /* End of xfer, send stop or repstart */ 5458c2ecf20Sopenharmony_ci st_i2c_terminate_xfer(i2c_dev); 5468c2ecf20Sopenharmony_ci } else if (c->count == 1) { 5478c2ecf20Sopenharmony_ci /* Penultimate byte to xfer, disable ACK gen. */ 5488c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_ACKG); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci /* Last received byte is to be handled by NACK interrupt */ 5518c2ecf20Sopenharmony_ci ien = SSC_IEN_NACKEN | SSC_IEN_ARBLEN; 5528c2ecf20Sopenharmony_ci writel_relaxed(ien, i2c_dev->base + SSC_IEN); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci st_i2c_rd_fill_tx_fifo(i2c_dev, c->count); 5558c2ecf20Sopenharmony_ci } else { 5568c2ecf20Sopenharmony_ci st_i2c_rd_fill_tx_fifo(i2c_dev, c->count - 1); 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci} 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci/** 5618c2ecf20Sopenharmony_ci * st_i2c_isr() - Interrupt routine 5628c2ecf20Sopenharmony_ci * @irq: interrupt number 5638c2ecf20Sopenharmony_ci * @data: Controller's private data 5648c2ecf20Sopenharmony_ci */ 5658c2ecf20Sopenharmony_cistatic irqreturn_t st_i2c_isr_thread(int irq, void *data) 5668c2ecf20Sopenharmony_ci{ 5678c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev = data; 5688c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 5698c2ecf20Sopenharmony_ci u32 sta, ien; 5708c2ecf20Sopenharmony_ci int it; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci ien = readl_relaxed(i2c_dev->base + SSC_IEN); 5738c2ecf20Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* Use __fls() to check error bits first */ 5768c2ecf20Sopenharmony_ci it = __fls(sta & ien); 5778c2ecf20Sopenharmony_ci if (it < 0) { 5788c2ecf20Sopenharmony_ci dev_dbg(i2c_dev->dev, "spurious it (sta=0x%04x, ien=0x%04x)\n", 5798c2ecf20Sopenharmony_ci sta, ien); 5808c2ecf20Sopenharmony_ci return IRQ_NONE; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci switch (1 << it) { 5848c2ecf20Sopenharmony_ci case SSC_STA_TE: 5858c2ecf20Sopenharmony_ci if (c->addr & I2C_M_RD) 5868c2ecf20Sopenharmony_ci st_i2c_handle_read(i2c_dev); 5878c2ecf20Sopenharmony_ci else 5888c2ecf20Sopenharmony_ci st_i2c_handle_write(i2c_dev); 5898c2ecf20Sopenharmony_ci break; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci case SSC_STA_STOP: 5928c2ecf20Sopenharmony_ci case SSC_STA_REPSTRT: 5938c2ecf20Sopenharmony_ci writel_relaxed(0, i2c_dev->base + SSC_IEN); 5948c2ecf20Sopenharmony_ci complete(&i2c_dev->complete); 5958c2ecf20Sopenharmony_ci break; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci case SSC_STA_NACK: 5988c2ecf20Sopenharmony_ci writel_relaxed(SSC_CLR_NACK, i2c_dev->base + SSC_CLR); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci /* Last received byte handled by NACK interrupt */ 6018c2ecf20Sopenharmony_ci if ((c->addr & I2C_M_RD) && (c->count == 1) && (c->xfered)) { 6028c2ecf20Sopenharmony_ci st_i2c_handle_read(i2c_dev); 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN; 6078c2ecf20Sopenharmony_ci writel_relaxed(it, i2c_dev->base + SSC_IEN); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); 6108c2ecf20Sopenharmony_ci c->result = -EIO; 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci case SSC_STA_ARBL: 6148c2ecf20Sopenharmony_ci writel_relaxed(SSC_CLR_SSCARBL, i2c_dev->base + SSC_CLR); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN; 6178c2ecf20Sopenharmony_ci writel_relaxed(it, i2c_dev->base + SSC_IEN); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); 6208c2ecf20Sopenharmony_ci c->result = -EAGAIN; 6218c2ecf20Sopenharmony_ci break; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci default: 6248c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, 6258c2ecf20Sopenharmony_ci "it %d unhandled (sta=0x%04x)\n", it, sta); 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci /* 6298c2ecf20Sopenharmony_ci * Read IEN register to ensure interrupt mask write is effective 6308c2ecf20Sopenharmony_ci * before re-enabling interrupt at GIC level, and thus avoid spurious 6318c2ecf20Sopenharmony_ci * interrupts. 6328c2ecf20Sopenharmony_ci */ 6338c2ecf20Sopenharmony_ci readl(i2c_dev->base + SSC_IEN); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci return IRQ_HANDLED; 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci/** 6398c2ecf20Sopenharmony_ci * st_i2c_xfer_msg() - Transfer a single I2C message 6408c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data 6418c2ecf20Sopenharmony_ci * @msg: I2C message to transfer 6428c2ecf20Sopenharmony_ci * @is_first: first message of the sequence 6438c2ecf20Sopenharmony_ci * @is_last: last message of the sequence 6448c2ecf20Sopenharmony_ci */ 6458c2ecf20Sopenharmony_cistatic int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg, 6468c2ecf20Sopenharmony_ci bool is_first, bool is_last) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 6498c2ecf20Sopenharmony_ci u32 ctl, i2c, it; 6508c2ecf20Sopenharmony_ci unsigned long timeout; 6518c2ecf20Sopenharmony_ci int ret; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci c->addr = i2c_8bit_addr_from_msg(msg); 6548c2ecf20Sopenharmony_ci c->buf = msg->buf; 6558c2ecf20Sopenharmony_ci c->count = msg->len; 6568c2ecf20Sopenharmony_ci c->xfered = 0; 6578c2ecf20Sopenharmony_ci c->result = 0; 6588c2ecf20Sopenharmony_ci c->stop = is_last; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci reinit_completion(&i2c_dev->complete); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci ctl = SSC_CTL_EN | SSC_CTL_MS | SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO; 6638c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci i2c = SSC_I2C_TXENB; 6668c2ecf20Sopenharmony_ci if (c->addr & I2C_M_RD) 6678c2ecf20Sopenharmony_ci i2c |= SSC_I2C_ACKG; 6688c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, i2c); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci /* Write slave address */ 6718c2ecf20Sopenharmony_ci st_i2c_write_tx_fifo(i2c_dev, c->addr); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci /* Pre-fill Tx fifo with data in case of write */ 6748c2ecf20Sopenharmony_ci if (!(c->addr & I2C_M_RD)) 6758c2ecf20Sopenharmony_ci st_i2c_wr_fill_tx_fifo(i2c_dev); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci it = SSC_IEN_NACKEN | SSC_IEN_TEEN | SSC_IEN_ARBLEN; 6788c2ecf20Sopenharmony_ci writel_relaxed(it, i2c_dev->base + SSC_IEN); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci if (is_first) { 6818c2ecf20Sopenharmony_ci ret = st_i2c_wait_free_bus(i2c_dev); 6828c2ecf20Sopenharmony_ci if (ret) 6838c2ecf20Sopenharmony_ci return ret; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG); 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci timeout = wait_for_completion_timeout(&i2c_dev->complete, 6898c2ecf20Sopenharmony_ci i2c_dev->adap.timeout); 6908c2ecf20Sopenharmony_ci ret = c->result; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci if (!timeout) { 6938c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "Write to slave 0x%x timed out\n", 6948c2ecf20Sopenharmony_ci c->addr); 6958c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci i2c = SSC_I2C_STOPG | SSC_I2C_REPSTRTG; 6998c2ecf20Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, i2c); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci writel_relaxed(SSC_CLR_SSCSTOP | SSC_CLR_REPSTRT, 7028c2ecf20Sopenharmony_ci i2c_dev->base + SSC_CLR); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci return ret; 7058c2ecf20Sopenharmony_ci} 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci/** 7088c2ecf20Sopenharmony_ci * st_i2c_xfer() - Transfer a single I2C message 7098c2ecf20Sopenharmony_ci * @i2c_adap: Adapter pointer to the controller 7108c2ecf20Sopenharmony_ci * @msgs: Pointer to data to be written. 7118c2ecf20Sopenharmony_ci * @num: Number of messages to be executed 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_cistatic int st_i2c_xfer(struct i2c_adapter *i2c_adap, 7148c2ecf20Sopenharmony_ci struct i2c_msg msgs[], int num) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); 7178c2ecf20Sopenharmony_ci int ret, i; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci i2c_dev->busy = true; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci ret = clk_prepare_enable(i2c_dev->clk); 7228c2ecf20Sopenharmony_ci if (ret) { 7238c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n"); 7248c2ecf20Sopenharmony_ci return ret; 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci pinctrl_pm_select_default_state(i2c_dev->dev); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci st_i2c_hw_config(i2c_dev); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci for (i = 0; (i < num) && !ret; i++) 7328c2ecf20Sopenharmony_ci ret = st_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0, i == num - 1); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci pinctrl_pm_select_idle_state(i2c_dev->dev); 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci clk_disable_unprepare(i2c_dev->clk); 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci i2c_dev->busy = false; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci return (ret < 0) ? ret : i; 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 7448c2ecf20Sopenharmony_cistatic int st_i2c_suspend(struct device *dev) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (i2c_dev->busy) 7498c2ecf20Sopenharmony_ci return -EBUSY; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci pinctrl_pm_select_sleep_state(dev); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci return 0; 7548c2ecf20Sopenharmony_ci} 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_cistatic int st_i2c_resume(struct device *dev) 7578c2ecf20Sopenharmony_ci{ 7588c2ecf20Sopenharmony_ci pinctrl_pm_select_default_state(dev); 7598c2ecf20Sopenharmony_ci /* Go in idle state if available */ 7608c2ecf20Sopenharmony_ci pinctrl_pm_select_idle_state(dev); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci return 0; 7638c2ecf20Sopenharmony_ci} 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume); 7668c2ecf20Sopenharmony_ci#define ST_I2C_PM (&st_i2c_pm) 7678c2ecf20Sopenharmony_ci#else 7688c2ecf20Sopenharmony_ci#define ST_I2C_PM NULL 7698c2ecf20Sopenharmony_ci#endif 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_cistatic u32 st_i2c_func(struct i2c_adapter *adap) 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 7748c2ecf20Sopenharmony_ci} 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_cistatic const struct i2c_algorithm st_i2c_algo = { 7778c2ecf20Sopenharmony_ci .master_xfer = st_i2c_xfer, 7788c2ecf20Sopenharmony_ci .functionality = st_i2c_func, 7798c2ecf20Sopenharmony_ci}; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic struct i2c_bus_recovery_info st_i2c_recovery_info = { 7828c2ecf20Sopenharmony_ci .recover_bus = st_i2c_recover_bus, 7838c2ecf20Sopenharmony_ci}; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_cistatic int st_i2c_of_get_deglitch(struct device_node *np, 7868c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci int ret; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "st,i2c-min-scl-pulse-width-us", 7918c2ecf20Sopenharmony_ci &i2c_dev->scl_min_width_us); 7928c2ecf20Sopenharmony_ci if ((ret == -ENODATA) || (ret == -EOVERFLOW)) { 7938c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "st,i2c-min-scl-pulse-width-us invalid\n"); 7948c2ecf20Sopenharmony_ci return ret; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "st,i2c-min-sda-pulse-width-us", 7988c2ecf20Sopenharmony_ci &i2c_dev->sda_min_width_us); 7998c2ecf20Sopenharmony_ci if ((ret == -ENODATA) || (ret == -EOVERFLOW)) { 8008c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "st,i2c-min-sda-pulse-width-us invalid\n"); 8018c2ecf20Sopenharmony_ci return ret; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci return 0; 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic int st_i2c_probe(struct platform_device *pdev) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 8108c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev; 8118c2ecf20Sopenharmony_ci struct resource *res; 8128c2ecf20Sopenharmony_ci u32 clk_rate; 8138c2ecf20Sopenharmony_ci struct i2c_adapter *adap; 8148c2ecf20Sopenharmony_ci int ret; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); 8178c2ecf20Sopenharmony_ci if (!i2c_dev) 8188c2ecf20Sopenharmony_ci return -ENOMEM; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8218c2ecf20Sopenharmony_ci i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); 8228c2ecf20Sopenharmony_ci if (IS_ERR(i2c_dev->base)) 8238c2ecf20Sopenharmony_ci return PTR_ERR(i2c_dev->base); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci i2c_dev->irq = irq_of_parse_and_map(np, 0); 8268c2ecf20Sopenharmony_ci if (!i2c_dev->irq) { 8278c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "IRQ missing or invalid\n"); 8288c2ecf20Sopenharmony_ci return -EINVAL; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci i2c_dev->clk = of_clk_get_by_name(np, "ssc"); 8328c2ecf20Sopenharmony_ci if (IS_ERR(i2c_dev->clk)) { 8338c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to request clock\n"); 8348c2ecf20Sopenharmony_ci return PTR_ERR(i2c_dev->clk); 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci i2c_dev->mode = I2C_MODE_STANDARD; 8388c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "clock-frequency", &clk_rate); 8398c2ecf20Sopenharmony_ci if (!ret && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) 8408c2ecf20Sopenharmony_ci i2c_dev->mode = I2C_MODE_FAST; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci i2c_dev->dev = &pdev->dev; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq, 8458c2ecf20Sopenharmony_ci NULL, st_i2c_isr_thread, 8468c2ecf20Sopenharmony_ci IRQF_ONESHOT, pdev->name, i2c_dev); 8478c2ecf20Sopenharmony_ci if (ret) { 8488c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); 8498c2ecf20Sopenharmony_ci return ret; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci pinctrl_pm_select_default_state(i2c_dev->dev); 8538c2ecf20Sopenharmony_ci /* In case idle state available, select it */ 8548c2ecf20Sopenharmony_ci pinctrl_pm_select_idle_state(i2c_dev->dev); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci ret = st_i2c_of_get_deglitch(np, i2c_dev); 8578c2ecf20Sopenharmony_ci if (ret) 8588c2ecf20Sopenharmony_ci return ret; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci adap = &i2c_dev->adap; 8618c2ecf20Sopenharmony_ci i2c_set_adapdata(adap, i2c_dev); 8628c2ecf20Sopenharmony_ci snprintf(adap->name, sizeof(adap->name), "ST I2C(%pa)", &res->start); 8638c2ecf20Sopenharmony_ci adap->owner = THIS_MODULE; 8648c2ecf20Sopenharmony_ci adap->timeout = 2 * HZ; 8658c2ecf20Sopenharmony_ci adap->retries = 0; 8668c2ecf20Sopenharmony_ci adap->algo = &st_i2c_algo; 8678c2ecf20Sopenharmony_ci adap->bus_recovery_info = &st_i2c_recovery_info; 8688c2ecf20Sopenharmony_ci adap->dev.parent = &pdev->dev; 8698c2ecf20Sopenharmony_ci adap->dev.of_node = pdev->dev.of_node; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci init_completion(&i2c_dev->complete); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci ret = i2c_add_adapter(adap); 8748c2ecf20Sopenharmony_ci if (ret) 8758c2ecf20Sopenharmony_ci return ret; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, i2c_dev); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci dev_info(i2c_dev->dev, "%s initialized\n", adap->name); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci return 0; 8828c2ecf20Sopenharmony_ci} 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_cistatic int st_i2c_remove(struct platform_device *pdev) 8858c2ecf20Sopenharmony_ci{ 8868c2ecf20Sopenharmony_ci struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci i2c_del_adapter(&i2c_dev->adap); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci return 0; 8918c2ecf20Sopenharmony_ci} 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_cistatic const struct of_device_id st_i2c_match[] = { 8948c2ecf20Sopenharmony_ci { .compatible = "st,comms-ssc-i2c", }, 8958c2ecf20Sopenharmony_ci { .compatible = "st,comms-ssc4-i2c", }, 8968c2ecf20Sopenharmony_ci {}, 8978c2ecf20Sopenharmony_ci}; 8988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, st_i2c_match); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_cistatic struct platform_driver st_i2c_driver = { 9018c2ecf20Sopenharmony_ci .driver = { 9028c2ecf20Sopenharmony_ci .name = "st-i2c", 9038c2ecf20Sopenharmony_ci .of_match_table = st_i2c_match, 9048c2ecf20Sopenharmony_ci .pm = ST_I2C_PM, 9058c2ecf20Sopenharmony_ci }, 9068c2ecf20Sopenharmony_ci .probe = st_i2c_probe, 9078c2ecf20Sopenharmony_ci .remove = st_i2c_remove, 9088c2ecf20Sopenharmony_ci}; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_cimodule_platform_driver(st_i2c_driver); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ciMODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>"); 9138c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics I2C driver"); 9148c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 915