18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drivers/i2c/busses/i2c-tegra.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2010 Google, Inc. 68c2ecf20Sopenharmony_ci * Author: Colin Cross <ccross@android.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 108c2ecf20Sopenharmony_ci#include <linux/clk.h> 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 138c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/i2c.h> 168c2ecf20Sopenharmony_ci#include <linux/init.h> 178c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 188c2ecf20Sopenharmony_ci#include <linux/io.h> 198c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 208c2ecf20Sopenharmony_ci#include <linux/irq.h> 218c2ecf20Sopenharmony_ci#include <linux/kernel.h> 228c2ecf20Sopenharmony_ci#include <linux/ktime.h> 238c2ecf20Sopenharmony_ci#include <linux/module.h> 248c2ecf20Sopenharmony_ci#include <linux/of_device.h> 258c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 268c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 278c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 288c2ecf20Sopenharmony_ci#include <linux/reset.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define BYTES_PER_FIFO_WORD 4 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define I2C_CNFG 0x000 338c2ecf20Sopenharmony_ci#define I2C_CNFG_DEBOUNCE_CNT GENMASK(14, 12) 348c2ecf20Sopenharmony_ci#define I2C_CNFG_PACKET_MODE_EN BIT(10) 358c2ecf20Sopenharmony_ci#define I2C_CNFG_NEW_MASTER_FSM BIT(11) 368c2ecf20Sopenharmony_ci#define I2C_CNFG_MULTI_MASTER_MODE BIT(17) 378c2ecf20Sopenharmony_ci#define I2C_STATUS 0x01c 388c2ecf20Sopenharmony_ci#define I2C_SL_CNFG 0x020 398c2ecf20Sopenharmony_ci#define I2C_SL_CNFG_NACK BIT(1) 408c2ecf20Sopenharmony_ci#define I2C_SL_CNFG_NEWSL BIT(2) 418c2ecf20Sopenharmony_ci#define I2C_SL_ADDR1 0x02c 428c2ecf20Sopenharmony_ci#define I2C_SL_ADDR2 0x030 438c2ecf20Sopenharmony_ci#define I2C_TLOW_SEXT 0x034 448c2ecf20Sopenharmony_ci#define I2C_TX_FIFO 0x050 458c2ecf20Sopenharmony_ci#define I2C_RX_FIFO 0x054 468c2ecf20Sopenharmony_ci#define I2C_PACKET_TRANSFER_STATUS 0x058 478c2ecf20Sopenharmony_ci#define I2C_FIFO_CONTROL 0x05c 488c2ecf20Sopenharmony_ci#define I2C_FIFO_CONTROL_TX_FLUSH BIT(1) 498c2ecf20Sopenharmony_ci#define I2C_FIFO_CONTROL_RX_FLUSH BIT(0) 508c2ecf20Sopenharmony_ci#define I2C_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 5) 518c2ecf20Sopenharmony_ci#define I2C_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 2) 528c2ecf20Sopenharmony_ci#define I2C_FIFO_STATUS 0x060 538c2ecf20Sopenharmony_ci#define I2C_FIFO_STATUS_TX GENMASK(7, 4) 548c2ecf20Sopenharmony_ci#define I2C_FIFO_STATUS_RX GENMASK(3, 0) 558c2ecf20Sopenharmony_ci#define I2C_INT_MASK 0x064 568c2ecf20Sopenharmony_ci#define I2C_INT_STATUS 0x068 578c2ecf20Sopenharmony_ci#define I2C_INT_BUS_CLR_DONE BIT(11) 588c2ecf20Sopenharmony_ci#define I2C_INT_PACKET_XFER_COMPLETE BIT(7) 598c2ecf20Sopenharmony_ci#define I2C_INT_NO_ACK BIT(3) 608c2ecf20Sopenharmony_ci#define I2C_INT_ARBITRATION_LOST BIT(2) 618c2ecf20Sopenharmony_ci#define I2C_INT_TX_FIFO_DATA_REQ BIT(1) 628c2ecf20Sopenharmony_ci#define I2C_INT_RX_FIFO_DATA_REQ BIT(0) 638c2ecf20Sopenharmony_ci#define I2C_CLK_DIVISOR 0x06c 648c2ecf20Sopenharmony_ci#define I2C_CLK_DIVISOR_STD_FAST_MODE GENMASK(31, 16) 658c2ecf20Sopenharmony_ci#define I2C_CLK_DIVISOR_HSMODE GENMASK(15, 0) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#define DVC_CTRL_REG1 0x000 688c2ecf20Sopenharmony_ci#define DVC_CTRL_REG1_INTR_EN BIT(10) 698c2ecf20Sopenharmony_ci#define DVC_CTRL_REG3 0x008 708c2ecf20Sopenharmony_ci#define DVC_CTRL_REG3_SW_PROG BIT(26) 718c2ecf20Sopenharmony_ci#define DVC_CTRL_REG3_I2C_DONE_INTR_EN BIT(30) 728c2ecf20Sopenharmony_ci#define DVC_STATUS 0x00c 738c2ecf20Sopenharmony_ci#define DVC_STATUS_I2C_DONE_INTR BIT(30) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define I2C_ERR_NONE 0x00 768c2ecf20Sopenharmony_ci#define I2C_ERR_NO_ACK BIT(0) 778c2ecf20Sopenharmony_ci#define I2C_ERR_ARBITRATION_LOST BIT(1) 788c2ecf20Sopenharmony_ci#define I2C_ERR_UNKNOWN_INTERRUPT BIT(2) 798c2ecf20Sopenharmony_ci#define I2C_ERR_RX_BUFFER_OVERFLOW BIT(3) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define PACKET_HEADER0_HEADER_SIZE GENMASK(29, 28) 828c2ecf20Sopenharmony_ci#define PACKET_HEADER0_PACKET_ID GENMASK(23, 16) 838c2ecf20Sopenharmony_ci#define PACKET_HEADER0_CONT_ID GENMASK(15, 12) 848c2ecf20Sopenharmony_ci#define PACKET_HEADER0_PROTOCOL GENMASK(7, 4) 858c2ecf20Sopenharmony_ci#define PACKET_HEADER0_PROTOCOL_I2C 1 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define I2C_HEADER_CONT_ON_NAK BIT(21) 888c2ecf20Sopenharmony_ci#define I2C_HEADER_READ BIT(19) 898c2ecf20Sopenharmony_ci#define I2C_HEADER_10BIT_ADDR BIT(18) 908c2ecf20Sopenharmony_ci#define I2C_HEADER_IE_ENABLE BIT(17) 918c2ecf20Sopenharmony_ci#define I2C_HEADER_REPEAT_START BIT(16) 928c2ecf20Sopenharmony_ci#define I2C_HEADER_CONTINUE_XFER BIT(15) 938c2ecf20Sopenharmony_ci#define I2C_HEADER_SLAVE_ADDR_SHIFT 1 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define I2C_BUS_CLEAR_CNFG 0x084 968c2ecf20Sopenharmony_ci#define I2C_BC_SCLK_THRESHOLD GENMASK(23, 16) 978c2ecf20Sopenharmony_ci#define I2C_BC_STOP_COND BIT(2) 988c2ecf20Sopenharmony_ci#define I2C_BC_TERMINATE BIT(1) 998c2ecf20Sopenharmony_ci#define I2C_BC_ENABLE BIT(0) 1008c2ecf20Sopenharmony_ci#define I2C_BUS_CLEAR_STATUS 0x088 1018c2ecf20Sopenharmony_ci#define I2C_BC_STATUS BIT(0) 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define I2C_CONFIG_LOAD 0x08c 1048c2ecf20Sopenharmony_ci#define I2C_MSTR_CONFIG_LOAD BIT(0) 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define I2C_CLKEN_OVERRIDE 0x090 1078c2ecf20Sopenharmony_ci#define I2C_MST_CORE_CLKEN_OVR BIT(0) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_0 0x094 1108c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_THIGH GENMASK(13, 8) 1118c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_TLOW GENMASK(5, 0) 1128c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_1 0x098 1138c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_TBUF GENMASK(29, 24) 1148c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_TSU_STO GENMASK(21, 16) 1158c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_THD_STA GENMASK(13, 8) 1168c2ecf20Sopenharmony_ci#define I2C_INTERFACE_TIMING_TSU_STA GENMASK(5, 0) 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_0 0x09c 1198c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(13, 8) 1208c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(5, 0) 1218c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_1 0x0a0 1228c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_TSU_STO GENMASK(21, 16) 1238c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_THD_STA GENMASK(13, 8) 1248c2ecf20Sopenharmony_ci#define I2C_HS_INTERFACE_TIMING_TSU_STA GENMASK(5, 0) 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_CONTROL 0x0b4 1278c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_CONTROL_RX_FLUSH BIT(0) 1288c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_CONTROL_TX_FLUSH BIT(1) 1298c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 4) 1308c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 16) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_STATUS 0x0b8 1338c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_STATUS_TX GENMASK(23, 16) 1348c2ecf20Sopenharmony_ci#define I2C_MST_FIFO_STATUS_RX GENMASK(7, 0) 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* configuration load timeout in microseconds */ 1378c2ecf20Sopenharmony_ci#define I2C_CONFIG_LOAD_TIMEOUT 1000000 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* packet header size in bytes */ 1408c2ecf20Sopenharmony_ci#define I2C_PACKET_HEADER_SIZE 12 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* 1438c2ecf20Sopenharmony_ci * I2C Controller will use PIO mode for transfers up to 32 bytes in order to 1448c2ecf20Sopenharmony_ci * avoid DMA overhead, otherwise external APB DMA controller will be used. 1458c2ecf20Sopenharmony_ci * Note that the actual MAX PIO length is 20 bytes because 32 bytes include 1468c2ecf20Sopenharmony_ci * I2C_PACKET_HEADER_SIZE. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci#define I2C_PIO_MODE_PREFERRED_LEN 32 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* 1518c2ecf20Sopenharmony_ci * msg_end_type: The bus control which needs to be sent at end of transfer. 1528c2ecf20Sopenharmony_ci * @MSG_END_STOP: Send stop pulse. 1538c2ecf20Sopenharmony_ci * @MSG_END_REPEAT_START: Send repeat-start. 1548c2ecf20Sopenharmony_ci * @MSG_END_CONTINUE: Don't send stop or repeat-start. 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_cienum msg_end_type { 1578c2ecf20Sopenharmony_ci MSG_END_STOP, 1588c2ecf20Sopenharmony_ci MSG_END_REPEAT_START, 1598c2ecf20Sopenharmony_ci MSG_END_CONTINUE, 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/** 1638c2ecf20Sopenharmony_ci * struct tegra_i2c_hw_feature : per hardware generation features 1648c2ecf20Sopenharmony_ci * @has_continue_xfer_support: continue-transfer supported 1658c2ecf20Sopenharmony_ci * @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer 1668c2ecf20Sopenharmony_ci * completion interrupt on per packet basis. 1678c2ecf20Sopenharmony_ci * @has_config_load_reg: Has the config load register to load the new 1688c2ecf20Sopenharmony_ci * configuration. 1698c2ecf20Sopenharmony_ci * @clk_divisor_hs_mode: Clock divisor in HS mode. 1708c2ecf20Sopenharmony_ci * @clk_divisor_std_mode: Clock divisor in standard mode. It is 1718c2ecf20Sopenharmony_ci * applicable if there is no fast clock source i.e. single clock 1728c2ecf20Sopenharmony_ci * source. 1738c2ecf20Sopenharmony_ci * @clk_divisor_fast_mode: Clock divisor in fast mode. It is 1748c2ecf20Sopenharmony_ci * applicable if there is no fast clock source i.e. single clock 1758c2ecf20Sopenharmony_ci * source. 1768c2ecf20Sopenharmony_ci * @clk_divisor_fast_plus_mode: Clock divisor in fast mode plus. It is 1778c2ecf20Sopenharmony_ci * applicable if there is no fast clock source (i.e. single 1788c2ecf20Sopenharmony_ci * clock source). 1798c2ecf20Sopenharmony_ci * @has_multi_master_mode: The I2C controller supports running in single-master 1808c2ecf20Sopenharmony_ci * or multi-master mode. 1818c2ecf20Sopenharmony_ci * @has_slcg_override_reg: The I2C controller supports a register that 1828c2ecf20Sopenharmony_ci * overrides the second level clock gating. 1838c2ecf20Sopenharmony_ci * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that 1848c2ecf20Sopenharmony_ci * provides additional features and allows for longer messages to 1858c2ecf20Sopenharmony_ci * be transferred in one go. 1868c2ecf20Sopenharmony_ci * @quirks: I2C adapter quirks for limiting write/read transfer size and not 1878c2ecf20Sopenharmony_ci * allowing 0 length transfers. 1888c2ecf20Sopenharmony_ci * @supports_bus_clear: Bus Clear support to recover from bus hang during 1898c2ecf20Sopenharmony_ci * SDA stuck low from device for some unknown reasons. 1908c2ecf20Sopenharmony_ci * @has_apb_dma: Support of APBDMA on corresponding Tegra chip. 1918c2ecf20Sopenharmony_ci * @tlow_std_mode: Low period of the clock in standard mode. 1928c2ecf20Sopenharmony_ci * @thigh_std_mode: High period of the clock in standard mode. 1938c2ecf20Sopenharmony_ci * @tlow_fast_fastplus_mode: Low period of the clock in fast/fast-plus modes. 1948c2ecf20Sopenharmony_ci * @thigh_fast_fastplus_mode: High period of the clock in fast/fast-plus modes. 1958c2ecf20Sopenharmony_ci * @setup_hold_time_std_mode: Setup and hold time for start and stop conditions 1968c2ecf20Sopenharmony_ci * in standard mode. 1978c2ecf20Sopenharmony_ci * @setup_hold_time_fast_fast_plus_mode: Setup and hold time for start and stop 1988c2ecf20Sopenharmony_ci * conditions in fast/fast-plus modes. 1998c2ecf20Sopenharmony_ci * @setup_hold_time_hs_mode: Setup and hold time for start and stop conditions 2008c2ecf20Sopenharmony_ci * in HS mode. 2018c2ecf20Sopenharmony_ci * @has_interface_timing_reg: Has interface timing register to program the tuned 2028c2ecf20Sopenharmony_ci * timing settings. 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_cistruct tegra_i2c_hw_feature { 2058c2ecf20Sopenharmony_ci bool has_continue_xfer_support; 2068c2ecf20Sopenharmony_ci bool has_per_pkt_xfer_complete_irq; 2078c2ecf20Sopenharmony_ci bool has_config_load_reg; 2088c2ecf20Sopenharmony_ci u32 clk_divisor_hs_mode; 2098c2ecf20Sopenharmony_ci u32 clk_divisor_std_mode; 2108c2ecf20Sopenharmony_ci u32 clk_divisor_fast_mode; 2118c2ecf20Sopenharmony_ci u32 clk_divisor_fast_plus_mode; 2128c2ecf20Sopenharmony_ci bool has_multi_master_mode; 2138c2ecf20Sopenharmony_ci bool has_slcg_override_reg; 2148c2ecf20Sopenharmony_ci bool has_mst_fifo; 2158c2ecf20Sopenharmony_ci const struct i2c_adapter_quirks *quirks; 2168c2ecf20Sopenharmony_ci bool supports_bus_clear; 2178c2ecf20Sopenharmony_ci bool has_apb_dma; 2188c2ecf20Sopenharmony_ci u32 tlow_std_mode; 2198c2ecf20Sopenharmony_ci u32 thigh_std_mode; 2208c2ecf20Sopenharmony_ci u32 tlow_fast_fastplus_mode; 2218c2ecf20Sopenharmony_ci u32 thigh_fast_fastplus_mode; 2228c2ecf20Sopenharmony_ci u32 setup_hold_time_std_mode; 2238c2ecf20Sopenharmony_ci u32 setup_hold_time_fast_fast_plus_mode; 2248c2ecf20Sopenharmony_ci u32 setup_hold_time_hs_mode; 2258c2ecf20Sopenharmony_ci bool has_interface_timing_reg; 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci/** 2298c2ecf20Sopenharmony_ci * struct tegra_i2c_dev - per device I2C context 2308c2ecf20Sopenharmony_ci * @dev: device reference for power management 2318c2ecf20Sopenharmony_ci * @hw: Tegra I2C HW feature 2328c2ecf20Sopenharmony_ci * @adapter: core I2C layer adapter information 2338c2ecf20Sopenharmony_ci * @div_clk: clock reference for div clock of I2C controller 2348c2ecf20Sopenharmony_ci * @clocks: array of I2C controller clocks 2358c2ecf20Sopenharmony_ci * @nclocks: number of clocks in the array 2368c2ecf20Sopenharmony_ci * @rst: reset control for the I2C controller 2378c2ecf20Sopenharmony_ci * @base: ioremapped registers cookie 2388c2ecf20Sopenharmony_ci * @base_phys: physical base address of the I2C controller 2398c2ecf20Sopenharmony_ci * @cont_id: I2C controller ID, used for packet header 2408c2ecf20Sopenharmony_ci * @irq: IRQ number of transfer complete interrupt 2418c2ecf20Sopenharmony_ci * @is_dvc: identifies the DVC I2C controller, has a different register layout 2428c2ecf20Sopenharmony_ci * @is_vi: identifies the VI I2C controller, has a different register layout 2438c2ecf20Sopenharmony_ci * @msg_complete: transfer completion notifier 2448c2ecf20Sopenharmony_ci * @msg_err: error code for completed message 2458c2ecf20Sopenharmony_ci * @msg_buf: pointer to current message data 2468c2ecf20Sopenharmony_ci * @msg_buf_remaining: size of unsent data in the message buffer 2478c2ecf20Sopenharmony_ci * @msg_read: indicates that the transfer is a read access 2488c2ecf20Sopenharmony_ci * @bus_clk_rate: current I2C bus clock rate 2498c2ecf20Sopenharmony_ci * @multimaster_mode: indicates that I2C controller is in multi-master mode 2508c2ecf20Sopenharmony_ci * @tx_dma_chan: DMA transmit channel 2518c2ecf20Sopenharmony_ci * @rx_dma_chan: DMA receive channel 2528c2ecf20Sopenharmony_ci * @dma_phys: handle to DMA resources 2538c2ecf20Sopenharmony_ci * @dma_buf: pointer to allocated DMA buffer 2548c2ecf20Sopenharmony_ci * @dma_buf_size: DMA buffer size 2558c2ecf20Sopenharmony_ci * @dma_mode: indicates active DMA transfer 2568c2ecf20Sopenharmony_ci * @dma_complete: DMA completion notifier 2578c2ecf20Sopenharmony_ci * @atomic_mode: indicates active atomic transfer 2588c2ecf20Sopenharmony_ci */ 2598c2ecf20Sopenharmony_cistruct tegra_i2c_dev { 2608c2ecf20Sopenharmony_ci struct device *dev; 2618c2ecf20Sopenharmony_ci struct i2c_adapter adapter; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci const struct tegra_i2c_hw_feature *hw; 2648c2ecf20Sopenharmony_ci struct reset_control *rst; 2658c2ecf20Sopenharmony_ci unsigned int cont_id; 2668c2ecf20Sopenharmony_ci unsigned int irq; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci phys_addr_t base_phys; 2698c2ecf20Sopenharmony_ci void __iomem *base; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci struct clk_bulk_data clocks[2]; 2728c2ecf20Sopenharmony_ci unsigned int nclocks; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci struct clk *div_clk; 2758c2ecf20Sopenharmony_ci u32 bus_clk_rate; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci struct completion msg_complete; 2788c2ecf20Sopenharmony_ci size_t msg_buf_remaining; 2798c2ecf20Sopenharmony_ci int msg_err; 2808c2ecf20Sopenharmony_ci u8 *msg_buf; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci struct completion dma_complete; 2838c2ecf20Sopenharmony_ci struct dma_chan *tx_dma_chan; 2848c2ecf20Sopenharmony_ci struct dma_chan *rx_dma_chan; 2858c2ecf20Sopenharmony_ci unsigned int dma_buf_size; 2868c2ecf20Sopenharmony_ci struct device *dma_dev; 2878c2ecf20Sopenharmony_ci dma_addr_t dma_phys; 2888c2ecf20Sopenharmony_ci void *dma_buf; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci bool multimaster_mode; 2918c2ecf20Sopenharmony_ci bool atomic_mode; 2928c2ecf20Sopenharmony_ci bool dma_mode; 2938c2ecf20Sopenharmony_ci bool msg_read; 2948c2ecf20Sopenharmony_ci bool is_dvc; 2958c2ecf20Sopenharmony_ci bool is_vi; 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, 2998c2ecf20Sopenharmony_ci unsigned int reg) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + reg); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci return readl_relaxed(i2c_dev->base + reg); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci/* 3108c2ecf20Sopenharmony_ci * If necessary, i2c_writel() and i2c_readl() will offset the register 3118c2ecf20Sopenharmony_ci * in order to talk to the I2C block inside the DVC block. 3128c2ecf20Sopenharmony_ci */ 3138c2ecf20Sopenharmony_cistatic u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci if (i2c_dev->is_dvc) 3168c2ecf20Sopenharmony_ci reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; 3178c2ecf20Sopenharmony_ci else if (i2c_dev->is_vi) 3188c2ecf20Sopenharmony_ci reg = 0xc00 + (reg << 2); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci return reg; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* read back register to make sure that register writes completed */ 3288c2ecf20Sopenharmony_ci if (reg != I2C_TX_FIFO) 3298c2ecf20Sopenharmony_ci readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); 3308c2ecf20Sopenharmony_ci else if (i2c_dev->is_vi) 3318c2ecf20Sopenharmony_ci readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS)); 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistatic void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data, 3408c2ecf20Sopenharmony_ci unsigned int reg, unsigned int len) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data, 3468c2ecf20Sopenharmony_ci unsigned int reg, unsigned int len) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci u32 *data32 = data; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* 3518c2ecf20Sopenharmony_ci * VI I2C controller has known hardware bug where writes get stuck 3528c2ecf20Sopenharmony_ci * when immediate multiple writes happen to TX_FIFO register. 3538c2ecf20Sopenharmony_ci * Recommended software work around is to read I2C register after 3548c2ecf20Sopenharmony_ci * each write to TX_FIFO register to flush out the data. 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ci while (len--) 3578c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, *data32++, reg); 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, 3618c2ecf20Sopenharmony_ci unsigned int reg, unsigned int len) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci u32 int_mask; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) & ~mask; 3718c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci u32 int_mask; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask; 3798c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic void tegra_i2c_dma_complete(void *args) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = args; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci complete(&i2c_dev->dma_complete); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *dma_desc; 3928c2ecf20Sopenharmony_ci enum dma_transfer_direction dir; 3938c2ecf20Sopenharmony_ci struct dma_chan *chan; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci reinit_completion(&i2c_dev->dma_complete); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; 4008c2ecf20Sopenharmony_ci chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys, 4038c2ecf20Sopenharmony_ci len, dir, DMA_PREP_INTERRUPT | 4048c2ecf20Sopenharmony_ci DMA_CTRL_ACK); 4058c2ecf20Sopenharmony_ci if (!dma_desc) { 4068c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to get %s DMA descriptor\n", 4078c2ecf20Sopenharmony_ci i2c_dev->msg_read ? "RX" : "TX"); 4088c2ecf20Sopenharmony_ci return -EINVAL; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci dma_desc->callback = tegra_i2c_dma_complete; 4128c2ecf20Sopenharmony_ci dma_desc->callback_param = i2c_dev; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci dmaengine_submit(dma_desc); 4158c2ecf20Sopenharmony_ci dma_async_issue_pending(chan); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci return 0; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci if (i2c_dev->dma_buf) { 4238c2ecf20Sopenharmony_ci dma_free_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size, 4248c2ecf20Sopenharmony_ci i2c_dev->dma_buf, i2c_dev->dma_phys); 4258c2ecf20Sopenharmony_ci i2c_dev->dma_buf = NULL; 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (i2c_dev->tx_dma_chan) { 4298c2ecf20Sopenharmony_ci dma_release_channel(i2c_dev->tx_dma_chan); 4308c2ecf20Sopenharmony_ci i2c_dev->tx_dma_chan = NULL; 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (i2c_dev->rx_dma_chan) { 4348c2ecf20Sopenharmony_ci dma_release_channel(i2c_dev->rx_dma_chan); 4358c2ecf20Sopenharmony_ci i2c_dev->rx_dma_chan = NULL; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct dma_chan *chan; 4428c2ecf20Sopenharmony_ci dma_addr_t dma_phys; 4438c2ecf20Sopenharmony_ci u32 *dma_buf; 4448c2ecf20Sopenharmony_ci int err; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if (!i2c_dev->hw->has_apb_dma || i2c_dev->is_vi) 4478c2ecf20Sopenharmony_ci return 0; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) { 4508c2ecf20Sopenharmony_ci dev_dbg(i2c_dev->dev, "DMA support not enabled\n"); 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci chan = dma_request_chan(i2c_dev->dev, "rx"); 4558c2ecf20Sopenharmony_ci if (IS_ERR(chan)) { 4568c2ecf20Sopenharmony_ci err = PTR_ERR(chan); 4578c2ecf20Sopenharmony_ci goto err_out; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci i2c_dev->rx_dma_chan = chan; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci chan = dma_request_chan(i2c_dev->dev, "tx"); 4638c2ecf20Sopenharmony_ci if (IS_ERR(chan)) { 4648c2ecf20Sopenharmony_ci err = PTR_ERR(chan); 4658c2ecf20Sopenharmony_ci goto err_out; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci i2c_dev->tx_dma_chan = chan; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device); 4718c2ecf20Sopenharmony_ci i2c_dev->dma_dev = chan->device->dev; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len + 4748c2ecf20Sopenharmony_ci I2C_PACKET_HEADER_SIZE; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci dma_buf = dma_alloc_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size, 4778c2ecf20Sopenharmony_ci &dma_phys, GFP_KERNEL | __GFP_NOWARN); 4788c2ecf20Sopenharmony_ci if (!dma_buf) { 4798c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to allocate DMA buffer\n"); 4808c2ecf20Sopenharmony_ci err = -ENOMEM; 4818c2ecf20Sopenharmony_ci goto err_out; 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci i2c_dev->dma_buf = dma_buf; 4858c2ecf20Sopenharmony_ci i2c_dev->dma_phys = dma_phys; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci return 0; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cierr_out: 4908c2ecf20Sopenharmony_ci tegra_i2c_release_dma(i2c_dev); 4918c2ecf20Sopenharmony_ci if (err != -EPROBE_DEFER) { 4928c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "cannot use DMA: %d\n", err); 4938c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "falling back to PIO\n"); 4948c2ecf20Sopenharmony_ci return 0; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci return err; 4988c2ecf20Sopenharmony_ci} 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci/* 5018c2ecf20Sopenharmony_ci * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller) 5028c2ecf20Sopenharmony_ci * block. This block is identical to the rest of the I2C blocks, except that 5038c2ecf20Sopenharmony_ci * it only supports master mode, it has registers moved around, and it needs 5048c2ecf20Sopenharmony_ci * some extra init to get it into I2C mode. The register moves are handled 5058c2ecf20Sopenharmony_ci * by i2c_readl() and i2c_writel(). 5068c2ecf20Sopenharmony_ci */ 5078c2ecf20Sopenharmony_cistatic void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci u32 val; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci val = dvc_readl(i2c_dev, DVC_CTRL_REG3); 5128c2ecf20Sopenharmony_ci val |= DVC_CTRL_REG3_SW_PROG; 5138c2ecf20Sopenharmony_ci val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN; 5148c2ecf20Sopenharmony_ci dvc_writel(i2c_dev, val, DVC_CTRL_REG3); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci val = dvc_readl(i2c_dev, DVC_CTRL_REG1); 5178c2ecf20Sopenharmony_ci val |= DVC_CTRL_REG1_INTR_EN; 5188c2ecf20Sopenharmony_ci dvc_writel(i2c_dev, val, DVC_CTRL_REG1); 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_cistatic void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci u32 value; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) | 5268c2ecf20Sopenharmony_ci FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4); 5278c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) | 5308c2ecf20Sopenharmony_ci FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) | 5318c2ecf20Sopenharmony_ci FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) | 5328c2ecf20Sopenharmony_ci FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4); 5338c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) | 5368c2ecf20Sopenharmony_ci FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8); 5378c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) | 5408c2ecf20Sopenharmony_ci FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) | 5418c2ecf20Sopenharmony_ci FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11); 5428c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND; 5458c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT); 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_cistatic int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev, 5518c2ecf20Sopenharmony_ci u32 reg, u32 mask, u32 delay_us, 5528c2ecf20Sopenharmony_ci u32 timeout_us) 5538c2ecf20Sopenharmony_ci{ 5548c2ecf20Sopenharmony_ci void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg); 5558c2ecf20Sopenharmony_ci u32 val; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci if (!i2c_dev->atomic_mode && !in_irq()) 5588c2ecf20Sopenharmony_ci return readl_relaxed_poll_timeout(addr, val, !(val & mask), 5598c2ecf20Sopenharmony_ci delay_us, timeout_us); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci return readl_relaxed_poll_timeout_atomic(addr, val, !(val & mask), 5628c2ecf20Sopenharmony_ci delay_us, timeout_us); 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_cistatic int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) 5668c2ecf20Sopenharmony_ci{ 5678c2ecf20Sopenharmony_ci u32 mask, val, offset; 5688c2ecf20Sopenharmony_ci int err; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) { 5718c2ecf20Sopenharmony_ci mask = I2C_MST_FIFO_CONTROL_TX_FLUSH | 5728c2ecf20Sopenharmony_ci I2C_MST_FIFO_CONTROL_RX_FLUSH; 5738c2ecf20Sopenharmony_ci offset = I2C_MST_FIFO_CONTROL; 5748c2ecf20Sopenharmony_ci } else { 5758c2ecf20Sopenharmony_ci mask = I2C_FIFO_CONTROL_TX_FLUSH | 5768c2ecf20Sopenharmony_ci I2C_FIFO_CONTROL_RX_FLUSH; 5778c2ecf20Sopenharmony_ci offset = I2C_FIFO_CONTROL; 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, offset); 5818c2ecf20Sopenharmony_ci val |= mask; 5828c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, offset); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 1000000); 5858c2ecf20Sopenharmony_ci if (err) { 5868c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to flush FIFO\n"); 5878c2ecf20Sopenharmony_ci return err; 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return 0; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci int err; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci if (!i2c_dev->hw->has_config_load_reg) 5988c2ecf20Sopenharmony_ci return 0; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0xffffffff, 6038c2ecf20Sopenharmony_ci 1000, I2C_CONFIG_LOAD_TIMEOUT); 6048c2ecf20Sopenharmony_ci if (err) { 6058c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to load config\n"); 6068c2ecf20Sopenharmony_ci return err; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci return 0; 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; 6158c2ecf20Sopenharmony_ci int err; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci /* 6188c2ecf20Sopenharmony_ci * The reset shouldn't ever fail in practice. The failure will be a 6198c2ecf20Sopenharmony_ci * sign of a severe problem that needs to be resolved. Still we don't 6208c2ecf20Sopenharmony_ci * want to fail the initialization completely because this may break 6218c2ecf20Sopenharmony_ci * kernel boot up since voltage regulators use I2C. Hence, we will 6228c2ecf20Sopenharmony_ci * emit a noisy warning on error, which won't stay unnoticed and 6238c2ecf20Sopenharmony_ci * won't hose machine entirely. 6248c2ecf20Sopenharmony_ci */ 6258c2ecf20Sopenharmony_ci err = reset_control_reset(i2c_dev->rst); 6268c2ecf20Sopenharmony_ci WARN_ON_ONCE(err); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci if (i2c_dev->is_dvc) 6298c2ecf20Sopenharmony_ci tegra_dvc_init(i2c_dev); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN | 6328c2ecf20Sopenharmony_ci FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2); 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_multi_master_mode) 6358c2ecf20Sopenharmony_ci val |= I2C_CNFG_MULTI_MASTER_MODE; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, I2C_CNFG); 6388c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, 0, I2C_INT_MASK); 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci if (i2c_dev->is_vi) 6418c2ecf20Sopenharmony_ci tegra_i2c_vi_init(i2c_dev); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci switch (i2c_dev->bus_clk_rate) { 6448c2ecf20Sopenharmony_ci case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ: 6458c2ecf20Sopenharmony_ci default: 6468c2ecf20Sopenharmony_ci tlow = i2c_dev->hw->tlow_fast_fastplus_mode; 6478c2ecf20Sopenharmony_ci thigh = i2c_dev->hw->thigh_fast_fastplus_mode; 6488c2ecf20Sopenharmony_ci tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ) 6518c2ecf20Sopenharmony_ci non_hs_mode = i2c_dev->hw->clk_divisor_fast_plus_mode; 6528c2ecf20Sopenharmony_ci else 6538c2ecf20Sopenharmony_ci non_hs_mode = i2c_dev->hw->clk_divisor_fast_mode; 6548c2ecf20Sopenharmony_ci break; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci case 0 ... I2C_MAX_STANDARD_MODE_FREQ: 6578c2ecf20Sopenharmony_ci tlow = i2c_dev->hw->tlow_std_mode; 6588c2ecf20Sopenharmony_ci thigh = i2c_dev->hw->thigh_std_mode; 6598c2ecf20Sopenharmony_ci tsu_thd = i2c_dev->hw->setup_hold_time_std_mode; 6608c2ecf20Sopenharmony_ci non_hs_mode = i2c_dev->hw->clk_divisor_std_mode; 6618c2ecf20Sopenharmony_ci break; 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci /* make sure clock divisor programmed correctly */ 6658c2ecf20Sopenharmony_ci clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE, 6668c2ecf20Sopenharmony_ci i2c_dev->hw->clk_divisor_hs_mode) | 6678c2ecf20Sopenharmony_ci FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE, non_hs_mode); 6688c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_interface_timing_reg) { 6718c2ecf20Sopenharmony_ci val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) | 6728c2ecf20Sopenharmony_ci FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow); 6738c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, I2C_INTERFACE_TIMING_0); 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* 6778c2ecf20Sopenharmony_ci * Configure setup and hold times only when tsu_thd is non-zero. 6788c2ecf20Sopenharmony_ci * Otherwise, preserve the chip default values. 6798c2ecf20Sopenharmony_ci */ 6808c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_interface_timing_reg && tsu_thd) 6818c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci err = clk_set_rate(i2c_dev->div_clk, 6868c2ecf20Sopenharmony_ci i2c_dev->bus_clk_rate * clk_multiplier); 6878c2ecf20Sopenharmony_ci if (err) { 6888c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to set div-clk rate: %d\n", err); 6898c2ecf20Sopenharmony_ci return err; 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci if (!i2c_dev->is_dvc && !i2c_dev->is_vi) { 6938c2ecf20Sopenharmony_ci u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; 6968c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG); 6978c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1); 6988c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2); 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci err = tegra_i2c_flush_fifos(i2c_dev); 7028c2ecf20Sopenharmony_ci if (err) 7038c2ecf20Sopenharmony_ci return err; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg) 7068c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci err = tegra_i2c_wait_for_config_load(i2c_dev); 7098c2ecf20Sopenharmony_ci if (err) 7108c2ecf20Sopenharmony_ci return err; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci return 0; 7138c2ecf20Sopenharmony_ci} 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_cistatic int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci u32 cnfg; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* 7208c2ecf20Sopenharmony_ci * NACK interrupt is generated before the I2C controller generates 7218c2ecf20Sopenharmony_ci * the STOP condition on the bus. So, wait for 2 clock periods 7228c2ecf20Sopenharmony_ci * before disabling the controller so that the STOP condition has 7238c2ecf20Sopenharmony_ci * been delivered properly. 7248c2ecf20Sopenharmony_ci */ 7258c2ecf20Sopenharmony_ci udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate)); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci cnfg = i2c_readl(i2c_dev, I2C_CNFG); 7288c2ecf20Sopenharmony_ci if (cnfg & I2C_CNFG_PACKET_MODE_EN) 7298c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci return tegra_i2c_wait_for_config_load(i2c_dev); 7328c2ecf20Sopenharmony_ci} 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_cistatic int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci size_t buf_remaining = i2c_dev->msg_buf_remaining; 7378c2ecf20Sopenharmony_ci unsigned int words_to_transfer, rx_fifo_avail; 7388c2ecf20Sopenharmony_ci u8 *buf = i2c_dev->msg_buf; 7398c2ecf20Sopenharmony_ci u32 val; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci /* 7428c2ecf20Sopenharmony_ci * Catch overflow due to message fully sent before the check for 7438c2ecf20Sopenharmony_ci * RX FIFO availability. 7448c2ecf20Sopenharmony_ci */ 7458c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining))) 7468c2ecf20Sopenharmony_ci return -EINVAL; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) { 7498c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS); 7508c2ecf20Sopenharmony_ci rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val); 7518c2ecf20Sopenharmony_ci } else { 7528c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); 7538c2ecf20Sopenharmony_ci rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val); 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* round down to exclude partial word at the end of buffer */ 7578c2ecf20Sopenharmony_ci words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; 7588c2ecf20Sopenharmony_ci if (words_to_transfer > rx_fifo_avail) 7598c2ecf20Sopenharmony_ci words_to_transfer = rx_fifo_avail; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci buf += words_to_transfer * BYTES_PER_FIFO_WORD; 7648c2ecf20Sopenharmony_ci buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; 7658c2ecf20Sopenharmony_ci rx_fifo_avail -= words_to_transfer; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci /* 7688c2ecf20Sopenharmony_ci * If there is a partial word at the end of buffer, handle it 7698c2ecf20Sopenharmony_ci * manually to prevent overwriting past the end of buffer. 7708c2ecf20Sopenharmony_ci */ 7718c2ecf20Sopenharmony_ci if (rx_fifo_avail > 0 && buf_remaining > 0) { 7728c2ecf20Sopenharmony_ci /* 7738c2ecf20Sopenharmony_ci * buf_remaining > 3 check not needed as rx_fifo_avail == 0 7748c2ecf20Sopenharmony_ci * when (words_to_transfer was > rx_fifo_avail) earlier 7758c2ecf20Sopenharmony_ci * in this function. 7768c2ecf20Sopenharmony_ci */ 7778c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, I2C_RX_FIFO); 7788c2ecf20Sopenharmony_ci val = cpu_to_le32(val); 7798c2ecf20Sopenharmony_ci memcpy(buf, &val, buf_remaining); 7808c2ecf20Sopenharmony_ci buf_remaining = 0; 7818c2ecf20Sopenharmony_ci rx_fifo_avail--; 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci /* RX FIFO must be drained, otherwise it's an Overflow case. */ 7858c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(rx_fifo_avail)) 7868c2ecf20Sopenharmony_ci return -EINVAL; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci i2c_dev->msg_buf_remaining = buf_remaining; 7898c2ecf20Sopenharmony_ci i2c_dev->msg_buf = buf; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci return 0; 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci size_t buf_remaining = i2c_dev->msg_buf_remaining; 7978c2ecf20Sopenharmony_ci unsigned int words_to_transfer, tx_fifo_avail; 7988c2ecf20Sopenharmony_ci u8 *buf = i2c_dev->msg_buf; 7998c2ecf20Sopenharmony_ci u32 val; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) { 8028c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS); 8038c2ecf20Sopenharmony_ci tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val); 8048c2ecf20Sopenharmony_ci } else { 8058c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); 8068c2ecf20Sopenharmony_ci tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val); 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci /* round down to exclude partial word at the end of buffer */ 8108c2ecf20Sopenharmony_ci words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci /* 8138c2ecf20Sopenharmony_ci * This hunk pushes 4 bytes at a time into the TX FIFO. 8148c2ecf20Sopenharmony_ci * 8158c2ecf20Sopenharmony_ci * It's very common to have < 4 bytes, hence there is no word 8168c2ecf20Sopenharmony_ci * to push if we have less than 4 bytes to transfer. 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_ci if (words_to_transfer) { 8198c2ecf20Sopenharmony_ci if (words_to_transfer > tx_fifo_avail) 8208c2ecf20Sopenharmony_ci words_to_transfer = tx_fifo_avail; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci /* 8238c2ecf20Sopenharmony_ci * Update state before writing to FIFO. Note that this may 8248c2ecf20Sopenharmony_ci * cause us to finish writing all bytes (AKA buf_remaining 8258c2ecf20Sopenharmony_ci * goes to 0), hence we have a potential for an interrupt 8268c2ecf20Sopenharmony_ci * (PACKET_XFER_COMPLETE is not maskable), but GIC interrupt 8278c2ecf20Sopenharmony_ci * is disabled at this point. 8288c2ecf20Sopenharmony_ci */ 8298c2ecf20Sopenharmony_ci buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; 8308c2ecf20Sopenharmony_ci tx_fifo_avail -= words_to_transfer; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci i2c_dev->msg_buf_remaining = buf_remaining; 8338c2ecf20Sopenharmony_ci i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci if (i2c_dev->is_vi) 8368c2ecf20Sopenharmony_ci i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); 8378c2ecf20Sopenharmony_ci else 8388c2ecf20Sopenharmony_ci i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci buf += words_to_transfer * BYTES_PER_FIFO_WORD; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci /* 8448c2ecf20Sopenharmony_ci * If there is a partial word at the end of buffer, handle it manually 8458c2ecf20Sopenharmony_ci * to prevent reading past the end of buffer, which could cross a page 8468c2ecf20Sopenharmony_ci * boundary and fault. 8478c2ecf20Sopenharmony_ci */ 8488c2ecf20Sopenharmony_ci if (tx_fifo_avail > 0 && buf_remaining > 0) { 8498c2ecf20Sopenharmony_ci /* 8508c2ecf20Sopenharmony_ci * buf_remaining > 3 check not needed as tx_fifo_avail == 0 8518c2ecf20Sopenharmony_ci * when (words_to_transfer was > tx_fifo_avail) earlier 8528c2ecf20Sopenharmony_ci * in this function for non-zero words_to_transfer. 8538c2ecf20Sopenharmony_ci */ 8548c2ecf20Sopenharmony_ci memcpy(&val, buf, buf_remaining); 8558c2ecf20Sopenharmony_ci val = le32_to_cpu(val); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci i2c_dev->msg_buf_remaining = 0; 8588c2ecf20Sopenharmony_ci i2c_dev->msg_buf = NULL; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, I2C_TX_FIFO); 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci return 0; 8648c2ecf20Sopenharmony_ci} 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_cistatic irqreturn_t tegra_i2c_isr(int irq, void *dev_id) 8678c2ecf20Sopenharmony_ci{ 8688c2ecf20Sopenharmony_ci const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; 8698c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = dev_id; 8708c2ecf20Sopenharmony_ci u32 status; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci status = i2c_readl(i2c_dev, I2C_INT_STATUS); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci if (status == 0) { 8758c2ecf20Sopenharmony_ci dev_warn(i2c_dev->dev, "IRQ status 0 %08x %08x %08x\n", 8768c2ecf20Sopenharmony_ci i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), 8778c2ecf20Sopenharmony_ci i2c_readl(i2c_dev, I2C_STATUS), 8788c2ecf20Sopenharmony_ci i2c_readl(i2c_dev, I2C_CNFG)); 8798c2ecf20Sopenharmony_ci i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT; 8808c2ecf20Sopenharmony_ci goto err; 8818c2ecf20Sopenharmony_ci } 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (status & status_err) { 8848c2ecf20Sopenharmony_ci tegra_i2c_disable_packet_mode(i2c_dev); 8858c2ecf20Sopenharmony_ci if (status & I2C_INT_NO_ACK) 8868c2ecf20Sopenharmony_ci i2c_dev->msg_err |= I2C_ERR_NO_ACK; 8878c2ecf20Sopenharmony_ci if (status & I2C_INT_ARBITRATION_LOST) 8888c2ecf20Sopenharmony_ci i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; 8898c2ecf20Sopenharmony_ci goto err; 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci /* 8938c2ecf20Sopenharmony_ci * I2C transfer is terminated during the bus clear, so skip 8948c2ecf20Sopenharmony_ci * processing the other interrupts. 8958c2ecf20Sopenharmony_ci */ 8968c2ecf20Sopenharmony_ci if (i2c_dev->hw->supports_bus_clear && (status & I2C_INT_BUS_CLR_DONE)) 8978c2ecf20Sopenharmony_ci goto err; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci if (!i2c_dev->dma_mode) { 9008c2ecf20Sopenharmony_ci if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { 9018c2ecf20Sopenharmony_ci if (tegra_i2c_empty_rx_fifo(i2c_dev)) { 9028c2ecf20Sopenharmony_ci /* 9038c2ecf20Sopenharmony_ci * Overflow error condition: message fully sent, 9048c2ecf20Sopenharmony_ci * with no XFER_COMPLETE interrupt but hardware 9058c2ecf20Sopenharmony_ci * asks to transfer more. 9068c2ecf20Sopenharmony_ci */ 9078c2ecf20Sopenharmony_ci i2c_dev->msg_err |= I2C_ERR_RX_BUFFER_OVERFLOW; 9088c2ecf20Sopenharmony_ci goto err; 9098c2ecf20Sopenharmony_ci } 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { 9138c2ecf20Sopenharmony_ci if (i2c_dev->msg_buf_remaining) 9148c2ecf20Sopenharmony_ci tegra_i2c_fill_tx_fifo(i2c_dev); 9158c2ecf20Sopenharmony_ci else 9168c2ecf20Sopenharmony_ci tegra_i2c_mask_irq(i2c_dev, 9178c2ecf20Sopenharmony_ci I2C_INT_TX_FIFO_DATA_REQ); 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, status, I2C_INT_STATUS); 9228c2ecf20Sopenharmony_ci if (i2c_dev->is_dvc) 9238c2ecf20Sopenharmony_ci dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci /* 9268c2ecf20Sopenharmony_ci * During message read XFER_COMPLETE interrupt is triggered prior to 9278c2ecf20Sopenharmony_ci * DMA completion and during message write XFER_COMPLETE interrupt is 9288c2ecf20Sopenharmony_ci * triggered after DMA completion. 9298c2ecf20Sopenharmony_ci * 9308c2ecf20Sopenharmony_ci * PACKETS_XFER_COMPLETE indicates completion of all bytes of transfer, 9318c2ecf20Sopenharmony_ci * so forcing msg_buf_remaining to 0 in DMA mode. 9328c2ecf20Sopenharmony_ci */ 9338c2ecf20Sopenharmony_ci if (status & I2C_INT_PACKET_XFER_COMPLETE) { 9348c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode) 9358c2ecf20Sopenharmony_ci i2c_dev->msg_buf_remaining = 0; 9368c2ecf20Sopenharmony_ci /* 9378c2ecf20Sopenharmony_ci * Underflow error condition: XFER_COMPLETE before message 9388c2ecf20Sopenharmony_ci * fully sent. 9398c2ecf20Sopenharmony_ci */ 9408c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(i2c_dev->msg_buf_remaining)) { 9418c2ecf20Sopenharmony_ci i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT; 9428c2ecf20Sopenharmony_ci goto err; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci complete(&i2c_dev->msg_complete); 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci goto done; 9478c2ecf20Sopenharmony_cierr: 9488c2ecf20Sopenharmony_ci /* mask all interrupts on error */ 9498c2ecf20Sopenharmony_ci tegra_i2c_mask_irq(i2c_dev, 9508c2ecf20Sopenharmony_ci I2C_INT_NO_ACK | 9518c2ecf20Sopenharmony_ci I2C_INT_ARBITRATION_LOST | 9528c2ecf20Sopenharmony_ci I2C_INT_PACKET_XFER_COMPLETE | 9538c2ecf20Sopenharmony_ci I2C_INT_TX_FIFO_DATA_REQ | 9548c2ecf20Sopenharmony_ci I2C_INT_RX_FIFO_DATA_REQ); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci if (i2c_dev->hw->supports_bus_clear) 9578c2ecf20Sopenharmony_ci tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, status, I2C_INT_STATUS); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci if (i2c_dev->is_dvc) 9628c2ecf20Sopenharmony_ci dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode) { 9658c2ecf20Sopenharmony_ci if (i2c_dev->msg_read) 9668c2ecf20Sopenharmony_ci dmaengine_terminate_async(i2c_dev->rx_dma_chan); 9678c2ecf20Sopenharmony_ci else 9688c2ecf20Sopenharmony_ci dmaengine_terminate_async(i2c_dev->tx_dma_chan); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci complete(&i2c_dev->dma_complete); 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci complete(&i2c_dev->msg_complete); 9748c2ecf20Sopenharmony_cidone: 9758c2ecf20Sopenharmony_ci return IRQ_HANDLED; 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cistatic void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, 9798c2ecf20Sopenharmony_ci size_t len) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct dma_slave_config slv_config = {0}; 9828c2ecf20Sopenharmony_ci u32 val, reg, dma_burst, reg_offset; 9838c2ecf20Sopenharmony_ci struct dma_chan *chan; 9848c2ecf20Sopenharmony_ci int err; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) 9878c2ecf20Sopenharmony_ci reg = I2C_MST_FIFO_CONTROL; 9888c2ecf20Sopenharmony_ci else 9898c2ecf20Sopenharmony_ci reg = I2C_FIFO_CONTROL; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode) { 9928c2ecf20Sopenharmony_ci if (len & 0xF) 9938c2ecf20Sopenharmony_ci dma_burst = 1; 9948c2ecf20Sopenharmony_ci else if (len & 0x10) 9958c2ecf20Sopenharmony_ci dma_burst = 4; 9968c2ecf20Sopenharmony_ci else 9978c2ecf20Sopenharmony_ci dma_burst = 8; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci if (i2c_dev->msg_read) { 10008c2ecf20Sopenharmony_ci chan = i2c_dev->rx_dma_chan; 10018c2ecf20Sopenharmony_ci reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci slv_config.src_addr = i2c_dev->base_phys + reg_offset; 10048c2ecf20Sopenharmony_ci slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 10058c2ecf20Sopenharmony_ci slv_config.src_maxburst = dma_burst; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) 10088c2ecf20Sopenharmony_ci val = I2C_MST_FIFO_CONTROL_RX_TRIG(dma_burst); 10098c2ecf20Sopenharmony_ci else 10108c2ecf20Sopenharmony_ci val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst); 10118c2ecf20Sopenharmony_ci } else { 10128c2ecf20Sopenharmony_ci chan = i2c_dev->tx_dma_chan; 10138c2ecf20Sopenharmony_ci reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci slv_config.dst_addr = i2c_dev->base_phys + reg_offset; 10168c2ecf20Sopenharmony_ci slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 10178c2ecf20Sopenharmony_ci slv_config.dst_maxburst = dma_burst; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) 10208c2ecf20Sopenharmony_ci val = I2C_MST_FIFO_CONTROL_TX_TRIG(dma_burst); 10218c2ecf20Sopenharmony_ci else 10228c2ecf20Sopenharmony_ci val = I2C_FIFO_CONTROL_TX_TRIG(dma_burst); 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci slv_config.device_fc = true; 10268c2ecf20Sopenharmony_ci err = dmaengine_slave_config(chan, &slv_config); 10278c2ecf20Sopenharmony_ci if (err) { 10288c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "DMA config failed: %d\n", err); 10298c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "falling back to PIO\n"); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci tegra_i2c_release_dma(i2c_dev); 10328c2ecf20Sopenharmony_ci i2c_dev->dma_mode = false; 10338c2ecf20Sopenharmony_ci } else { 10348c2ecf20Sopenharmony_ci goto out; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_mst_fifo) 10398c2ecf20Sopenharmony_ci val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) | 10408c2ecf20Sopenharmony_ci I2C_MST_FIFO_CONTROL_RX_TRIG(1); 10418c2ecf20Sopenharmony_ci else 10428c2ecf20Sopenharmony_ci val = I2C_FIFO_CONTROL_TX_TRIG(8) | 10438c2ecf20Sopenharmony_ci I2C_FIFO_CONTROL_RX_TRIG(1); 10448c2ecf20Sopenharmony_ciout: 10458c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, reg); 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev, 10498c2ecf20Sopenharmony_ci struct completion *complete, 10508c2ecf20Sopenharmony_ci unsigned int timeout_ms) 10518c2ecf20Sopenharmony_ci{ 10528c2ecf20Sopenharmony_ci ktime_t ktime = ktime_get(); 10538c2ecf20Sopenharmony_ci ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci do { 10568c2ecf20Sopenharmony_ci u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci if (status) 10598c2ecf20Sopenharmony_ci tegra_i2c_isr(i2c_dev->irq, i2c_dev); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (completion_done(complete)) { 10628c2ecf20Sopenharmony_ci s64 delta = ktime_ms_delta(ktimeout, ktime); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci return msecs_to_jiffies(delta) ?: 1; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci ktime = ktime_get(); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci } while (ktime_before(ktime, ktimeout)); 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci return 0; 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_cistatic unsigned long tegra_i2c_wait_completion(struct tegra_i2c_dev *i2c_dev, 10758c2ecf20Sopenharmony_ci struct completion *complete, 10768c2ecf20Sopenharmony_ci unsigned int timeout_ms) 10778c2ecf20Sopenharmony_ci{ 10788c2ecf20Sopenharmony_ci unsigned long ret; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if (i2c_dev->atomic_mode) { 10818c2ecf20Sopenharmony_ci ret = tegra_i2c_poll_completion(i2c_dev, complete, timeout_ms); 10828c2ecf20Sopenharmony_ci } else { 10838c2ecf20Sopenharmony_ci enable_irq(i2c_dev->irq); 10848c2ecf20Sopenharmony_ci ret = wait_for_completion_timeout(complete, 10858c2ecf20Sopenharmony_ci msecs_to_jiffies(timeout_ms)); 10868c2ecf20Sopenharmony_ci disable_irq(i2c_dev->irq); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci /* 10898c2ecf20Sopenharmony_ci * Under some rare circumstances (like running KASAN + 10908c2ecf20Sopenharmony_ci * NFS root) CPU, which handles interrupt, may stuck in 10918c2ecf20Sopenharmony_ci * uninterruptible state for a significant time. In this 10928c2ecf20Sopenharmony_ci * case we will get timeout if I2C transfer is running on 10938c2ecf20Sopenharmony_ci * a sibling CPU, despite of IRQ being raised. 10948c2ecf20Sopenharmony_ci * 10958c2ecf20Sopenharmony_ci * In order to handle this rare condition, the IRQ status 10968c2ecf20Sopenharmony_ci * needs to be checked after timeout. 10978c2ecf20Sopenharmony_ci */ 10988c2ecf20Sopenharmony_ci if (ret == 0) 10998c2ecf20Sopenharmony_ci ret = tegra_i2c_poll_completion(i2c_dev, complete, 0); 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci return ret; 11038c2ecf20Sopenharmony_ci} 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_cistatic int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) 11068c2ecf20Sopenharmony_ci{ 11078c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 11088c2ecf20Sopenharmony_ci u32 val, time_left; 11098c2ecf20Sopenharmony_ci int err; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci reinit_completion(&i2c_dev->msg_complete); 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci val = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND | 11148c2ecf20Sopenharmony_ci I2C_BC_TERMINATE; 11158c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG); 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci err = tegra_i2c_wait_for_config_load(i2c_dev); 11188c2ecf20Sopenharmony_ci if (err) 11198c2ecf20Sopenharmony_ci return err; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci val |= I2C_BC_ENABLE; 11228c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG); 11238c2ecf20Sopenharmony_ci tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 50); 11268c2ecf20Sopenharmony_ci tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci if (time_left == 0) { 11298c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to clear bus\n"); 11308c2ecf20Sopenharmony_ci return -ETIMEDOUT; 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci val = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS); 11348c2ecf20Sopenharmony_ci if (!(val & I2C_BC_STATUS)) { 11358c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "un-recovered arbitration lost\n"); 11368c2ecf20Sopenharmony_ci return -EIO; 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci return -EAGAIN; 11408c2ecf20Sopenharmony_ci} 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev, 11438c2ecf20Sopenharmony_ci struct i2c_msg *msg, 11448c2ecf20Sopenharmony_ci enum msg_end_type end_state) 11458c2ecf20Sopenharmony_ci{ 11468c2ecf20Sopenharmony_ci u32 *dma_buf = i2c_dev->dma_buf; 11478c2ecf20Sopenharmony_ci u32 packet_header; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) | 11508c2ecf20Sopenharmony_ci FIELD_PREP(PACKET_HEADER0_PROTOCOL, 11518c2ecf20Sopenharmony_ci PACKET_HEADER0_PROTOCOL_I2C) | 11528c2ecf20Sopenharmony_ci FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) | 11538c2ecf20Sopenharmony_ci FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode && !i2c_dev->msg_read) 11568c2ecf20Sopenharmony_ci *dma_buf++ = packet_header; 11578c2ecf20Sopenharmony_ci else 11588c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci packet_header = msg->len - 1; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode && !i2c_dev->msg_read) 11638c2ecf20Sopenharmony_ci *dma_buf++ = packet_header; 11648c2ecf20Sopenharmony_ci else 11658c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci packet_header = I2C_HEADER_IE_ENABLE; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (end_state == MSG_END_CONTINUE) 11708c2ecf20Sopenharmony_ci packet_header |= I2C_HEADER_CONTINUE_XFER; 11718c2ecf20Sopenharmony_ci else if (end_state == MSG_END_REPEAT_START) 11728c2ecf20Sopenharmony_ci packet_header |= I2C_HEADER_REPEAT_START; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_TEN) { 11758c2ecf20Sopenharmony_ci packet_header |= msg->addr; 11768c2ecf20Sopenharmony_ci packet_header |= I2C_HEADER_10BIT_ADDR; 11778c2ecf20Sopenharmony_ci } else { 11788c2ecf20Sopenharmony_ci packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT; 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_IGNORE_NAK) 11828c2ecf20Sopenharmony_ci packet_header |= I2C_HEADER_CONT_ON_NAK; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_RD) 11858c2ecf20Sopenharmony_ci packet_header |= I2C_HEADER_READ; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode && !i2c_dev->msg_read) 11888c2ecf20Sopenharmony_ci *dma_buf++ = packet_header; 11898c2ecf20Sopenharmony_ci else 11908c2ecf20Sopenharmony_ci i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_cistatic int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev, 11948c2ecf20Sopenharmony_ci struct i2c_msg *msg) 11958c2ecf20Sopenharmony_ci{ 11968c2ecf20Sopenharmony_ci if (i2c_dev->msg_err == I2C_ERR_NONE) 11978c2ecf20Sopenharmony_ci return 0; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci tegra_i2c_init(i2c_dev); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci /* start recovery upon arbitration loss in single master mode */ 12028c2ecf20Sopenharmony_ci if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) { 12038c2ecf20Sopenharmony_ci if (!i2c_dev->multimaster_mode) 12048c2ecf20Sopenharmony_ci return i2c_recover_bus(&i2c_dev->adapter); 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci return -EAGAIN; 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci if (i2c_dev->msg_err == I2C_ERR_NO_ACK) { 12108c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_IGNORE_NAK) 12118c2ecf20Sopenharmony_ci return 0; 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci return -EREMOTEIO; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci return -EIO; 12178c2ecf20Sopenharmony_ci} 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_cistatic int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, 12208c2ecf20Sopenharmony_ci struct i2c_msg *msg, 12218c2ecf20Sopenharmony_ci enum msg_end_type end_state) 12228c2ecf20Sopenharmony_ci{ 12238c2ecf20Sopenharmony_ci unsigned long time_left, xfer_time = 100; 12248c2ecf20Sopenharmony_ci size_t xfer_size; 12258c2ecf20Sopenharmony_ci u32 int_mask; 12268c2ecf20Sopenharmony_ci int err; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci err = tegra_i2c_flush_fifos(i2c_dev); 12298c2ecf20Sopenharmony_ci if (err) 12308c2ecf20Sopenharmony_ci return err; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci i2c_dev->msg_buf = msg->buf; 12338c2ecf20Sopenharmony_ci i2c_dev->msg_buf_remaining = msg->len; 12348c2ecf20Sopenharmony_ci i2c_dev->msg_err = I2C_ERR_NONE; 12358c2ecf20Sopenharmony_ci i2c_dev->msg_read = !!(msg->flags & I2C_M_RD); 12368c2ecf20Sopenharmony_ci reinit_completion(&i2c_dev->msg_complete); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci if (i2c_dev->msg_read) 12398c2ecf20Sopenharmony_ci xfer_size = msg->len; 12408c2ecf20Sopenharmony_ci else 12418c2ecf20Sopenharmony_ci xfer_size = msg->len + I2C_PACKET_HEADER_SIZE; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci xfer_size = ALIGN(xfer_size, BYTES_PER_FIFO_WORD); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci i2c_dev->dma_mode = xfer_size > I2C_PIO_MODE_PREFERRED_LEN && 12468c2ecf20Sopenharmony_ci i2c_dev->dma_buf && !i2c_dev->atomic_mode; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci tegra_i2c_config_fifo_trig(i2c_dev, xfer_size); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci /* 12518c2ecf20Sopenharmony_ci * Transfer time in mSec = Total bits / transfer rate 12528c2ecf20Sopenharmony_ci * Total bits = 9 bits per byte (including ACK bit) + Start & stop bits 12538c2ecf20Sopenharmony_ci */ 12548c2ecf20Sopenharmony_ci xfer_time += DIV_ROUND_CLOSEST(((xfer_size * 9) + 2) * MSEC_PER_SEC, 12558c2ecf20Sopenharmony_ci i2c_dev->bus_clk_rate); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; 12588c2ecf20Sopenharmony_ci tegra_i2c_unmask_irq(i2c_dev, int_mask); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode) { 12618c2ecf20Sopenharmony_ci if (i2c_dev->msg_read) { 12628c2ecf20Sopenharmony_ci dma_sync_single_for_device(i2c_dev->dma_dev, 12638c2ecf20Sopenharmony_ci i2c_dev->dma_phys, 12648c2ecf20Sopenharmony_ci xfer_size, DMA_FROM_DEVICE); 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci err = tegra_i2c_dma_submit(i2c_dev, xfer_size); 12678c2ecf20Sopenharmony_ci if (err) 12688c2ecf20Sopenharmony_ci return err; 12698c2ecf20Sopenharmony_ci } else { 12708c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(i2c_dev->dma_dev, 12718c2ecf20Sopenharmony_ci i2c_dev->dma_phys, 12728c2ecf20Sopenharmony_ci xfer_size, DMA_TO_DEVICE); 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci tegra_i2c_push_packet_header(i2c_dev, msg, end_state); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci if (!i2c_dev->msg_read) { 12798c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode) { 12808c2ecf20Sopenharmony_ci memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE, 12818c2ecf20Sopenharmony_ci msg->buf, msg->len); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci dma_sync_single_for_device(i2c_dev->dma_dev, 12848c2ecf20Sopenharmony_ci i2c_dev->dma_phys, 12858c2ecf20Sopenharmony_ci xfer_size, DMA_TO_DEVICE); 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci err = tegra_i2c_dma_submit(i2c_dev, xfer_size); 12888c2ecf20Sopenharmony_ci if (err) 12898c2ecf20Sopenharmony_ci return err; 12908c2ecf20Sopenharmony_ci } else { 12918c2ecf20Sopenharmony_ci tegra_i2c_fill_tx_fifo(i2c_dev); 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_per_pkt_xfer_complete_irq) 12968c2ecf20Sopenharmony_ci int_mask |= I2C_INT_PACKET_XFER_COMPLETE; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci if (!i2c_dev->dma_mode) { 12998c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_RD) 13008c2ecf20Sopenharmony_ci int_mask |= I2C_INT_RX_FIFO_DATA_REQ; 13018c2ecf20Sopenharmony_ci else if (i2c_dev->msg_buf_remaining) 13028c2ecf20Sopenharmony_ci int_mask |= I2C_INT_TX_FIFO_DATA_REQ; 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci tegra_i2c_unmask_irq(i2c_dev, int_mask); 13068c2ecf20Sopenharmony_ci dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n", 13078c2ecf20Sopenharmony_ci i2c_readl(i2c_dev, I2C_INT_MASK)); 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci if (i2c_dev->dma_mode) { 13108c2ecf20Sopenharmony_ci time_left = tegra_i2c_wait_completion(i2c_dev, 13118c2ecf20Sopenharmony_ci &i2c_dev->dma_complete, 13128c2ecf20Sopenharmony_ci xfer_time); 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci /* 13158c2ecf20Sopenharmony_ci * Synchronize DMA first, since dmaengine_terminate_sync() 13168c2ecf20Sopenharmony_ci * performs synchronization after the transfer's termination 13178c2ecf20Sopenharmony_ci * and we want to get a completion if transfer succeeded. 13188c2ecf20Sopenharmony_ci */ 13198c2ecf20Sopenharmony_ci dmaengine_synchronize(i2c_dev->msg_read ? 13208c2ecf20Sopenharmony_ci i2c_dev->rx_dma_chan : 13218c2ecf20Sopenharmony_ci i2c_dev->tx_dma_chan); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci dmaengine_terminate_sync(i2c_dev->msg_read ? 13248c2ecf20Sopenharmony_ci i2c_dev->rx_dma_chan : 13258c2ecf20Sopenharmony_ci i2c_dev->tx_dma_chan); 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci if (!time_left && !completion_done(&i2c_dev->dma_complete)) { 13288c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "DMA transfer timed out\n"); 13298c2ecf20Sopenharmony_ci tegra_i2c_init(i2c_dev); 13308c2ecf20Sopenharmony_ci return -ETIMEDOUT; 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) { 13348c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(i2c_dev->dma_dev, 13358c2ecf20Sopenharmony_ci i2c_dev->dma_phys, 13368c2ecf20Sopenharmony_ci xfer_size, DMA_FROM_DEVICE); 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, msg->len); 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci } 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 13438c2ecf20Sopenharmony_ci xfer_time); 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci tegra_i2c_mask_irq(i2c_dev, int_mask); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci if (time_left == 0) { 13488c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "I2C transfer timed out\n"); 13498c2ecf20Sopenharmony_ci tegra_i2c_init(i2c_dev); 13508c2ecf20Sopenharmony_ci return -ETIMEDOUT; 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci dev_dbg(i2c_dev->dev, "transfer complete: %lu %d %d\n", 13548c2ecf20Sopenharmony_ci time_left, completion_done(&i2c_dev->msg_complete), 13558c2ecf20Sopenharmony_ci i2c_dev->msg_err); 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci i2c_dev->dma_mode = false; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci err = tegra_i2c_error_recover(i2c_dev, msg); 13608c2ecf20Sopenharmony_ci if (err) 13618c2ecf20Sopenharmony_ci return err; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci return 0; 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_cistatic int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], 13678c2ecf20Sopenharmony_ci int num) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 13708c2ecf20Sopenharmony_ci int i, ret; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(i2c_dev->dev); 13738c2ecf20Sopenharmony_ci if (ret < 0) { 13748c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret); 13758c2ecf20Sopenharmony_ci pm_runtime_put_noidle(i2c_dev->dev); 13768c2ecf20Sopenharmony_ci return ret; 13778c2ecf20Sopenharmony_ci } 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 13808c2ecf20Sopenharmony_ci enum msg_end_type end_type = MSG_END_STOP; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci if (i < (num - 1)) { 13838c2ecf20Sopenharmony_ci /* check whether follow up message is coming */ 13848c2ecf20Sopenharmony_ci if (msgs[i + 1].flags & I2C_M_NOSTART) 13858c2ecf20Sopenharmony_ci end_type = MSG_END_CONTINUE; 13868c2ecf20Sopenharmony_ci else 13878c2ecf20Sopenharmony_ci end_type = MSG_END_REPEAT_START; 13888c2ecf20Sopenharmony_ci } 13898c2ecf20Sopenharmony_ci ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], end_type); 13908c2ecf20Sopenharmony_ci if (ret) 13918c2ecf20Sopenharmony_ci break; 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci pm_runtime_put(i2c_dev->dev); 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci return ret ?: i; 13978c2ecf20Sopenharmony_ci} 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_cistatic int tegra_i2c_xfer_atomic(struct i2c_adapter *adap, 14008c2ecf20Sopenharmony_ci struct i2c_msg msgs[], int num) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 14038c2ecf20Sopenharmony_ci int ret; 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci i2c_dev->atomic_mode = true; 14068c2ecf20Sopenharmony_ci ret = tegra_i2c_xfer(adap, msgs, num); 14078c2ecf20Sopenharmony_ci i2c_dev->atomic_mode = false; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci return ret; 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic u32 tegra_i2c_func(struct i2c_adapter *adap) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 14158c2ecf20Sopenharmony_ci u32 ret = I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | 14168c2ecf20Sopenharmony_ci I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci if (i2c_dev->hw->has_continue_xfer_support) 14198c2ecf20Sopenharmony_ci ret |= I2C_FUNC_NOSTART; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci return ret; 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic const struct i2c_algorithm tegra_i2c_algo = { 14258c2ecf20Sopenharmony_ci .master_xfer = tegra_i2c_xfer, 14268c2ecf20Sopenharmony_ci .master_xfer_atomic = tegra_i2c_xfer_atomic, 14278c2ecf20Sopenharmony_ci .functionality = tegra_i2c_func, 14288c2ecf20Sopenharmony_ci}; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci/* payload size is only 12 bit */ 14318c2ecf20Sopenharmony_cistatic const struct i2c_adapter_quirks tegra_i2c_quirks = { 14328c2ecf20Sopenharmony_ci .flags = I2C_AQ_NO_ZERO_LEN, 14338c2ecf20Sopenharmony_ci .max_read_len = SZ_4K, 14348c2ecf20Sopenharmony_ci .max_write_len = SZ_4K - I2C_PACKET_HEADER_SIZE, 14358c2ecf20Sopenharmony_ci}; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_cistatic const struct i2c_adapter_quirks tegra194_i2c_quirks = { 14388c2ecf20Sopenharmony_ci .flags = I2C_AQ_NO_ZERO_LEN, 14398c2ecf20Sopenharmony_ci .max_write_len = SZ_64K - I2C_PACKET_HEADER_SIZE, 14408c2ecf20Sopenharmony_ci}; 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_cistatic struct i2c_bus_recovery_info tegra_i2c_recovery_info = { 14438c2ecf20Sopenharmony_ci .recover_bus = tegra_i2c_issue_bus_clear, 14448c2ecf20Sopenharmony_ci}; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra20_i2c_hw = { 14478c2ecf20Sopenharmony_ci .has_continue_xfer_support = false, 14488c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = false, 14498c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 3, 14508c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0, 14518c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0, 14528c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0, 14538c2ecf20Sopenharmony_ci .has_config_load_reg = false, 14548c2ecf20Sopenharmony_ci .has_multi_master_mode = false, 14558c2ecf20Sopenharmony_ci .has_slcg_override_reg = false, 14568c2ecf20Sopenharmony_ci .has_mst_fifo = false, 14578c2ecf20Sopenharmony_ci .quirks = &tegra_i2c_quirks, 14588c2ecf20Sopenharmony_ci .supports_bus_clear = false, 14598c2ecf20Sopenharmony_ci .has_apb_dma = true, 14608c2ecf20Sopenharmony_ci .tlow_std_mode = 0x4, 14618c2ecf20Sopenharmony_ci .thigh_std_mode = 0x2, 14628c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x4, 14638c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 14648c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0x0, 14658c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0x0, 14668c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0x0, 14678c2ecf20Sopenharmony_ci .has_interface_timing_reg = false, 14688c2ecf20Sopenharmony_ci}; 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra30_i2c_hw = { 14718c2ecf20Sopenharmony_ci .has_continue_xfer_support = true, 14728c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = false, 14738c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 3, 14748c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0, 14758c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0, 14768c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0, 14778c2ecf20Sopenharmony_ci .has_config_load_reg = false, 14788c2ecf20Sopenharmony_ci .has_multi_master_mode = false, 14798c2ecf20Sopenharmony_ci .has_slcg_override_reg = false, 14808c2ecf20Sopenharmony_ci .has_mst_fifo = false, 14818c2ecf20Sopenharmony_ci .quirks = &tegra_i2c_quirks, 14828c2ecf20Sopenharmony_ci .supports_bus_clear = false, 14838c2ecf20Sopenharmony_ci .has_apb_dma = true, 14848c2ecf20Sopenharmony_ci .tlow_std_mode = 0x4, 14858c2ecf20Sopenharmony_ci .thigh_std_mode = 0x2, 14868c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x4, 14878c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 14888c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0x0, 14898c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0x0, 14908c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0x0, 14918c2ecf20Sopenharmony_ci .has_interface_timing_reg = false, 14928c2ecf20Sopenharmony_ci}; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra114_i2c_hw = { 14958c2ecf20Sopenharmony_ci .has_continue_xfer_support = true, 14968c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = true, 14978c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 1, 14988c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0x19, 14998c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0x19, 15008c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0x10, 15018c2ecf20Sopenharmony_ci .has_config_load_reg = false, 15028c2ecf20Sopenharmony_ci .has_multi_master_mode = false, 15038c2ecf20Sopenharmony_ci .has_slcg_override_reg = false, 15048c2ecf20Sopenharmony_ci .has_mst_fifo = false, 15058c2ecf20Sopenharmony_ci .quirks = &tegra_i2c_quirks, 15068c2ecf20Sopenharmony_ci .supports_bus_clear = true, 15078c2ecf20Sopenharmony_ci .has_apb_dma = true, 15088c2ecf20Sopenharmony_ci .tlow_std_mode = 0x4, 15098c2ecf20Sopenharmony_ci .thigh_std_mode = 0x2, 15108c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x4, 15118c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 15128c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0x0, 15138c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0x0, 15148c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0x0, 15158c2ecf20Sopenharmony_ci .has_interface_timing_reg = false, 15168c2ecf20Sopenharmony_ci}; 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra124_i2c_hw = { 15198c2ecf20Sopenharmony_ci .has_continue_xfer_support = true, 15208c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = true, 15218c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 1, 15228c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0x19, 15238c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0x19, 15248c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0x10, 15258c2ecf20Sopenharmony_ci .has_config_load_reg = true, 15268c2ecf20Sopenharmony_ci .has_multi_master_mode = false, 15278c2ecf20Sopenharmony_ci .has_slcg_override_reg = true, 15288c2ecf20Sopenharmony_ci .has_mst_fifo = false, 15298c2ecf20Sopenharmony_ci .quirks = &tegra_i2c_quirks, 15308c2ecf20Sopenharmony_ci .supports_bus_clear = true, 15318c2ecf20Sopenharmony_ci .has_apb_dma = true, 15328c2ecf20Sopenharmony_ci .tlow_std_mode = 0x4, 15338c2ecf20Sopenharmony_ci .thigh_std_mode = 0x2, 15348c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x4, 15358c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 15368c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0x0, 15378c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0x0, 15388c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0x0, 15398c2ecf20Sopenharmony_ci .has_interface_timing_reg = true, 15408c2ecf20Sopenharmony_ci}; 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra210_i2c_hw = { 15438c2ecf20Sopenharmony_ci .has_continue_xfer_support = true, 15448c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = true, 15458c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 1, 15468c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0x19, 15478c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0x19, 15488c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0x10, 15498c2ecf20Sopenharmony_ci .has_config_load_reg = true, 15508c2ecf20Sopenharmony_ci .has_multi_master_mode = false, 15518c2ecf20Sopenharmony_ci .has_slcg_override_reg = true, 15528c2ecf20Sopenharmony_ci .has_mst_fifo = false, 15538c2ecf20Sopenharmony_ci .quirks = &tegra_i2c_quirks, 15548c2ecf20Sopenharmony_ci .supports_bus_clear = true, 15558c2ecf20Sopenharmony_ci .has_apb_dma = true, 15568c2ecf20Sopenharmony_ci .tlow_std_mode = 0x4, 15578c2ecf20Sopenharmony_ci .thigh_std_mode = 0x2, 15588c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x4, 15598c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 15608c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0, 15618c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0, 15628c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0, 15638c2ecf20Sopenharmony_ci .has_interface_timing_reg = true, 15648c2ecf20Sopenharmony_ci}; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra186_i2c_hw = { 15678c2ecf20Sopenharmony_ci .has_continue_xfer_support = true, 15688c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = true, 15698c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 1, 15708c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0x16, 15718c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0x19, 15728c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0x10, 15738c2ecf20Sopenharmony_ci .has_config_load_reg = true, 15748c2ecf20Sopenharmony_ci .has_multi_master_mode = false, 15758c2ecf20Sopenharmony_ci .has_slcg_override_reg = true, 15768c2ecf20Sopenharmony_ci .has_mst_fifo = false, 15778c2ecf20Sopenharmony_ci .quirks = &tegra_i2c_quirks, 15788c2ecf20Sopenharmony_ci .supports_bus_clear = true, 15798c2ecf20Sopenharmony_ci .has_apb_dma = false, 15808c2ecf20Sopenharmony_ci .tlow_std_mode = 0x4, 15818c2ecf20Sopenharmony_ci .thigh_std_mode = 0x3, 15828c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x4, 15838c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 15848c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0, 15858c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0, 15868c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0, 15878c2ecf20Sopenharmony_ci .has_interface_timing_reg = true, 15888c2ecf20Sopenharmony_ci}; 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_cistatic const struct tegra_i2c_hw_feature tegra194_i2c_hw = { 15918c2ecf20Sopenharmony_ci .has_continue_xfer_support = true, 15928c2ecf20Sopenharmony_ci .has_per_pkt_xfer_complete_irq = true, 15938c2ecf20Sopenharmony_ci .clk_divisor_hs_mode = 1, 15948c2ecf20Sopenharmony_ci .clk_divisor_std_mode = 0x4f, 15958c2ecf20Sopenharmony_ci .clk_divisor_fast_mode = 0x3c, 15968c2ecf20Sopenharmony_ci .clk_divisor_fast_plus_mode = 0x16, 15978c2ecf20Sopenharmony_ci .has_config_load_reg = true, 15988c2ecf20Sopenharmony_ci .has_multi_master_mode = true, 15998c2ecf20Sopenharmony_ci .has_slcg_override_reg = true, 16008c2ecf20Sopenharmony_ci .has_mst_fifo = true, 16018c2ecf20Sopenharmony_ci .quirks = &tegra194_i2c_quirks, 16028c2ecf20Sopenharmony_ci .supports_bus_clear = true, 16038c2ecf20Sopenharmony_ci .has_apb_dma = false, 16048c2ecf20Sopenharmony_ci .tlow_std_mode = 0x8, 16058c2ecf20Sopenharmony_ci .thigh_std_mode = 0x7, 16068c2ecf20Sopenharmony_ci .tlow_fast_fastplus_mode = 0x2, 16078c2ecf20Sopenharmony_ci .thigh_fast_fastplus_mode = 0x2, 16088c2ecf20Sopenharmony_ci .setup_hold_time_std_mode = 0x08080808, 16098c2ecf20Sopenharmony_ci .setup_hold_time_fast_fast_plus_mode = 0x02020202, 16108c2ecf20Sopenharmony_ci .setup_hold_time_hs_mode = 0x090909, 16118c2ecf20Sopenharmony_ci .has_interface_timing_reg = true, 16128c2ecf20Sopenharmony_ci}; 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_cistatic const struct of_device_id tegra_i2c_of_match[] = { 16158c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, }, 16168c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, }, 16178c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, }, 16188c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, }, 16198c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, }, 16208c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, }, 16218c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, 16228c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, 16238c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, 16248c2ecf20Sopenharmony_ci {}, 16258c2ecf20Sopenharmony_ci}; 16268c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, tegra_i2c_of_match); 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_cistatic void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) 16298c2ecf20Sopenharmony_ci{ 16308c2ecf20Sopenharmony_ci struct device_node *np = i2c_dev->dev->of_node; 16318c2ecf20Sopenharmony_ci bool multi_mode; 16328c2ecf20Sopenharmony_ci int err; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci err = of_property_read_u32(np, "clock-frequency", 16358c2ecf20Sopenharmony_ci &i2c_dev->bus_clk_rate); 16368c2ecf20Sopenharmony_ci if (err) 16378c2ecf20Sopenharmony_ci i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci multi_mode = of_property_read_bool(np, "multi-master"); 16408c2ecf20Sopenharmony_ci i2c_dev->multimaster_mode = multi_mode; 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) 16438c2ecf20Sopenharmony_ci i2c_dev->is_dvc = true; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi")) 16468c2ecf20Sopenharmony_ci i2c_dev->is_vi = true; 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_cistatic int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) 16508c2ecf20Sopenharmony_ci{ 16518c2ecf20Sopenharmony_ci int err; 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci i2c_dev->clocks[i2c_dev->nclocks++].id = "div-clk"; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw) 16568c2ecf20Sopenharmony_ci i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk"; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci if (i2c_dev->is_vi) 16598c2ecf20Sopenharmony_ci i2c_dev->clocks[i2c_dev->nclocks++].id = "slow"; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks, 16628c2ecf20Sopenharmony_ci i2c_dev->clocks); 16638c2ecf20Sopenharmony_ci if (err) 16648c2ecf20Sopenharmony_ci return err; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci err = clk_bulk_prepare(i2c_dev->nclocks, i2c_dev->clocks); 16678c2ecf20Sopenharmony_ci if (err) 16688c2ecf20Sopenharmony_ci return err; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci i2c_dev->div_clk = i2c_dev->clocks[0].clk; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci if (!i2c_dev->multimaster_mode) 16738c2ecf20Sopenharmony_ci return 0; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci err = clk_enable(i2c_dev->div_clk); 16768c2ecf20Sopenharmony_ci if (err) { 16778c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "failed to enable div-clk: %d\n", err); 16788c2ecf20Sopenharmony_ci goto unprepare_clocks; 16798c2ecf20Sopenharmony_ci } 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci return 0; 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ciunprepare_clocks: 16848c2ecf20Sopenharmony_ci clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks); 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci return err; 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_cistatic void tegra_i2c_release_clocks(struct tegra_i2c_dev *i2c_dev) 16908c2ecf20Sopenharmony_ci{ 16918c2ecf20Sopenharmony_ci if (i2c_dev->multimaster_mode) 16928c2ecf20Sopenharmony_ci clk_disable(i2c_dev->div_clk); 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks); 16958c2ecf20Sopenharmony_ci} 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_cistatic int tegra_i2c_init_hardware(struct tegra_i2c_dev *i2c_dev) 16988c2ecf20Sopenharmony_ci{ 16998c2ecf20Sopenharmony_ci int ret; 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(i2c_dev->dev); 17028c2ecf20Sopenharmony_ci if (ret < 0) 17038c2ecf20Sopenharmony_ci dev_err(i2c_dev->dev, "runtime resume failed: %d\n", ret); 17048c2ecf20Sopenharmony_ci else 17058c2ecf20Sopenharmony_ci ret = tegra_i2c_init(i2c_dev); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci pm_runtime_put(i2c_dev->dev); 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci return ret; 17108c2ecf20Sopenharmony_ci} 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_cistatic int tegra_i2c_probe(struct platform_device *pdev) 17138c2ecf20Sopenharmony_ci{ 17148c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev; 17158c2ecf20Sopenharmony_ci struct resource *res; 17168c2ecf20Sopenharmony_ci int err; 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); 17198c2ecf20Sopenharmony_ci if (!i2c_dev) 17208c2ecf20Sopenharmony_ci return -ENOMEM; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, i2c_dev); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci init_completion(&i2c_dev->msg_complete); 17258c2ecf20Sopenharmony_ci init_completion(&i2c_dev->dma_complete); 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci i2c_dev->hw = of_device_get_match_data(&pdev->dev); 17288c2ecf20Sopenharmony_ci i2c_dev->cont_id = pdev->id; 17298c2ecf20Sopenharmony_ci i2c_dev->dev = &pdev->dev; 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 17328c2ecf20Sopenharmony_ci if (IS_ERR(i2c_dev->base)) 17338c2ecf20Sopenharmony_ci return PTR_ERR(i2c_dev->base); 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci i2c_dev->base_phys = res->start; 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci err = platform_get_irq(pdev, 0); 17388c2ecf20Sopenharmony_ci if (err < 0) 17398c2ecf20Sopenharmony_ci return err; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci i2c_dev->irq = err; 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci /* interrupt will be enabled during of transfer time */ 17448c2ecf20Sopenharmony_ci irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN); 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci err = devm_request_irq(i2c_dev->dev, i2c_dev->irq, tegra_i2c_isr, 17478c2ecf20Sopenharmony_ci IRQF_NO_SUSPEND, dev_name(i2c_dev->dev), 17488c2ecf20Sopenharmony_ci i2c_dev); 17498c2ecf20Sopenharmony_ci if (err) 17508c2ecf20Sopenharmony_ci return err; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); 17538c2ecf20Sopenharmony_ci if (IS_ERR(i2c_dev->rst)) { 17548c2ecf20Sopenharmony_ci dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), 17558c2ecf20Sopenharmony_ci "failed to get reset control\n"); 17568c2ecf20Sopenharmony_ci return PTR_ERR(i2c_dev->rst); 17578c2ecf20Sopenharmony_ci } 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci tegra_i2c_parse_dt(i2c_dev); 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci err = tegra_i2c_init_clocks(i2c_dev); 17628c2ecf20Sopenharmony_ci if (err) 17638c2ecf20Sopenharmony_ci return err; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci err = tegra_i2c_init_dma(i2c_dev); 17668c2ecf20Sopenharmony_ci if (err) 17678c2ecf20Sopenharmony_ci goto release_clocks; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci /* 17708c2ecf20Sopenharmony_ci * VI I2C is in VE power domain which is not always ON and not 17718c2ecf20Sopenharmony_ci * IRQ-safe. Thus, IRQ-safe device shouldn't be attached to a 17728c2ecf20Sopenharmony_ci * non IRQ-safe domain because this prevents powering off the power 17738c2ecf20Sopenharmony_ci * domain. 17748c2ecf20Sopenharmony_ci * 17758c2ecf20Sopenharmony_ci * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't 17768c2ecf20Sopenharmony_ci * be used for atomic transfers. 17778c2ecf20Sopenharmony_ci */ 17788c2ecf20Sopenharmony_ci if (!i2c_dev->is_vi) 17798c2ecf20Sopenharmony_ci pm_runtime_irq_safe(i2c_dev->dev); 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci pm_runtime_enable(i2c_dev->dev); 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci err = tegra_i2c_init_hardware(i2c_dev); 17848c2ecf20Sopenharmony_ci if (err) 17858c2ecf20Sopenharmony_ci goto release_rpm; 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); 17888c2ecf20Sopenharmony_ci i2c_dev->adapter.dev.of_node = i2c_dev->dev->of_node; 17898c2ecf20Sopenharmony_ci i2c_dev->adapter.dev.parent = i2c_dev->dev; 17908c2ecf20Sopenharmony_ci i2c_dev->adapter.retries = 1; 17918c2ecf20Sopenharmony_ci i2c_dev->adapter.timeout = 6 * HZ; 17928c2ecf20Sopenharmony_ci i2c_dev->adapter.quirks = i2c_dev->hw->quirks; 17938c2ecf20Sopenharmony_ci i2c_dev->adapter.owner = THIS_MODULE; 17948c2ecf20Sopenharmony_ci i2c_dev->adapter.class = I2C_CLASS_DEPRECATED; 17958c2ecf20Sopenharmony_ci i2c_dev->adapter.algo = &tegra_i2c_algo; 17968c2ecf20Sopenharmony_ci i2c_dev->adapter.nr = pdev->id; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci if (i2c_dev->hw->supports_bus_clear) 17998c2ecf20Sopenharmony_ci i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev), 18028c2ecf20Sopenharmony_ci sizeof(i2c_dev->adapter.name)); 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci err = i2c_add_numbered_adapter(&i2c_dev->adapter); 18058c2ecf20Sopenharmony_ci if (err) 18068c2ecf20Sopenharmony_ci goto release_rpm; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci return 0; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_cirelease_rpm: 18118c2ecf20Sopenharmony_ci pm_runtime_disable(i2c_dev->dev); 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci tegra_i2c_release_dma(i2c_dev); 18148c2ecf20Sopenharmony_cirelease_clocks: 18158c2ecf20Sopenharmony_ci tegra_i2c_release_clocks(i2c_dev); 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci return err; 18188c2ecf20Sopenharmony_ci} 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_cistatic int tegra_i2c_remove(struct platform_device *pdev) 18218c2ecf20Sopenharmony_ci{ 18228c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci i2c_del_adapter(&i2c_dev->adapter); 18258c2ecf20Sopenharmony_ci pm_runtime_disable(i2c_dev->dev); 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci tegra_i2c_release_dma(i2c_dev); 18288c2ecf20Sopenharmony_ci tegra_i2c_release_clocks(i2c_dev); 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci return 0; 18318c2ecf20Sopenharmony_ci} 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_cistatic int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) 18348c2ecf20Sopenharmony_ci{ 18358c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); 18368c2ecf20Sopenharmony_ci int err; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci err = pinctrl_pm_select_default_state(dev); 18398c2ecf20Sopenharmony_ci if (err) 18408c2ecf20Sopenharmony_ci return err; 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci err = clk_bulk_enable(i2c_dev->nclocks, i2c_dev->clocks); 18438c2ecf20Sopenharmony_ci if (err) 18448c2ecf20Sopenharmony_ci return err; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci /* 18478c2ecf20Sopenharmony_ci * VI I2C device is attached to VE power domain which goes through 18488c2ecf20Sopenharmony_ci * power ON/OFF during runtime PM resume/suspend, meaning that 18498c2ecf20Sopenharmony_ci * controller needs to be re-initialized after power ON. 18508c2ecf20Sopenharmony_ci */ 18518c2ecf20Sopenharmony_ci if (i2c_dev->is_vi) { 18528c2ecf20Sopenharmony_ci err = tegra_i2c_init(i2c_dev); 18538c2ecf20Sopenharmony_ci if (err) 18548c2ecf20Sopenharmony_ci goto disable_clocks; 18558c2ecf20Sopenharmony_ci } 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci return 0; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_cidisable_clocks: 18608c2ecf20Sopenharmony_ci clk_bulk_disable(i2c_dev->nclocks, i2c_dev->clocks); 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci return err; 18638c2ecf20Sopenharmony_ci} 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_cistatic int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev) 18668c2ecf20Sopenharmony_ci{ 18678c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci clk_bulk_disable(i2c_dev->nclocks, i2c_dev->clocks); 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci return pinctrl_pm_select_idle_state(dev); 18728c2ecf20Sopenharmony_ci} 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_cistatic int __maybe_unused tegra_i2c_suspend(struct device *dev) 18758c2ecf20Sopenharmony_ci{ 18768c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); 18778c2ecf20Sopenharmony_ci int err; 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_ci i2c_mark_adapter_suspended(&i2c_dev->adapter); 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci if (!pm_runtime_status_suspended(dev)) { 18828c2ecf20Sopenharmony_ci err = tegra_i2c_runtime_suspend(dev); 18838c2ecf20Sopenharmony_ci if (err) 18848c2ecf20Sopenharmony_ci return err; 18858c2ecf20Sopenharmony_ci } 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci return 0; 18888c2ecf20Sopenharmony_ci} 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_cistatic int __maybe_unused tegra_i2c_resume(struct device *dev) 18918c2ecf20Sopenharmony_ci{ 18928c2ecf20Sopenharmony_ci struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); 18938c2ecf20Sopenharmony_ci int err; 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci /* 18968c2ecf20Sopenharmony_ci * We need to ensure that clocks are enabled so that registers can be 18978c2ecf20Sopenharmony_ci * restored in tegra_i2c_init(). 18988c2ecf20Sopenharmony_ci */ 18998c2ecf20Sopenharmony_ci err = tegra_i2c_runtime_resume(dev); 19008c2ecf20Sopenharmony_ci if (err) 19018c2ecf20Sopenharmony_ci return err; 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci err = tegra_i2c_init(i2c_dev); 19048c2ecf20Sopenharmony_ci if (err) 19058c2ecf20Sopenharmony_ci return err; 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci /* 19088c2ecf20Sopenharmony_ci * In case we are runtime suspended, disable clocks again so that we 19098c2ecf20Sopenharmony_ci * don't unbalance the clock reference counts during the next runtime 19108c2ecf20Sopenharmony_ci * resume transition. 19118c2ecf20Sopenharmony_ci */ 19128c2ecf20Sopenharmony_ci if (pm_runtime_status_suspended(dev)) { 19138c2ecf20Sopenharmony_ci err = tegra_i2c_runtime_suspend(dev); 19148c2ecf20Sopenharmony_ci if (err) 19158c2ecf20Sopenharmony_ci return err; 19168c2ecf20Sopenharmony_ci } 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci i2c_mark_adapter_resumed(&i2c_dev->adapter); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci return 0; 19218c2ecf20Sopenharmony_ci} 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_cistatic const struct dev_pm_ops tegra_i2c_pm = { 19248c2ecf20Sopenharmony_ci SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume) 19258c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume, 19268c2ecf20Sopenharmony_ci NULL) 19278c2ecf20Sopenharmony_ci}; 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_cistatic struct platform_driver tegra_i2c_driver = { 19308c2ecf20Sopenharmony_ci .probe = tegra_i2c_probe, 19318c2ecf20Sopenharmony_ci .remove = tegra_i2c_remove, 19328c2ecf20Sopenharmony_ci .driver = { 19338c2ecf20Sopenharmony_ci .name = "tegra-i2c", 19348c2ecf20Sopenharmony_ci .of_match_table = tegra_i2c_of_match, 19358c2ecf20Sopenharmony_ci .pm = &tegra_i2c_pm, 19368c2ecf20Sopenharmony_ci }, 19378c2ecf20Sopenharmony_ci}; 19388c2ecf20Sopenharmony_cimodule_platform_driver(tegra_i2c_driver); 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra I2C Bus Controller driver"); 19418c2ecf20Sopenharmony_ciMODULE_AUTHOR("Colin Cross"); 19428c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1943