18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Synopsys DesignWare I2C adapter driver (master only). 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Based on the TI DAVINCI I2C adapter driver. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2006 Texas Instruments. 88c2ecf20Sopenharmony_ci * Copyright (C) 2007 MontaVista Software Inc. 98c2ecf20Sopenharmony_ci * Copyright (C) 2009 Provigent Ltd. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/err.h> 138c2ecf20Sopenharmony_ci#include <linux/errno.h> 148c2ecf20Sopenharmony_ci#include <linux/export.h> 158c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 168c2ecf20Sopenharmony_ci#include <linux/i2c.h> 178c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 188c2ecf20Sopenharmony_ci#include <linux/io.h> 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 218c2ecf20Sopenharmony_ci#include <linux/regmap.h> 228c2ecf20Sopenharmony_ci#include <linux/reset.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "i2c-designware-core.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci /* Configure Tx/Rx FIFO threshold levels */ 298c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_TX_TL, dev->tx_fifo_depth / 2); 308c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_RX_TL, 0); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci /* Configure the I2C master */ 338c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_CON, dev->master_cfg); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci const char *mode_str, *fp_str = ""; 398c2ecf20Sopenharmony_ci u32 comp_param1; 408c2ecf20Sopenharmony_ci u32 sda_falling_time, scl_falling_time; 418c2ecf20Sopenharmony_ci struct i2c_timings *t = &dev->timings; 428c2ecf20Sopenharmony_ci u32 ic_clk; 438c2ecf20Sopenharmony_ci int ret; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci ret = i2c_dw_acquire_lock(dev); 468c2ecf20Sopenharmony_ci if (ret) 478c2ecf20Sopenharmony_ci return ret; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &comp_param1); 508c2ecf20Sopenharmony_ci i2c_dw_release_lock(dev); 518c2ecf20Sopenharmony_ci if (ret) 528c2ecf20Sopenharmony_ci return ret; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* Set standard and fast speed dividers for high/low periods */ 558c2ecf20Sopenharmony_ci sda_falling_time = t->sda_fall_ns ?: 300; /* ns */ 568c2ecf20Sopenharmony_ci scl_falling_time = t->scl_fall_ns ?: 300; /* ns */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* Calculate SCL timing parameters for standard mode if not set */ 598c2ecf20Sopenharmony_ci if (!dev->ss_hcnt || !dev->ss_lcnt) { 608c2ecf20Sopenharmony_ci ic_clk = i2c_dw_clk_rate(dev); 618c2ecf20Sopenharmony_ci dev->ss_hcnt = 628c2ecf20Sopenharmony_ci i2c_dw_scl_hcnt(ic_clk, 638c2ecf20Sopenharmony_ci 4000, /* tHD;STA = tHIGH = 4.0 us */ 648c2ecf20Sopenharmony_ci sda_falling_time, 658c2ecf20Sopenharmony_ci 0, /* 0: DW default, 1: Ideal */ 668c2ecf20Sopenharmony_ci 0); /* No offset */ 678c2ecf20Sopenharmony_ci dev->ss_lcnt = 688c2ecf20Sopenharmony_ci i2c_dw_scl_lcnt(ic_clk, 698c2ecf20Sopenharmony_ci 4700, /* tLOW = 4.7 us */ 708c2ecf20Sopenharmony_ci scl_falling_time, 718c2ecf20Sopenharmony_ci 0); /* No offset */ 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n", 748c2ecf20Sopenharmony_ci dev->ss_hcnt, dev->ss_lcnt); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* 778c2ecf20Sopenharmony_ci * Set SCL timing parameters for fast mode or fast mode plus. Only 788c2ecf20Sopenharmony_ci * difference is the timing parameter values since the registers are 798c2ecf20Sopenharmony_ci * the same. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci if (t->bus_freq_hz == 1000000) { 828c2ecf20Sopenharmony_ci /* 838c2ecf20Sopenharmony_ci * Check are Fast Mode Plus parameters available. Calculate 848c2ecf20Sopenharmony_ci * SCL timing parameters for Fast Mode Plus if not set. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci if (dev->fp_hcnt && dev->fp_lcnt) { 878c2ecf20Sopenharmony_ci dev->fs_hcnt = dev->fp_hcnt; 888c2ecf20Sopenharmony_ci dev->fs_lcnt = dev->fp_lcnt; 898c2ecf20Sopenharmony_ci } else { 908c2ecf20Sopenharmony_ci ic_clk = i2c_dw_clk_rate(dev); 918c2ecf20Sopenharmony_ci dev->fs_hcnt = 928c2ecf20Sopenharmony_ci i2c_dw_scl_hcnt(ic_clk, 938c2ecf20Sopenharmony_ci 260, /* tHIGH = 260 ns */ 948c2ecf20Sopenharmony_ci sda_falling_time, 958c2ecf20Sopenharmony_ci 0, /* DW default */ 968c2ecf20Sopenharmony_ci 0); /* No offset */ 978c2ecf20Sopenharmony_ci dev->fs_lcnt = 988c2ecf20Sopenharmony_ci i2c_dw_scl_lcnt(ic_clk, 998c2ecf20Sopenharmony_ci 500, /* tLOW = 500 ns */ 1008c2ecf20Sopenharmony_ci scl_falling_time, 1018c2ecf20Sopenharmony_ci 0); /* No offset */ 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci fp_str = " Plus"; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci /* 1068c2ecf20Sopenharmony_ci * Calculate SCL timing parameters for fast mode if not set. They are 1078c2ecf20Sopenharmony_ci * needed also in high speed mode. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci if (!dev->fs_hcnt || !dev->fs_lcnt) { 1108c2ecf20Sopenharmony_ci ic_clk = i2c_dw_clk_rate(dev); 1118c2ecf20Sopenharmony_ci dev->fs_hcnt = 1128c2ecf20Sopenharmony_ci i2c_dw_scl_hcnt(ic_clk, 1138c2ecf20Sopenharmony_ci 600, /* tHD;STA = tHIGH = 0.6 us */ 1148c2ecf20Sopenharmony_ci sda_falling_time, 1158c2ecf20Sopenharmony_ci 0, /* 0: DW default, 1: Ideal */ 1168c2ecf20Sopenharmony_ci 0); /* No offset */ 1178c2ecf20Sopenharmony_ci dev->fs_lcnt = 1188c2ecf20Sopenharmony_ci i2c_dw_scl_lcnt(ic_clk, 1198c2ecf20Sopenharmony_ci 1300, /* tLOW = 1.3 us */ 1208c2ecf20Sopenharmony_ci scl_falling_time, 1218c2ecf20Sopenharmony_ci 0); /* No offset */ 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n", 1248c2ecf20Sopenharmony_ci fp_str, dev->fs_hcnt, dev->fs_lcnt); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Check is high speed possible and fall back to fast mode if not */ 1278c2ecf20Sopenharmony_ci if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) == 1288c2ecf20Sopenharmony_ci DW_IC_CON_SPEED_HIGH) { 1298c2ecf20Sopenharmony_ci if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK) 1308c2ecf20Sopenharmony_ci != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) { 1318c2ecf20Sopenharmony_ci dev_err(dev->dev, "High Speed not supported!\n"); 1328c2ecf20Sopenharmony_ci t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ; 1338c2ecf20Sopenharmony_ci dev->master_cfg &= ~DW_IC_CON_SPEED_MASK; 1348c2ecf20Sopenharmony_ci dev->master_cfg |= DW_IC_CON_SPEED_FAST; 1358c2ecf20Sopenharmony_ci dev->hs_hcnt = 0; 1368c2ecf20Sopenharmony_ci dev->hs_lcnt = 0; 1378c2ecf20Sopenharmony_ci } else if (!dev->hs_hcnt || !dev->hs_lcnt) { 1388c2ecf20Sopenharmony_ci ic_clk = i2c_dw_clk_rate(dev); 1398c2ecf20Sopenharmony_ci dev->hs_hcnt = 1408c2ecf20Sopenharmony_ci i2c_dw_scl_hcnt(ic_clk, 1418c2ecf20Sopenharmony_ci 160, /* tHIGH = 160 ns */ 1428c2ecf20Sopenharmony_ci sda_falling_time, 1438c2ecf20Sopenharmony_ci 0, /* DW default */ 1448c2ecf20Sopenharmony_ci 0); /* No offset */ 1458c2ecf20Sopenharmony_ci dev->hs_lcnt = 1468c2ecf20Sopenharmony_ci i2c_dw_scl_lcnt(ic_clk, 1478c2ecf20Sopenharmony_ci 320, /* tLOW = 320 ns */ 1488c2ecf20Sopenharmony_ci scl_falling_time, 1498c2ecf20Sopenharmony_ci 0); /* No offset */ 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n", 1528c2ecf20Sopenharmony_ci dev->hs_hcnt, dev->hs_lcnt); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci ret = i2c_dw_set_sda_hold(dev); 1568c2ecf20Sopenharmony_ci if (ret) 1578c2ecf20Sopenharmony_ci goto out; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci switch (dev->master_cfg & DW_IC_CON_SPEED_MASK) { 1608c2ecf20Sopenharmony_ci case DW_IC_CON_SPEED_STD: 1618c2ecf20Sopenharmony_ci mode_str = "Standard Mode"; 1628c2ecf20Sopenharmony_ci break; 1638c2ecf20Sopenharmony_ci case DW_IC_CON_SPEED_HIGH: 1648c2ecf20Sopenharmony_ci mode_str = "High Speed Mode"; 1658c2ecf20Sopenharmony_ci break; 1668c2ecf20Sopenharmony_ci default: 1678c2ecf20Sopenharmony_ci mode_str = "Fast Mode"; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "Bus speed: %s%s\n", mode_str, fp_str); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciout: 1728c2ecf20Sopenharmony_ci return ret; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/** 1768c2ecf20Sopenharmony_ci * i2c_dw_init() - Initialize the designware I2C master hardware 1778c2ecf20Sopenharmony_ci * @dev: device private data 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * This functions configures and enables the I2C master. 1808c2ecf20Sopenharmony_ci * This function is called during I2C init function, and in case of timeout at 1818c2ecf20Sopenharmony_ci * run time. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_cistatic int i2c_dw_init_master(struct dw_i2c_dev *dev) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci int ret; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci ret = i2c_dw_acquire_lock(dev); 1888c2ecf20Sopenharmony_ci if (ret) 1898c2ecf20Sopenharmony_ci return ret; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* Disable the adapter */ 1928c2ecf20Sopenharmony_ci __i2c_dw_disable(dev); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* Write standard speed timing parameters */ 1958c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt); 1968c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* Write fast mode/fast mode plus timing parameters */ 1998c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt); 2008c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* Write high speed timing parameters if supported */ 2038c2ecf20Sopenharmony_ci if (dev->hs_hcnt && dev->hs_lcnt) { 2048c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_HS_SCL_HCNT, dev->hs_hcnt); 2058c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* Write SDA hold time if supported */ 2098c2ecf20Sopenharmony_ci if (dev->sda_hold_time) 2108c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci i2c_dw_configure_fifo_master(dev); 2138c2ecf20Sopenharmony_ci i2c_dw_release_lock(dev); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic void i2c_dw_xfer_init(struct dw_i2c_dev *dev) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci struct i2c_msg *msgs = dev->msgs; 2218c2ecf20Sopenharmony_ci u32 ic_con = 0, ic_tar = 0; 2228c2ecf20Sopenharmony_ci u32 dummy; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* Disable the adapter */ 2258c2ecf20Sopenharmony_ci __i2c_dw_disable(dev); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* If the slave address is ten bit address, enable 10BITADDR */ 2288c2ecf20Sopenharmony_ci if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { 2298c2ecf20Sopenharmony_ci ic_con = DW_IC_CON_10BITADDR_MASTER; 2308c2ecf20Sopenharmony_ci /* 2318c2ecf20Sopenharmony_ci * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing 2328c2ecf20Sopenharmony_ci * mode has to be enabled via bit 12 of IC_TAR register. 2338c2ecf20Sopenharmony_ci * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be 2348c2ecf20Sopenharmony_ci * detected from registers. 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_ci ic_tar = DW_IC_TAR_10BITADDR_MASTER; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci regmap_update_bits(dev->map, DW_IC_CON, DW_IC_CON_10BITADDR_MASTER, 2408c2ecf20Sopenharmony_ci ic_con); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* 2438c2ecf20Sopenharmony_ci * Set the slave (target) address and enable 10-bit addressing mode 2448c2ecf20Sopenharmony_ci * if applicable. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_TAR, 2478c2ecf20Sopenharmony_ci msgs[dev->msg_write_idx].addr | ic_tar); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* Enforce disabled interrupts (due to HW issues) */ 2508c2ecf20Sopenharmony_ci i2c_dw_disable_int(dev); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* Enable the adapter */ 2538c2ecf20Sopenharmony_ci __i2c_dw_enable(dev); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* Dummy read to avoid the register getting stuck on Bay Trail */ 2568c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_ENABLE_STATUS, &dummy); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* Clear and enable interrupts */ 2598c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); 2608c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK); 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci/* 2648c2ecf20Sopenharmony_ci * Initiate (and continue) low level master read/write transaction. 2658c2ecf20Sopenharmony_ci * This function is only called from i2c_dw_isr, and pumping i2c_msg 2668c2ecf20Sopenharmony_ci * messages into the tx buffer. Even if the size of i2c_msg data is 2678c2ecf20Sopenharmony_ci * longer than the size of the tx buffer, it handles everything. 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_cistatic void 2708c2ecf20Sopenharmony_cii2c_dw_xfer_msg(struct dw_i2c_dev *dev) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci struct i2c_msg *msgs = dev->msgs; 2738c2ecf20Sopenharmony_ci u32 intr_mask; 2748c2ecf20Sopenharmony_ci int tx_limit, rx_limit; 2758c2ecf20Sopenharmony_ci u32 addr = msgs[dev->msg_write_idx].addr; 2768c2ecf20Sopenharmony_ci u32 buf_len = dev->tx_buf_len; 2778c2ecf20Sopenharmony_ci u8 *buf = dev->tx_buf; 2788c2ecf20Sopenharmony_ci bool need_restart = false; 2798c2ecf20Sopenharmony_ci unsigned int flr; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci intr_mask = DW_IC_INTR_MASTER_MASK; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { 2848c2ecf20Sopenharmony_ci u32 flags = msgs[dev->msg_write_idx].flags; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* 2878c2ecf20Sopenharmony_ci * If target address has changed, we need to 2888c2ecf20Sopenharmony_ci * reprogram the target address in the I2C 2898c2ecf20Sopenharmony_ci * adapter when we are done with this transfer. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ci if (msgs[dev->msg_write_idx].addr != addr) { 2928c2ecf20Sopenharmony_ci dev_err(dev->dev, 2938c2ecf20Sopenharmony_ci "%s: invalid target address\n", __func__); 2948c2ecf20Sopenharmony_ci dev->msg_err = -EINVAL; 2958c2ecf20Sopenharmony_ci break; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { 2998c2ecf20Sopenharmony_ci /* new i2c_msg */ 3008c2ecf20Sopenharmony_ci buf = msgs[dev->msg_write_idx].buf; 3018c2ecf20Sopenharmony_ci buf_len = msgs[dev->msg_write_idx].len; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* If both IC_EMPTYFIFO_HOLD_MASTER_EN and 3048c2ecf20Sopenharmony_ci * IC_RESTART_EN are set, we must manually 3058c2ecf20Sopenharmony_ci * set restart bit between messages. 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_ci if ((dev->master_cfg & DW_IC_CON_RESTART_EN) && 3088c2ecf20Sopenharmony_ci (dev->msg_write_idx > 0)) 3098c2ecf20Sopenharmony_ci need_restart = true; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_TXFLR, &flr); 3138c2ecf20Sopenharmony_ci tx_limit = dev->tx_fifo_depth - flr; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_RXFLR, &flr); 3168c2ecf20Sopenharmony_ci rx_limit = dev->rx_fifo_depth - flr; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { 3198c2ecf20Sopenharmony_ci u32 cmd = 0; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* 3228c2ecf20Sopenharmony_ci * If IC_EMPTYFIFO_HOLD_MASTER_EN is set we must 3238c2ecf20Sopenharmony_ci * manually set the stop bit. However, it cannot be 3248c2ecf20Sopenharmony_ci * detected from the registers so we set it always 3258c2ecf20Sopenharmony_ci * when writing/reading the last byte. 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* 3298c2ecf20Sopenharmony_ci * i2c-core always sets the buffer length of 3308c2ecf20Sopenharmony_ci * I2C_FUNC_SMBUS_BLOCK_DATA to 1. The length will 3318c2ecf20Sopenharmony_ci * be adjusted when receiving the first byte. 3328c2ecf20Sopenharmony_ci * Thus we can't stop the transaction here. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_ci if (dev->msg_write_idx == dev->msgs_num - 1 && 3358c2ecf20Sopenharmony_ci buf_len == 1 && !(flags & I2C_M_RECV_LEN)) 3368c2ecf20Sopenharmony_ci cmd |= BIT(9); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci if (need_restart) { 3398c2ecf20Sopenharmony_ci cmd |= BIT(10); 3408c2ecf20Sopenharmony_ci need_restart = false; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* Avoid rx buffer overrun */ 3468c2ecf20Sopenharmony_ci if (dev->rx_outstanding >= dev->rx_fifo_depth) 3478c2ecf20Sopenharmony_ci break; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_DATA_CMD, 3508c2ecf20Sopenharmony_ci cmd | 0x100); 3518c2ecf20Sopenharmony_ci rx_limit--; 3528c2ecf20Sopenharmony_ci dev->rx_outstanding++; 3538c2ecf20Sopenharmony_ci } else { 3548c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_DATA_CMD, 3558c2ecf20Sopenharmony_ci cmd | *buf++); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci tx_limit--; buf_len--; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci dev->tx_buf = buf; 3618c2ecf20Sopenharmony_ci dev->tx_buf_len = buf_len; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* 3648c2ecf20Sopenharmony_ci * Because we don't know the buffer length in the 3658c2ecf20Sopenharmony_ci * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop the 3668c2ecf20Sopenharmony_ci * transaction here. Also disable the TX_EMPTY IRQ 3678c2ecf20Sopenharmony_ci * while waiting for the data length byte to avoid the 3688c2ecf20Sopenharmony_ci * bogus interrupts flood. 3698c2ecf20Sopenharmony_ci */ 3708c2ecf20Sopenharmony_ci if (flags & I2C_M_RECV_LEN) { 3718c2ecf20Sopenharmony_ci dev->status |= STATUS_WRITE_IN_PROGRESS; 3728c2ecf20Sopenharmony_ci intr_mask &= ~DW_IC_INTR_TX_EMPTY; 3738c2ecf20Sopenharmony_ci break; 3748c2ecf20Sopenharmony_ci } else if (buf_len > 0) { 3758c2ecf20Sopenharmony_ci /* more bytes to be written */ 3768c2ecf20Sopenharmony_ci dev->status |= STATUS_WRITE_IN_PROGRESS; 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci } else 3798c2ecf20Sopenharmony_ci dev->status &= ~STATUS_WRITE_IN_PROGRESS; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* 3838c2ecf20Sopenharmony_ci * If i2c_msg index search is completed, we don't need TX_EMPTY 3848c2ecf20Sopenharmony_ci * interrupt any more. 3858c2ecf20Sopenharmony_ci */ 3868c2ecf20Sopenharmony_ci if (dev->msg_write_idx == dev->msgs_num) 3878c2ecf20Sopenharmony_ci intr_mask &= ~DW_IC_INTR_TX_EMPTY; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (dev->msg_err) 3908c2ecf20Sopenharmony_ci intr_mask = 0; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_INTR_MASK, intr_mask); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic u8 3968c2ecf20Sopenharmony_cii2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci struct i2c_msg *msgs = dev->msgs; 3998c2ecf20Sopenharmony_ci u32 flags = msgs[dev->msg_read_idx].flags; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* 4028c2ecf20Sopenharmony_ci * Adjust the buffer length and mask the flag 4038c2ecf20Sopenharmony_ci * after receiving the first byte. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_ci len += (flags & I2C_CLIENT_PEC) ? 2 : 1; 4068c2ecf20Sopenharmony_ci dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding); 4078c2ecf20Sopenharmony_ci msgs[dev->msg_read_idx].len = len; 4088c2ecf20Sopenharmony_ci msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* 4118c2ecf20Sopenharmony_ci * Received buffer length, re-enable TX_EMPTY interrupt 4128c2ecf20Sopenharmony_ci * to resume the SMBUS transaction. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci regmap_update_bits(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY, 4158c2ecf20Sopenharmony_ci DW_IC_INTR_TX_EMPTY); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci return len; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void 4218c2ecf20Sopenharmony_cii2c_dw_read(struct dw_i2c_dev *dev) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci struct i2c_msg *msgs = dev->msgs; 4248c2ecf20Sopenharmony_ci unsigned int rx_valid; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { 4278c2ecf20Sopenharmony_ci u32 len, tmp; 4288c2ecf20Sopenharmony_ci u8 *buf; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) 4318c2ecf20Sopenharmony_ci continue; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (!(dev->status & STATUS_READ_IN_PROGRESS)) { 4348c2ecf20Sopenharmony_ci len = msgs[dev->msg_read_idx].len; 4358c2ecf20Sopenharmony_ci buf = msgs[dev->msg_read_idx].buf; 4368c2ecf20Sopenharmony_ci } else { 4378c2ecf20Sopenharmony_ci len = dev->rx_buf_len; 4388c2ecf20Sopenharmony_ci buf = dev->rx_buf; 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_RXFLR, &rx_valid); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci for (; len > 0 && rx_valid > 0; len--, rx_valid--) { 4448c2ecf20Sopenharmony_ci u32 flags = msgs[dev->msg_read_idx].flags; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); 4478c2ecf20Sopenharmony_ci /* Ensure length byte is a valid value */ 4488c2ecf20Sopenharmony_ci if (flags & I2C_M_RECV_LEN) { 4498c2ecf20Sopenharmony_ci /* 4508c2ecf20Sopenharmony_ci * if IC_EMPTYFIFO_HOLD_MASTER_EN is set, which cannot be 4518c2ecf20Sopenharmony_ci * detected from the registers, the controller can be 4528c2ecf20Sopenharmony_ci * disabled if the STOP bit is set. But it is only set 4538c2ecf20Sopenharmony_ci * after receiving block data response length in 4548c2ecf20Sopenharmony_ci * I2C_FUNC_SMBUS_BLOCK_DATA case. That needs to read 4558c2ecf20Sopenharmony_ci * another byte with STOP bit set when the block data 4568c2ecf20Sopenharmony_ci * response length is invalid to complete the transaction. 4578c2ecf20Sopenharmony_ci */ 4588c2ecf20Sopenharmony_ci if (!tmp || tmp > I2C_SMBUS_BLOCK_MAX) 4598c2ecf20Sopenharmony_ci tmp = 1; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci len = i2c_dw_recv_len(dev, tmp); 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci *buf++ = tmp; 4648c2ecf20Sopenharmony_ci dev->rx_outstanding--; 4658c2ecf20Sopenharmony_ci } 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (len > 0) { 4688c2ecf20Sopenharmony_ci dev->status |= STATUS_READ_IN_PROGRESS; 4698c2ecf20Sopenharmony_ci dev->rx_buf_len = len; 4708c2ecf20Sopenharmony_ci dev->rx_buf = buf; 4718c2ecf20Sopenharmony_ci return; 4728c2ecf20Sopenharmony_ci } else 4738c2ecf20Sopenharmony_ci dev->status &= ~STATUS_READ_IN_PROGRESS; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci/* 4788c2ecf20Sopenharmony_ci * Prepare controller for a transaction and call i2c_dw_xfer_msg. 4798c2ecf20Sopenharmony_ci */ 4808c2ecf20Sopenharmony_cistatic int 4818c2ecf20Sopenharmony_cii2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci struct dw_i2c_dev *dev = i2c_get_adapdata(adap); 4848c2ecf20Sopenharmony_ci int ret; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci pm_runtime_get_sync(dev->dev); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (dev_WARN_ONCE(dev->dev, dev->suspended, "Transfer while suspended\n")) { 4918c2ecf20Sopenharmony_ci ret = -ESHUTDOWN; 4928c2ecf20Sopenharmony_ci goto done_nolock; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci reinit_completion(&dev->cmd_complete); 4968c2ecf20Sopenharmony_ci dev->msgs = msgs; 4978c2ecf20Sopenharmony_ci dev->msgs_num = num; 4988c2ecf20Sopenharmony_ci dev->cmd_err = 0; 4998c2ecf20Sopenharmony_ci dev->msg_write_idx = 0; 5008c2ecf20Sopenharmony_ci dev->msg_read_idx = 0; 5018c2ecf20Sopenharmony_ci dev->msg_err = 0; 5028c2ecf20Sopenharmony_ci dev->status = STATUS_IDLE; 5038c2ecf20Sopenharmony_ci dev->abort_source = 0; 5048c2ecf20Sopenharmony_ci dev->rx_outstanding = 0; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci ret = i2c_dw_acquire_lock(dev); 5078c2ecf20Sopenharmony_ci if (ret) 5088c2ecf20Sopenharmony_ci goto done_nolock; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci ret = i2c_dw_wait_bus_not_busy(dev); 5118c2ecf20Sopenharmony_ci if (ret < 0) 5128c2ecf20Sopenharmony_ci goto done; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /* Start the transfers */ 5158c2ecf20Sopenharmony_ci i2c_dw_xfer_init(dev); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* Wait for tx to complete */ 5188c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) { 5198c2ecf20Sopenharmony_ci dev_err(dev->dev, "controller timed out\n"); 5208c2ecf20Sopenharmony_ci /* i2c_dw_init implicitly disables the adapter */ 5218c2ecf20Sopenharmony_ci i2c_recover_bus(&dev->adapter); 5228c2ecf20Sopenharmony_ci i2c_dw_init_master(dev); 5238c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 5248c2ecf20Sopenharmony_ci goto done; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* 5288c2ecf20Sopenharmony_ci * We must disable the adapter before returning and signaling the end 5298c2ecf20Sopenharmony_ci * of the current transfer. Otherwise the hardware might continue 5308c2ecf20Sopenharmony_ci * generating interrupts which in turn causes a race condition with 5318c2ecf20Sopenharmony_ci * the following transfer. Needs some more investigation if the 5328c2ecf20Sopenharmony_ci * additional interrupts are a hardware bug or this driver doesn't 5338c2ecf20Sopenharmony_ci * handle them correctly yet. 5348c2ecf20Sopenharmony_ci */ 5358c2ecf20Sopenharmony_ci __i2c_dw_disable_nowait(dev); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (dev->msg_err) { 5388c2ecf20Sopenharmony_ci ret = dev->msg_err; 5398c2ecf20Sopenharmony_ci goto done; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci /* No error */ 5438c2ecf20Sopenharmony_ci if (likely(!dev->cmd_err && !dev->status)) { 5448c2ecf20Sopenharmony_ci ret = num; 5458c2ecf20Sopenharmony_ci goto done; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* We have an error */ 5498c2ecf20Sopenharmony_ci if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { 5508c2ecf20Sopenharmony_ci ret = i2c_dw_handle_tx_abort(dev); 5518c2ecf20Sopenharmony_ci goto done; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci if (dev->status) 5558c2ecf20Sopenharmony_ci dev_err(dev->dev, 5568c2ecf20Sopenharmony_ci "transfer terminated early - interrupt latency too high?\n"); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci ret = -EIO; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_cidone: 5618c2ecf20Sopenharmony_ci i2c_dw_release_lock(dev); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cidone_nolock: 5648c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dev->dev); 5658c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(dev->dev); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci return ret; 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_cistatic const struct i2c_algorithm i2c_dw_algo = { 5718c2ecf20Sopenharmony_ci .master_xfer = i2c_dw_xfer, 5728c2ecf20Sopenharmony_ci .functionality = i2c_dw_func, 5738c2ecf20Sopenharmony_ci}; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cistatic const struct i2c_adapter_quirks i2c_dw_quirks = { 5768c2ecf20Sopenharmony_ci .flags = I2C_AQ_NO_ZERO_LEN, 5778c2ecf20Sopenharmony_ci}; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cistatic u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci u32 stat, dummy; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* 5848c2ecf20Sopenharmony_ci * The IC_INTR_STAT register just indicates "enabled" interrupts. 5858c2ecf20Sopenharmony_ci * The unmasked raw version of interrupt status bits is available 5868c2ecf20Sopenharmony_ci * in the IC_RAW_INTR_STAT register. 5878c2ecf20Sopenharmony_ci * 5888c2ecf20Sopenharmony_ci * That is, 5898c2ecf20Sopenharmony_ci * stat = readl(IC_INTR_STAT); 5908c2ecf20Sopenharmony_ci * equals to, 5918c2ecf20Sopenharmony_ci * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK); 5928c2ecf20Sopenharmony_ci * 5938c2ecf20Sopenharmony_ci * The raw version might be useful for debugging purposes. 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_INTR_STAT, &stat); 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci /* 5988c2ecf20Sopenharmony_ci * Do not use the IC_CLR_INTR register to clear interrupts, or 5998c2ecf20Sopenharmony_ci * you'll miss some interrupts, triggered during the period from 6008c2ecf20Sopenharmony_ci * readl(IC_INTR_STAT) to readl(IC_CLR_INTR). 6018c2ecf20Sopenharmony_ci * 6028c2ecf20Sopenharmony_ci * Instead, use the separately-prepared IC_CLR_* registers. 6038c2ecf20Sopenharmony_ci */ 6048c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_RX_UNDER) 6058c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy); 6068c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_RX_OVER) 6078c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy); 6088c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_TX_OVER) 6098c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy); 6108c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_RD_REQ) 6118c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_RD_REQ, &dummy); 6128c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_TX_ABRT) { 6138c2ecf20Sopenharmony_ci /* 6148c2ecf20Sopenharmony_ci * The IC_TX_ABRT_SOURCE register is cleared whenever 6158c2ecf20Sopenharmony_ci * the IC_CLR_TX_ABRT is read. Preserve it beforehand. 6168c2ecf20Sopenharmony_ci */ 6178c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_TX_ABRT_SOURCE, &dev->abort_source); 6188c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy); 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_RX_DONE) 6218c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy); 6228c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_ACTIVITY) 6238c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy); 6248c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_STOP_DET) 6258c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy); 6268c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_START_DET) 6278c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy); 6288c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_GEN_CALL) 6298c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci return stat; 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci/* 6358c2ecf20Sopenharmony_ci * Interrupt service routine. This gets called whenever an I2C master interrupt 6368c2ecf20Sopenharmony_ci * occurs. 6378c2ecf20Sopenharmony_ci */ 6388c2ecf20Sopenharmony_cistatic int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci u32 stat; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci stat = i2c_dw_read_clear_intrbits(dev); 6438c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_TX_ABRT) { 6448c2ecf20Sopenharmony_ci dev->cmd_err |= DW_IC_ERR_TX_ABRT; 6458c2ecf20Sopenharmony_ci dev->status = STATUS_IDLE; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* 6488c2ecf20Sopenharmony_ci * Anytime TX_ABRT is set, the contents of the tx/rx 6498c2ecf20Sopenharmony_ci * buffers are flushed. Make sure to skip them. 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_INTR_MASK, 0); 6528c2ecf20Sopenharmony_ci goto tx_aborted; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_RX_FULL) 6568c2ecf20Sopenharmony_ci i2c_dw_read(dev); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (stat & DW_IC_INTR_TX_EMPTY) 6598c2ecf20Sopenharmony_ci i2c_dw_xfer_msg(dev); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci /* 6628c2ecf20Sopenharmony_ci * No need to modify or disable the interrupt mask here. 6638c2ecf20Sopenharmony_ci * i2c_dw_xfer_msg() will take care of it according to 6648c2ecf20Sopenharmony_ci * the current transmit status. 6658c2ecf20Sopenharmony_ci */ 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_citx_aborted: 6688c2ecf20Sopenharmony_ci if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) 6698c2ecf20Sopenharmony_ci complete(&dev->cmd_complete); 6708c2ecf20Sopenharmony_ci else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { 6718c2ecf20Sopenharmony_ci /* Workaround to trigger pending interrupt */ 6728c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_INTR_MASK, &stat); 6738c2ecf20Sopenharmony_ci i2c_dw_disable_int(dev); 6748c2ecf20Sopenharmony_ci regmap_write(dev->map, DW_IC_INTR_MASK, stat); 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci return 0; 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cistatic irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci struct dw_i2c_dev *dev = dev_id; 6838c2ecf20Sopenharmony_ci u32 stat, enabled; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_ENABLE, &enabled); 6868c2ecf20Sopenharmony_ci regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); 6878c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat); 6888c2ecf20Sopenharmony_ci if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY)) 6898c2ecf20Sopenharmony_ci return IRQ_NONE; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci i2c_dw_irq_handler_master(dev); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci return IRQ_HANDLED; 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_civoid i2c_dw_configure_master(struct dw_i2c_dev *dev) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci struct i2c_timings *t = &dev->timings; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | 7038c2ecf20Sopenharmony_ci DW_IC_CON_RESTART_EN; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci dev->mode = DW_IC_MASTER; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci switch (t->bus_freq_hz) { 7088c2ecf20Sopenharmony_ci case I2C_MAX_STANDARD_MODE_FREQ: 7098c2ecf20Sopenharmony_ci dev->master_cfg |= DW_IC_CON_SPEED_STD; 7108c2ecf20Sopenharmony_ci break; 7118c2ecf20Sopenharmony_ci case I2C_MAX_HIGH_SPEED_MODE_FREQ: 7128c2ecf20Sopenharmony_ci dev->master_cfg |= DW_IC_CON_SPEED_HIGH; 7138c2ecf20Sopenharmony_ci break; 7148c2ecf20Sopenharmony_ci default: 7158c2ecf20Sopenharmony_ci dev->master_cfg |= DW_IC_CON_SPEED_FAST; 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(i2c_dw_configure_master); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_cistatic void i2c_dw_prepare_recovery(struct i2c_adapter *adap) 7218c2ecf20Sopenharmony_ci{ 7228c2ecf20Sopenharmony_ci struct dw_i2c_dev *dev = i2c_get_adapdata(adap); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci i2c_dw_disable(dev); 7258c2ecf20Sopenharmony_ci reset_control_assert(dev->rst); 7268c2ecf20Sopenharmony_ci i2c_dw_prepare_clk(dev, false); 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_cistatic void i2c_dw_unprepare_recovery(struct i2c_adapter *adap) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci struct dw_i2c_dev *dev = i2c_get_adapdata(adap); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci i2c_dw_prepare_clk(dev, true); 7348c2ecf20Sopenharmony_ci reset_control_deassert(dev->rst); 7358c2ecf20Sopenharmony_ci i2c_dw_init_master(dev); 7368c2ecf20Sopenharmony_ci} 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_cistatic int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci struct i2c_bus_recovery_info *rinfo = &dev->rinfo; 7418c2ecf20Sopenharmony_ci struct i2c_adapter *adap = &dev->adapter; 7428c2ecf20Sopenharmony_ci struct gpio_desc *gpio; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci gpio = devm_gpiod_get_optional(dev->dev, "scl", GPIOD_OUT_HIGH); 7458c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(gpio)) 7468c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(gpio); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci rinfo->scl_gpiod = gpio; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci gpio = devm_gpiod_get_optional(dev->dev, "sda", GPIOD_IN); 7518c2ecf20Sopenharmony_ci if (IS_ERR(gpio)) 7528c2ecf20Sopenharmony_ci return PTR_ERR(gpio); 7538c2ecf20Sopenharmony_ci rinfo->sda_gpiod = gpio; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci rinfo->recover_bus = i2c_generic_scl_recovery; 7568c2ecf20Sopenharmony_ci rinfo->prepare_recovery = i2c_dw_prepare_recovery; 7578c2ecf20Sopenharmony_ci rinfo->unprepare_recovery = i2c_dw_unprepare_recovery; 7588c2ecf20Sopenharmony_ci adap->bus_recovery_info = rinfo; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci dev_info(dev->dev, "running with gpio recovery mode! scl%s", 7618c2ecf20Sopenharmony_ci rinfo->sda_gpiod ? ",sda" : ""); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci return 0; 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ciint i2c_dw_probe_master(struct dw_i2c_dev *dev) 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci struct i2c_adapter *adap = &dev->adapter; 7698c2ecf20Sopenharmony_ci unsigned long irq_flags; 7708c2ecf20Sopenharmony_ci int ret; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci init_completion(&dev->cmd_complete); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci dev->init = i2c_dw_init_master; 7758c2ecf20Sopenharmony_ci dev->disable = i2c_dw_disable; 7768c2ecf20Sopenharmony_ci dev->disable_int = i2c_dw_disable_int; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci ret = i2c_dw_init_regmap(dev); 7798c2ecf20Sopenharmony_ci if (ret) 7808c2ecf20Sopenharmony_ci return ret; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci ret = i2c_dw_set_timings_master(dev); 7838c2ecf20Sopenharmony_ci if (ret) 7848c2ecf20Sopenharmony_ci return ret; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci ret = i2c_dw_set_fifo_size(dev); 7878c2ecf20Sopenharmony_ci if (ret) 7888c2ecf20Sopenharmony_ci return ret; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ret = dev->init(dev); 7918c2ecf20Sopenharmony_ci if (ret) 7928c2ecf20Sopenharmony_ci return ret; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci snprintf(adap->name, sizeof(adap->name), 7958c2ecf20Sopenharmony_ci "Synopsys DesignWare I2C adapter"); 7968c2ecf20Sopenharmony_ci adap->retries = 3; 7978c2ecf20Sopenharmony_ci adap->algo = &i2c_dw_algo; 7988c2ecf20Sopenharmony_ci adap->quirks = &i2c_dw_quirks; 7998c2ecf20Sopenharmony_ci adap->dev.parent = dev->dev; 8008c2ecf20Sopenharmony_ci i2c_set_adapdata(adap, dev); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { 8038c2ecf20Sopenharmony_ci irq_flags = IRQF_NO_SUSPEND; 8048c2ecf20Sopenharmony_ci } else { 8058c2ecf20Sopenharmony_ci irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND; 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci i2c_dw_disable_int(dev); 8098c2ecf20Sopenharmony_ci ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags, 8108c2ecf20Sopenharmony_ci dev_name(dev->dev), dev); 8118c2ecf20Sopenharmony_ci if (ret) { 8128c2ecf20Sopenharmony_ci dev_err(dev->dev, "failure requesting irq %i: %d\n", 8138c2ecf20Sopenharmony_ci dev->irq, ret); 8148c2ecf20Sopenharmony_ci return ret; 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci ret = i2c_dw_init_recovery_info(dev); 8188c2ecf20Sopenharmony_ci if (ret) 8198c2ecf20Sopenharmony_ci return ret; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci /* 8228c2ecf20Sopenharmony_ci * Increment PM usage count during adapter registration in order to 8238c2ecf20Sopenharmony_ci * avoid possible spurious runtime suspend when adapter device is 8248c2ecf20Sopenharmony_ci * registered to the device core and immediate resume in case bus has 8258c2ecf20Sopenharmony_ci * registered I2C slaves that do I2C transfers in their probe. 8268c2ecf20Sopenharmony_ci */ 8278c2ecf20Sopenharmony_ci pm_runtime_get_noresume(dev->dev); 8288c2ecf20Sopenharmony_ci ret = i2c_add_numbered_adapter(adap); 8298c2ecf20Sopenharmony_ci if (ret) 8308c2ecf20Sopenharmony_ci dev_err(dev->dev, "failure adding adapter: %d\n", ret); 8318c2ecf20Sopenharmony_ci pm_runtime_put_noidle(dev->dev); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci return ret; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(i2c_dw_probe_master); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Synopsys DesignWare I2C bus master adapter"); 8388c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 839