16bec23bfSVadim Pasternak /* 26bec23bfSVadim Pasternak * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 36bec23bfSVadim Pasternak * Copyright (c) 2016 Michael Shych <michaels@mellanox.com> 46bec23bfSVadim Pasternak * 56bec23bfSVadim Pasternak * Redistribution and use in source and binary forms, with or without 66bec23bfSVadim Pasternak * modification, are permitted provided that the following conditions are met: 76bec23bfSVadim Pasternak * 86bec23bfSVadim Pasternak * 1. Redistributions of source code must retain the above copyright 96bec23bfSVadim Pasternak * notice, this list of conditions and the following disclaimer. 106bec23bfSVadim Pasternak * 2. Redistributions in binary form must reproduce the above copyright 116bec23bfSVadim Pasternak * notice, this list of conditions and the following disclaimer in the 126bec23bfSVadim Pasternak * documentation and/or other materials provided with the distribution. 136bec23bfSVadim Pasternak * 3. Neither the names of the copyright holders nor the names of its 146bec23bfSVadim Pasternak * contributors may be used to endorse or promote products derived from 156bec23bfSVadim Pasternak * this software without specific prior written permission. 166bec23bfSVadim Pasternak * 176bec23bfSVadim Pasternak * Alternatively, this software may be distributed under the terms of the 186bec23bfSVadim Pasternak * GNU General Public License ("GPL") version 2 as published by the Free 196bec23bfSVadim Pasternak * Software Foundation. 206bec23bfSVadim Pasternak * 216bec23bfSVadim Pasternak * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 226bec23bfSVadim Pasternak * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 236bec23bfSVadim Pasternak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 246bec23bfSVadim Pasternak * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 256bec23bfSVadim Pasternak * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 266bec23bfSVadim Pasternak * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 276bec23bfSVadim Pasternak * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 286bec23bfSVadim Pasternak * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 296bec23bfSVadim Pasternak * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 306bec23bfSVadim Pasternak * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 316bec23bfSVadim Pasternak * POSSIBILITY OF SUCH DAMAGE. 326bec23bfSVadim Pasternak */ 336bec23bfSVadim Pasternak 346bec23bfSVadim Pasternak #include <linux/delay.h> 356bec23bfSVadim Pasternak #include <linux/i2c.h> 366bec23bfSVadim Pasternak #include <linux/init.h> 376bec23bfSVadim Pasternak #include <linux/io.h> 386bec23bfSVadim Pasternak #include <linux/kernel.h> 396bec23bfSVadim Pasternak #include <linux/module.h> 406bec23bfSVadim Pasternak #include <linux/platform_device.h> 416bec23bfSVadim Pasternak 426bec23bfSVadim Pasternak /* General defines */ 436bec23bfSVadim Pasternak #define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR 0x2000 446bec23bfSVadim Pasternak #define MLXCPLD_I2C_DEVICE_NAME "i2c_mlxcpld" 456bec23bfSVadim Pasternak #define MLXCPLD_I2C_VALID_FLAG (I2C_M_RECV_LEN | I2C_M_RD) 466bec23bfSVadim Pasternak #define MLXCPLD_I2C_BUS_NUM 1 476bec23bfSVadim Pasternak #define MLXCPLD_I2C_DATA_REG_SZ 36 48313ce648SMichael Shych #define MLXCPLD_I2C_DATA_SZ_BIT BIT(5) 49313ce648SMichael Shych #define MLXCPLD_I2C_DATA_SZ_MASK GENMASK(6, 5) 50c9bfdc7cSMichael Shych #define MLXCPLD_I2C_SMBUS_BLK_BIT BIT(7) 516bec23bfSVadim Pasternak #define MLXCPLD_I2C_MAX_ADDR_LEN 4 526bec23bfSVadim Pasternak #define MLXCPLD_I2C_RETR_NUM 2 536bec23bfSVadim Pasternak #define MLXCPLD_I2C_XFER_TO 500000 /* usec */ 546bec23bfSVadim Pasternak #define MLXCPLD_I2C_POLL_TIME 2000 /* usec */ 556bec23bfSVadim Pasternak 566bec23bfSVadim Pasternak /* LPC I2C registers */ 57313ce648SMichael Shych #define MLXCPLD_LPCI2C_CPBLTY_REG 0x0 586bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_CTRL_REG 0x1 596bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_HALF_CYC_REG 0x4 606bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_I2C_HOLD_REG 0x5 616bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_CMD_REG 0x6 626bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_NUM_DAT_REG 0x7 636bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_NUM_ADDR_REG 0x8 646bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_STATUS_REG 0x9 656bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_DATA_REG 0xa 666bec23bfSVadim Pasternak 676bec23bfSVadim Pasternak /* LPC I2C masks and parametres */ 686bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_RST_SEL_MASK 0x1 696bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_TRANS_END 0x1 706bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_STATUS_NACK 0x10 716bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_NO_IND 0 726bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_ACK_IND 1 736bec23bfSVadim Pasternak #define MLXCPLD_LPCI2C_NACK_IND 2 746bec23bfSVadim Pasternak 756bec23bfSVadim Pasternak struct mlxcpld_i2c_curr_xfer { 766bec23bfSVadim Pasternak u8 cmd; 776bec23bfSVadim Pasternak u8 addr_width; 786bec23bfSVadim Pasternak u8 data_len; 796bec23bfSVadim Pasternak u8 msg_num; 806bec23bfSVadim Pasternak struct i2c_msg *msg; 816bec23bfSVadim Pasternak }; 826bec23bfSVadim Pasternak 836bec23bfSVadim Pasternak struct mlxcpld_i2c_priv { 846bec23bfSVadim Pasternak struct i2c_adapter adap; 856bec23bfSVadim Pasternak u32 base_addr; 866bec23bfSVadim Pasternak struct mutex lock; 876bec23bfSVadim Pasternak struct mlxcpld_i2c_curr_xfer xfer; 886bec23bfSVadim Pasternak struct device *dev; 89c9bfdc7cSMichael Shych bool smbus_block; 906bec23bfSVadim Pasternak }; 916bec23bfSVadim Pasternak 926bec23bfSVadim Pasternak static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr) 936bec23bfSVadim Pasternak { 946bec23bfSVadim Pasternak int i; 956bec23bfSVadim Pasternak 966bec23bfSVadim Pasternak for (i = 0; i < len - len % 4; i += 4) 976bec23bfSVadim Pasternak outl(*(u32 *)(data + i), addr + i); 986bec23bfSVadim Pasternak for (; i < len; ++i) 996bec23bfSVadim Pasternak outb(*(data + i), addr + i); 1006bec23bfSVadim Pasternak } 1016bec23bfSVadim Pasternak 1026bec23bfSVadim Pasternak static void mlxcpld_i2c_lpc_read_buf(u8 *data, u8 len, u32 addr) 1036bec23bfSVadim Pasternak { 1046bec23bfSVadim Pasternak int i; 1056bec23bfSVadim Pasternak 1066bec23bfSVadim Pasternak for (i = 0; i < len - len % 4; i += 4) 1076bec23bfSVadim Pasternak *(u32 *)(data + i) = inl(addr + i); 1086bec23bfSVadim Pasternak for (; i < len; ++i) 1096bec23bfSVadim Pasternak *(data + i) = inb(addr + i); 1106bec23bfSVadim Pasternak } 1116bec23bfSVadim Pasternak 1126bec23bfSVadim Pasternak static void mlxcpld_i2c_read_comm(struct mlxcpld_i2c_priv *priv, u8 offs, 1136bec23bfSVadim Pasternak u8 *data, u8 datalen) 1146bec23bfSVadim Pasternak { 1156bec23bfSVadim Pasternak u32 addr = priv->base_addr + offs; 1166bec23bfSVadim Pasternak 1176bec23bfSVadim Pasternak switch (datalen) { 1186bec23bfSVadim Pasternak case 1: 1196bec23bfSVadim Pasternak *(data) = inb(addr); 1206bec23bfSVadim Pasternak break; 1216bec23bfSVadim Pasternak case 2: 1226bec23bfSVadim Pasternak *((u16 *)data) = inw(addr); 1236bec23bfSVadim Pasternak break; 1246bec23bfSVadim Pasternak case 3: 1256bec23bfSVadim Pasternak *((u16 *)data) = inw(addr); 1266bec23bfSVadim Pasternak *(data + 2) = inb(addr + 2); 1276bec23bfSVadim Pasternak break; 1286bec23bfSVadim Pasternak case 4: 1296bec23bfSVadim Pasternak *((u32 *)data) = inl(addr); 1306bec23bfSVadim Pasternak break; 1316bec23bfSVadim Pasternak default: 1326bec23bfSVadim Pasternak mlxcpld_i2c_lpc_read_buf(data, datalen, addr); 1336bec23bfSVadim Pasternak break; 1346bec23bfSVadim Pasternak } 1356bec23bfSVadim Pasternak } 1366bec23bfSVadim Pasternak 1376bec23bfSVadim Pasternak static void mlxcpld_i2c_write_comm(struct mlxcpld_i2c_priv *priv, u8 offs, 1386bec23bfSVadim Pasternak u8 *data, u8 datalen) 1396bec23bfSVadim Pasternak { 1406bec23bfSVadim Pasternak u32 addr = priv->base_addr + offs; 1416bec23bfSVadim Pasternak 1426bec23bfSVadim Pasternak switch (datalen) { 1436bec23bfSVadim Pasternak case 1: 1446bec23bfSVadim Pasternak outb(*(data), addr); 1456bec23bfSVadim Pasternak break; 1466bec23bfSVadim Pasternak case 2: 1476bec23bfSVadim Pasternak outw(*((u16 *)data), addr); 1486bec23bfSVadim Pasternak break; 1496bec23bfSVadim Pasternak case 3: 1506bec23bfSVadim Pasternak outw(*((u16 *)data), addr); 1516bec23bfSVadim Pasternak outb(*(data + 2), addr + 2); 1526bec23bfSVadim Pasternak break; 1536bec23bfSVadim Pasternak case 4: 1546bec23bfSVadim Pasternak outl(*((u32 *)data), addr); 1556bec23bfSVadim Pasternak break; 1566bec23bfSVadim Pasternak default: 1576bec23bfSVadim Pasternak mlxcpld_i2c_lpc_write_buf(data, datalen, addr); 1586bec23bfSVadim Pasternak break; 1596bec23bfSVadim Pasternak } 1606bec23bfSVadim Pasternak } 1616bec23bfSVadim Pasternak 1626bec23bfSVadim Pasternak /* 1636bec23bfSVadim Pasternak * Check validity of received i2c messages parameters. 1646bec23bfSVadim Pasternak * Returns 0 if OK, other - in case of invalid parameters. 1656bec23bfSVadim Pasternak */ 1666bec23bfSVadim Pasternak static int mlxcpld_i2c_check_msg_params(struct mlxcpld_i2c_priv *priv, 1676bec23bfSVadim Pasternak struct i2c_msg *msgs, int num) 1686bec23bfSVadim Pasternak { 1696bec23bfSVadim Pasternak int i; 1706bec23bfSVadim Pasternak 1716bec23bfSVadim Pasternak if (!num) { 1726bec23bfSVadim Pasternak dev_err(priv->dev, "Incorrect 0 num of messages\n"); 1736bec23bfSVadim Pasternak return -EINVAL; 1746bec23bfSVadim Pasternak } 1756bec23bfSVadim Pasternak 1766bec23bfSVadim Pasternak if (unlikely(msgs[0].addr > 0x7f)) { 1776bec23bfSVadim Pasternak dev_err(priv->dev, "Invalid address 0x%03x\n", 1786bec23bfSVadim Pasternak msgs[0].addr); 1796bec23bfSVadim Pasternak return -EINVAL; 1806bec23bfSVadim Pasternak } 1816bec23bfSVadim Pasternak 1826bec23bfSVadim Pasternak for (i = 0; i < num; ++i) { 1836bec23bfSVadim Pasternak if (unlikely(!msgs[i].buf)) { 1846bec23bfSVadim Pasternak dev_err(priv->dev, "Invalid buf in msg[%d]\n", 1856bec23bfSVadim Pasternak i); 1866bec23bfSVadim Pasternak return -EINVAL; 1876bec23bfSVadim Pasternak } 1886bec23bfSVadim Pasternak if (unlikely(msgs[0].addr != msgs[i].addr)) { 1896bec23bfSVadim Pasternak dev_err(priv->dev, "Invalid addr in msg[%d]\n", 1906bec23bfSVadim Pasternak i); 1916bec23bfSVadim Pasternak return -EINVAL; 1926bec23bfSVadim Pasternak } 1936bec23bfSVadim Pasternak } 1946bec23bfSVadim Pasternak 1956bec23bfSVadim Pasternak return 0; 1966bec23bfSVadim Pasternak } 1976bec23bfSVadim Pasternak 1986bec23bfSVadim Pasternak /* 1996bec23bfSVadim Pasternak * Check if transfer is completed and status of operation. 2006bec23bfSVadim Pasternak * Returns 0 - transfer completed (both ACK or NACK), 2016bec23bfSVadim Pasternak * negative - transfer isn't finished. 2026bec23bfSVadim Pasternak */ 2036bec23bfSVadim Pasternak static int mlxcpld_i2c_check_status(struct mlxcpld_i2c_priv *priv, int *status) 2046bec23bfSVadim Pasternak { 2056bec23bfSVadim Pasternak u8 val; 2066bec23bfSVadim Pasternak 2076bec23bfSVadim Pasternak mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1); 2086bec23bfSVadim Pasternak 2096bec23bfSVadim Pasternak if (val & MLXCPLD_LPCI2C_TRANS_END) { 2106bec23bfSVadim Pasternak if (val & MLXCPLD_LPCI2C_STATUS_NACK) 2116bec23bfSVadim Pasternak /* 2126bec23bfSVadim Pasternak * The slave is unable to accept the data. No such 2136bec23bfSVadim Pasternak * slave, command not understood, or unable to accept 2146bec23bfSVadim Pasternak * any more data. 2156bec23bfSVadim Pasternak */ 2166bec23bfSVadim Pasternak *status = MLXCPLD_LPCI2C_NACK_IND; 2176bec23bfSVadim Pasternak else 2186bec23bfSVadim Pasternak *status = MLXCPLD_LPCI2C_ACK_IND; 2196bec23bfSVadim Pasternak return 0; 2206bec23bfSVadim Pasternak } 2216bec23bfSVadim Pasternak *status = MLXCPLD_LPCI2C_NO_IND; 2226bec23bfSVadim Pasternak 2236bec23bfSVadim Pasternak return -EIO; 2246bec23bfSVadim Pasternak } 2256bec23bfSVadim Pasternak 2266bec23bfSVadim Pasternak static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv, 2276bec23bfSVadim Pasternak struct i2c_msg *msgs, int num, 2286bec23bfSVadim Pasternak u8 comm_len) 2296bec23bfSVadim Pasternak { 2306bec23bfSVadim Pasternak priv->xfer.msg = msgs; 2316bec23bfSVadim Pasternak priv->xfer.msg_num = num; 2326bec23bfSVadim Pasternak 2336bec23bfSVadim Pasternak /* 2346bec23bfSVadim Pasternak * All upper layers currently are never use transfer with more than 2356bec23bfSVadim Pasternak * 2 messages. Actually, it's also not so relevant in Mellanox systems 2366bec23bfSVadim Pasternak * because of HW limitation. Max size of transfer is not more than 32 237313ce648SMichael Shych * or 68 bytes in the current x86 LPCI2C bridge. 2386bec23bfSVadim Pasternak */ 2396bec23bfSVadim Pasternak priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD; 2406bec23bfSVadim Pasternak 2416bec23bfSVadim Pasternak if (priv->xfer.cmd == I2C_M_RD && comm_len != msgs[0].len) { 2426bec23bfSVadim Pasternak priv->xfer.addr_width = msgs[0].len; 2436bec23bfSVadim Pasternak priv->xfer.data_len = comm_len - priv->xfer.addr_width; 2446bec23bfSVadim Pasternak } else { 2456bec23bfSVadim Pasternak priv->xfer.addr_width = 0; 2466bec23bfSVadim Pasternak priv->xfer.data_len = comm_len; 2476bec23bfSVadim Pasternak } 2486bec23bfSVadim Pasternak } 2496bec23bfSVadim Pasternak 2506bec23bfSVadim Pasternak /* Reset CPLD LPCI2C block */ 2516bec23bfSVadim Pasternak static void mlxcpld_i2c_reset(struct mlxcpld_i2c_priv *priv) 2526bec23bfSVadim Pasternak { 2536bec23bfSVadim Pasternak u8 val; 2546bec23bfSVadim Pasternak 2556bec23bfSVadim Pasternak mutex_lock(&priv->lock); 2566bec23bfSVadim Pasternak 2576bec23bfSVadim Pasternak mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1); 2586bec23bfSVadim Pasternak val &= ~MLXCPLD_LPCI2C_RST_SEL_MASK; 2596bec23bfSVadim Pasternak mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1); 2606bec23bfSVadim Pasternak 2616bec23bfSVadim Pasternak mutex_unlock(&priv->lock); 2626bec23bfSVadim Pasternak } 2636bec23bfSVadim Pasternak 2646bec23bfSVadim Pasternak /* Make sure the CPLD is ready to start transmitting. */ 2656bec23bfSVadim Pasternak static int mlxcpld_i2c_check_busy(struct mlxcpld_i2c_priv *priv) 2666bec23bfSVadim Pasternak { 2676bec23bfSVadim Pasternak u8 val; 2686bec23bfSVadim Pasternak 2696bec23bfSVadim Pasternak mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1); 2706bec23bfSVadim Pasternak 2716bec23bfSVadim Pasternak if (val & MLXCPLD_LPCI2C_TRANS_END) 2726bec23bfSVadim Pasternak return 0; 2736bec23bfSVadim Pasternak 2746bec23bfSVadim Pasternak return -EIO; 2756bec23bfSVadim Pasternak } 2766bec23bfSVadim Pasternak 2776bec23bfSVadim Pasternak static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv) 2786bec23bfSVadim Pasternak { 2796bec23bfSVadim Pasternak int timeout = 0; 2806bec23bfSVadim Pasternak 2816bec23bfSVadim Pasternak do { 2826bec23bfSVadim Pasternak if (!mlxcpld_i2c_check_busy(priv)) 2836bec23bfSVadim Pasternak break; 2846bec23bfSVadim Pasternak usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME); 2856bec23bfSVadim Pasternak timeout += MLXCPLD_I2C_POLL_TIME; 2866bec23bfSVadim Pasternak } while (timeout <= MLXCPLD_I2C_XFER_TO); 2876bec23bfSVadim Pasternak 2886bec23bfSVadim Pasternak if (timeout > MLXCPLD_I2C_XFER_TO) 2896bec23bfSVadim Pasternak return -ETIMEDOUT; 2906bec23bfSVadim Pasternak 2916bec23bfSVadim Pasternak return 0; 2926bec23bfSVadim Pasternak } 2936bec23bfSVadim Pasternak 2946bec23bfSVadim Pasternak /* 2956bec23bfSVadim Pasternak * Wait for master transfer to complete. 2966bec23bfSVadim Pasternak * It puts current process to sleep until we get interrupt or timeout expires. 2976bec23bfSVadim Pasternak * Returns the number of transferred or read bytes or error (<0). 2986bec23bfSVadim Pasternak */ 2996bec23bfSVadim Pasternak static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv) 3006bec23bfSVadim Pasternak { 3016bec23bfSVadim Pasternak int status, i, timeout = 0; 302c9bfdc7cSMichael Shych u8 datalen, val; 3036bec23bfSVadim Pasternak 3046bec23bfSVadim Pasternak do { 3056bec23bfSVadim Pasternak usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME); 3066bec23bfSVadim Pasternak if (!mlxcpld_i2c_check_status(priv, &status)) 3076bec23bfSVadim Pasternak break; 3086bec23bfSVadim Pasternak timeout += MLXCPLD_I2C_POLL_TIME; 3096bec23bfSVadim Pasternak } while (status == 0 && timeout < MLXCPLD_I2C_XFER_TO); 3106bec23bfSVadim Pasternak 3116bec23bfSVadim Pasternak switch (status) { 3126bec23bfSVadim Pasternak case MLXCPLD_LPCI2C_NO_IND: 3136bec23bfSVadim Pasternak return -ETIMEDOUT; 3146bec23bfSVadim Pasternak 3156bec23bfSVadim Pasternak case MLXCPLD_LPCI2C_ACK_IND: 3166bec23bfSVadim Pasternak if (priv->xfer.cmd != I2C_M_RD) 3176bec23bfSVadim Pasternak return (priv->xfer.addr_width + priv->xfer.data_len); 3186bec23bfSVadim Pasternak 3196bec23bfSVadim Pasternak if (priv->xfer.msg_num == 1) 3206bec23bfSVadim Pasternak i = 0; 3216bec23bfSVadim Pasternak else 3226bec23bfSVadim Pasternak i = 1; 3236bec23bfSVadim Pasternak 3246bec23bfSVadim Pasternak if (!priv->xfer.msg[i].buf) 3256bec23bfSVadim Pasternak return -EINVAL; 3266bec23bfSVadim Pasternak 3276bec23bfSVadim Pasternak /* 3286bec23bfSVadim Pasternak * Actual read data len will be always the same as 3296bec23bfSVadim Pasternak * requested len. 0xff (line pull-up) will be returned 3306bec23bfSVadim Pasternak * if slave has no data to return. Thus don't read 331c9bfdc7cSMichael Shych * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD. Only in case of 332c9bfdc7cSMichael Shych * SMBus block read transaction data len can be different, 333c9bfdc7cSMichael Shych * check this case. 3346bec23bfSVadim Pasternak */ 335c9bfdc7cSMichael Shych mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val, 336c9bfdc7cSMichael Shych 1); 337c9bfdc7cSMichael Shych if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) { 338c9bfdc7cSMichael Shych mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG, 339c9bfdc7cSMichael Shych &datalen, 1); 340c9bfdc7cSMichael Shych if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) { 341c9bfdc7cSMichael Shych dev_err(priv->dev, "Incorrect smbus block read message len\n"); 342c9bfdc7cSMichael Shych return -E2BIG; 343c9bfdc7cSMichael Shych } 344c9bfdc7cSMichael Shych } else { 3456bec23bfSVadim Pasternak datalen = priv->xfer.data_len; 346c9bfdc7cSMichael Shych } 3476bec23bfSVadim Pasternak 3486bec23bfSVadim Pasternak mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG, 3496bec23bfSVadim Pasternak priv->xfer.msg[i].buf, datalen); 3506bec23bfSVadim Pasternak 3516bec23bfSVadim Pasternak return datalen; 3526bec23bfSVadim Pasternak 3536bec23bfSVadim Pasternak case MLXCPLD_LPCI2C_NACK_IND: 3546bec23bfSVadim Pasternak return -ENXIO; 3556bec23bfSVadim Pasternak 3566bec23bfSVadim Pasternak default: 3576bec23bfSVadim Pasternak return -EINVAL; 3586bec23bfSVadim Pasternak } 3596bec23bfSVadim Pasternak } 3606bec23bfSVadim Pasternak 3616bec23bfSVadim Pasternak static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv) 3626bec23bfSVadim Pasternak { 3636bec23bfSVadim Pasternak int i, len = 0; 364c9bfdc7cSMichael Shych u8 cmd, val; 3656bec23bfSVadim Pasternak 3666bec23bfSVadim Pasternak mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG, 3676bec23bfSVadim Pasternak &priv->xfer.data_len, 1); 368c9bfdc7cSMichael Shych 369c9bfdc7cSMichael Shych val = priv->xfer.addr_width; 370c9bfdc7cSMichael Shych /* Notify HW about SMBus block read transaction */ 371c9bfdc7cSMichael Shych if (priv->smbus_block && priv->xfer.msg_num >= 2 && 372c9bfdc7cSMichael Shych priv->xfer.msg[1].len == 1 && 373c9bfdc7cSMichael Shych (priv->xfer.msg[1].flags & I2C_M_RECV_LEN) && 374c9bfdc7cSMichael Shych (priv->xfer.msg[1].flags & I2C_M_RD)) 375c9bfdc7cSMichael Shych val |= MLXCPLD_I2C_SMBUS_BLK_BIT; 376c9bfdc7cSMichael Shych 377c9bfdc7cSMichael Shych mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val, 1); 3786bec23bfSVadim Pasternak 3796bec23bfSVadim Pasternak for (i = 0; i < priv->xfer.msg_num; i++) { 3806bec23bfSVadim Pasternak if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) { 3816bec23bfSVadim Pasternak /* Don't write to CPLD buffer in read transaction */ 3826bec23bfSVadim Pasternak mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_DATA_REG + 3836bec23bfSVadim Pasternak len, priv->xfer.msg[i].buf, 3846bec23bfSVadim Pasternak priv->xfer.msg[i].len); 3856bec23bfSVadim Pasternak len += priv->xfer.msg[i].len; 3866bec23bfSVadim Pasternak } 3876bec23bfSVadim Pasternak } 3886bec23bfSVadim Pasternak 3896bec23bfSVadim Pasternak /* 3906bec23bfSVadim Pasternak * Set target slave address with command for master transfer. 3916bec23bfSVadim Pasternak * It should be latest executed function before CPLD transaction. 3926bec23bfSVadim Pasternak */ 3936bec23bfSVadim Pasternak cmd = (priv->xfer.msg[0].addr << 1) | priv->xfer.cmd; 3946bec23bfSVadim Pasternak mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CMD_REG, &cmd, 1); 3956bec23bfSVadim Pasternak } 3966bec23bfSVadim Pasternak 3976bec23bfSVadim Pasternak /* 3986bec23bfSVadim Pasternak * Generic lpc-i2c transfer. 3996bec23bfSVadim Pasternak * Returns the number of processed messages or error (<0). 4006bec23bfSVadim Pasternak */ 4016bec23bfSVadim Pasternak static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 4026bec23bfSVadim Pasternak int num) 4036bec23bfSVadim Pasternak { 4046bec23bfSVadim Pasternak struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap); 4056bec23bfSVadim Pasternak u8 comm_len = 0; 4066bec23bfSVadim Pasternak int i, err; 4076bec23bfSVadim Pasternak 4086bec23bfSVadim Pasternak err = mlxcpld_i2c_check_msg_params(priv, msgs, num); 4096bec23bfSVadim Pasternak if (err) { 4106bec23bfSVadim Pasternak dev_err(priv->dev, "Incorrect message\n"); 4116bec23bfSVadim Pasternak return err; 4126bec23bfSVadim Pasternak } 4136bec23bfSVadim Pasternak 4146bec23bfSVadim Pasternak for (i = 0; i < num; ++i) 4156bec23bfSVadim Pasternak comm_len += msgs[i].len; 4166bec23bfSVadim Pasternak 4176bec23bfSVadim Pasternak /* Check bus state */ 4186bec23bfSVadim Pasternak if (mlxcpld_i2c_wait_for_free(priv)) { 4196bec23bfSVadim Pasternak dev_err(priv->dev, "LPCI2C bridge is busy\n"); 4206bec23bfSVadim Pasternak 4216bec23bfSVadim Pasternak /* 4226bec23bfSVadim Pasternak * Usually it means something serious has happened. 4236bec23bfSVadim Pasternak * We can not have unfinished previous transfer 4246bec23bfSVadim Pasternak * so it doesn't make any sense to try to stop it. 4256bec23bfSVadim Pasternak * Probably we were not able to recover from the 4266bec23bfSVadim Pasternak * previous error. 4276bec23bfSVadim Pasternak * The only reasonable thing - is soft reset. 4286bec23bfSVadim Pasternak */ 4296bec23bfSVadim Pasternak mlxcpld_i2c_reset(priv); 4306bec23bfSVadim Pasternak if (mlxcpld_i2c_check_busy(priv)) { 4316bec23bfSVadim Pasternak dev_err(priv->dev, "LPCI2C bridge is busy after reset\n"); 4326bec23bfSVadim Pasternak return -EIO; 4336bec23bfSVadim Pasternak } 4346bec23bfSVadim Pasternak } 4356bec23bfSVadim Pasternak 4366bec23bfSVadim Pasternak mlxcpld_i2c_set_transf_data(priv, msgs, num, comm_len); 4376bec23bfSVadim Pasternak 4386bec23bfSVadim Pasternak mutex_lock(&priv->lock); 4396bec23bfSVadim Pasternak 4406bec23bfSVadim Pasternak /* Do real transfer. Can't fail */ 4416bec23bfSVadim Pasternak mlxcpld_i2c_xfer_msg(priv); 4426bec23bfSVadim Pasternak 4436bec23bfSVadim Pasternak /* Wait for transaction complete */ 4446bec23bfSVadim Pasternak err = mlxcpld_i2c_wait_for_tc(priv); 4456bec23bfSVadim Pasternak 4466bec23bfSVadim Pasternak mutex_unlock(&priv->lock); 4476bec23bfSVadim Pasternak 4486bec23bfSVadim Pasternak return err < 0 ? err : num; 4496bec23bfSVadim Pasternak } 4506bec23bfSVadim Pasternak 4516bec23bfSVadim Pasternak static u32 mlxcpld_i2c_func(struct i2c_adapter *adap) 4526bec23bfSVadim Pasternak { 453845f2a6dSMichael Shych struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap); 454845f2a6dSMichael Shych 455845f2a6dSMichael Shych if (priv->smbus_block) 456845f2a6dSMichael Shych return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 457845f2a6dSMichael Shych I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA; 458845f2a6dSMichael Shych else 459845f2a6dSMichael Shych return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 460845f2a6dSMichael Shych I2C_FUNC_SMBUS_I2C_BLOCK; 4616bec23bfSVadim Pasternak } 4626bec23bfSVadim Pasternak 4636bec23bfSVadim Pasternak static const struct i2c_algorithm mlxcpld_i2c_algo = { 4646bec23bfSVadim Pasternak .master_xfer = mlxcpld_i2c_xfer, 4656bec23bfSVadim Pasternak .functionality = mlxcpld_i2c_func 4666bec23bfSVadim Pasternak }; 4676bec23bfSVadim Pasternak 468ae3923a2SBhumika Goyal static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = { 4696bec23bfSVadim Pasternak .flags = I2C_AQ_COMB_WRITE_THEN_READ, 4706bec23bfSVadim Pasternak .max_read_len = MLXCPLD_I2C_DATA_REG_SZ - MLXCPLD_I2C_MAX_ADDR_LEN, 4716bec23bfSVadim Pasternak .max_write_len = MLXCPLD_I2C_DATA_REG_SZ, 4726bec23bfSVadim Pasternak .max_comb_1st_msg_len = 4, 4736bec23bfSVadim Pasternak }; 4746bec23bfSVadim Pasternak 475313ce648SMichael Shych static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = { 476313ce648SMichael Shych .flags = I2C_AQ_COMB_WRITE_THEN_READ, 477313ce648SMichael Shych .max_read_len = MLXCPLD_I2C_DATA_REG_SZ * 2 - MLXCPLD_I2C_MAX_ADDR_LEN, 478313ce648SMichael Shych .max_write_len = MLXCPLD_I2C_DATA_REG_SZ * 2, 479313ce648SMichael Shych .max_comb_1st_msg_len = 4, 480313ce648SMichael Shych }; 481313ce648SMichael Shych 4826bec23bfSVadim Pasternak static struct i2c_adapter mlxcpld_i2c_adapter = { 4836bec23bfSVadim Pasternak .owner = THIS_MODULE, 4846bec23bfSVadim Pasternak .name = "i2c-mlxcpld", 4856bec23bfSVadim Pasternak .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, 4866bec23bfSVadim Pasternak .algo = &mlxcpld_i2c_algo, 4876bec23bfSVadim Pasternak .quirks = &mlxcpld_i2c_quirks, 4886bec23bfSVadim Pasternak .retries = MLXCPLD_I2C_RETR_NUM, 4896bec23bfSVadim Pasternak .nr = MLXCPLD_I2C_BUS_NUM, 4906bec23bfSVadim Pasternak }; 4916bec23bfSVadim Pasternak 4926bec23bfSVadim Pasternak static int mlxcpld_i2c_probe(struct platform_device *pdev) 4936bec23bfSVadim Pasternak { 4946bec23bfSVadim Pasternak struct mlxcpld_i2c_priv *priv; 4956bec23bfSVadim Pasternak int err; 496313ce648SMichael Shych u8 val; 4976bec23bfSVadim Pasternak 4986bec23bfSVadim Pasternak priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 4996bec23bfSVadim Pasternak if (!priv) 5006bec23bfSVadim Pasternak return -ENOMEM; 5016bec23bfSVadim Pasternak 5026bec23bfSVadim Pasternak mutex_init(&priv->lock); 5036bec23bfSVadim Pasternak platform_set_drvdata(pdev, priv); 5046bec23bfSVadim Pasternak 5056bec23bfSVadim Pasternak priv->dev = &pdev->dev; 506*13067ef7SVadim Pasternak priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR; 5076bec23bfSVadim Pasternak 5086bec23bfSVadim Pasternak /* Register with i2c layer */ 5096bec23bfSVadim Pasternak mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO); 510313ce648SMichael Shych /* Read capability register */ 511313ce648SMichael Shych mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CPBLTY_REG, &val, 1); 512313ce648SMichael Shych /* Check support for extended transaction length */ 513313ce648SMichael Shych if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT) 514313ce648SMichael Shych mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext; 515c9bfdc7cSMichael Shych /* Check support for smbus block transaction */ 516c9bfdc7cSMichael Shych if (val & MLXCPLD_I2C_SMBUS_BLK_BIT) 517c9bfdc7cSMichael Shych priv->smbus_block = true; 518ae4aa68dSMichael Shych if (pdev->id >= -1) 519ae4aa68dSMichael Shych mlxcpld_i2c_adapter.nr = pdev->id; 5206bec23bfSVadim Pasternak priv->adap = mlxcpld_i2c_adapter; 5216bec23bfSVadim Pasternak priv->adap.dev.parent = &pdev->dev; 5226bec23bfSVadim Pasternak i2c_set_adapdata(&priv->adap, priv); 5236bec23bfSVadim Pasternak 5246bec23bfSVadim Pasternak err = i2c_add_numbered_adapter(&priv->adap); 5256bec23bfSVadim Pasternak if (err) 5266bec23bfSVadim Pasternak mutex_destroy(&priv->lock); 5276bec23bfSVadim Pasternak 5286bec23bfSVadim Pasternak return err; 5296bec23bfSVadim Pasternak } 5306bec23bfSVadim Pasternak 5316bec23bfSVadim Pasternak static int mlxcpld_i2c_remove(struct platform_device *pdev) 5326bec23bfSVadim Pasternak { 5336bec23bfSVadim Pasternak struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev); 5346bec23bfSVadim Pasternak 5356bec23bfSVadim Pasternak i2c_del_adapter(&priv->adap); 5366bec23bfSVadim Pasternak mutex_destroy(&priv->lock); 5376bec23bfSVadim Pasternak 5386bec23bfSVadim Pasternak return 0; 5396bec23bfSVadim Pasternak } 5406bec23bfSVadim Pasternak 5416bec23bfSVadim Pasternak static struct platform_driver mlxcpld_i2c_driver = { 5426bec23bfSVadim Pasternak .probe = mlxcpld_i2c_probe, 5436bec23bfSVadim Pasternak .remove = mlxcpld_i2c_remove, 5446bec23bfSVadim Pasternak .driver = { 5456bec23bfSVadim Pasternak .name = MLXCPLD_I2C_DEVICE_NAME, 5466bec23bfSVadim Pasternak }, 5476bec23bfSVadim Pasternak }; 5486bec23bfSVadim Pasternak 5496bec23bfSVadim Pasternak module_platform_driver(mlxcpld_i2c_driver); 5506bec23bfSVadim Pasternak 5516bec23bfSVadim Pasternak MODULE_AUTHOR("Michael Shych <michaels@mellanox.com>"); 5526bec23bfSVadim Pasternak MODULE_DESCRIPTION("Mellanox I2C-CPLD controller driver"); 5536bec23bfSVadim Pasternak MODULE_LICENSE("Dual BSD/GPL"); 5546bec23bfSVadim Pasternak MODULE_ALIAS("platform:i2c-mlxcpld"); 555