18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2009 ST-Ericsson SA 48c2ecf20Sopenharmony_ci * Copyright (C) 2009 STMicroelectronics 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * I2C master mode controller driver, used in Nomadik 8815 78c2ecf20Sopenharmony_ci * and Ux500 platforms. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> 108c2ecf20Sopenharmony_ci * Author: Sachin Verma <sachin.verma@st.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/amba/bus.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 178c2ecf20Sopenharmony_ci#include <linux/i2c.h> 188c2ecf20Sopenharmony_ci#include <linux/err.h> 198c2ecf20Sopenharmony_ci#include <linux/clk.h> 208c2ecf20Sopenharmony_ci#include <linux/io.h> 218c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 228c2ecf20Sopenharmony_ci#include <linux/of.h> 238c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define DRIVER_NAME "nmk-i2c" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* I2C Controller register offsets */ 288c2ecf20Sopenharmony_ci#define I2C_CR (0x000) 298c2ecf20Sopenharmony_ci#define I2C_SCR (0x004) 308c2ecf20Sopenharmony_ci#define I2C_HSMCR (0x008) 318c2ecf20Sopenharmony_ci#define I2C_MCR (0x00C) 328c2ecf20Sopenharmony_ci#define I2C_TFR (0x010) 338c2ecf20Sopenharmony_ci#define I2C_SR (0x014) 348c2ecf20Sopenharmony_ci#define I2C_RFR (0x018) 358c2ecf20Sopenharmony_ci#define I2C_TFTR (0x01C) 368c2ecf20Sopenharmony_ci#define I2C_RFTR (0x020) 378c2ecf20Sopenharmony_ci#define I2C_DMAR (0x024) 388c2ecf20Sopenharmony_ci#define I2C_BRCR (0x028) 398c2ecf20Sopenharmony_ci#define I2C_IMSCR (0x02C) 408c2ecf20Sopenharmony_ci#define I2C_RISR (0x030) 418c2ecf20Sopenharmony_ci#define I2C_MISR (0x034) 428c2ecf20Sopenharmony_ci#define I2C_ICR (0x038) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* Control registers */ 458c2ecf20Sopenharmony_ci#define I2C_CR_PE (0x1 << 0) /* Peripheral Enable */ 468c2ecf20Sopenharmony_ci#define I2C_CR_OM (0x3 << 1) /* Operating mode */ 478c2ecf20Sopenharmony_ci#define I2C_CR_SAM (0x1 << 3) /* Slave addressing mode */ 488c2ecf20Sopenharmony_ci#define I2C_CR_SM (0x3 << 4) /* Speed mode */ 498c2ecf20Sopenharmony_ci#define I2C_CR_SGCM (0x1 << 6) /* Slave general call mode */ 508c2ecf20Sopenharmony_ci#define I2C_CR_FTX (0x1 << 7) /* Flush Transmit */ 518c2ecf20Sopenharmony_ci#define I2C_CR_FRX (0x1 << 8) /* Flush Receive */ 528c2ecf20Sopenharmony_ci#define I2C_CR_DMA_TX_EN (0x1 << 9) /* DMA Tx enable */ 538c2ecf20Sopenharmony_ci#define I2C_CR_DMA_RX_EN (0x1 << 10) /* DMA Rx Enable */ 548c2ecf20Sopenharmony_ci#define I2C_CR_DMA_SLE (0x1 << 11) /* DMA sync. logic enable */ 558c2ecf20Sopenharmony_ci#define I2C_CR_LM (0x1 << 12) /* Loopback mode */ 568c2ecf20Sopenharmony_ci#define I2C_CR_FON (0x3 << 13) /* Filtering on */ 578c2ecf20Sopenharmony_ci#define I2C_CR_FS (0x3 << 15) /* Force stop enable */ 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* Master controller (MCR) register */ 608c2ecf20Sopenharmony_ci#define I2C_MCR_OP (0x1 << 0) /* Operation */ 618c2ecf20Sopenharmony_ci#define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */ 628c2ecf20Sopenharmony_ci#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */ 638c2ecf20Sopenharmony_ci#define I2C_MCR_SB (0x1 << 11) /* Extended address */ 648c2ecf20Sopenharmony_ci#define I2C_MCR_AM (0x3 << 12) /* Address type */ 658c2ecf20Sopenharmony_ci#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */ 668c2ecf20Sopenharmony_ci#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Status register (SR) */ 698c2ecf20Sopenharmony_ci#define I2C_SR_OP (0x3 << 0) /* Operation */ 708c2ecf20Sopenharmony_ci#define I2C_SR_STATUS (0x3 << 2) /* controller status */ 718c2ecf20Sopenharmony_ci#define I2C_SR_CAUSE (0x7 << 4) /* Abort cause */ 728c2ecf20Sopenharmony_ci#define I2C_SR_TYPE (0x3 << 7) /* Receive type */ 738c2ecf20Sopenharmony_ci#define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* Interrupt mask set/clear (IMSCR) bits */ 768c2ecf20Sopenharmony_ci#define I2C_IT_TXFE (0x1 << 0) 778c2ecf20Sopenharmony_ci#define I2C_IT_TXFNE (0x1 << 1) 788c2ecf20Sopenharmony_ci#define I2C_IT_TXFF (0x1 << 2) 798c2ecf20Sopenharmony_ci#define I2C_IT_TXFOVR (0x1 << 3) 808c2ecf20Sopenharmony_ci#define I2C_IT_RXFE (0x1 << 4) 818c2ecf20Sopenharmony_ci#define I2C_IT_RXFNF (0x1 << 5) 828c2ecf20Sopenharmony_ci#define I2C_IT_RXFF (0x1 << 6) 838c2ecf20Sopenharmony_ci#define I2C_IT_RFSR (0x1 << 16) 848c2ecf20Sopenharmony_ci#define I2C_IT_RFSE (0x1 << 17) 858c2ecf20Sopenharmony_ci#define I2C_IT_WTSR (0x1 << 18) 868c2ecf20Sopenharmony_ci#define I2C_IT_MTD (0x1 << 19) 878c2ecf20Sopenharmony_ci#define I2C_IT_STD (0x1 << 20) 888c2ecf20Sopenharmony_ci#define I2C_IT_MAL (0x1 << 24) 898c2ecf20Sopenharmony_ci#define I2C_IT_BERR (0x1 << 25) 908c2ecf20Sopenharmony_ci#define I2C_IT_MTDWS (0x1 << 28) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define GEN_MASK(val, mask, sb) (((val) << (sb)) & (mask)) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* some bits in ICR are reserved */ 958c2ecf20Sopenharmony_ci#define I2C_CLEAR_ALL_INTS 0x131f007f 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* first three msb bits are reserved */ 988c2ecf20Sopenharmony_ci#define IRQ_MASK(mask) (mask & 0x1fffffff) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* maximum threshold value */ 1018c2ecf20Sopenharmony_ci#define MAX_I2C_FIFO_THRESHOLD 15 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cienum i2c_freq_mode { 1048c2ecf20Sopenharmony_ci I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ 1058c2ecf20Sopenharmony_ci I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */ 1068c2ecf20Sopenharmony_ci I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */ 1078c2ecf20Sopenharmony_ci I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */ 1088c2ecf20Sopenharmony_ci}; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/** 1118c2ecf20Sopenharmony_ci * struct i2c_vendor_data - per-vendor variations 1128c2ecf20Sopenharmony_ci * @has_mtdws: variant has the MTDWS bit 1138c2ecf20Sopenharmony_ci * @fifodepth: variant FIFO depth 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_cistruct i2c_vendor_data { 1168c2ecf20Sopenharmony_ci bool has_mtdws; 1178c2ecf20Sopenharmony_ci u32 fifodepth; 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cienum i2c_status { 1218c2ecf20Sopenharmony_ci I2C_NOP, 1228c2ecf20Sopenharmony_ci I2C_ON_GOING, 1238c2ecf20Sopenharmony_ci I2C_OK, 1248c2ecf20Sopenharmony_ci I2C_ABORT 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* operation */ 1288c2ecf20Sopenharmony_cienum i2c_operation { 1298c2ecf20Sopenharmony_ci I2C_NO_OPERATION = 0xff, 1308c2ecf20Sopenharmony_ci I2C_WRITE = 0x00, 1318c2ecf20Sopenharmony_ci I2C_READ = 0x01 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/** 1358c2ecf20Sopenharmony_ci * struct i2c_nmk_client - client specific data 1368c2ecf20Sopenharmony_ci * @slave_adr: 7-bit slave address 1378c2ecf20Sopenharmony_ci * @count: no. bytes to be transferred 1388c2ecf20Sopenharmony_ci * @buffer: client data buffer 1398c2ecf20Sopenharmony_ci * @xfer_bytes: bytes transferred till now 1408c2ecf20Sopenharmony_ci * @operation: current I2C operation 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_cistruct i2c_nmk_client { 1438c2ecf20Sopenharmony_ci unsigned short slave_adr; 1448c2ecf20Sopenharmony_ci unsigned long count; 1458c2ecf20Sopenharmony_ci unsigned char *buffer; 1468c2ecf20Sopenharmony_ci unsigned long xfer_bytes; 1478c2ecf20Sopenharmony_ci enum i2c_operation operation; 1488c2ecf20Sopenharmony_ci}; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/** 1518c2ecf20Sopenharmony_ci * struct nmk_i2c_dev - private data structure of the controller. 1528c2ecf20Sopenharmony_ci * @vendor: vendor data for this variant. 1538c2ecf20Sopenharmony_ci * @adev: parent amba device. 1548c2ecf20Sopenharmony_ci * @adap: corresponding I2C adapter. 1558c2ecf20Sopenharmony_ci * @irq: interrupt line for the controller. 1568c2ecf20Sopenharmony_ci * @virtbase: virtual io memory area. 1578c2ecf20Sopenharmony_ci * @clk: hardware i2c block clock. 1588c2ecf20Sopenharmony_ci * @cli: holder of client specific data. 1598c2ecf20Sopenharmony_ci * @clk_freq: clock frequency for the operation mode 1608c2ecf20Sopenharmony_ci * @tft: Tx FIFO Threshold in bytes 1618c2ecf20Sopenharmony_ci * @rft: Rx FIFO Threshold in bytes 1628c2ecf20Sopenharmony_ci * @timeout Slave response timeout (ms) 1638c2ecf20Sopenharmony_ci * @sm: speed mode 1648c2ecf20Sopenharmony_ci * @stop: stop condition. 1658c2ecf20Sopenharmony_ci * @xfer_complete: acknowledge completion for a I2C message. 1668c2ecf20Sopenharmony_ci * @result: controller propogated result. 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_cistruct nmk_i2c_dev { 1698c2ecf20Sopenharmony_ci struct i2c_vendor_data *vendor; 1708c2ecf20Sopenharmony_ci struct amba_device *adev; 1718c2ecf20Sopenharmony_ci struct i2c_adapter adap; 1728c2ecf20Sopenharmony_ci int irq; 1738c2ecf20Sopenharmony_ci void __iomem *virtbase; 1748c2ecf20Sopenharmony_ci struct clk *clk; 1758c2ecf20Sopenharmony_ci struct i2c_nmk_client cli; 1768c2ecf20Sopenharmony_ci u32 clk_freq; 1778c2ecf20Sopenharmony_ci unsigned char tft; 1788c2ecf20Sopenharmony_ci unsigned char rft; 1798c2ecf20Sopenharmony_ci int timeout; 1808c2ecf20Sopenharmony_ci enum i2c_freq_mode sm; 1818c2ecf20Sopenharmony_ci int stop; 1828c2ecf20Sopenharmony_ci struct completion xfer_complete; 1838c2ecf20Sopenharmony_ci int result; 1848c2ecf20Sopenharmony_ci}; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* controller's abort causes */ 1878c2ecf20Sopenharmony_cistatic const char *abort_causes[] = { 1888c2ecf20Sopenharmony_ci "no ack received after address transmission", 1898c2ecf20Sopenharmony_ci "no ack received during data phase", 1908c2ecf20Sopenharmony_ci "ack received after xmission of master code", 1918c2ecf20Sopenharmony_ci "master lost arbitration", 1928c2ecf20Sopenharmony_ci "slave restarts", 1938c2ecf20Sopenharmony_ci "slave reset", 1948c2ecf20Sopenharmony_ci "overflow, maxsize is 2047 bytes", 1958c2ecf20Sopenharmony_ci}; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic inline void i2c_set_bit(void __iomem *reg, u32 mask) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci writel(readl(reg) | mask, reg); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic inline void i2c_clr_bit(void __iomem *reg, u32 mask) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci writel(readl(reg) & ~mask, reg); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/** 2088c2ecf20Sopenharmony_ci * flush_i2c_fifo() - This function flushes the I2C FIFO 2098c2ecf20Sopenharmony_ci * @dev: private data of I2C Driver 2108c2ecf20Sopenharmony_ci * 2118c2ecf20Sopenharmony_ci * This function flushes the I2C Tx and Rx FIFOs. It returns 2128c2ecf20Sopenharmony_ci * 0 on successful flushing of FIFO 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_cistatic int flush_i2c_fifo(struct nmk_i2c_dev *dev) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci#define LOOP_ATTEMPTS 10 2178c2ecf20Sopenharmony_ci int i; 2188c2ecf20Sopenharmony_ci unsigned long timeout; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* 2218c2ecf20Sopenharmony_ci * flush the transmit and receive FIFO. The flushing 2228c2ecf20Sopenharmony_ci * operation takes several cycles before to be completed. 2238c2ecf20Sopenharmony_ci * On the completion, the I2C internal logic clears these 2248c2ecf20Sopenharmony_ci * bits, until then no one must access Tx, Rx FIFO and 2258c2ecf20Sopenharmony_ci * should poll on these bits waiting for the completion. 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ci writel((I2C_CR_FTX | I2C_CR_FRX), dev->virtbase + I2C_CR); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci for (i = 0; i < LOOP_ATTEMPTS; i++) { 2308c2ecf20Sopenharmony_ci timeout = jiffies + dev->adap.timeout; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci while (!time_after(jiffies, timeout)) { 2338c2ecf20Sopenharmony_ci if ((readl(dev->virtbase + I2C_CR) & 2348c2ecf20Sopenharmony_ci (I2C_CR_FTX | I2C_CR_FRX)) == 0) 2358c2ecf20Sopenharmony_ci return 0; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, 2408c2ecf20Sopenharmony_ci "flushing operation timed out giving up after %d attempts", 2418c2ecf20Sopenharmony_ci LOOP_ATTEMPTS); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return -ETIMEDOUT; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/** 2478c2ecf20Sopenharmony_ci * disable_all_interrupts() - Disable all interrupts of this I2c Bus 2488c2ecf20Sopenharmony_ci * @dev: private data of I2C Driver 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_cistatic void disable_all_interrupts(struct nmk_i2c_dev *dev) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci u32 mask = IRQ_MASK(0); 2538c2ecf20Sopenharmony_ci writel(mask, dev->virtbase + I2C_IMSCR); 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/** 2578c2ecf20Sopenharmony_ci * clear_all_interrupts() - Clear all interrupts of I2C Controller 2588c2ecf20Sopenharmony_ci * @dev: private data of I2C Driver 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_cistatic void clear_all_interrupts(struct nmk_i2c_dev *dev) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci u32 mask; 2638c2ecf20Sopenharmony_ci mask = IRQ_MASK(I2C_CLEAR_ALL_INTS); 2648c2ecf20Sopenharmony_ci writel(mask, dev->virtbase + I2C_ICR); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/** 2688c2ecf20Sopenharmony_ci * init_hw() - initialize the I2C hardware 2698c2ecf20Sopenharmony_ci * @dev: private data of I2C Driver 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_cistatic int init_hw(struct nmk_i2c_dev *dev) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci int stat; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci stat = flush_i2c_fifo(dev); 2768c2ecf20Sopenharmony_ci if (stat) 2778c2ecf20Sopenharmony_ci goto exit; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* disable the controller */ 2808c2ecf20Sopenharmony_ci i2c_clr_bit(dev->virtbase + I2C_CR , I2C_CR_PE); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci disable_all_interrupts(dev); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci clear_all_interrupts(dev); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci dev->cli.operation = I2C_NO_OPERATION; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ciexit: 2898c2ecf20Sopenharmony_ci return stat; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/* enable peripheral, master mode operation */ 2938c2ecf20Sopenharmony_ci#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE) 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci/** 2968c2ecf20Sopenharmony_ci * load_i2c_mcr_reg() - load the MCR register 2978c2ecf20Sopenharmony_ci * @dev: private data of controller 2988c2ecf20Sopenharmony_ci * @flags: message flags 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_cistatic u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev, u16 flags) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci u32 mcr = 0; 3038c2ecf20Sopenharmony_ci unsigned short slave_adr_3msb_bits; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (unlikely(flags & I2C_M_TEN)) { 3088c2ecf20Sopenharmony_ci /* 10-bit address transaction */ 3098c2ecf20Sopenharmony_ci mcr |= GEN_MASK(2, I2C_MCR_AM, 12); 3108c2ecf20Sopenharmony_ci /* 3118c2ecf20Sopenharmony_ci * Get the top 3 bits. 3128c2ecf20Sopenharmony_ci * EA10 represents extended address in MCR. This includes 3138c2ecf20Sopenharmony_ci * the extension (MSB bits) of the 7 bit address loaded 3148c2ecf20Sopenharmony_ci * in A7 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci slave_adr_3msb_bits = (dev->cli.slave_adr >> 7) & 0x7; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci mcr |= GEN_MASK(slave_adr_3msb_bits, I2C_MCR_EA10, 8); 3198c2ecf20Sopenharmony_ci } else { 3208c2ecf20Sopenharmony_ci /* 7-bit address transaction */ 3218c2ecf20Sopenharmony_ci mcr |= GEN_MASK(1, I2C_MCR_AM, 12); 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* start byte procedure not applied */ 3258c2ecf20Sopenharmony_ci mcr |= GEN_MASK(0, I2C_MCR_SB, 11); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* check the operation, master read/write? */ 3288c2ecf20Sopenharmony_ci if (dev->cli.operation == I2C_WRITE) 3298c2ecf20Sopenharmony_ci mcr |= GEN_MASK(I2C_WRITE, I2C_MCR_OP, 0); 3308c2ecf20Sopenharmony_ci else 3318c2ecf20Sopenharmony_ci mcr |= GEN_MASK(I2C_READ, I2C_MCR_OP, 0); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* stop or repeated start? */ 3348c2ecf20Sopenharmony_ci if (dev->stop) 3358c2ecf20Sopenharmony_ci mcr |= GEN_MASK(1, I2C_MCR_STOP, 14); 3368c2ecf20Sopenharmony_ci else 3378c2ecf20Sopenharmony_ci mcr &= ~(GEN_MASK(1, I2C_MCR_STOP, 14)); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci mcr |= GEN_MASK(dev->cli.count, I2C_MCR_LENGTH, 15); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci return mcr; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/** 3458c2ecf20Sopenharmony_ci * setup_i2c_controller() - setup the controller 3468c2ecf20Sopenharmony_ci * @dev: private data of controller 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_cistatic void setup_i2c_controller(struct nmk_i2c_dev *dev) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci u32 brcr1, brcr2; 3518c2ecf20Sopenharmony_ci u32 i2c_clk, div; 3528c2ecf20Sopenharmony_ci u32 ns; 3538c2ecf20Sopenharmony_ci u16 slsu; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci writel(0x0, dev->virtbase + I2C_CR); 3568c2ecf20Sopenharmony_ci writel(0x0, dev->virtbase + I2C_HSMCR); 3578c2ecf20Sopenharmony_ci writel(0x0, dev->virtbase + I2C_TFTR); 3588c2ecf20Sopenharmony_ci writel(0x0, dev->virtbase + I2C_RFTR); 3598c2ecf20Sopenharmony_ci writel(0x0, dev->virtbase + I2C_DMAR); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci i2c_clk = clk_get_rate(dev->clk); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* 3648c2ecf20Sopenharmony_ci * set the slsu: 3658c2ecf20Sopenharmony_ci * 3668c2ecf20Sopenharmony_ci * slsu defines the data setup time after SCL clock 3678c2ecf20Sopenharmony_ci * stretching in terms of i2c clk cycles + 1 (zero means 3688c2ecf20Sopenharmony_ci * "wait one cycle"), the needed setup time for the three 3698c2ecf20Sopenharmony_ci * modes are 250ns, 100ns, 10ns respectively. 3708c2ecf20Sopenharmony_ci * 3718c2ecf20Sopenharmony_ci * As the time for one cycle T in nanoseconds is 3728c2ecf20Sopenharmony_ci * T = (1/f) * 1000000000 => 3738c2ecf20Sopenharmony_ci * slsu = cycles / (1000000000 / f) + 1 3748c2ecf20Sopenharmony_ci */ 3758c2ecf20Sopenharmony_ci ns = DIV_ROUND_UP_ULL(1000000000ULL, i2c_clk); 3768c2ecf20Sopenharmony_ci switch (dev->sm) { 3778c2ecf20Sopenharmony_ci case I2C_FREQ_MODE_FAST: 3788c2ecf20Sopenharmony_ci case I2C_FREQ_MODE_FAST_PLUS: 3798c2ecf20Sopenharmony_ci slsu = DIV_ROUND_UP(100, ns); /* Fast */ 3808c2ecf20Sopenharmony_ci break; 3818c2ecf20Sopenharmony_ci case I2C_FREQ_MODE_HIGH_SPEED: 3828c2ecf20Sopenharmony_ci slsu = DIV_ROUND_UP(10, ns); /* High */ 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci case I2C_FREQ_MODE_STANDARD: 3858c2ecf20Sopenharmony_ci default: 3868c2ecf20Sopenharmony_ci slsu = DIV_ROUND_UP(250, ns); /* Standard */ 3878c2ecf20Sopenharmony_ci break; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci slsu += 1; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci dev_dbg(&dev->adev->dev, "calculated SLSU = %04x\n", slsu); 3928c2ecf20Sopenharmony_ci writel(slsu << 16, dev->virtbase + I2C_SCR); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* 3958c2ecf20Sopenharmony_ci * The spec says, in case of std. mode the divider is 3968c2ecf20Sopenharmony_ci * 2 whereas it is 3 for fast and fastplus mode of 3978c2ecf20Sopenharmony_ci * operation. TODO - high speed support. 3988c2ecf20Sopenharmony_ci */ 3998c2ecf20Sopenharmony_ci div = (dev->clk_freq > I2C_MAX_STANDARD_MODE_FREQ) ? 3 : 2; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* 4028c2ecf20Sopenharmony_ci * generate the mask for baud rate counters. The controller 4038c2ecf20Sopenharmony_ci * has two baud rate counters. One is used for High speed 4048c2ecf20Sopenharmony_ci * operation, and the other is for std, fast mode, fast mode 4058c2ecf20Sopenharmony_ci * plus operation. Currently we do not supprt high speed mode 4068c2ecf20Sopenharmony_ci * so set brcr1 to 0. 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci brcr1 = 0 << 16; 4098c2ecf20Sopenharmony_ci brcr2 = (i2c_clk/(dev->clk_freq * div)) & 0xffff; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* set the baud rate counter register */ 4128c2ecf20Sopenharmony_ci writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* 4158c2ecf20Sopenharmony_ci * set the speed mode. Currently we support 4168c2ecf20Sopenharmony_ci * only standard and fast mode of operation 4178c2ecf20Sopenharmony_ci * TODO - support for fast mode plus (up to 1Mb/s) 4188c2ecf20Sopenharmony_ci * and high speed (up to 3.4 Mb/s) 4198c2ecf20Sopenharmony_ci */ 4208c2ecf20Sopenharmony_ci if (dev->sm > I2C_FREQ_MODE_FAST) { 4218c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, 4228c2ecf20Sopenharmony_ci "do not support this mode defaulting to std. mode\n"); 4238c2ecf20Sopenharmony_ci brcr2 = i2c_clk / (I2C_MAX_STANDARD_MODE_FREQ * 2) & 0xffff; 4248c2ecf20Sopenharmony_ci writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); 4258c2ecf20Sopenharmony_ci writel(I2C_FREQ_MODE_STANDARD << 4, 4268c2ecf20Sopenharmony_ci dev->virtbase + I2C_CR); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci writel(dev->sm << 4, dev->virtbase + I2C_CR); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci /* set the Tx and Rx FIFO threshold */ 4318c2ecf20Sopenharmony_ci writel(dev->tft, dev->virtbase + I2C_TFTR); 4328c2ecf20Sopenharmony_ci writel(dev->rft, dev->virtbase + I2C_RFTR); 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/** 4368c2ecf20Sopenharmony_ci * read_i2c() - Read from I2C client device 4378c2ecf20Sopenharmony_ci * @dev: private data of I2C Driver 4388c2ecf20Sopenharmony_ci * @flags: message flags 4398c2ecf20Sopenharmony_ci * 4408c2ecf20Sopenharmony_ci * This function reads from i2c client device when controller is in 4418c2ecf20Sopenharmony_ci * master mode. There is a completion timeout. If there is no transfer 4428c2ecf20Sopenharmony_ci * before timeout error is returned. 4438c2ecf20Sopenharmony_ci */ 4448c2ecf20Sopenharmony_cistatic int read_i2c(struct nmk_i2c_dev *dev, u16 flags) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci int status = 0; 4478c2ecf20Sopenharmony_ci u32 mcr, irq_mask; 4488c2ecf20Sopenharmony_ci unsigned long timeout; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci mcr = load_i2c_mcr_reg(dev, flags); 4518c2ecf20Sopenharmony_ci writel(mcr, dev->virtbase + I2C_MCR); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* load the current CR value */ 4548c2ecf20Sopenharmony_ci writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR, 4558c2ecf20Sopenharmony_ci dev->virtbase + I2C_CR); 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* enable the controller */ 4588c2ecf20Sopenharmony_ci i2c_set_bit(dev->virtbase + I2C_CR, I2C_CR_PE); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci init_completion(&dev->xfer_complete); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* enable interrupts by setting the mask */ 4638c2ecf20Sopenharmony_ci irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF | 4648c2ecf20Sopenharmony_ci I2C_IT_MAL | I2C_IT_BERR); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if (dev->stop || !dev->vendor->has_mtdws) 4678c2ecf20Sopenharmony_ci irq_mask |= I2C_IT_MTD; 4688c2ecf20Sopenharmony_ci else 4698c2ecf20Sopenharmony_ci irq_mask |= I2C_IT_MTDWS; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask); 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask, 4748c2ecf20Sopenharmony_ci dev->virtbase + I2C_IMSCR); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci timeout = wait_for_completion_timeout( 4778c2ecf20Sopenharmony_ci &dev->xfer_complete, dev->adap.timeout); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (timeout == 0) { 4808c2ecf20Sopenharmony_ci /* Controller timed out */ 4818c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n", 4828c2ecf20Sopenharmony_ci dev->cli.slave_adr); 4838c2ecf20Sopenharmony_ci status = -ETIMEDOUT; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci return status; 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic void fill_tx_fifo(struct nmk_i2c_dev *dev, int no_bytes) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci int count; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci for (count = (no_bytes - 2); 4938c2ecf20Sopenharmony_ci (count > 0) && 4948c2ecf20Sopenharmony_ci (dev->cli.count != 0); 4958c2ecf20Sopenharmony_ci count--) { 4968c2ecf20Sopenharmony_ci /* write to the Tx FIFO */ 4978c2ecf20Sopenharmony_ci writeb(*dev->cli.buffer, 4988c2ecf20Sopenharmony_ci dev->virtbase + I2C_TFR); 4998c2ecf20Sopenharmony_ci dev->cli.buffer++; 5008c2ecf20Sopenharmony_ci dev->cli.count--; 5018c2ecf20Sopenharmony_ci dev->cli.xfer_bytes++; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci/** 5078c2ecf20Sopenharmony_ci * write_i2c() - Write data to I2C client. 5088c2ecf20Sopenharmony_ci * @dev: private data of I2C Driver 5098c2ecf20Sopenharmony_ci * @flags: message flags 5108c2ecf20Sopenharmony_ci * 5118c2ecf20Sopenharmony_ci * This function writes data to I2C client 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_cistatic int write_i2c(struct nmk_i2c_dev *dev, u16 flags) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci u32 status = 0; 5168c2ecf20Sopenharmony_ci u32 mcr, irq_mask; 5178c2ecf20Sopenharmony_ci unsigned long timeout; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci mcr = load_i2c_mcr_reg(dev, flags); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci writel(mcr, dev->virtbase + I2C_MCR); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* load the current CR value */ 5248c2ecf20Sopenharmony_ci writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR, 5258c2ecf20Sopenharmony_ci dev->virtbase + I2C_CR); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* enable the controller */ 5288c2ecf20Sopenharmony_ci i2c_set_bit(dev->virtbase + I2C_CR , I2C_CR_PE); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci init_completion(&dev->xfer_complete); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* enable interrupts by settings the masks */ 5338c2ecf20Sopenharmony_ci irq_mask = (I2C_IT_TXFOVR | I2C_IT_MAL | I2C_IT_BERR); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Fill the TX FIFO with transmit data */ 5368c2ecf20Sopenharmony_ci fill_tx_fifo(dev, MAX_I2C_FIFO_THRESHOLD); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if (dev->cli.count != 0) 5398c2ecf20Sopenharmony_ci irq_mask |= I2C_IT_TXFNE; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* 5428c2ecf20Sopenharmony_ci * check if we want to transfer a single or multiple bytes, if so 5438c2ecf20Sopenharmony_ci * set the MTDWS bit (Master Transaction Done Without Stop) 5448c2ecf20Sopenharmony_ci * to start repeated start operation 5458c2ecf20Sopenharmony_ci */ 5468c2ecf20Sopenharmony_ci if (dev->stop || !dev->vendor->has_mtdws) 5478c2ecf20Sopenharmony_ci irq_mask |= I2C_IT_MTD; 5488c2ecf20Sopenharmony_ci else 5498c2ecf20Sopenharmony_ci irq_mask |= I2C_IT_MTDWS; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask, 5548c2ecf20Sopenharmony_ci dev->virtbase + I2C_IMSCR); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci timeout = wait_for_completion_timeout( 5578c2ecf20Sopenharmony_ci &dev->xfer_complete, dev->adap.timeout); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci if (timeout == 0) { 5608c2ecf20Sopenharmony_ci /* Controller timed out */ 5618c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n", 5628c2ecf20Sopenharmony_ci dev->cli.slave_adr); 5638c2ecf20Sopenharmony_ci status = -ETIMEDOUT; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci return status; 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci/** 5708c2ecf20Sopenharmony_ci * nmk_i2c_xfer_one() - transmit a single I2C message 5718c2ecf20Sopenharmony_ci * @dev: device with a message encoded into it 5728c2ecf20Sopenharmony_ci * @flags: message flags 5738c2ecf20Sopenharmony_ci */ 5748c2ecf20Sopenharmony_cistatic int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci int status; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci if (flags & I2C_M_RD) { 5798c2ecf20Sopenharmony_ci /* read operation */ 5808c2ecf20Sopenharmony_ci dev->cli.operation = I2C_READ; 5818c2ecf20Sopenharmony_ci status = read_i2c(dev, flags); 5828c2ecf20Sopenharmony_ci } else { 5838c2ecf20Sopenharmony_ci /* write operation */ 5848c2ecf20Sopenharmony_ci dev->cli.operation = I2C_WRITE; 5858c2ecf20Sopenharmony_ci status = write_i2c(dev, flags); 5868c2ecf20Sopenharmony_ci } 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci if (status || (dev->result)) { 5898c2ecf20Sopenharmony_ci u32 i2c_sr; 5908c2ecf20Sopenharmony_ci u32 cause; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci i2c_sr = readl(dev->virtbase + I2C_SR); 5938c2ecf20Sopenharmony_ci /* 5948c2ecf20Sopenharmony_ci * Check if the controller I2C operation status 5958c2ecf20Sopenharmony_ci * is set to ABORT(11b). 5968c2ecf20Sopenharmony_ci */ 5978c2ecf20Sopenharmony_ci if (((i2c_sr >> 2) & 0x3) == 0x3) { 5988c2ecf20Sopenharmony_ci /* get the abort cause */ 5998c2ecf20Sopenharmony_ci cause = (i2c_sr >> 4) & 0x7; 6008c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, "%s\n", 6018c2ecf20Sopenharmony_ci cause >= ARRAY_SIZE(abort_causes) ? 6028c2ecf20Sopenharmony_ci "unknown reason" : 6038c2ecf20Sopenharmony_ci abort_causes[cause]); 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci (void) init_hw(dev); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci status = status ? status : dev->result; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci return status; 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci/** 6158c2ecf20Sopenharmony_ci * nmk_i2c_xfer() - I2C transfer function used by kernel framework 6168c2ecf20Sopenharmony_ci * @i2c_adap: Adapter pointer to the controller 6178c2ecf20Sopenharmony_ci * @msgs: Pointer to data to be written. 6188c2ecf20Sopenharmony_ci * @num_msgs: Number of messages to be executed 6198c2ecf20Sopenharmony_ci * 6208c2ecf20Sopenharmony_ci * This is the function called by the generic kernel i2c_transfer() 6218c2ecf20Sopenharmony_ci * or i2c_smbus...() API calls. Note that this code is protected by the 6228c2ecf20Sopenharmony_ci * semaphore set in the kernel i2c_transfer() function. 6238c2ecf20Sopenharmony_ci * 6248c2ecf20Sopenharmony_ci * NOTE: 6258c2ecf20Sopenharmony_ci * READ TRANSFER : We impose a restriction of the first message to be the 6268c2ecf20Sopenharmony_ci * index message for any read transaction. 6278c2ecf20Sopenharmony_ci * - a no index is coded as '0', 6288c2ecf20Sopenharmony_ci * - 2byte big endian index is coded as '3' 6298c2ecf20Sopenharmony_ci * !!! msg[0].buf holds the actual index. 6308c2ecf20Sopenharmony_ci * This is compatible with generic messages of smbus emulator 6318c2ecf20Sopenharmony_ci * that send a one byte index. 6328c2ecf20Sopenharmony_ci * eg. a I2C transation to read 2 bytes from index 0 6338c2ecf20Sopenharmony_ci * idx = 0; 6348c2ecf20Sopenharmony_ci * msg[0].addr = client->addr; 6358c2ecf20Sopenharmony_ci * msg[0].flags = 0x0; 6368c2ecf20Sopenharmony_ci * msg[0].len = 1; 6378c2ecf20Sopenharmony_ci * msg[0].buf = &idx; 6388c2ecf20Sopenharmony_ci * 6398c2ecf20Sopenharmony_ci * msg[1].addr = client->addr; 6408c2ecf20Sopenharmony_ci * msg[1].flags = I2C_M_RD; 6418c2ecf20Sopenharmony_ci * msg[1].len = 2; 6428c2ecf20Sopenharmony_ci * msg[1].buf = rd_buff 6438c2ecf20Sopenharmony_ci * i2c_transfer(adap, msg, 2); 6448c2ecf20Sopenharmony_ci * 6458c2ecf20Sopenharmony_ci * WRITE TRANSFER : The I2C standard interface interprets all data as payload. 6468c2ecf20Sopenharmony_ci * If you want to emulate an SMBUS write transaction put the 6478c2ecf20Sopenharmony_ci * index as first byte(or first and second) in the payload. 6488c2ecf20Sopenharmony_ci * eg. a I2C transation to write 2 bytes from index 1 6498c2ecf20Sopenharmony_ci * wr_buff[0] = 0x1; 6508c2ecf20Sopenharmony_ci * wr_buff[1] = 0x23; 6518c2ecf20Sopenharmony_ci * wr_buff[2] = 0x46; 6528c2ecf20Sopenharmony_ci * msg[0].flags = 0x0; 6538c2ecf20Sopenharmony_ci * msg[0].len = 3; 6548c2ecf20Sopenharmony_ci * msg[0].buf = wr_buff; 6558c2ecf20Sopenharmony_ci * i2c_transfer(adap, msg, 1); 6568c2ecf20Sopenharmony_ci * 6578c2ecf20Sopenharmony_ci * To read or write a block of data (multiple bytes) using SMBUS emulation 6588c2ecf20Sopenharmony_ci * please use the i2c_smbus_read_i2c_block_data() 6598c2ecf20Sopenharmony_ci * or i2c_smbus_write_i2c_block_data() API 6608c2ecf20Sopenharmony_ci */ 6618c2ecf20Sopenharmony_cistatic int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, 6628c2ecf20Sopenharmony_ci struct i2c_msg msgs[], int num_msgs) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci int status = 0; 6658c2ecf20Sopenharmony_ci int i; 6668c2ecf20Sopenharmony_ci struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); 6678c2ecf20Sopenharmony_ci int j; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci pm_runtime_get_sync(&dev->adev->dev); 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* Attempt three times to send the message queue */ 6728c2ecf20Sopenharmony_ci for (j = 0; j < 3; j++) { 6738c2ecf20Sopenharmony_ci /* setup the i2c controller */ 6748c2ecf20Sopenharmony_ci setup_i2c_controller(dev); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci for (i = 0; i < num_msgs; i++) { 6778c2ecf20Sopenharmony_ci dev->cli.slave_adr = msgs[i].addr; 6788c2ecf20Sopenharmony_ci dev->cli.buffer = msgs[i].buf; 6798c2ecf20Sopenharmony_ci dev->cli.count = msgs[i].len; 6808c2ecf20Sopenharmony_ci dev->stop = (i < (num_msgs - 1)) ? 0 : 1; 6818c2ecf20Sopenharmony_ci dev->result = 0; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci status = nmk_i2c_xfer_one(dev, msgs[i].flags); 6848c2ecf20Sopenharmony_ci if (status != 0) 6858c2ecf20Sopenharmony_ci break; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci if (status == 0) 6888c2ecf20Sopenharmony_ci break; 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci pm_runtime_put_sync(&dev->adev->dev); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* return the no. messages processed */ 6948c2ecf20Sopenharmony_ci if (status) 6958c2ecf20Sopenharmony_ci return status; 6968c2ecf20Sopenharmony_ci else 6978c2ecf20Sopenharmony_ci return num_msgs; 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci/** 7018c2ecf20Sopenharmony_ci * disable_interrupts() - disable the interrupts 7028c2ecf20Sopenharmony_ci * @dev: private data of controller 7038c2ecf20Sopenharmony_ci * @irq: interrupt number 7048c2ecf20Sopenharmony_ci */ 7058c2ecf20Sopenharmony_cistatic int disable_interrupts(struct nmk_i2c_dev *dev, u32 irq) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci irq = IRQ_MASK(irq); 7088c2ecf20Sopenharmony_ci writel(readl(dev->virtbase + I2C_IMSCR) & ~(I2C_CLEAR_ALL_INTS & irq), 7098c2ecf20Sopenharmony_ci dev->virtbase + I2C_IMSCR); 7108c2ecf20Sopenharmony_ci return 0; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci/** 7148c2ecf20Sopenharmony_ci * i2c_irq_handler() - interrupt routine 7158c2ecf20Sopenharmony_ci * @irq: interrupt number 7168c2ecf20Sopenharmony_ci * @arg: data passed to the handler 7178c2ecf20Sopenharmony_ci * 7188c2ecf20Sopenharmony_ci * This is the interrupt handler for the i2c driver. Currently 7198c2ecf20Sopenharmony_ci * it handles the major interrupts like Rx & Tx FIFO management 7208c2ecf20Sopenharmony_ci * interrupts, master transaction interrupts, arbitration and 7218c2ecf20Sopenharmony_ci * bus error interrupts. The rest of the interrupts are treated as 7228c2ecf20Sopenharmony_ci * unhandled. 7238c2ecf20Sopenharmony_ci */ 7248c2ecf20Sopenharmony_cistatic irqreturn_t i2c_irq_handler(int irq, void *arg) 7258c2ecf20Sopenharmony_ci{ 7268c2ecf20Sopenharmony_ci struct nmk_i2c_dev *dev = arg; 7278c2ecf20Sopenharmony_ci u32 tft, rft; 7288c2ecf20Sopenharmony_ci u32 count; 7298c2ecf20Sopenharmony_ci u32 misr, src; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci /* load Tx FIFO and Rx FIFO threshold values */ 7328c2ecf20Sopenharmony_ci tft = readl(dev->virtbase + I2C_TFTR); 7338c2ecf20Sopenharmony_ci rft = readl(dev->virtbase + I2C_RFTR); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci /* read interrupt status register */ 7368c2ecf20Sopenharmony_ci misr = readl(dev->virtbase + I2C_MISR); 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci src = __ffs(misr); 7398c2ecf20Sopenharmony_ci switch ((1 << src)) { 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci /* Transmit FIFO nearly empty interrupt */ 7428c2ecf20Sopenharmony_ci case I2C_IT_TXFNE: 7438c2ecf20Sopenharmony_ci { 7448c2ecf20Sopenharmony_ci if (dev->cli.operation == I2C_READ) { 7458c2ecf20Sopenharmony_ci /* 7468c2ecf20Sopenharmony_ci * in read operation why do we care for writing? 7478c2ecf20Sopenharmony_ci * so disable the Transmit FIFO interrupt 7488c2ecf20Sopenharmony_ci */ 7498c2ecf20Sopenharmony_ci disable_interrupts(dev, I2C_IT_TXFNE); 7508c2ecf20Sopenharmony_ci } else { 7518c2ecf20Sopenharmony_ci fill_tx_fifo(dev, (MAX_I2C_FIFO_THRESHOLD - tft)); 7528c2ecf20Sopenharmony_ci /* 7538c2ecf20Sopenharmony_ci * if done, close the transfer by disabling the 7548c2ecf20Sopenharmony_ci * corresponding TXFNE interrupt 7558c2ecf20Sopenharmony_ci */ 7568c2ecf20Sopenharmony_ci if (dev->cli.count == 0) 7578c2ecf20Sopenharmony_ci disable_interrupts(dev, I2C_IT_TXFNE); 7588c2ecf20Sopenharmony_ci } 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci break; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci /* 7638c2ecf20Sopenharmony_ci * Rx FIFO nearly full interrupt. 7648c2ecf20Sopenharmony_ci * This is set when the numer of entries in Rx FIFO is 7658c2ecf20Sopenharmony_ci * greater or equal than the threshold value programmed 7668c2ecf20Sopenharmony_ci * in RFT 7678c2ecf20Sopenharmony_ci */ 7688c2ecf20Sopenharmony_ci case I2C_IT_RXFNF: 7698c2ecf20Sopenharmony_ci for (count = rft; count > 0; count--) { 7708c2ecf20Sopenharmony_ci /* Read the Rx FIFO */ 7718c2ecf20Sopenharmony_ci *dev->cli.buffer = readb(dev->virtbase + I2C_RFR); 7728c2ecf20Sopenharmony_ci dev->cli.buffer++; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci dev->cli.count -= rft; 7758c2ecf20Sopenharmony_ci dev->cli.xfer_bytes += rft; 7768c2ecf20Sopenharmony_ci break; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci /* Rx FIFO full */ 7798c2ecf20Sopenharmony_ci case I2C_IT_RXFF: 7808c2ecf20Sopenharmony_ci for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) { 7818c2ecf20Sopenharmony_ci *dev->cli.buffer = readb(dev->virtbase + I2C_RFR); 7828c2ecf20Sopenharmony_ci dev->cli.buffer++; 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci dev->cli.count -= MAX_I2C_FIFO_THRESHOLD; 7858c2ecf20Sopenharmony_ci dev->cli.xfer_bytes += MAX_I2C_FIFO_THRESHOLD; 7868c2ecf20Sopenharmony_ci break; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci /* Master Transaction Done with/without stop */ 7898c2ecf20Sopenharmony_ci case I2C_IT_MTD: 7908c2ecf20Sopenharmony_ci case I2C_IT_MTDWS: 7918c2ecf20Sopenharmony_ci if (dev->cli.operation == I2C_READ) { 7928c2ecf20Sopenharmony_ci while (!(readl(dev->virtbase + I2C_RISR) 7938c2ecf20Sopenharmony_ci & I2C_IT_RXFE)) { 7948c2ecf20Sopenharmony_ci if (dev->cli.count == 0) 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci *dev->cli.buffer = 7978c2ecf20Sopenharmony_ci readb(dev->virtbase + I2C_RFR); 7988c2ecf20Sopenharmony_ci dev->cli.buffer++; 7998c2ecf20Sopenharmony_ci dev->cli.count--; 8008c2ecf20Sopenharmony_ci dev->cli.xfer_bytes++; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci disable_all_interrupts(dev); 8058c2ecf20Sopenharmony_ci clear_all_interrupts(dev); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (dev->cli.count) { 8088c2ecf20Sopenharmony_ci dev->result = -EIO; 8098c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, 8108c2ecf20Sopenharmony_ci "%lu bytes still remain to be xfered\n", 8118c2ecf20Sopenharmony_ci dev->cli.count); 8128c2ecf20Sopenharmony_ci (void) init_hw(dev); 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci complete(&dev->xfer_complete); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci break; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci /* Master Arbitration lost interrupt */ 8198c2ecf20Sopenharmony_ci case I2C_IT_MAL: 8208c2ecf20Sopenharmony_ci dev->result = -EIO; 8218c2ecf20Sopenharmony_ci (void) init_hw(dev); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MAL); 8248c2ecf20Sopenharmony_ci complete(&dev->xfer_complete); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci break; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci /* 8298c2ecf20Sopenharmony_ci * Bus Error interrupt. 8308c2ecf20Sopenharmony_ci * This happens when an unexpected start/stop condition occurs 8318c2ecf20Sopenharmony_ci * during the transaction. 8328c2ecf20Sopenharmony_ci */ 8338c2ecf20Sopenharmony_ci case I2C_IT_BERR: 8348c2ecf20Sopenharmony_ci dev->result = -EIO; 8358c2ecf20Sopenharmony_ci /* get the status */ 8368c2ecf20Sopenharmony_ci if (((readl(dev->virtbase + I2C_SR) >> 2) & 0x3) == I2C_ABORT) 8378c2ecf20Sopenharmony_ci (void) init_hw(dev); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_BERR); 8408c2ecf20Sopenharmony_ci complete(&dev->xfer_complete); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci break; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci /* 8458c2ecf20Sopenharmony_ci * Tx FIFO overrun interrupt. 8468c2ecf20Sopenharmony_ci * This is set when a write operation in Tx FIFO is performed and 8478c2ecf20Sopenharmony_ci * the Tx FIFO is full. 8488c2ecf20Sopenharmony_ci */ 8498c2ecf20Sopenharmony_ci case I2C_IT_TXFOVR: 8508c2ecf20Sopenharmony_ci dev->result = -EIO; 8518c2ecf20Sopenharmony_ci (void) init_hw(dev); 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, "Tx Fifo Over run\n"); 8548c2ecf20Sopenharmony_ci complete(&dev->xfer_complete); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci break; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci /* unhandled interrupts by this driver - TODO*/ 8598c2ecf20Sopenharmony_ci case I2C_IT_TXFE: 8608c2ecf20Sopenharmony_ci case I2C_IT_TXFF: 8618c2ecf20Sopenharmony_ci case I2C_IT_RXFE: 8628c2ecf20Sopenharmony_ci case I2C_IT_RFSR: 8638c2ecf20Sopenharmony_ci case I2C_IT_RFSE: 8648c2ecf20Sopenharmony_ci case I2C_IT_WTSR: 8658c2ecf20Sopenharmony_ci case I2C_IT_STD: 8668c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, "unhandled Interrupt\n"); 8678c2ecf20Sopenharmony_ci break; 8688c2ecf20Sopenharmony_ci default: 8698c2ecf20Sopenharmony_ci dev_err(&dev->adev->dev, "spurious Interrupt..\n"); 8708c2ecf20Sopenharmony_ci break; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci return IRQ_HANDLED; 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 8778c2ecf20Sopenharmony_cistatic int nmk_i2c_suspend_late(struct device *dev) 8788c2ecf20Sopenharmony_ci{ 8798c2ecf20Sopenharmony_ci int ret; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci ret = pm_runtime_force_suspend(dev); 8828c2ecf20Sopenharmony_ci if (ret) 8838c2ecf20Sopenharmony_ci return ret; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci pinctrl_pm_select_sleep_state(dev); 8868c2ecf20Sopenharmony_ci return 0; 8878c2ecf20Sopenharmony_ci} 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_cistatic int nmk_i2c_resume_early(struct device *dev) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci return pm_runtime_force_resume(dev); 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci#endif 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 8968c2ecf20Sopenharmony_cistatic int nmk_i2c_runtime_suspend(struct device *dev) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci struct amba_device *adev = to_amba_device(dev); 8998c2ecf20Sopenharmony_ci struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci clk_disable_unprepare(nmk_i2c->clk); 9028c2ecf20Sopenharmony_ci pinctrl_pm_select_idle_state(dev); 9038c2ecf20Sopenharmony_ci return 0; 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic int nmk_i2c_runtime_resume(struct device *dev) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci struct amba_device *adev = to_amba_device(dev); 9098c2ecf20Sopenharmony_ci struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); 9108c2ecf20Sopenharmony_ci int ret; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci ret = clk_prepare_enable(nmk_i2c->clk); 9138c2ecf20Sopenharmony_ci if (ret) { 9148c2ecf20Sopenharmony_ci dev_err(dev, "can't prepare_enable clock\n"); 9158c2ecf20Sopenharmony_ci return ret; 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci pinctrl_pm_select_default_state(dev); 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci ret = init_hw(nmk_i2c); 9218c2ecf20Sopenharmony_ci if (ret) { 9228c2ecf20Sopenharmony_ci clk_disable_unprepare(nmk_i2c->clk); 9238c2ecf20Sopenharmony_ci pinctrl_pm_select_idle_state(dev); 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci return ret; 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ci#endif 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_cistatic const struct dev_pm_ops nmk_i2c_pm = { 9318c2ecf20Sopenharmony_ci SET_LATE_SYSTEM_SLEEP_PM_OPS(nmk_i2c_suspend_late, nmk_i2c_resume_early) 9328c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, 9338c2ecf20Sopenharmony_ci nmk_i2c_runtime_resume, 9348c2ecf20Sopenharmony_ci NULL) 9358c2ecf20Sopenharmony_ci}; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_cistatic unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic const struct i2c_algorithm nmk_i2c_algo = { 9438c2ecf20Sopenharmony_ci .master_xfer = nmk_i2c_xfer, 9448c2ecf20Sopenharmony_ci .functionality = nmk_i2c_functionality 9458c2ecf20Sopenharmony_ci}; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_cistatic void nmk_i2c_of_probe(struct device_node *np, 9488c2ecf20Sopenharmony_ci struct nmk_i2c_dev *nmk) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci /* Default to 100 kHz if no frequency is given in the node */ 9518c2ecf20Sopenharmony_ci if (of_property_read_u32(np, "clock-frequency", &nmk->clk_freq)) 9528c2ecf20Sopenharmony_ci nmk->clk_freq = I2C_MAX_STANDARD_MODE_FREQ; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* This driver only supports 'standard' and 'fast' modes of operation. */ 9558c2ecf20Sopenharmony_ci if (nmk->clk_freq <= I2C_MAX_STANDARD_MODE_FREQ) 9568c2ecf20Sopenharmony_ci nmk->sm = I2C_FREQ_MODE_STANDARD; 9578c2ecf20Sopenharmony_ci else 9588c2ecf20Sopenharmony_ci nmk->sm = I2C_FREQ_MODE_FAST; 9598c2ecf20Sopenharmony_ci nmk->tft = 1; /* Tx FIFO threshold */ 9608c2ecf20Sopenharmony_ci nmk->rft = 8; /* Rx FIFO threshold */ 9618c2ecf20Sopenharmony_ci nmk->timeout = 200; /* Slave response timeout(ms) */ 9628c2ecf20Sopenharmony_ci} 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_cistatic int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci int ret = 0; 9678c2ecf20Sopenharmony_ci struct device_node *np = adev->dev.of_node; 9688c2ecf20Sopenharmony_ci struct nmk_i2c_dev *dev; 9698c2ecf20Sopenharmony_ci struct i2c_adapter *adap; 9708c2ecf20Sopenharmony_ci struct i2c_vendor_data *vendor = id->data; 9718c2ecf20Sopenharmony_ci u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); 9748c2ecf20Sopenharmony_ci if (!dev) 9758c2ecf20Sopenharmony_ci return -ENOMEM; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci dev->vendor = vendor; 9788c2ecf20Sopenharmony_ci dev->adev = adev; 9798c2ecf20Sopenharmony_ci nmk_i2c_of_probe(np, dev); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if (dev->tft > max_fifo_threshold) { 9828c2ecf20Sopenharmony_ci dev_warn(&adev->dev, "requested TX FIFO threshold %u, adjusted down to %u\n", 9838c2ecf20Sopenharmony_ci dev->tft, max_fifo_threshold); 9848c2ecf20Sopenharmony_ci dev->tft = max_fifo_threshold; 9858c2ecf20Sopenharmony_ci } 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci if (dev->rft > max_fifo_threshold) { 9888c2ecf20Sopenharmony_ci dev_warn(&adev->dev, "requested RX FIFO threshold %u, adjusted down to %u\n", 9898c2ecf20Sopenharmony_ci dev->rft, max_fifo_threshold); 9908c2ecf20Sopenharmony_ci dev->rft = max_fifo_threshold; 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci amba_set_drvdata(adev, dev); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, 9968c2ecf20Sopenharmony_ci resource_size(&adev->res)); 9978c2ecf20Sopenharmony_ci if (!dev->virtbase) 9988c2ecf20Sopenharmony_ci return -ENOMEM; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci dev->irq = adev->irq[0]; 10018c2ecf20Sopenharmony_ci ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0, 10028c2ecf20Sopenharmony_ci DRIVER_NAME, dev); 10038c2ecf20Sopenharmony_ci if (ret) { 10048c2ecf20Sopenharmony_ci dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); 10058c2ecf20Sopenharmony_ci return ret; 10068c2ecf20Sopenharmony_ci } 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci dev->clk = devm_clk_get_enabled(&adev->dev, NULL); 10098c2ecf20Sopenharmony_ci if (IS_ERR(dev->clk)) { 10108c2ecf20Sopenharmony_ci dev_err(&adev->dev, "could enable i2c clock\n"); 10118c2ecf20Sopenharmony_ci return PTR_ERR(dev->clk); 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci init_hw(dev); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci adap = &dev->adap; 10178c2ecf20Sopenharmony_ci adap->dev.of_node = np; 10188c2ecf20Sopenharmony_ci adap->dev.parent = &adev->dev; 10198c2ecf20Sopenharmony_ci adap->owner = THIS_MODULE; 10208c2ecf20Sopenharmony_ci adap->class = I2C_CLASS_DEPRECATED; 10218c2ecf20Sopenharmony_ci adap->algo = &nmk_i2c_algo; 10228c2ecf20Sopenharmony_ci adap->timeout = msecs_to_jiffies(dev->timeout); 10238c2ecf20Sopenharmony_ci snprintf(adap->name, sizeof(adap->name), 10248c2ecf20Sopenharmony_ci "Nomadik I2C at %pR", &adev->res); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci i2c_set_adapdata(adap, dev); 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci dev_info(&adev->dev, 10298c2ecf20Sopenharmony_ci "initialize %s on virtual base %p\n", 10308c2ecf20Sopenharmony_ci adap->name, dev->virtbase); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci ret = i2c_add_adapter(adap); 10338c2ecf20Sopenharmony_ci if (ret) 10348c2ecf20Sopenharmony_ci return ret; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci pm_runtime_put(&adev->dev); 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci return 0; 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_cistatic void nmk_i2c_remove(struct amba_device *adev) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci struct nmk_i2c_dev *dev = amba_get_drvdata(adev); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci i2c_del_adapter(&dev->adap); 10468c2ecf20Sopenharmony_ci flush_i2c_fifo(dev); 10478c2ecf20Sopenharmony_ci disable_all_interrupts(dev); 10488c2ecf20Sopenharmony_ci clear_all_interrupts(dev); 10498c2ecf20Sopenharmony_ci /* disable the controller */ 10508c2ecf20Sopenharmony_ci i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); 10518c2ecf20Sopenharmony_ci} 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_cistatic struct i2c_vendor_data vendor_stn8815 = { 10548c2ecf20Sopenharmony_ci .has_mtdws = false, 10558c2ecf20Sopenharmony_ci .fifodepth = 16, /* Guessed from TFTR/RFTR = 7 */ 10568c2ecf20Sopenharmony_ci}; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic struct i2c_vendor_data vendor_db8500 = { 10598c2ecf20Sopenharmony_ci .has_mtdws = true, 10608c2ecf20Sopenharmony_ci .fifodepth = 32, /* Guessed from TFTR/RFTR = 15 */ 10618c2ecf20Sopenharmony_ci}; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_cistatic const struct amba_id nmk_i2c_ids[] = { 10648c2ecf20Sopenharmony_ci { 10658c2ecf20Sopenharmony_ci .id = 0x00180024, 10668c2ecf20Sopenharmony_ci .mask = 0x00ffffff, 10678c2ecf20Sopenharmony_ci .data = &vendor_stn8815, 10688c2ecf20Sopenharmony_ci }, 10698c2ecf20Sopenharmony_ci { 10708c2ecf20Sopenharmony_ci .id = 0x00380024, 10718c2ecf20Sopenharmony_ci .mask = 0x00ffffff, 10728c2ecf20Sopenharmony_ci .data = &vendor_db8500, 10738c2ecf20Sopenharmony_ci }, 10748c2ecf20Sopenharmony_ci {}, 10758c2ecf20Sopenharmony_ci}; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(amba, nmk_i2c_ids); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_cistatic struct amba_driver nmk_i2c_driver = { 10808c2ecf20Sopenharmony_ci .drv = { 10818c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 10828c2ecf20Sopenharmony_ci .name = DRIVER_NAME, 10838c2ecf20Sopenharmony_ci .pm = &nmk_i2c_pm, 10848c2ecf20Sopenharmony_ci }, 10858c2ecf20Sopenharmony_ci .id_table = nmk_i2c_ids, 10868c2ecf20Sopenharmony_ci .probe = nmk_i2c_probe, 10878c2ecf20Sopenharmony_ci .remove = nmk_i2c_remove, 10888c2ecf20Sopenharmony_ci}; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistatic int __init nmk_i2c_init(void) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci return amba_driver_register(&nmk_i2c_driver); 10938c2ecf20Sopenharmony_ci} 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistatic void __exit nmk_i2c_exit(void) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci amba_driver_unregister(&nmk_i2c_driver); 10988c2ecf20Sopenharmony_ci} 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_cisubsys_initcall(nmk_i2c_init); 11018c2ecf20Sopenharmony_cimodule_exit(nmk_i2c_exit); 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sachin Verma"); 11048c2ecf20Sopenharmony_ciMODULE_AUTHOR("Srinidhi KASAGAR"); 11058c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); 11068c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1107